Medley Developer Blog

株式会社メドレーのエンジニア・デザイナーによるブログです

新卒エンジニアが2年目でプロジェクトリーダーを経験して得た学び

はじめまして。メドレーのエンジニア熊本です。新卒で入社し今年で3年目になりまして、2019年度エンジニア新卒の研修を終えてから早2年が経とうとしています。

そんな私ですが去年の11月頃から先月までの間、とあるプロジェクトのリーダーを任せてもらっていたので、そのお話をさせていただきます。

はじめに

私は新卒研修を終えてから医療介護求人サイトジョブメドレーのチームで開発をしていましたが、そのジョブメドレーを支える社内管理システムのリニューアルプロジェクトに初期から携わっていました。

こちらのプロジェクトにつきましては、弊社デザイナーの酒井がデザイナーがデザインツールを使わずに、Reactを使ってデザインした話を、弊社エンジニアの山田がGraphQL, TypeScript, Reactを用いて型安全に社内システムをリニューアルした話を以前ブログにしていますので、よろしければあわせてご覧ください。

その社内管理システムをどのような流れでリニューアルし、その中で自分の役割がどう変化しどう対応したのかなどについて、次の章からお話ししていきます。

プロジェクトについて

リニューアルの背景やシステムの概要については上に紹介した記事でも説明しているため割愛しますが、求職者や求人を掲載する顧客に関する業務を行っているシステムをおよそ1年半かけて刷新するという大きなプロジェクトでした。

システムの中でも求職者関連を「Phase1」、顧客関連を「Phase2」として分割し、リニューアルを進めました。

プロジェクト内での自分の役割の変遷

Phase1の最初期は先輩方がアーキテクチャの設計やスケジューリングをしていました。当時まだ新卒1年目で未熟な私でしたが、権限管理のテーブル設計をするタスクをアサインしてもらいました。ここでは詳細を省きますが、初めてのテーブル設計で右も左も分からない状態から責任感を持って何とか形にすることができ、(もちろんリニューアル中に多少の見直しはありましたが)大きな達成感を得たことを覚えています。

各種設計、技術選定、開発の進め方などが大方固まり本格的に開発が始まるわけですが、Phase1の際は先輩社員がプロジェクトリーダーとして引っ張っていただき、自分は開発メンバーの一員としてAPIの作成などに奮闘していました。

GraphQLといった技術やスケジュールが厳密に引かれたプロジェクトでの開発など初めて経験することも多々ありましたが、先輩方にサポートをいただいたり、同期と切磋琢磨しながら取り組めたおかげで、Phase1を乗り切ることができました。

さて、ここからが本題になりますが、Phase2になるとプロジェクトメンバーの入れ替えや私自身の目標設定も重なり、プロジェクトリーダーを任せてもらうことになります。まずはプロジェクトリーダーに任命されてから、どういった仕事をしていたのかご紹介します。

プロジェクトリーダーの仕事

プロジェクトリーダーとして期待されていたことは以下の通りです。

  • プロジェクト管理
  • システム設計
  • 開発
  • チームマネジメント

これを更に細分化し、私の実業務と照らし合わせながら並べてみると、多少粒度にばらつきがあるかもしれませんが以下のようなことが挙げられます。

  1. 要件定義・画面設計
    1. ディレクターとデザイナー主導で進めつつ、エンジニアも実データや既存ロジックを踏まえた観点を持ち合わせて参加しました
  2. 開発方針の検討
  3. 開発タスクへの落とし込み
  4. 技術調査・選定
  5. API設計
  6. 工数算出・スケジューリング
  7. 実装・レビュー
  8. QA(Quality Assurance)テスト
  9. リリースマネジメント

Phase2は段階的にリリースを行ったため、その度に1から9までを繰り返していたような流れになります。また、上記に加え、定例ミーティングでの報告や開発メンバーのタスクマネジメントも随時行っていました。

もちろん苦労したことは多く、全部を挙げようとするとキリがないのですが、その中でもいくつかに絞った上で紹介したいと思います。

苦労と工夫

1. 「そもそも何をやればいいのか」

まず最初に苦労したことは「そもそも何をやればいいのかわからない」ということでした。初めから先ほど挙げたような動きをイメージできていたわけではなく、記事や本を読み漁ったり先輩との1on1で質問攻めにしたりと基本的な知識を叩き込むわけですが、実際にとった最初の動きとしては「できる部分を見つけてやっていく」ということだったと思います。 自分がリーダーに任命された時点でのプロジェクトの状況としては要件定義や画面設計が進んでいる最中でしたが、これらがまとまるのを待つのではなく「全部決まらないとやれないこと」と「現時点でやれること」を切り分けて動きました。こうしたところから少しずつリズムを作り、最終的に先ほど列挙したような一通りのことがイメージ・実行できるようになったのだと思います。

2. 工数見積もり

一般的に工数見積もりに関する記事は世の中に多く存在しますが、私の場合は工数見積もりの方法がわからなかったというよりも、「どういう思想で見積もったのか、どういう選択肢があるのか」を曖昧にしていたことが当初の問題でした。

初めて見積もった時は単に開発タスクを積み上げた工数を報告して満足してしまいましたが、様々な方のフィードバックを受けプロダクト価値を高めるためにどういう動きができるのかを考える必要があったことを痛感しました。単純に工数を積み上げる場合や事業的な都合を踏まえてミニマムで開発する場合など、いくつかの選択肢をそれぞれの軸で考える必要があったことを学びました(この時期は夜な夜な夢の中で工数見積もりをしていたのも今ではいい思い出です)。

3. 意思決定

これはいつになっても正解が存在する類のものではないのですが、特に意思決定には苦労しました。意思決定といっても開発方針から技術選定まで様々な粒度のものがありますが、特に最初から苦労したのは技術的な決定でした。

それまで先輩に頼ることの多かった私がプロジェクトリーダーになった直後から何もかもできるようになるわけではないことは明々白々ですが、「自分が決めないと」と焦ってしまっていた時期もあったと思います。

そこで一度立ち止まって意識したことは、「何ができて何ができないのかを他者に明示する」ことでした。はっきりと自分に足りていないことを他者に伝えることで、周りもサポートしやすくなると思いますし、自分自身なにがやれることなのか明確になるので単純なことですが効果的であったと思います。他にも開発メンバーの提案で、インセプションデッキを取り入れてみたことも効果的でした。

また、意思決定とは文脈が少し変わってきますが、モブプロやペアプロを実施してチーム力を高め属人化をなくしつつ開発効率を向上させる取り組みも、時間が経てば経つほど効果を実感できて良かったと思います。このようにアジャイル開発の手法からチームにフィットする手法をいくつか取り入れることもできました。

プロジェクトを通して成長したこと

これまで小出しで色々とお話しさせていただきましたが、自分が特に成長したと感じていることをまとめさせていただきます。

一通りの経験を通して得られたリード力

API設計だけ」ではなく一通り全てを任せていただいたことはとても大きな経験になりました。初めて個人ではなくチーム・プロジェクト全体として効率が良くなる動きを考える経験もできたと思います。

技術力

もちろん実装を通じて得た技術は数えきれないほどありますが、その中でも特に責任を持って他者のコードをレビューしたり、自分が書くコードの影響範囲やスコープを意識し続けたことが大きな糧になっている気がします。

リスク管理

スケジュール遅延のリスク、方向性がずれてしまうリスク、技術的なリスク、様々ありますがこれらのリスクヘッジを考える力がプロジェクトリーダーには必要です。

リスク管理において「先読みが大切」とよく言われますが、私の場合はある先輩社員から「常に2週間先を見据えておけ」という具体的な日数のアドバイスをいただきました。具体的にすることであらゆることが想像しやすくなりましたし、それを1年以上毎日意識し実行し続けたことが、プロジェクトをやり切ることができた要因にもなっていると思います。もちろんこの言葉は家宝にしようと思っています。

価値に対する視野

何よりも「プロダクトのユーザーに価値を提供すること」の意味を理解しました。ここまでに書いてきたようなスケジュール管理やリスク管理などは、あくまでプロジェクトを遂行する上で必要な仕事の一つでしかないはずです。プロジェクトを通してシステムを使っている社員、更にはその先の顧客・求職者へ如何に価値を提供できるか考えるべきですが、一時期は「どうやるのか・なにをやるのか」というプロジェクト自体を完遂させることしか考えられていない時期もありました。

視野が狭くなっていたことに周りからの指摘で気づくことができ、それ以降は「そもそも本当にこの機能はいるのか」などユーザーの立場からの観点も徐々に身に付けることができました。これがきっかけとなり、周りとも頻繁に「なぜやるのか」を議論できるようになったと思います。新卒1年目で口酸っぱく言われていた「目的意識」をようやく腹落ちさせ体現することができました。

最後に

最後となりますが、プロジェクトリーダーについて語ってきた私ですが、入社するまではWeb開発未経験でして、メドレーでの成長を非常に実感しています。そんなメドレーではエンジニア・デザイナーをはじめ多くのポジションで新たなメンバーを募集していますので、少しでもご興味をお持ちいただけた方は、是非お気軽にお話しさせていただければと思います!

ここまでお付き合いいただき、ありがとうございました。

www.medley.jp

オンライン診察機能に画面共有を実装した話

事業本部 プロダクト開発室エンジニアの日下です。

オンライン診療・服薬指導・クラウド診療支援システム「CLINICS」の、患者・医療機関に向けたアプリケーションの機能開発、開発基盤、インフラ周りを担当しております。

今回 CLINICS が提供するオンライン診療機能に「画面共有機能」を追加しましたので、その背景・技術的な話をまとめます。

画面共有機能実装の背景

CLINICS とオンライン診療

普段皆さんが病院にかかるとき、多くの場合は病院に行き、医師の診察を対面で受け、会計をして帰るといった流れになるかと思います。

CLINICS のオンライン診療はこの流れをインターネットを通して提供するサービスです。

※ オンライン診療は、一度、初診等で対面診療を受けた際に医師が可能と判断した場合、次回以降の診察において可能になります。また、現在は新型コロナウイルス感染症対策時限措置として、初診からオンライン診療を受けることが可能となっています。

CLINICS を利用した場合、事前に予約した時間にスマホまたは PC で待機をする、医師の診察をビデオチャットで受け、会計はクレジットカードで行われるという流れとなっています。

クラウド診療支援システムとしての CLINICS は 2016 年に「オンライン診療のためのシステム」としてローンチされ、2018 年にはクラウド型電子カルテ機能を2019 年には予約管理システム機能を2020 年にはかかりつけ薬局支援システム Pharms との連携機能も追加し、患者向けアプリからオンライン服薬指導をシームレスに受けることができるようになりました。

プロダクト開発室ではこれらオンライン診療機能・電子カルテ機能・予約管理機能・連携機能の改善を日々行っています。

画面共有機能の需要の高まり、実装の決定

このように CLINICS の改善を日々行なっている中、昨年から始まった新型コロナウイルス感染症(COVID-19)の流行に伴った需要の増加により、オンライン診療の件数が急増しました。

CLINICS も数多くの医療機関にご利用いただく中で、オンライン診療に関わるさまざまなご要望をいただくようになりました。その中でも特に多かったものが、今回紹介する画面共有機能です。

対面での診察の際に医師が検査結果などを患者に見せながら説明するように、オンラインで診察する場合でも資料をリアルタイムで共有しながら説明ができるようになれば、今まで以上にオンラインでも質の高い診察を行えるようになります。

こういったユースケース、要望などを検討した結果、CLINICS を利用するすべての医療機関及び患者にとって大きな恩恵が見込まれたため、オンライン診察(ビデオチャット)中に医師の PC 画面をリアルタイムで患者に共有する機能として実装をすることにしました。

f:id:medley_inc:20210729115806p:plain

画面共有機能の実装

画面共有をする医師側向けのコードでどういった実装方法があるのか、大まかな流れをまとめます。

※ 以下に記載しているコードは説明のための疑似コードですので、このままでは動作しないことにご注意ください。また、医師側の実装例を掲載しているため、患者側(画面共有を受ける側)の実装は別途必要になります。

オンライン診察開始までの処理

オンライン診察を開始するには医師側のマイクとカメラで取得した情報を患者側に送付する必要があります。ここではそこまでの実装の流れを見ていきます。

カメラ・マイクのストリームの取得

オンライン診察開始時点で医師側のマイク・カメラの情報を共有するため、まずはそれらのストリームを取得する必要があります。こういったメディアコンテンツのストリームを司るインターフェイスとして MediaStream が定義されています。

マイク・カメラの MediaStream は、例えば MediaDevices.getUserMedia() を利用して取得できます。

const userMediaStream: MediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });

SkyWay 経由でオンライン診察を始める

WebRTC で P2Pビデオチャットを利用するためには、初期の接続のための処理及び接続の維持などの処理を行う必要があります。弊社ではこのあたりの処理を WebRTC SaaSSkyWay 及びその SDK を利用することで簡略化しています。

オンライン診察開始時には、先程取得した医師側のマイク・カメラの MediaStream を SkyWay の SDK に渡すことで、一対一でのリアルタイムビデオチャットを実現できます。

import Peer, { MediaConnection } from "skyway-js";

const peer = new Peer({ key: "your-api-key" });

// 事前に患者と共有しておいたpeer idに対してcallメソッドとMediaStreamを渡すことで診察を開始できる。
const mediaConnection: MediaConnection = peer.call("shared-peer-id", userMediaStream);

// 注: 患者側は送付された処理をハンドリングする機能を実装する必要がある

ここまでがオンライン診察を開始するまでの処理です。

※ 詳細は SkyWay 公式のチュートリアルなどを参照ください。

画面共有の処理

ここまでで患者に対して医師側のカメラ・マイクで取得された映像・音声が表示されている状態のため、これを切り替える処理が必要になります。今回は現在接続に利用している MediaStream を、画面共有用の MediaStream に入れ替えることで実現しました。

画面の MediaStream の取得

まずは共有する画面の MediaStream を取得する必要があります。これは MediaDevices.getDisplayMedia() を使うことで実現できます。

const displayStream: MediaStream = await navigator.mediaDevices.getDisplayMedia({ video: true });

画面共有用の MediaStream を作る

getDisplayMedia() から共有する画面の MediaStream を取得できるものの、そのまま利用するとマイクの音声が入りません。

これは getDisplayMedia() から取れる MediaStream にマイクの音声が含まれていないことが原因なので、必要な画像・音声の組み合わせを持った画面共有用の MediaStream を作成することで対処ができます。

MediaStreamTrack を組みあわせて画面共有用の MediaStream を作る

画面共有用の MediaStream を作成する前にまず、MediaStreamTrack と MediaStream の関係を理解する必要があります。

MediaStreamTrack はストリームに含まれる一つのメディアトラックを表現するものです。 kind という読み取り専用プロパティがあり、オーディオトラックであれば "audio" が、ビデオトラックであれば "video" が設定されています。

また、 MediaStream は複数の MediaStreamTrack から成り、オーディオトラック・ビデオトラックを取り出すメソッドがそれぞれ MediaStream.getAudioTracks()MediaStream.getVideoTracks() として実装されています。

これらを組み合わせることで、マイクと画面の MediaStreamTrack を持つ MediaStream を作ることができ、これを SkyWay の SDK に渡すことで、画面共有を実現できます。

const [displayVideoTrack]: MediaStreamTrack[] = displayStream.getVideoTracks();
// 画面共有の音声はマイクの音声を利用したいので、userMediaStreamからaudioTrackを取り出しておく
const [userAudioTrack]: MediaStreamTrack[] = userMediaStream.getAudioTracks();

// 画面共有するためのMediaStreamを作成する(画面のvideoTrack、マイクのaudioTrackを持つMediaStreamを作る)
const sharingMediaStream: MediaStream = new MediaStream([displayVideoTrack, userAudioTrack]);

MediaStream の入れ替え

最後に画面共有状態への切り替えです。マイク・カメラが共有されている状態からの切り替えにはいくつかの方法が考えられます。

例えば、多重化であれば MediaConnection( Skyway の SDK の単位で、「接続先 Peer へのメディアチャネル接続」を管理する)の多重化、MediaStream の多重化、MediaStreamTrack の多重化がそれぞれ考えられます。これらの方法はマイク・カメラの切り替え時のチラつき抑制など実装上の選択肢が増えるメリットがある一方で、通信量が多くなってしまう点がデメリットと言えます。

今回は多重化をせずに既存の MediaStream を切り替える実装を紹介します。この方法のメリットは、多重化に比べると通信量が少なく、またすでに MediaStream が一つである前提で作られている場合は、画面共有を受ける側の実装の変更が不要という点です。

この方法は、 SkyWay の SDK であれば MediaConnection の replaceStream というメソッドに対して新しい MediaStream を渡すことで実現ができます。

// 画面共有用のMediaStreamを渡すことで、画面共有を開始する
// MediaConnection は先程 `peer.call` した際の返り値として取れているため、それを利用する
mediaConnection.replaceStream(sharingMediaStream);

実装前に懸念していたマイク・カメラの切り替え時のチラつきなども気になるほどはなく、実用に足るような品質を保つことができることを確認しています。

実装の全体概要

以上の流れを実装すると、次のようなコードになります。

import Peer, { MediaConnection } from "skyway-js";

/** 医師側のマイク・カメラを共有してオンライン診察開始するところまで **/
// getUserMedia()でカメラ・マイクのストリームを取得
const userMediaStream: MediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });

// Skyway sdkの初期化処理
const peer = new Peer({ key: "your-api-key" });

// オンライン診察の開始
const mediaConnection: MediaConnection = peer.call("peerId", userMediaStream);

/** 画面共有を開始する処理 **/
// 画面共有する画面のstreamを取る
const displayStream: MediaStream = await navigator.mediaDevices.getDisplayMedia({ video: true });
const [displayVideoTrack]: MediaStreamTrack[] = displayStream.getVideoTracks();

// 画面共有の音声はマイクの音声を利用したいので、userMediaStreamからaudioTrackを取り出しておく
const [userAudioTrack]: MediaStreamTrack[] = userMediaStream.getAudioTracks();

// 画面共有するためのMediaStreamを作成する(画面のvideoTrack、マイクのaudioTrackを持つMediaStreamを作る)
const sharingStream: MediaStream = new MediaStream([displayVideoTrack, userAudioTrack]);

// 画面共有用のMediaStreamを渡すことで、画面共有を開始する
mediaConnection.replaceStream(sharingStream);

開発中に遭遇した問題への対応

スリープモード・共有を停止ボタンを押したときの対応

Google Chrome で画面共有の際に表示される「共有を停止」ボタンを押下したり、PC をスリープモードにすると、画面の MediaStreamTrack が途切れてしまいます。

これは該当の MediaStreamTrack に "ended" のイベントリスナを登録しておくことでハンドリングできます。

displayVideoTrack.addEventListener("ended", handleEndedEvent, { once: true });

TypeScript の型の対応

現状 TypeScript の型が getDisplayMedia() に対応していなかったため、今回は実装の参考にしている skyway-conf で利用されている型を流用する形で対応をしました。

declare global {
    interface MediaDevices {
        getDisplayMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;
    }
}

これは根本的には TypeScript の dom.d.ts に型定義が入っていないことが起因していますが、TypeScript4.4 で対応がされるようです

まとめ

昨今の状況により、オンライン診察のニーズが高まり、画面共有機能の重要性が高まりました。 診察中の画面共有機能は以下の api を組み合わせることで実現することができます。

  • PC 画面の MediaStream は getDisplayMedia() を使うことで取得
  • MediaStream に含める音声・画像ストリームを変更したい場合は MediaStreamTrack の組み合わせを変えることで作成
  • 接続中の MediaStream の変更は SkyWay の SDKMediaConnection.replaceStream() を使う

最後に

CLINICS では本稿で紹介した画面共有などの新規機能の導入や日々の改善を通じて、医療機関・患者双方に支持されるプロダクトを目指し開発を行っています。興味を持たれたエンジニアの方がいらっしゃいましたらぜひこちらにご連絡いただければと思います。

www.medley.jp

「ChatOps稟議」×「電子契約締結のAPI連携」でワークフローの生産性を追求した話

はじめに

はじめまして、コーポレートエンジニアの山下です。

2020年にSlackを活用したChatOps稟議ワークフローを内製で開発したのですが、さらに、2021年4月にこのSlack稟議と電子契約システムであるクラウドサインを連携させて、電子契約をもっと便利に使い、生産性の向上を実現しましたのでお話しいたします。

まず、当社の稟議システムは2020年12月の当社の記事のおさらいになりますが、稟議の作業がSlack上で完結する、ChatOpsによる稟議ワークフローとなっております。本稿については2021年7月に執筆しておりますので丁度導入から1年程経過し、その間大きなトラブルも無く、今も当社の極めて迅速な意思決定の一助になっています。ChatOpsによる稟議ワークフローについては、直近、2021年6月にLayerX社がLayerXワークフローの新機能として発表し、サービスとしても提供され、日経新聞でも取り上げられていることから、今現在のパラダイムとして、先進的で有効な一手法であったと再認識しております。

今回、新型コロナウイルス感染拡大防止に伴うリモートワークの加速という状況もあり、当社で2021年4月に電子契約システムとしてクラウドサインを導入しました。電子契約に限らず、契約押印作業は稟議の後続作業に当たるため、ただ導入して使用するのみならず、クラウドサインのAPIを利用して稟議上にあるデータを電子契約に送信させることでシームレスな連携を実現しています。本稿では当社が行ったシームレスな連携手法について詳細をご説明いたします。

TeamSpiritとクラウドサインのAPI連携について

実装概要

弊社の稟議システムであるTeamSpiritクラウドサインとの連携についてお話しします。まず、本稿の開発部分とシステム構成は下記になっております。

f:id:medley_inc:20210715210552p:plain

処理内容の詳細は後ほど述べますが、概要としてはTeamSprit(Apex)からクラウドサインのAPIをコールし、クラウドサイン上で作成した契約文書へ稟議に記載されている契約書ファイルや先方担当者等の情報を連携する仕組みとなっております。これにより契約担当者はクラウドサインにログイン後、下記の3ステップで先方に送信できるようになっています。

  1. 記載内容の確認
  2. 押印・署名箇所の設定
  3. 先方への送信

クラウドサインを使用して契約文書を一から作成する場合のユーザ作業と、当社で採用したAPI連携行った場合のユーザ作業を比較したものが下記の表です。作業が半分程度削減されたことが分かります。

作業項番 一から作成する場合 API連携を利用した当社の場合
1 ログイン ログイン
2 契約文書の作成(件名、契約文書としての宛名設定等) なし
3 契約書ファイルのアップロード なし
4 先方の送信先設定 なし
5 押印欄の設定 押印欄の設定
6 先方への送信 先方への送信

実装

今回の開発で使用したクラウドサインAPIは下記の5つのAPIを使用しました (※以降、クラウドサインAPIに倣い、変数を表現する場合は{}で括ります)。

API種類 使用用途
post /token アクセストークンの取得
post /document 契約文書の作成
put /documents/{documentID}/attribute 契約文書の作成で設定できない、細かい項目の設定
post /documents/{documentID}/files ファイルのアップロード
post /documents/{documentID}/participants 先方の送信先設定

全体像で記載したクラウドサインの連携部について、上記のAPIを織り交ぜて詳細化すると下図のようになります。

f:id:medley_inc:20210715210621p:plain

実装方法としてはクラウドサインAPIのリファレンスを参照し、テスト実行時に出力されるcurlコマンドを参考に同様のレスポンスを得るようにApexでHTTPリクエストを実装しました。アクセストークンの取得を例にとると下記のようになります。

APIリファレンスでのcurlコマンド例

curl -X 'POST' \
'https://api.cloudsign.jp/token' \
-H 'accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'client_id=xxxxxxyyyyyyzzzzzz'

Apexでのリクエスト実装例

HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint('https://api.cloudsign.jp/token');
req.setHeader('accept', 'application/json');
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
req.setBody('client_id=' + 'xxxxxxyyyyyyzzzzzz');

私自身、ApexもクラウドサインAPIもこの案件を担当するまで触ったことがありませんでしたが、リクエストの試行から実装まで2週間かからない程度で実装することができました。

ただし、実装や運用にあたっては下記2点について注意が必要になります。

  1. Apexからクラウドサインへのファイルのアップロードは単純ではない
  2. アクセストークンの有効期限はクラウドサインでコントロールされる

1. Apexからクラウドサインへのファイルのアップロードは単純ではない

ファイルのアップロードについては今回使用したAPIの中で、唯一、テスト実行のcurlとApexのリクエスト実装で差分が生まれます。まず、その差分を確認するためにcurlコマンド例とApexのリクエスト実装例でheader、bodyにセットしている値を比較してみます。

APIリファレンスでのcurlコマンド例

curl -X 'POST' \
'https://api.cloudsign.jp/documents/{document_id}/files' \
-H 'accept: application/json' \
-H 'Authorization: AAAAAABBBBBBCCCCCC' \
-H 'Content-Type: multipart/form-data' \
-F 'name=テスト' \
-F 'uploadfile=@テスト.pdf;type=application/pdf'

Apexでのリクエスト実装例

HttpRequest req = new HttpRequest();
req.setMethod('POST');
     req.setEndpoint('https://api.cloudsign.jp/documents/{document_id}/files');
req.setHeader('accept', 'application/json');
req.setHeader('Authorization', ‘AAAAAABBBBBBCCCCCC’);
req.setHeader('Content-Type', 'multipart/form-data; boundary={boundary}');  // ※1
req.setBodyAsBlob({multipartBody});  // ※2

主な違いは ※1, ※2 とコメントした部分になります。

ApexではHTTPリクエストの値を手で書いていくことになるので、テスト実行例のようにcurlがよしなに処理している部分(-Fオプションの部分やApexで記載しているboundary)も実装しなければなりません。これが単純に実装できない理由になります。

boundaryについてはmultipart/form-dataを送信する際に必要な境界でヘッダーでどの文字列が境界であるかを設定します。curlの-Fオプションで定義していた文字列とファイル指定部分は、Apexでファイル(バイナリ)を扱うため、そのbodyに含まれる文字列も含めてBlob型で扱う必要があります(Content-Transfer-Encoding: base64API提供側が対応している場合は例外になります)。そのため、文字列とバイナリデータを結合し一つのBlobにする方法は下記になります。

  1. 「バイナリデータ」、「bodyの開始からバイナリデータまでの文字列」、「バイナリデータ以降から終端までの文字列」の3グループに分ける。
  2. 3グループをそれぞれBase64で符号化する。
  3. 符号化した「バイナリデータ」と「bodyの開始からバイナリデータまでの文字列」について、Base64のデータパディングを示す”=”が含まれないように改行コードで調整する。
  4. 「bodyの開始からバイナリデータまでの文字列」、「バイナリデータ」、「バイナリデータ以降から終端までの文字列」の順で結合する。
  5. 結合したBase64のデータを復号して、一つのBlobとする。

2. アクセストークンの有効期限はクラウドサインでコントロールされる

アクセストークンやその有効期限はtoken APIを発行した際のレスポンスとしてクラウドサインから発行されます。

発行されたレスポンス例

{
     "access_token": "AAAAAABBBBBBCCCCCC",
     "token_type": “xxxx”,
     "expires_in": 3600
}

このレスポンスの内、expires_inの値がトークンの有効期限になります。掲題の通り、有効期限の管理はクラウドサイン側で行われ、有効期限内に再度トークンのリクエストを行った場合、経過した時間だけexpires_inの値が小さくなった結果が返ってきて、access_tokenなどは同じ値が取得されます。有効期限内にtoken APIを再度実行した結果が下記になります。

有効期限切れ前にtoken APIを発行した際のレスポンス例

{
     "access_token": "AAAAAABBBBBBCCCCCC",
     "token_type": “xxxx”,
     "expires_in": 762
}

一方、有効期限後にトークンのリクエストを実行すると、それまでと異なるアクセストークンを取得し、新しい有効期限が設定されます。

有効期限切れ後にtoken APIを発行した際のレスポンス例

{
     "access_token": "XXXXXXYYYYYYZZZZZZ",
     "token_type": "xxxx",
     "expires_in": 3600
}

そのため、API連携が一度動いた後、有効期限ぎりぎりでもう一度API連携が動いてしまった場合、タイミングが悪いと契約文書の作成から最終処理である先方の送信先設定までのプロセス内のどこかから、トークンの有効期限切れが発生する可能性が想定されます。実際に期限切れが発生した場合、発生時以降に発行したその回のAPI連携処理が失敗します。

トークンの有効期限切れが発生した際、APIリファレンスよりHTTPステータスコードが401かつエラー内容が”unauthorized”で応答されることから、当社ではこのエラーを受けた場合にトークンを再取得して処理をリトライするように実装しました。

押印文書作成を例にとると下記のような実装イメージになります。

//クラウドサイン上に押印文書を作成し、作成した文書IDを取得する
public String getDocumentId(String authToken, String title, String message){

    ・・・中略・・・

    HTTPResponse res = http.send(req);

    if (res.getStatusCode() == 200){
        ・・・正常に終了した際の処理・・・
    }
  
    //タイミングが悪くtokenがタイムアウトした場合、トークンを取得し直して、リトライする
    else if (res.getStatusCode() == 401){
        //レスポンスの内容を確認するため、エラーレスポンスの中身を取得する
        Map<String, Object> responseBody = new Map<String, Object>();
        responseBody = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
        String errorVal = (String)responseBody.get('error');

        //リファレンス上、アクセストークンが無効(有効期限切れ)の場合、'unauthorized’となる
        if (errorVal.equals('unauthorized')){
            //クラウドサインのアクセストークンの再取得
            authToken = getAuthToken();
            //単純再帰で再実行する。
            documentId = getDocumentId(authToken, title, message);
        }
        ・・・中略・・・
    }
    ・・・以下省略・・・
}

実装を終えて

上記を実装した結果、稟議と入力内容が同じ、または、稟議から生成できる内容は全てシステム連携で自動生成するため、押印担当は稟議とクラウドサインの画面を並べて転記するような煩雑な作業を必要としない環境になりました。また、契約書の製本、郵送等の紙媒体であるが故の事務の削減ができるようになる等の、電子契約を導入することのそもそものメリットも併せて享受しています。

当社では2021年4月後半からクラウドサインを導入しましたが、2021年6月時点ではすでに月間で締結した契約書の「3割以上」が電子契約を活用しており、押印担当の展望として今後も利用を拡大していく予定です。

コーポレートエンジニア募集中

メドレーのコーポレート部門では、本稿のように、SaaSの導入ひとつとっても検討を尽くし、既存のシステムと有機的に結合させることで「徹底的に合理性を追求した組織基盤や、仕掛けづくり」を行っています。

面白そう!興味がある!と感じた方は、ぜひ当社採用ページからご応募お願いします!

最後までお読みいただきありがとうございました。

www.medley.jp

Pharmsのブランドルーツを辿る

「2020年9月に調剤薬局向けのプロダクトをリリースする」

このプレスリリースが発表されたのは、COVID-19の感染拡大に端を発する緊急事態宣言が発令されていた2020年4月半ば。その1ヶ月後、私はリモートワーク下でのオンラインMTGになじめない状態のまま、調剤薬局向けプロダクトのブランディングについて役員陣や主要プロジェクトメンバーにプレゼンを行っていた。

今回は当時のプレゼン資料をたどりながらPharmsのブランド設計について説明していこうと思う。

医薬分業のルーツとは

デザイナーとして前田がメドレーに入社してから、オンライン診療や電子カルテなど、主に医療機関向けのプロダクトデザインを担当していたものの、調剤薬局のプロダクトデザインは未知の領域。ブランディングを検討する上で、薬の処方を行う医師と調剤を実施する薬剤師が分担して行う医薬分業のルーツついて調べることからはじめた。

医薬分業は、毒殺を恐れたフリードリヒ2世が主治医の処方した薬を、毒が盛られてないか他者にチェックさせたのが始まりとされている。

(参考:公益社団法人 日本薬剤師会HP|医薬分業とは

f:id:medley_inc:20210625142428p:plain

医療プラットフォームの未来を見据えたブランド定義

次に、調剤に関する法制度や競合などの外部要因、メドレーとしてのブランド力や開発力などの内部要因について簡易なSWOT分析を行い、調剤薬局のプロジェクトの妥当性を検証。メドレーが取り組む医療プラットフォーム事業(※)に、あらたに調剤薬局プロジェクトが加わることによる他のプロダクトとのバランスも考慮しながらブランドネーミング検討を行っていった。

f:id:medley_inc:20210625142452p:plain

※) 医療プラットフォーム事業では、患者と医療領域の業務システムをSaaSプロダクトでつなぎ、患者と医療機関双方にとって、テクノロジーの恩恵を受けることのできるプラットフォームづくりを行っている。主要サービスはクラウド診療支援システム「CLINICS」やオンライン診療・服薬指導アプリ「CLINICS」。

メドレーのこれまでの歴史を振り返ると、プロダクト内容を明確かつ端的に表したネーミングが多く、メドレーらしさ = 「中央突破なネーミング」ということを定義し、ネーミングを検討していった。

f:id:medley_inc:20210625142510p:plain

最終的に調剤薬局を表す「Pharmacies(ファーマシーズ)」と「Pharms(ファームス)」の2案に絞込み、それぞれのメリット・デメリットを整理していった。

f:id:medley_inc:20210625142528p:plain

当時、社内では調剤薬局システム = Pharmaciesと呼ばれており、その中央突破なネーミングが最有力候補であった。一方で、ブランドで体現すべきアイデンティティの欠如や、呼びづらさなどが課題として散見された。さらには医療プラットフォーム全体を見据えたブランド構築という観点から考慮すると、バランス面での課題が浮き彫りになり、それら課題をクリアにして誕生したのがPharms(ファームス)である。

ヴィジュアル・アイデンティティの設計

ブランド名が固まれば、あとはヴィジュアル・アイデンティティを突き詰めていくのみ。視認性や可読性を考慮したフォントフェイスの検証や調剤薬局と想起させるブランドカラーの選定、またシンボルの設計などに取り掛かっていく。

ブランドカラーの選定においては、なんとなく「緑」というイメージがチーム内でもあったが、より精緻化するため、薬の起源や調剤薬局本来の役割を踏まえ詳細に落とし込んでいった。

f:id:medley_inc:20210625142546p:plain

ロゴにシンボルを含めるか、含めないかも検討のひとつであったが、医療プラットフォーム事業にあるCLINICSのロゴがシンボルマーク付きであるため、医療プラットフォームに関連するプロダクト = シンボルを定義するというルールを策定しシンボルも設計。シンボルは薬の構造式に利用される「ハニカム構造」をモチーフとし、ブランドカラーと合わせて詳細に作り込んでいった。

f:id:medley_inc:20210625142603p:plain

また、Pharmsの製品紹介用ランディングページやプロダクトデザインのモックアップを作成し、ロゴとのバランスなども考慮しながら調整を行っていった。

f:id:medley_inc:20210625142619p:plain

最終的に、患者・調剤薬局医療機関の3者のつながりを三角形で表現しつつ、中心を先述した「ハニカム構造」をモチーフとした形状と、Pharmsの頭文字「P」をカプセルと錠剤で表現して、調剤薬局システムとしてシンボルマークに命を吹き込んだ。

f:id:medley_inc:20210625142638p:plain

まとめ

このような過程を経て、Pharmsのブランドが完成したのだが、これらは調剤薬局システムの開発としては氷山の一角でしかない。本丸はプロダクトデザイン。一般的にはロゴとプロダクトデザインは別プロジェクトで進行したり、担当するデザイナーが別だったりすることも多いのではないだろうか。

Pharmsはブランド設計、プロダクトデザイン、マーケティング資材といったデザイン領域をすべて私が担当していくことになるのだが、それ故に事業全体を俯瞰し理解しながらデザインやUIデザインに魂を込めて携わることができた。デザイナーキャリアとしてもここまで幅広く携われたことは非常に貴重な経験を得ることができたと自負している。

続いてプロダクトデザイン開発の秘話について語りたいところだが、現在Pharms以外の医療プラットフォーム事業に関連する新たなプロダクト開発に注力しているため、その話はまたの機会に。


医療プラットフォーム事業に関連するプロダクトをこれからも創出し成長させていく面白い時期にあり、現在デザイナーを積極採用中です。カジュアルに話を聞きたい、医療領域のデザインに興味があるといったデザイナーの方は、ぜひこちらまでご連絡いただけると幸いです。

www.medley.jp

メドレーでセキュリティエンジニアとして働くということ

はじめまして。メドレーでセキュリティエンジニアをしている三浦です。

私はメドレーには今年(2021年)の2月に入社し、このブログを執筆している時点で入社4ヶ月目となります。現在、全社的なセキュリティを担当しています。

今回のブログは以下のような構成でお届けします。

目次

  1. 自己紹介と、本ブログのテーマについて
  2. 前職でのセキュリティエンジニアとしての仕事
  3. メドレーでのセキュリティエンジニアの仕事
  4. セキュリティエンジニアとしての活動内容や役割の違いと気づき、課題
  5. セキュリティエンジニア募集中!

自己紹介と、本ブログのテーマについて

私は前職でセキュリティ専業会社のセキュリティエンジニアとして脆弱性診断やペネトレーションテストのほか、セキュリティ研修の講師、ファイアウォールやWebアプリケーションファイアウォール(WAF)と呼ばれる機器の導入支援などに携わっていました。

このなかでも脆弱性診断の案件に多く関わっていたこともあり、最後には脆弱性診断のサービスオーナーとしてサービスに関わるすべてを取りまとめる立場でした。

今では事業会社のセキュリティエンジニアとして活動しているわけですが、このブログではセキュリティエンジニアとしての活動内容や役割にどのような変化があり、その変化により直面している自分自身の課題や苦労について書いていきます。

前職でのセキュリティエンジニアとしての仕事

先述のとおり前職では脆弱性診断に関わることが多かったため、ここでは脆弱性診断について取り上げます。

脆弱性診断はスポット案件として実施することがほとんどでしたので、案件の流れという観点で仕事内容を整理すると以下のようになります。

  1. 営業フォロー(同行やQ&Aなど)
  2. スケジュールや診断対象などについてお客様にヒアリング
    1. ここで診断用環境の準備をお願いすることが多い
  3. 診断対象の調査、クロール作業
  4. スケジュール感や制限事項についてお客様とすり合わせ
  5. 計画書を作成
  6. 社内で計画書レビュー、お客様へ送付
  7. 診断作業
    1. 自動診断ツールの調整
    2. 手動診断の実施
    3. 出力結果の精査、再現性の確認
    4. 速報があれば当日中に整理して送付
  8. 診断結果のエビデンス整理
  9. 報告書の下書き、リスク度合いの検討
  10. 社内で報告書レビュー
  11. お客様へ報告書を納品
  12. 報告会の実施

このなかで、特に診断担当者の技術的スキルが問われたのが「手動診断の実施」と「出力結果の精査、再現性の確認」で、全体のうち約4割ほど。残りはドキュメント作成、レビュー、ミーティング、業務改善といった定型業務が占めていました。

私は「この4割の部分に対して付加価値を提供したい」というエンジニアとしての気負いと、個人的な関心という2つの理由から、寝る時間を削っては脆弱性の悪用(Exploit)手法の習得と、知識的な補強としての資格取得に明け暮れる時期がありました。

結局、寝不足が続いたことが原因で肺炎を発症し、入院一歩前まで炎症マーカーが悪化するという自分自身の脆弱性が露呈することになったのですが。ちゃんと夜は寝ましょう。

話がすこし脱線しましたが、脆弱性診断やSI案件などは年度末にピークを迎えるものの年間を通じて五月雨で受注することも多く、一定の品質を維持しながらも納期を守るために目の前の案件で必死だったというのが今までの仕事のスタイルでした。

目の前の案件をひたすらこなし、組織に対して「報告書を提出して終わり」の関わり方に対して『これで社会の役に立っているのだろうか』という疑問が生まれたことが、メドレーに入社する転機になっています。

メドレーでのセキュリティエンジニアの仕事

さて、セキュリティサービスを提供する側で案件に追われていた私がメドレーでセキュリティエンジニアとして活動することになっているわけですが、具体的に今なにをしているのか?というと、大きくは以下の6つが挙げられます。

  • 自社サービスに対する脆弱性診断
  • 脅威情報や脆弱性情報の収集、周知
  • 全社的な業務プロセス上のリスク調査
  • 全社システムのBCP整備、保守
  • ISMS運用
  • セキュリティ相談

自社サービスに対する脆弱性診断というのは「脆弱性診断の内製化」で、脆弱性診断を外部の業者にお願いするのではなく自社内で実施して開発にフィードバックする形です。

内製による診断であっても、基本的な流れはすでにご紹介した流れで進めていますが、対象サービスをクロールしてから診断対象を確定させるまでの主要なポイントでは、操作手順に漏れがないかなどの観点で開発からのレビューを挟むようにしています。これは内製であるからこそ実現できているアプローチだと思います。

f:id:medley_inc:20210527151142p:plain
内製で実施している診断対象一覧の例

なお、ここまで脆弱性診断について書いてきましたが、これは現在の業務のほんの一部で、このほかにはISMSの運用(事務局)としての活動のほか、コーポレートITメンバーと共に事業継続計画(BCP)整備なども並行して進めなければなりません。とにかく関わる範囲が広く、そして、とても地道な活動です。

ですが、会社全体を俯瞰してセキュリティのことを意識して物事を考え続けられる立場というのはセキュリティ会社では経験できないことで、自社にとっての最適解は何か?を探求し続けることの新たな面白さを見いだすことができています。

セキュリティエンジニアとしての活動内容や役割の違いと気づき、課題

ここまでの内容でお気づきの方もいるかと思いますが、現在の業務はISMS運用を初めとしてリスクマネジメントの分野も多く、実務的なバックグラウンドのない業務も出てきています。

システム的なセキュリティに関しても「どうやって悪用できるか...好物のBOF*は無いのか..BOFはどこだ...」という攻撃観点の思考回路のみで判断するのではなく、「どのようなソリューションや仕組み、またはルールでリスク低減できるのか、そして、それをなるべく自動で運用できるようにはどうするか」という守る側にとっての実務的な課題を考えなければなりません。

* バッファオーバーフローのこと

このほかに、私が実際に感じているセキュリティエンジニアとしての気づきや考え方の変化を挙げていくと、以下のようなものがあります。

  • 攻撃手法の理解を踏まえ、(社内リソースを鑑みた)現実的に運用しうる対策の仕組みを提案できなければならないことを痛感した
  • 仕組み化やルール化するにも、エンジニアではない従業員の存在を考慮するようになった
  • 脆弱性単体の影響範囲や度合いではなく、システムの利用方法や情報の種類など、社内だからこそ持てる視点を持って評価するようになった
  • 「アップデートしたくてもできない」問題が生じないシステム設計が肝要であることを改めて認識した

これらの変化への対応については、すべてソリューションや自動化に対して私の知見がまだまだ不足しているため、これからは「攻撃者目線」の考え方に加えて「ソリューションと自動化」の知見を補完しながら、メドレーのセキュリティ向上に貢献し続けていきたいと考えています。

セキュリティエンジニア募集中!

最後となりますが、セキュリティエンジニアは関わる業務の幅広さに加え、絶対的な正解が存在しない問題にソリューションを提供することも多い仕事です。

メドレーでの内製による脆弱性診断や全社セキュリティに興味がある方はぜひジョインしてください。いつでもお待ちしています!

www.medley.jp

介護のほんねリニューアルの話

はじめまして。メドレーでデザイナーをしているおおのです。わたしはメドレーには昨年(2020年)の6月に入社し、現在老人ホーム・介護施設の検索サイト「介護のほんね」を担当しています。

介護のほんねは昨年リニューアルを行いました。今回は、そのリニューアルプロジェクトの中で自分が取り組んだこと(主にサイトトップのリニューアルについて)についてお話しようと思います。

目次

  1. 介護のほんねとは
  2. リニューアルの背景
  3. プロジェクトについて
  4. プロジェクトとの関わりについて
  5. サイトトップの制作
  6. プロジェクトを終えて

介護のほんねとは

介護のほんねは、納得できる老人ホーム・介護施設探しができる検索サイトです。介護のほんねには、全国にある多くの施設が掲載されています。予算やエリアなどお好みの条件で施設を検索したり、気になった施設へ見学予約や資料請求などお問い合わせができます。また社内の入居相談員による施設に関する資料送付や条件にあった施設紹介、施設見学の日程調整などのサポートにも対応しています。

リニューアルの背景

介護のほんねは2014年にローンチされました。しかし、長い間の運用の中で古いデザインと新しいデザインが入り混じっている部分があったり、SEOの観点での強化が必要だったり、今後の成長に向けて手直しする部分が積もり始めていました。また、2019年に「医療につよい老人ホーム検索サイト」にコンセプトを変更しましたが、より多くの方にご利用いただくためにも、医療につよいというコンセプトからさらに一歩進み、様々な状況のお客様に向き合い、お客様が介護に対して前向きに、そして後悔のない選択ができるよう寄り添うことのできるサービスにしていきたいという思いから今回のリニューアルが始まりました。

プロジェクトについて

リニューアルプロジェクトは昨年5月頃から始まり、外部のデザイン制作会社と連携して進められました。制作会社の方には、デザイン業務の支援をお願いしつつ、週1〜2回の定例で進捗報告や業務内容の確認を行っていました。

プロジェクトとの関わりについて

自分が入社したのが昨年6月後半だったので、デザインや開発も部分的に進んでいる状況でした。介護領域の勉強や、担当サービス、競合調査、リニューアルプロジェクトや介護のほんねのこれまでの歩みについてなどのキャッチアップと並行してリニューアルのデザインのことも考えていました。

そこで次のようなことを意識して動きました。

プロジェクトに対して

  • 社内のメンバーといつでもコミュニケーションがとれることを活かし、外注先とも相談して自分自身も手を動かしながらデザインをブラッシュアップすること

社内に対して

  • サービスに対するメンバーの思いを確認しつつ、これまでのサービスの歩みを尊重して動くこと
  • 社内のデザイナーの先輩など頼れる人には頼ること

サイトトップの制作

プロジェクトにジョイン後、主にサービスの顔であるサイトトップについて、アイデア出しやデザインをしました。

サイトトップにどのようなコンテンツを掲載するのか、また、お客様が介護に対して前向きに、そして後悔のない選択ができるよう寄り添いたいというサービスの思いをどのように表現すればよいか考えていきました。

掲載するコンテンツに関しては、サイトトップを誰に向けて作るのかという部分を介護施設探しが初めての人に設定し、このサイトでは施設が探せることを伝えてサービスのコア機能を全面に出しつつ、介護のほんねでの施設探しの魅力ポイントや、介護や施設探しに関するコラムやQ&Aなどお役立ち情報も掲載するようにしました。

▼ リニューアル前のサイトトップ

f:id:medley_inc:20210401103421p:plain

また、当時のサイトトップは上に貼ったキャプチャの通りで、落ち着いた青を基調としたクリーンで誠実そうな印象がありました。これまで築き上げてきたプロダクトのイメージや印象は、リニューアル後も受け継いで残していきたいなと思いました。

それをふまえた上で、サイトトップの新しいキャッチコピーやキービジュアルをどういうものにするのかプロジェクトのメンバーとアイデアを出しながら考えました。しかし、「どのアイデアも間違ってないけどもっといいのがありそうだな」という気持ちが拭えず、なかなか決まりませんでした。

そこで、改めて原点に帰って情報を整理するために次のことに取り組みました。

  • ユーザーを知る
  • 介護のほんねが提供する価値を整理する
  • 信頼できる情報から納得できる介護サービスと出会えることをキャッチコピーに落とす
  • 介護のほんねの世界観を視覚的に伝えられるようなメインビジュアルの選定

ユーザーを知る

まずはじめに介護のほんねのユーザーデータを1件1件見ていきました。そこにはお客様の情報や施設を探している理由など様々な情報がまとまっています。それらのデータを見ていくと、おおよそ4つのパターンにわけられることがわかりました。

① 退院後の施設を探したい
転倒など何かしらの理由で入院している家族の退院期限が迫っており、退院後に在宅での介護ではなく施設にいれる必要があるケース

② 施設を移動しないといけなくなった
介護度があがったことで施設の受け入れ可能範囲から外れた場合や、施設の中でトラブルがあるなどの事情により施設を移る必要があるケース

③ 今後に備えて早めに動きたい
今すぐ介護施設に入れる必要があるわけではないものの、親が高齢でひとり暮らしをしていて不安なためまだ自分で動けるうちに施設にいれておきたいケース

④ 在宅介護では限界がきてしまった
自分自身も高齢になってきたため、仕事や家事に加えて介護の両立が難しくなってきた方が施設を探しているケース

このようなお客様のデータを見ていると、事情が事情だけになるべく急いで施設を探しているものの、離れても家族が幸せに暮らせるように慎重に施設を探したい、という思いが伝わってきました。

▼ ユーザーの大まかなパターン

f:id:medley_inc:20210401115623p:plain

f:id:medley_inc:20210401115632p:plain

f:id:medley_inc:20210401115641p:plain

f:id:medley_inc:20210401115649p:plain

介護のほんねが提供する価値を整理する

次に、ユーザーの方に対して介護のほんねができることはどういうことかを整理しました。

介護のほんねは「老人ホーム・介護施設の検索サイト」ということからもわかるように、施設を探すことができ、プロの入居相談員が施設探しから実際の入居までサポートするサービスです。また介護のほんねとしては、お客様が介護に対して前向きに、そして後悔のない施設探しができるよう寄り添いたいという思いがあります。そこで、介護のほんねの価値を機能的なものと情緒的なものにわけて整理してみました。

機能的価値=すぐに納得できる施設が見つかること
情緒的価値=家族のために、いろんな思いをもって施設探しをしているユーザーに寄り添うこと

ユーザーデータから見えてきた「事情が事情だけになるべく急いで施設を探しているものの離れても幸せに暮らせるように慎重に施設を探したい」、そのようなユーザーに介護のほんねは寄り添って、後悔することなく納得できる施設がすぐに見つかるようにサポートしていくことを伝えたいなと思いました。

納得できる介護サービスと出会えることをキャッチコピーに落とす

ユーザーやサービスの提供価値について整理をしたところで、新しいコンセプトをサイトトップのキャッチコピーにどう落とし込むのかを考えました。

そもそもサイトトップのキャッチコピーですので、前提として「サービス概要、コンセプトが端的に伝わること」は大事にしたいと思いました。サービス概要は、繰り返しになりますが老人ホーム・介護施設の検索サイトです。そして端的にサービス価値を伝えるためにも、先程述べたサービスの機能的価値である「すぐに納得できる施設がみつかること」をキャッチコピーに盛り込もうと考えました。

色々アイデアを出した結果、「老人ホームが見つかる」というサービスのコア機能に加え、介護のほんねならではの「すぐに」見つかるということや、後悔のない納得いく施設選びができるというエッセンスを入れて、最終的に「納得できる老人ホームがすぐ見つかる」というコピーになりました。

介護のほんねの世界観を視覚的に伝えられるようなメインビジュアルの選定

キャッチコピーはサービスの機能やできることをわかりやすく伝えるものにしたため、キービジュアルは先程述べたサービスの情緒的価値のエッセンスをいれたいと思いました。それを踏まえ、いろんな思いを持った相談者の方に寄り添い、ご家族が施設に入居されてから始まる新しい生活を前向きに捉えられるようなビジュアルにしようと思いました。

キービジュアルの選定にあたり、チーム内で意見を集めながら、色々アイデアが出ました。入居後のイメージやサービス概要が伝わりやすい老人ホームの屋内風景の写真、入居後の楽しい生活が期待できそうな施設のスタッフと入居者の笑顔の写真や、サービスの寄り添うスタンスを抽象的に伝える手を握り合うような写真など、たくさんの写真をあてはめて検討を繰り返しました。

▼ イメージ選定

f:id:medley_inc:20210401103430p:plain

  • 車椅子が写りこんでいると、自立度が高い状態で施設を探している方(※介護の必要がない元気な方向けの施設もあり、元気なうちから施設に入られる方もいらっしゃいます)にとって自分が使っていいサービスではないのかとマイナスなイメージにならないか?
  • 施設スタッフと入居者が笑顔で写っている人が写ったモデル風の綺麗な写真だと素材感が出すぎて嘘っぽくならないか?
  • 手を包みこむなどモチーフが抽象的すぎるとかえって何も伝わらないのではないか?

写真を選ぶ中でチーム内でも相談しながら、小さな違和感をひとつずつつぶしていきました。そして、最終的に下のようなキービジュアルになりました。

▼ リニューアル前とリニューアル後

f:id:medley_inc:20210401115327p:plain

f:id:medley_inc:20210401115319p:plain

これからの新しい生活がポジティブなものに捉えられるような、スタッフと笑顔で生活する入居者が写っており、背景に程よく雑多感が残る素材感を抑えた写真を選びました。写真に写っているのは入居者と入居者に寄り添うスタッフですが、介護のほんねも同じように、施設探しをしている方に寄り添う姿勢がこの写真から間接的に伝われば嬉しいなと思っています。

プロジェクトを終えて

プロジェクトは一段落しましたが、スタートラインにたったところなので、まだまだ追加したい機能や磨き込みたい部分も山積みだなと感じています。

今回、自分のデザインに納得感をだすためにサービスや介護の知識、チームのメンバーが考えていることへの理解を深めながら並行してリニューアルのデザインを手掛けたことは、とてもやりがいのあるものでした。

また、リニューアルをきっかけに改めてサービスの価値や目指したい世界を整理できたのはとても良かったです。これからも介護のほんねの目指したい姿を見据えながら、より多くの方につかってもらえるようなサービスにしていきたいと思っています。

www.medley.jp

開発チームと一体となったQA

みなさんこんにちは、メドレーの QAエンジニア かみむら です。 入社して間もなく1年になります。 CLINICS開発チームのQA活動を行っています。

私自身の経歴としては、テスト・品質関連業務に足を突っ込んでから早20年になろうとしています。 2020年はメドレーのQAエンジニアが一気に0名→2名になりました。 先日 Magic Pod導入の記事 を公開した米山とはかつての同僚でもあります。 現在は別々の部署に所属していますが、お互い得意分野を発揮しつつ時折情報交換や相談ごとなどをしているような関係性です。 自分とは違うタイプの同職種がいると、何かと捗ります(その辺りはまた別の機会に…)。

CLINICS開発チームでは、エンジニア・デザイナー・QAエンジニアがワンチームで開発を進めています。 これまで私が経験してきた現場では、QAは開発チームの外側にいる(ステークホルダーとして)ことが多く、新鮮な気持ちでいます。

この記事では私の入社以降取り組んできたQA活動の概要についてお話ししたいと思います。

「CLINICSのQA」とは?

さて、何しろこれまで「QAエンジニア」という職種のひとが存在しなかった開発チームのため、まずは「CLINICSに必要なQAってなんだろう?」というところから考えはじめました。 もちろん、数々のプロダクトを大きな障害なくリリース・運用してきているので、それなりにQA/テストの技術力はあるはずです。

入社前にも、何度も

  • なぜ(他の手段ではなく)QAエンジニアの採用が必要なのか?
  • QAエンジニアにどんな役割を期待しているのか?

といった点を開発チームの上長と話し合いました。

なぜ(他の手段ではなく)QAエンジニアの採用が必要なのか?

私は第三者検証会社に所属していた期間が長いこともあり、品質についての悩みがある開発チームにテスト支援だったりコンサルティング的役割で関わることが多かったので、「てっとり早く他社に相談するのではなく、採用したいのはなぜだろう?」という疑問が単純にありました。

現場の思いとして、以下の点が挙げられていました。

  • プロダクト開発エンジニアがリリース時のリグレッションテスト(シナリオテスト)をメンテ・実施しているが、CLINICS(電子カルテ)の複雑さに追いついていくのが難しくなってきた
  • ここに対して専門性をもって取り組むことで、複雑なドメイン知識を扱うプロダクトを安定して開発リリースできる仕組みを作りたい

QAエンジニアにどんな役割を期待しているのか?

描いている組織体制像としては以下のようなお話でした。

  • QAエンジニアにテストフェーズだけ縦割り的に関わってもらうのではなく、プロダクト開発チームとしてひとつになって、有るべき開発プロセスを一緒につくり上げていきたい
  • 開発エンジニアがテストに関してしっかりと理解をしていくことで、そもそも品質の高いプロダクトをつくることができる、といった世界を目指したい

これら課題に対してチャレンジ的に「やってみたい」と強く思ったのと、私はこれまでにいろいろな現場の開発体制の中でテストエンジニア/QAエンジニアとして活動してきていましたが、「プロダクト開発チームとしてひとつになって」というところがすごく「それ良いな!」と思ったのを覚えています。 専門職に任せるのではなく、「一緒に理想の世界をつくりあげたい」という気持ちがとても見える良い組織だと思いました。

「QAエンジニア」「テストエンジニア」「SET/SWET」

ここで少し職種名に関する補足説明をしますと、「QAエンジニア」という呼称は比較的新しい概念なんじゃないかと思います。

一般的には「テストエンジニア」と言い、文字通り「テスト業務に特化したエンジニア」を指していました。その後『テストから見えてくる グーグルのソフトウェア開発 』(2013年日本語版発行)から「SET/SWET(Software Engineer in Test)」が日本でも認知され、国内の導入事例が出てきたことで一気に広まった印象です。

私の解釈では、「QAエンジニア」と呼称する場合、「テストエンジニア」や「SET/SWET」の素養も含みつつテスト以外にも「品質向上のための活動全般を積極的に担う役割」という意味合いが濃くなるんじゃないかと捉えています。

CLINICSのありたい「QA」の姿

上長と話し合った結果、以下のような活動をメインに据えていきましょうということになりました。

  1. (現状行っている)テストの改善
  2. プロセス改善
  3. 知識の底上げ

それぞれのトピックについて、現在CLINICSのQA活動としてどのように取り組んでいるかを1つずつ詳しく説明していきます。

「テストの改善」

現状CLINICSの開発サイクルは週1回のリリースとしています。 毎回リリース用にコードフリーズした環境に対してリグレッションテストを開発チーム全員で手作業(マニュアルテスト)により行っています。 日々の機能追加や改修の際に手をいれてはいますが、リグレッションテストのシナリオもツギハギ感がみえるようになってきました。 そして増えてきたシナリオによってどこがどう品質担保されているのか見通しが悪くなっている点が大きな悩みでした。

そこでまず、「現状のシナリオテストを分析し、全体的に再設計する」という計画をたて、現在は開発チームの中でもカルテに造詣の深い一部メンバーで定期的にMTG(レビュー会)を行いながらテスト設計の方針を組み立てています。 設計図ではマインドマップツールやマトリクスを作成して方向性や粒度をすり合わせしています。

私自身も、今までの業務でこれだけじっくり丁寧にテスト設計をしてきたことがないため、厳しくもたいへんやりがいのあるタスクとなっています。

「プロセス改善」

こちらはテストそのものではなく、開発チームのルーチンワークや体制に関わる改善です。

種まき的にスモールチームで新しいふりかえり手法を試してみたり、開発定例会で共有している障害情報とテスト実施中に見つかったバグの情報を一元化して残す仕組みを導入したりなど行いました。 特に「ふりかえり」については常に改善を意識できるプロセスで、上手なふりかえりをすればするほど開発品質が向上すると考えられているため、勉強会の後にフィードバックコメントをもらう仕組みをつくったりなどちょっとした隙間にも「ふりかえり」を小さく回せるように腐心しています。

それとまだ着手できていませんが、記録した障害・バグ情報も近いうちに分析・分類していって今後の開発に役立てたいと考えています。 バグ分析は時間がかかるのでなかなかサクッとはいきませんが、長期的視点では有用な財産になります。

また「開発プロセス」「業務フロー」自体の現状の悩みごとを現場の声として私が直接探るためと、開発チーム内で「共通の目標」を認識するためのブレストをリード陣と行いました。 進め方は「SaPID 」という改善手法を参考にしています。

SaPIDとは、”Systems analysis/Systems approach based Process Improvement methoD”の略語で、当事者自らが(最終的には仲間と共に)解決すべき問題点を特定し、現実的に解決、改善、そして革新を実現しながら段階的・継続的に自律運営へのゴールを目指す手法です。

誰かにやらせる、やらされるのではなく、当事者自らの意思、チーム・組織の意思で自律的に運営を進めることを志向するのが特徴です。

f:id:medley_inc:20210305203657p:plain

コロナ禍の中、日によってリモートで参加のメンバーがいたりなどふせんをつかったワークにも工夫が必要でしたが、最終的には「共通の目標」として

  • 自分と身の周りに役に立つ状況をつくる
  • 世間に認知されるプロダクトをつくる

というような定義をつくることができました。

「知識の底上げ」

CLINICSはこれまで中途採用メンバーが多かったため、OJT中心で体系的な教育はまだまだ整備をしている段階です。 新卒入社も増えてきている昨今ではメンバー全体で知識レベルが合わないことによる弊害が出てきており、目線を合わせていくことが喫緊の課題でした。

普段の業務の中で断片的な情報を得ることはできてもなかなか体系的な知識を効率的に身につけることは難しいので(専門書は分厚くてハードルが高い)、上長からのたっての願いでもあり、QAに従事している者にとっては割と初歩的なテスト技法から教えることにしました。 私のようにずっとQA活動をしてきた者にとっては当たり前の技法でも、開発エンジニアにとっては意外と知る機会がなかったりするものです。 覚えておくとテストの段階だけではなく設計品質もあげることができるので、定着するように日々取り組んでいます。

まずは教科書的な内容をCLINICSチームのConfluenceに書いて、講義形式でCLINICS開発チームのメンバーに説明し、実践編として宿題を出して答え合わせと解説を行う、という流れで行っています。 学習者としては話を聞いているだけでは覚えにくく、実際に手を動かしたり、日々の業務で本当に困った経験をすると学びたい欲に火がつくと思っているので、実践を大切にしています。 演習問題は以下のような書籍を参考にして作問しています。ありがとうございます、著者の方々。

ソフトウェアテスト技法ドリル―テスト設計の考え方と実際
はじめて学ぶソフトウェアのテスト技法
ソフトウェアテスト技法練習帳 ~知識を経験に変える40問~

一度教わっただけではなかなか覚えるのも難しいので、大事なテスト技法(境界値分析とか…)は折に触れて何度も何度も口にするようにしています。

(再)「CLINICSのQA」とは?

冒頭で引用した Magic Pod導入の記事 では、「テストの自動化は(リリース後即座に修正できない)アプリから着手していく」方針としました。 現在は、CLINICSのWebページ側のテスト自動化も推進しています。

テスト自動化の目的は現場によっていろいろと思いがあるものです。なぜ「テスト自動化をやるのか?」については、機械にリグレッションテストを任せて手が空いた分、より高度な(経験則が必要な)探索的テストができるようになるから、と考えています。

最初の問いに戻ります。
「CLINICSのQA」とは何か?

品質向上する仕組みが自然にできている自律した組織で、私は開発チームメンバーと「おもしろいテスト」「楽しいテスト」をしていきたい、と思っています。 それによって顧客が出会う可能性のある不具合が減り、「そもそも品質の高いプロダクトをつくることができるという世界」に近づけるのではないかな、と考えています。

「おもしろいテスト」「楽しいテスト」とは発見であり、学習であり、フィードバックのサイクルによって生まれます。 そのためにも前述の「プロセス改善」と「知識の底上げ」は両輪で進めていく必要があります。

品質向上のための手段は、テストの他にも実に多岐に渡ります。 長年やってきた私もまだ全貌を掴み切れていない「QAのエンジニアリング」ってこんなに奥深く楽しい! ということが開発チームメンバーの共通認識になるとうれしいです。

f:id:medley_inc:20210305203713p:plain

最後までお読みいただきありがとうございました。

www.medley.jp