Medley Developer Blog

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

小さく始めるDesign System ~メドレーTechLunch~

こんにちは、開発本部の舘野です。

先日、メドレーで定期開催している社内勉強会「TechLunch」にて、Design Systemについて発表しました。医療介護の求人サイト「ジョブメドレー」において、Design Systemを「小さく始める」手法で導入を進めているので、そのプロセスについて紹介させていただこうと思います。

Design Systemとは何か

Design Systemとは、SalesforceLightning Design SystemIBMCarbon Design Systemなどが代表的な例として挙げられると思いますが、平たく言ってしまうとプロダクト独自のBootstrapとなるものです。

UI開発の領域では、これまでスタイルガイドを作ることでデザイナーとエンジニア間の共通言語とし、プロダクトのUIの一貫性を保つように努めることが一般的かと思いますが、Design Systemではスタイルガイドだけでなくデザインの原則やUIコンポーネントCSSやJSなども含めてプロダクトのインターフェースに関わる全てを、1つのプロダクトとする考え方です。

Design Systemはスタイルガイドと明確にどこが違うのかについて言及しているウェブ上の記事の多くは、Nathan Curtis氏の「A Design System isn’t a Project. It’s a Product, Serving Products.」という言葉を引用して、その差異を示しています。

スタイルガイドがプロダクトにおけるプロジェクト以上の存在ではないのに対して、Design Systemはプロダクトに対してUIのエコシステムを提供するプロダクトである、ということがDesign Systemの基幹となる考え方だと思います。

ジョブメドレーにおけるDesign System

TechLunchで発表したスライドはこちら。 speakerdeck.com

今回Design Systemを段階的に導入しているのは、医療介護の求人サイト「ジョブメドレー」です。

ジョブメドレーのインターフェースが今後より一層色々な形でユーザに使われる場面が増えていくことが想定される中で、プロダクトのUIの一貫性や生産性を担保し続けていくためには、スタイルガイドを作るだけでなくDesign Systemによってより包括的にプロダクトのUI開発に対する取り組み方を変える必要があるのではと考えていました。

とはいえ最初からプロダクトのUI全てをDesign Systemに置き換えるというのは変化が大き過ぎるし、Design Systemがうまく機能せずに失敗する場合も考慮しておく必要があったので、導入がうまくいかないければすぐにやめられるように以下の点を導入前に決めていました。

  • 最初から一気に色々やらない
  • まずは一部だけ導入してみる
  • 上手くいく部分といかない部分を検証する
  • Design Systemの改善と段階導入を繰り返す

Design SystemはプロダクトにUIのエコシステムを提供するプロダクトなので、一定期間で作って終わりではなく継続して改善を繰り返していくという点では、このような進め方が適切と考えました。

実際のところ、現在のジョブメドレーでは一部分だけジョブメドレーのDesign Systemとしてnpm化したモジュールから提供するようにしています。

npm化してDesign Systemから提供するようにしたのは、以下の3つのみです。

  • jmds-tools

    • sass mixinやfunctionを提供するユーティリティモジュール
  • jmds-tokens

    • design tokens(デザイン上の値を信頼できる唯一の情報源として1つの場所で定義されるもの)
  • jmds-flex

    • flexboxユーティリティ

プロダクトのUIとして見ると、flexboxのユーティリティクラスをDesign systemから提供するようになっただけです。

ただ、今は全体のごく一部がDesign Systemから提供されていますが、Design Systemに移行できるUIコンポーネントを選定して段階的にnpm化をしていくことで、プロダクトのUIコンポーネントの多くがDesign Systemから提供されている状態にすることが可能だと思います。

単純にnpm化することが目的ではなく、npm化したDesign Systemをプロダクトチームでメンテナンスしていくことで、より一貫性のあるUIをジョブメドレーのプロダクトに提供していくことが目的です。

まとめ

今回は、TechLunchで発表したジョブメドレーにおけるDesign Systemの取り組みについて紹介させていただきました。

今回紹介したDesign Systemが今後デザイナー、エンジニア、プロダクトマネージャーと協力しながら、ジョブメドレーのプロダクトのUIを支える強固な土台へと成長させられるように取り組んでいこうと思います。

お知らせ

メドレーでは、医療介護の求人サイト「ジョブメドレー」の他にも、医師たちがつくるオンライン医療事典「MEDLEY」、口コミで探せる介護施設の検索サイト「介護のほんね」、オンライン診療アプリ「CLINICS」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。

ちょっと興味があるという方も、ぜひお気軽にご連絡ください!

www.medley.jp

メドレーが協賛させていただいた「MANABIYA」に行って来ました!

皆さんこんにちは。開発本部の日下です。普段はオンライン診療アプリ「CLINICS」およびオンライン医療事典「MEDLEY」の開発を担当しています。(昨年、新卒で昨年メドレーに入ったのでエンジニア歴は1年弱。ベテランが多いメドレーのエンジニアチームで奮闘しています)

先日開催されたエンジニア特化型Q&Aサイト「teratailさんのイベント、MANABIYAにメドレーがスポンサーとして協力させていただきました。 エンジニアの平木と参加しましたので、イベント当日の様子をレポートします。

MANABIYAとは

teratailはご存知の方も多いかもしれませんが、MANABIYAというイベントをご存じない方もいるかもしれません。 MANABIYAは今回が初開催のイベントで、”疑問” を日本中から集め、カンファレンスを通じて解決策を見出し、”知恵” を生み出すことを目的とし、秋葉原から近い3331 Arts Chiyodaにて2日間に渡って開催されました。

全体の雰囲気

f:id:medley_inc:20180411115536p:plain 全体的に初開催とは思えないほど人が多く、一部のセッションでは教室が満杯になり、入場制限がかかるほどでした。また、speakerとして豪華なメンバー面々が数多く集まっており、最初から最後まで、参加したすべてのセッションで立ち見が出てるほど盛況だったのがとても印象的でした。

また、イベントの名前にもなっているように、学び舎というイメージがぴったりのコンセプトで統一されているのも特徴的でした。 会場自体も元々中学校だったものを利用したアートギャラリーを使用しており、教室や階段など、元を活かした作りになっていたのでイベントの雰囲気ととてもマッチしていました。

f:id:medley_inc:20180411160342p:plain

f:id:medley_inc:20180411115957j:plain
元々教室だったところでセッションが行われました

セッション

セッションはWeb、インフラ、DB、プログラミングから、AI、IoT等の最近話題になっている分野まで幅広く開かれていました。

我々が参加した2日目はプログラミング、Web、IoTのセッションが主に開催されていました。

メドレーのプロダクトはすべてWebサービスとして提供されていることもあり、私は、Web関連のセッションを中心に、時間が空いたら他の分野のセッションもふらっと覗き見るような形で参加しました。

エンジニアとして成長する上で必要な戦略の話や、Service WorkerやWeb Paymentsなど最近環境が整ってきた技術をプロダクトに組み込んでみた話など、幅広く見ることができました。

f:id:medley_inc:20180411120051j:plain
入場制限状態でやっと入れたものの立ち見の方の後ろから見ることに

f:id:medley_inc:20180411120136j:plain
運良く前の方の席が取れましたが、こちらも立ち見の方がたくさんいらっしゃいました

個人的に古川氏による「Web Application 2018 From Performance Perspective」は特に勉強になったセッションでした。 Webサイトのパフォーマンスに関してのエッセンスを詰めたようなセッションで、その歴史と共に、その時々のベストプラクティス、そしてその時代のバイブルをまとめ、今どういった背景でどういった対策をするべきか、その指針となるような話聞くことができました。

f:id:medley_inc:20180411120434p:plain
サイトパフォーマンスの歴史の概要を説明していただきました

特に、Web側はSPAとして動いているCLINICSを開発しているため、 Server rendered pages are not optional という言葉の意味が衝撃的で、帰る途中からずっとそのあたりのことを考えてしまうほどでした。 Speaker Deckにスライドが上がっていますので、気になる方はそちらをご参照ください。

speakerdeck.com

Webアプリケーションのパフォーマンスに関することは個人的に気になっていたものの、どこから手を付けてよいのかわからず理解があまり進んでない分野だったため、必要な知識を40分という短い時間で把握することができたのは非常にありがたかったです。

まさにイベントの趣旨である”気になっていること”、「回答」を知りたいがなかなか ”知る機会がなかったこと” という ”疑問” を、カンファレンスを通じて解決策を見出し、”知恵” を生み出す体験ができたのではないかと思っています。

f:id:medley_inc:20180411120233j:plain
リアル版teratailも登場

まとめ

大規模かつ幅広い分野を取り扱っており、自分の専門や興味のある分野以外も同時に開催されたため、気軽に参加することができるイベントでした。 初めてエンジニアリングに触れて1年弱が経ち、その間に業務などを通じて学んできた過程で言語化できていなかったことが思っていた以上にあったことを、このイベントを通じて改めて知ることができました。

こういった大規模なイベントは初参加だったのですが、多くのことが知れたのでとても良かったです。 次回開催される際は、また行ってみようと思っています。

イベントでメドレーのことを知りご興味持っていただいた方は、お気軽にご連絡ください! どんなエンジニア・デザイナーが働いているか、どんなことをやっているか等、ぜひHPをご覧ください。 www.medley.jp www.wantedly.com

「サイトの会員登録増加」に効果が出た施策の話

こんにちは。開発本部で医療介護の求人サイト「ジョブメドレー」の開発を担当している田村です。 メドレー開発本部で行われている勉強会「TechLunch」で、ジョブメドレーについて「求人サイトでやって良かった会員登録施策」というタイトルでお話させていただきました。インターネットで検索するとこういう内容はたくさん出てきますが、そのうちの一つとして、参考にしていただければ幸いです。

背景

医療介護の求人サイト「ジョブメドレー」は、創業当初(2009年)にリリースし会社と共に進化し続けてきたメドレーで最も歴史のあるサービスです。リリース開始から9年ほど経ちますが、個人・事業所にとって使いやすく愛されるサービスとなるよう、日々改善を続けています。その中でも、サービスの成長に重要な要素の1つである「ユーザの獲得」に向けた施策は、とても大切にしています。昨年に実施した中で「サイトの会員登録増加に効果が出た施策」について、社内の他サービスにとってもノウハウとなればと、少しだけ紹介させていただきしました。

ABテストによる改善

まずはじめに、既存のサイト内で改善できる点を洗い出して優先順位を付けて費用対効果が高そうなものから着手しました。実際に以下の2つをABテストを行い改善しました。

  • LPの改善
    • デザイン変更
    • 入力フォームの変更
  • 会員登録バナーの変更

LPの改善

BEFORE / AFTERの変更点

  • ユーザの満足度や求人の特徴を強調
  • メリハリを付け、より直感的にわかりやすく
  • 職種をイメージしやすいビジュアルに変更

BEFORE / AFTERの変更点

  • 全ての入力項目のある長い1ステップ形式から入力項目を短く分割して5ステップ形式に変更
  • ユーザがゴールイメージができるように現在のステップを表示
  • 入力しやすいように各項目を大きく表示
  • 各ステップへの移動がしやすいようにスクロールしなくても「つぎへ」「もどる」ボタンが押せるようなボタン配置
  • サクサク入力できるように各ステップへの移動でページ遷移をさせない

どのくらい効果があったのか

ビジュアルや訴求内容のブラッシュアップ、そしてユーザビリティを改善したことで会員登録数が約1.2倍という結果になりました。1.2倍で少ないと思うかもしれませんが、サイトの規模が大きくなるほど、ちょっとした改善を積み上げていくことが重要だと考えています。

会員登録バナーの変更

BEFORE / AFTERの変更点

  • ユーザがイメージしやすい訴求内容に
  • 訴求内容を絞り、ユーザが内容をすぐ把握できるようにビジュアルを追加
  • サイトの配色に合ったバナーデザイン

どのくらい効果があったのか

バナーの訴求内容とデザインを変更したことで、CVRが約2倍という結果になりました。訴求内容を多く見せることも大事ですが、ユーザがバナーを見て内容をすぐに理解できることを重視しています。

ユーザの行動を分析して施策を立てる

ジョブメドレーには、会員登録をしていないユーザが気になった求人を保存しておくことができる「キープ機能」があります。求人の保存期限は2週間でこの期間内に会員登録をすると保存期限の上限がなくなり、気になった求人をずっと保存しておくことができます。

施策のきっかけは、ある調査でユーザが積極的にキープ機能を活用していることがわかったことです。このキープ機能を利用しているユーザに保存期間に関する会員登録のメリットを提示すれば、会員登録してくれるのでは?という仮説を持ち、施策を実施することになりました。

BEFORE / AFTERの変更点

  • キープボタンをクリックした際、モーダルを表示
  • 保存期間は2週間で会員登録すると期間を越えて利用できます!と表記
  • 会員登録ボタンを設置

どのくらい効果があったのか

具体的な数値は公表できませんが、リリース当初の会員登録数と比較すると、最近ではおよそ10倍程度の結果となりました。ユーザにしてほしい行動・適切な導線改善などから見えてくる施策があるので、積極的にユーザの行動を分析し施策を立てて実行することが重要だと言えます。

まとめ

いかがでしたでしょうか。今回ご紹介した内容の他にも、ジョブメドレーでは、様々な改善を日々続けています。こうした取り組みを通じて、ABテストでちょっとした改善を積み上げていくこと、ユーザの行動を分析し施策を立てて実行すること、そして地道な改善を積み上げていくことがサービスの成長には不可欠だと実感しています。こうした地道な取り組みに励むエンジニアの方は少なくないと思いますが、私たちが実施している施策事例が、皆様の参考となれば幸いです。

今後も「ジョブメドレー」を会社と共に成長し続けるサービスにしていきたいと思い、日々奮闘していきたいと思います。

お知らせ

メドレーでは、医療介護の求人サイト「ジョブメドレー」の他にも、医師たちがつくるオンライン医療事典「MEDLEY」、口コミで探せる介護施設の検索サイト「介護のほんね」、オンライン診療アプリ「CLINICS」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。

ちょっと興味があるという方も、ぜひお気軽にご連絡ください!

www.medley.jp

プラットフォームをまたぎブレない仕様を実現するための、ネイティブアプリ開発施策

こんにちは、開発本部の高井です。オンライン診療アプリ「CLINICS」のアプリ開発を主に担当しています。

CLINICSではWebに加えて、iOS版とAndroid版の各プラットフォームの仕様変更や機能追加などをほぼ同時に開発しているのですが、担当する人数が増えたりすることで、仕様に差が出たり、その結果手戻りが起きるということも増え始めていました。

そうした課題を解決するために実践した様々な施策の中から、特に有効だった3つの改善策について、今日はご紹介します。

背景

CLINICSの開発チームでは5人ほどのエンジニアがタスク単位で全てのプラットフォームを実装したり、大きいタスクの場合はプラットフォーム毎に別の開発者が担当する形で開発しています。

そのような形で機能追加や不具合対応の開発を進める中で、以下のような課題がありました。

  • プラットフォーム間で仕様やデザインが違う
  • リリース直前に仕様の違いが見つかり、手戻りが発生する
  • 各プラットフォームに対する習熟度にバラつきがあるため、開発者によって実装方法が違う

特にプラットフォーム毎に開発者がほぼ固定されてしまっていた時期には、コードレビューはしていても微妙な違いに気づかなかったり、同じUIにするのに実装コストが高くてあきらめたり、ということが起こりがちでした。 プラットフォーム間で仕様やデザインが違うとユーザ体験の質がプラットフォームによってバラついてしまいますし、デザインや企画の作業も増えてしまいます 。これらに加えて、エンジニアの人数が増えたり、デザイナーやカスタマーサポートなどエンジニア以外のメンバーとのコミュニケーションも増えたりしてきたこともあって、開発スピードも段々と遅くなってきていました。

そのような状況を改善するために、チーム内で継続的に実装方法や開発フローを見直し、改善策を実施してきました。

今回は以下の3つの改善策をご紹介します。具体的な実装については、主にiOSで使用しているコードを引用してご紹介します。(コードの一部を抜粋しているので、そのままでは使用することはできません。あくまでも参考コードとして読んでください。)

改善策1 DLS(デザイン言語システム)の導入

まずはDLS(デザイン言語システム)の導入についてです。DLSとは以前、本ブログでもデザイナーの前田がご紹介させていただきましたが(デザイン言語システムを入れたらコミュニケーションコストがぐっと下がった話〜メドレーTechLunch〜)、 UIに一貫性をもたせるため、配色やレイアウト、タイポグラフィやマージンなどのルール を策定し、チーム全体で継続的に運用していくための仕組みです。策定したルールを組み込んだ各コンポーネントのデザインを元に、Web / iOS / Androidの各プラットフォームでUIを実装して開発時に再利用できるようにしています。デザイン自体は下記のような形でSketchファイルで管理しています。

f:id:medley_inc:20180327164233p:plain

f:id:medley_inc:20180327164243p:plain

iOSについては各コンポーネントをカスタムビュークラスとして実装し、再利用できるようにしました。DLS導入以前はプラットフォーム毎に違ったUIやルールで開発していたので、実装段階で担当する開発者毎の認識によって品質や仕様に差が出ている状態でした。DLS導入によってそのような差が出にくくなり、一定の品質を保つことができるようになりました。 また、 UIの微調整などが減って、機能ロジックに重点を置いた開発に専念できるようになり、さらにデザイナーとの認識合わせが最小限になったことにより開発効率も上がった と感じています。UIの基盤をつくったことで新しく画面を開発する場合でもコンポーネントを組み合わせ、エンジニアだけで実装が完了することも多くなり、その分デザイナーは次の施策やプロジェクトに専念できるようになりました。

実装についてですが、各コンポーネント毎にxibファイルでUIパーツを作成し、それをクラスファイルで読み込んでカスタムビュークラスの見た目として使っています。カスタムビューは再利用しやすく、利用時にバラツキが出にくいように以下の点を満たすように実装しました。

  • Interface Builder/コードのどちらからでも初期化できる
  • ビルドする前にStoryboard上でUIパーツのデザインを確認できるようにIBDesignableとIBInspectableを指定する
  • カスタムビューの中でUI要素のマージンや高さを指定する

例えば、セレクトフォームコンポーネントのカスタムビューは以下のような実装になっています。

  • xibファイル f:id:medley_inc:20180327164320p:plain

  • クラスファイル

import UIKit

protocol ClinicsFormSelectDelegate: class {
    func didClickFormSelect(sender: ClinicsFormSelect)
}

@IBDesignable class ClinicsFormSelect: UIView {

    @IBOutlet weak var selectView: SelectView!
    @IBInspectable var labelText: String = "Form-parts" {
        didSet {
            selectView.labelText = labelText
        }
    }

    weak var delegate: ClinicsFormSelectDelegate?

    // コードから初期化する場合に呼ばれる
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    // Interface Builderから初期化する場合に呼ばれる
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    private func commonInit() {
        // xibファイルの読み込み
        let bundle = Bundle(for: type(of: self))
        let view = UINib(nibName: "ClinicsFormSelect", bundle: bundle).instantiate(withOwner: self, options: nil).first as! UIView
        addSubview(view)
        backgroundColor = .clear
        view.backgroundColor = .clear

        // 読み込んだViewのサイズがカスタムクラス(ClinicsFormSelect)と同じサイズになるようにConstraintを設定する
        view.translatesAutoresizingMaskIntoConstraints = false
        let bindings = ["view": view]
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|",
                                                      options:NSLayoutFormatOptions(rawValue: 0),
                                                      metrics:nil,
                                                      views: bindings))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|",
                                                      options:NSLayoutFormatOptions(rawValue: 0),
                                                      metrics:nil,
                                                      views: bindings))
    }

    // xibファイルの中に配置したUI要素へのアクションのハンドリング
    @IBAction func didTap(_ sender: UITapGestureRecognizer) {
        delegate?.didClickFormSelect(sender: self)
    }
}

CLINICSでは主にStoryboardを使ってUIを実装しているので、使用するときはStoryboardにUIViewを置き、コンポーネントのクラス名を指定して使います。テキストなどのプロパティを設定し、Constraintを指定して配置すれば完了です。ユーザによるアクションのハンドリングや動的にプロパティを切り替える必要がある場合は、呼び出し側で処理を追加します。

f:id:medley_inc:20180327172653p:plain

最終的にビルドすると以下のように表示されます。(表示されている内容は開発中に作成した仮のデータで実際のものとは異なります。)

f:id:medley_inc:20180327172923p:plain

改善策2 アプリエラーの共通化

以前は業務的に重要な処理のエラー以外はプラットフォーム毎で表示するエラーメッセージが異なっていたり、エラーハンドリング時に違った挙動をしていることがありました。その結果、ユーザ体験が一貫したものになっていないというだけでなく、お問い合わせがあってもカスタマーサポートが一次回答しにくかったり、伝えられた内容が曖昧なため開発者が調査するのに時間がかかったりすることがありました。

そこで、改めてフロント側で発生するエラーの定義を共通化し、エラーメッセージやエラーハンドリング時の処理も統一しました。 問い合わせの効率化のために共通のエラーコードも決めて、エラー発生時に表示されるアラートに追加し、それらのエラー定義はドキュメントで一覧化して、カスタマーサポートにも共有 するようにしました。

また、エラーハンドリング時にクラッシュレポートのログに記録する内容や送信するタイミングを統一して、開発者全員が理解しやすいようにしました。エラーコードの表示については、改善を検討していた時期にちょうど参加していたiOSDC Japan 2017で、同じような課題に対する知見を発表されていたのを見て、早速取り入れました。最近ではユーザからの問い合わせにもエラーコードが使われることがあり、実際にコミュニケーションコストを低下させることができているように思います。

エラーのフィードバックは細かいところではありますが、ユーザのアクションを継続させるために重要な要素のひとつです。CLINICSはユーザ属性が老若男女問わず幅広いので特に気を配って改善を行ってきました。 実装についてですが、iOSでは以下のように定義しています。

enum ApplicationError: Error {
    case commonRequestError(String)
    case createReservationCardError
    case createReservationScheduleIsFullError
    ~

    var errorCode: String {
        switch self {
        case let .commonRequestError(viewId):
            return "\(viewId)-0000"

        case .createReservationCardError:
            return "40-0001"

        case .createReservationScheduleIsFullError:
            return "40-0002"

       ~
var title: String {
        switch self {
        case .commonRequestError:
            return "接続エラー"

        case .createReservationCardError:
            return "決済失敗エラー"

        ~
var description: String {
        switch self {
        case .commonRequestError:
            return "データを正しく表示出来ない可能性があります。\n通信状況をお確かめいただくか、しばらく経ってから再度起動してください。"

        case .createReservationCardError:
            return "ご登録されているクレジットカードの決済中にエラーが発生しました。\nおそれいりますが、もう一度最初から操作ください。"
        ~

Androidでも同様にenumで定義しています。

enum class ApplicationError(var code: String, val title: String, val description: String) {
    CommonRequestError("0000", "接続エラー", "データを正しく表示出来ない可能性があります。\n通信状況をお確かめいただくか、しばらく経ってから再度起動してください。"),
    CreateReservationCardError("40-0001", "決済失敗エラー", "ご登録されているクレジットカードの決済中にエラーが発生しました。\nおそれいりますが、もう一度最初から操作ください。"),
    CreateReservationScheduleIsFullError("40-0002", "スケジュール空きなしエラー", "選択された予約日時のスケジュールに空きがありませんでした。\nおそれいりますが、別の予約日時をご選択のうえ、もう一度最初から操作ください。"),
    ~

改善策3 コードレビューの手順改善

リリース当初から実装者以外のメンバーによるレビューは適宜行なっていましたが、レビューの段階でデグレや仕様の違いを見逃してしまうことがあったので、レビュー体制の強化とメンバーのソース理解の向上を図るために、以下のようにルールを設定しました。

  • セルフマージはしない
  • PRに対して2人以上でレビューする
  • ビューの変更があった場合には画面キャプチャを貼る

それらを守りやすく、より効率的にするためにDangerも導入しました。 導入手順はこちらにまとめられているほか、検索すればけっこう出てくるので省略します。弊社ではiOSのCIはBitriseを使用しているのでBitrise上で実行してGitHubのPRに反映させています。

Dangerでは、以下の項目をチェックしています。上記のルールを反映しているのに加えて、PRの向き先とSwiftLintの実行結果もチェックしています。CLINICSのiOSアプリではGitFlowを導入しているため、releaseブランチとhot-fixブランチ以外からのPRの向き先がdevelopブランチになっていない場合には警告を出すようにしています。

  • レビュアーの人数が2人以上になっているか
  • ビューの変更(xib、storyboardを触ったかどうかのみ確認)があった場合に画面キャプチャを貼っているかどうか
  • PRがdevelopに向けて作成されているか
  • SwiftLintのチェックを通っているか

f:id:medley_inc:20180327164527p:plain

弊社がiOS開発で利用しているDangerファイルは以下の通りとなっています。導入する際のご参考にしてください。

# for only difference
github.dismiss_out_of_range_messages

# reviewers
warn("レビュアーは2人以上指定してください") if github.github.pr_json["requested_reviewers"].length < 2

# view changes
view_extensions = [".xib", ".storyboard"]
has_view_changes = git.modified_files.any? { |file| view_extensions.any? { |ext| file.end_with? ext }}
has_view_added = git.added_files.any? { |file| view_extensions.any? { |ext| file.end_with? ext }}
pr_has_screenshot = github.pr_body =~ /https?:\/\/\S*\.(png|jpg|jpeg|gif){1}/
warn("見た目に変更がある場合は画面キャプチャを貼ってください") if (has_view_changes or has_view_added) and !pr_has_screenshot

# base branch
is_to_master = github.branch_for_base == 'master'
is_to_develop = github.branch_for_base == 'develop'
is_from_releases = !!github.branch_for_head.match(/releases\/[0-9]+\.[0-9]+\.[0-9]/)
warn('PRはdevelopに向けてください') if !is_to_develop and !(is_from_releases and is_to_master)

# swiftLint
swiftlint.lint_files inline_mode: true

f:id:medley_inc:20180327164549p:plain

まとめ

CLINICSにおけるアプリ開発の品質と効率性を向上するための取り組みをご紹介しました。これらの取り組みによって プラットフォーム毎のデザインや機能のブレが少なくなり、認識ずれによる手戻りなどが少なくなったことで開発効率が上がった と感じます。プラットフォーム毎の違いを少なくして、より多くのメンバーがコードに手を入れやすい状態にすることで実装やコードレビューの質も向上しているように思います。

React Nativeなどを利用して、コードそのものを共通化する方法もあるとは思いますが、プラットフォーム毎に別のコードで開発する場合でも、仕様や実装のルールを工夫することでより効率的に開発できるのではないでしょうか。

CLINICSチームでは他にも実装や開発プロセス、プロダクト運用について日々改善を行なっています。今後も、こうした取り組みを積極的に実践し、KPT形式で振り返って、また次のアクションにつなげることで、多くの方に愛されるプロダクトを育てていきたいと思っています。

お知らせ

メドレーでは、エンジニアやデザイナーを募集しています。ご興味のある方は、こちらからどうぞ! www.medley.jp

非デザイナーのための「ブランド再入門」

こんにちは。開発本部の医療メディアチームでデザインをしている波切です。

メドレー開発本部で行われている勉強会「TechLunch」で、デザイナー以外の方も知っておいて損はない「ブランドとは?」というお話をさせていただきました。多くの方が何となく知っていることも多いかもしれませんが、再入門的に参考にしていただけると嬉しいです。

背景

メドレーでは時期を問わずプロダクトの在り方について常日頃から様々な場面で議論がなされています。

こういった議論の中でブランドとしてどのように見せられるのが良いだろうか、といった検討をすることも多々あり、改めてブランドについて学び直したいと思ったのが今回のきっかけになります。

TechLunchではエンジニア・デザイナー・ディレクター・医師(!)と様々な職種の人が参加しています。

この時代では当たり前かもしれないブランドの基礎を改めて学び直し、デザイナー以外の職種の方にも共有しましたので、ブログでもご紹介させていただければと思います。

ブランドってなんでしょう

ブランドとブランディングの違いって?

f:id:medley_inc:20180309175130p:plain

まずは混合しやすいブランドとブランディングの定義から。

 

ある特定の商品やサービスが消費者・顧客によって識別されているとき、

その商品やサービスを「ブランド」と呼ぶ

※製品名、パッケージング、広告、価格、使用経験などにより、その製品につけられた製品特性と価値(機能的および非機能的)とのユニークなコンビネーション。消費者・顧客の目から見た場合、その製品を競合から差別化するもの。

(via ブランド・マネージャー認定協会 用語集)

 

ブランディングとは、ブランドに対する共感や信頼などを通じて顧客にとっての価値を高めていく、企業と組織のマーケティング戦略の1つ。ブランドとして認知されていないものをブランドに育て上げる、あるいはブランド構成要素を強化し、活性・維持管理していくこと。また、その手法。ここでいうブランドとは高級消費財に限らず、その対象としては、商品やサービス、それらを供給する企業や団体のほか、人物・建築物・史跡・地域 ・祭事など、あらゆるものが該当する。

(via wikipedia:ブランディング)

ブランドとは「企業・製品に対して消費者が持っているイメージ(記号)であり、競合との差別化を生み出す価値の総体」を指し、

ブランディングは「ブランド価値を与えるための手段」と捉えることができると思います。

この定義になぞらえてコカ・コーラを例にブランドとして認知される具体的なステップとして紹介すると、以下のようになります。

f:id:medley_inc:20180309175152p:plain

  • ロゴなどの識別記号が記憶される
    • コカ・コーラのロゴが記憶される (生活者の頭の中に、ロゴなどの識別記号が記憶される)
  • 記号から体験が思い浮かぶ
    • コカ・コーラのロゴを見れば炭酸飲料であることや、爽やかな気分になれることが思い浮ぶ (識別記号を見れば、知覚体験を想起できる)
  • 体験から記号を思い出す
    • 爽やかな気分になりたいと思ったら、コカ・コーラを思い出す。ロゴが思い浮かぶ (知覚価値が頭に浮かんだら、識別記号が想起される) 

「ブランド連想」「ブランド資産」といった言葉もあり、ブランド(識別記号と知覚体験)に対してポジティブな印象を築き蓄積させることがブランディングのカギになってきます。

ブランド構築

f:id:medley_inc:20180309175222p:plain

前述の記号をブランドの土台とするとコーポレートアイデンティティ(CI)やヴィジュアルアイデンティティ(VI)といったクリエイティブが大きな役割を果たしますが、現在ではユーザーはブランドを知覚する機会が多く、差別化のためにもブランドは顧客体験をベースに作っていくことも重要になります。

「良い顧客体験を提供しブランドの競争力を高める」 という考え方に基づいて、ブランド戦略を考える順番は理想的な体験を描いてから必要なモノや技術を考えます。これはブランドに限らず様々な場面で意識したいことです。

ブランドに大事な一貫性

魅力的なブランドは顧客体験が蓄積して形成されていきます。蓄積されるブランド体験の要素は「体験の魅力度」「体験の量と時間」「体験の一貫性」と3つあり、ブランドの価値はこの3つの要素のかけ算にあります。

体験が魅力的であり、その体験の回数が多く長い時間にわたって経験し、体験自体に一貫性があるブランドがユーザーとって良いものとされます。

3つのうち特に重要なものは最後の 「体験の一貫性」 にあり、この一貫性は2つに分けることができます。

  • 時系列で一貫性:時代で左右されない顧客体験がブランドから提供される
  • 接点の一貫性:ブランドを買ったり利用する前から、購入プロセス、購入後の利用シーンにおいて、一貫した顧客体験ができる

「モノとコト」にも例えやすいところですが、製品としての一貫性に加えて体験する前後のグランドデザインにも一貫性を持たすことが重要になります。

f:id:medley_inc:20180309175407p:plain

例としてスターバックスは広告費をほとんどかけずに今のブランド認知度を築いたことは有名ですが、そこにはブランドの価値を築くためのブランディングに一貫性があり、かつそれらが時代性とマッチしたのが要因ではないかと思います。

ブランディングのメリット

  • 選択意思決定の単純化・固定化
    • 顧客の知識が整理されることで競合と差別化され再び同じ物を選ぶようになる
  • ユーザーのロイヤル化
    • 親しみや信頼が増大されることでブランドロイヤリティが形成される

なぜブランドにこだわるのか、という点でもこれらメリットを実現していくことが重要です。

デザイナーとして気遣い溢れるUIや、サービスの思想を記号に落とし込んだVIなどモノづくり視点でのこだわりや重要さを踏まえた上で、他職種の方にもこれらのメリットや競争としての必要であることを理解してもらえるよう働きかけることを意識していきたいところです。

ブランディングの悩みどころ

ここからは基礎を踏まえて、実践的に行われているブランディングで悩みやすいところを事例で紹介しながら簡単なディスカッションをしていきました。一部だけ抜粋してご紹介します。

製品ブランドの管理

f:id:medley_inc:20180309175511p:plain

会社のブランド管理の思想を定義できても、変化の早い業界であればイメージ通りになかなか通らないことも多々有りえます。

少ないブランド資産を活用する意味でもスタートアップは横串型に整理されることが多くありますが、ある程度の規模感になって基礎体力がある企業であると個別適応型でもブランドとして信頼性を保てますし、横串型に比べて動きやすさがあると思います。

一方で、プラットフォーマーとして存在したいなら横串のブランド価値からファンを囲い込むべきかもしれません。Techlunchの中でもメドレーであればどうあると良いかについて議論ができました。

ブランディングのタイミング

顧客体験の蓄積が重要なブランドでありますが、どの段階でブランディングに取り組むかは状況によりますが意見が出やすいところだと思います。

ICC FUKUOKA2017にてブランディングについてのセッションがあり、取り組むタイミングについての議論がうまくまとめられていたためTechlunchで事例として共有しました。プロダクトとしての差別化が基本であることに加えて、ブランドの在り方を組織にインストールさせるためにブランディングに取り組むケースも紹介されています。

 

僕はブランドが常に必要かと言うと“No”だと思います。

コモディティ化し始めたり、競争が始まって差別化しなくてはならない時に、プロダクトの機能などで差別化ができない、または必ずしもパフォーマンスで差別化ができない時に唯一残された選択が、ブランドを作るということであると思います。

[株式会社Bloom&Co. 彌野泰弘]

 

ユーザーを獲りにいくというフェーズですよね。

メルカリの場合、やはり最初の100万ダウンロードくらいまでは、結構チューニングをしながらオンラインのマーケティングで(ユーザーを)獲得してきてきました。

~中略~

やはり100万ダウンロードくらいあって、リテンションレートが高くユーザーが積み上がる状態になっていれば、大きくマスマーケティング(TVCM)をやっても獲得したユーザーは残りますからね。

[株式会社メルカリ 小泉文明]

僕は、ユーザーを獲得する手前でブランドが必要だと思っているんですよね。

ブランドというのは必ずしも外に対してだけではなくて、(組織の)中の人に対して必要であることもすごく多いのです。

~中略~

資生堂は当時130年くらい経っている会社だったので、その130年もこの後の130年も、世の中を美しくするとか、人を美しくするとか、それは女性に限らず、お化粧に限らず美しくするということが必要だよね、軸だよねという話になって、そのスローガンと共に前田新社長体制で進んでいくことになりました。

[株式会社dof 齋藤太郎]

(via スタートアップのブランディングはいつから必要か?【F17-7C #3】)

共有した後には、リリース当初からブランドやクリエイティブが作り込まれたプロダクトが最近話題になることが多いということも話に上がりました。

もちろんブランディングのタイミングは状況により千差万別ですが、プロダクトをゼロから作る際には、プロダクトの在り方と合わせてどんなブランドを作って行きたいのかも早めに考えられることが必要だ、など具体的なディスカッションも出来ました。

新たなブランドが受け入れられないことも

f:id:medley_inc:20180309175734p:plain

基本的にブランドを新しくすることは見慣れたものが変わってしまう恐怖から反発を生むケースが多いですが、その中でもGAPはロゴの2010年リニューアル公表後ネット上からの反発が強くわずか6日間という短期間で新しいロゴの使用を止め、元のロゴに戻してしまうという一件がありました。(この件は株価にも大きな影響を与えました)

一方、同じような境遇でAirbnbも2014年のリニューアル当初ロゴは不評でしたが今ではリニューアルの成功例として扱われる存在になっています。

 

Techlunchでも歴史の有無が差になったのか、など様々な意見が出てきました。この件はロゴとしての王道を極めようとした以上の背景を提示出来なかったGapに対して、Airbnbはサービスのストーリーをロゴに内包し、地道にロゴを介したコミュニケーションに徹したことが明暗を分けたように思います。

この事例はロゴのアイデンティティをどこまで確立させられたかの違いにあることに加えて、デザインの意思決定を一時的な多数意見に委ねた事例としても学ぶことが多いです。

まとめ

私個人が元々グラフィックデザインをしていた経験もあり、今まではブランディングの中でも興味がCIやVIに傾倒していましたが、体験全体がブランドに大きな影響を与えるこの時代、組織としてブランド構築をしていく意識が重要であることが今回の大きな学びでした。

また基礎を学ぶ上で書籍を読んでいましたが、最近の事例などを学ぶ際にはブログなどでの情報収集がとても有効で、学び方も変わってきているなと思いました。今回紹介した内容はあくまで入門編なので、興味があれば今回参考にさせていただいた本とブログ・記事からより深堀りが出来るのでオススメします。


プラットフォームブランディング

コーポレート・アイデンティティ戦略―デザインが企業経営を変える

ブランド・エクイティ研究の展望 ~価値をめぐる議論の系譜を中心に~

UXとブランド

ブランドアイデンティティとは|ブランド構築を成果に導くBIの創り方|成功事例有

スタートアップのブランディングはいつから必要か?

ロゴのリデザインーなぜGapが失敗しAirbnbが受け入れられたのか

武器になる「ロゴ」を生み出す、CIデザインとは何か?

 

Techlunchではデザイナー以外の方からも事例に対して意見が出たり、疑問に対して参加者でディスカッションが出来たことがとても有意義でした。今後はこれらを意識しながらブランドの土台となる価値や在り方をデザイン出来るようにしていきたいと思います。

お知らせ

 メドレーでは、医療介護の求人サイト「ジョブメドレー」、医師たちがつくるオンライン医療事典「MEDLEY」、口コミで探せる介護施設の検索サイト「介護のほんね」、オンライン診療アプリ「CLINICS」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。

 

興味のある方、ぜひメドレーへ遊びにいらしてください。

www.medley.jp


アナログな業界をテクノロジーで変える、X-TechなCTO大集合! - デブサミ2018に登壇して来ました -

こんにちは、メドレー広報の阿部です。先日開催されたDevelopers Summitデブサミ)2018に、メドレーのCTO・平山が登壇しました。

デブサミの今回のテーマは「変わるもの×変わらないもの」。

レガシーな業界がインターネットの力で変わりつつある、その面白さをエンジニアに知ってもらえたらいいですね、とCodeZineEdTechZine編集長の斉木さんと盛り上がったことで、トークセッションが実現。

「医療×IT」としてメドレーCTO・平山が、「金融×IT」としてマネーフォワードCTO・中出さんが、「飲食×IT」としてトレタCTO・増井さんが登壇。ファシリテーター CodeZine/EdTechZine編集長の斉木さんをお迎えしての実施となりました。

どんな話が飛び出したのか、一部ではありますが紹介します!

http://event.shoeisha.jp/static/images/event/741/1200.png

そもそもX-Techって?

 斉木さんは冒頭で、X-Techについて「ITの導入が遅れている業界において、 スタートアップが洗練されたIT技術により新たな価値や仕組みを提供する動き」と定義。実際に各事業ではどういう感じか?と話が進みました。

f:id:medley_inc:20180228141346j:plain

Fintechの将来像として「キャッシュレス社会を実現したい。お店にとって、現金って本当は不便なもののはず。毎日お釣り金を準備しないといけないし、あまり大金をお店に置いておけないから、定期的に銀行に入金しに行ったりしているのが現状。そういう煩わしさを、少しずつ無くしていきたいですね」と、マネーフォワード・中出さん。

お金=現金というような”当たり前”が深く根ざしているのは、医療の世界も同様です。

「医療は、未だに紙のカルテやFAX文化が残っていたり、そもそもインターネットが浸透していない。もちろん医療システムもありますが、医師や医療従事者の言うことをそのまま聞いて作ったというものも多くて、全体最適が取れていないという課題もあります」と弊社・平山も話します。

多くの店舗に共通する課題を本質的に解決していくことが大切

X-Techでは、インターネットサービスにより大きな変化がおこる分、これまで使い慣れていないサービスだけに、様々な改善要望が入ることも少なくありません。

「実際にサービスを使って頂いている飲食店から様々な要望を頂くのですが、弊社は一切カスタマイズをしない、というスタンスをとっています。飲食店の価格やタイプは様々だけど、突き詰めると実は課題は共通していたりする。ヒアリングしながら、本質的な課題を見つけて、解決策を提供するようにしています」と、予約/顧客管理サービス「トレタ」を提供するトレタ・増井さん。

これは医療でも同様で「レガシーな業界だと、医師のいう通りにプロダクトを作ることに従うなどの関係性も生まれやすいという状況はあります。でもそこは、専門分野が違う対等な存在と捉えて、プライドを持って議論をできることが大切ですよね」と平山も答えます。

f:id:medley_inc:20180228141409j:plain

X-Techで活躍できるエンジニアは?

CTO対談ということもあり、話は「X-Techを支える組織作り」に。

会社で働くエンジニアの特徴や求められるものを聞かれると、

「飲食経験者が多いわけではないのですが、食べるのが好きな人は多い。社員同士で食事に行くことも多く、たまにエンゲル計数大丈夫かなと思います(笑)。スタートアップだからこそ、求められる役割が固定されず日々変わっています。有機的に変わることに抵抗感がないことが大切ですね」と、増井さん。

中出さんも「たしかに、世の中の課題解決へのモチベーションが強いと思う」とこれに同意。さらに平山も「プロダクトに誇りを持っている人が多いですよね」と続けました。

X-Techならではの開発チームって?

最後に、組織づくりや採用で気をつけていることには、各社こんな回答がありました。

「マネーフォワードでは、プロダクトごとにチームを組んでいて、スモールチームで運営することを心がけています。技術選定も含めて、そのチームが使うべきと判断したらいいと。共有化も大切ですが、それが足かせになることもある。私がCTOになってから、そういうものは最低限に整理しました。」 (中出さん)

「採用はずっと頑張っているけど、ずっと足りていません。もともと経験的にシニア〜ミドル層を採用したいと考えていましたが、現在はジュニアまで幅を広げています。ただ、スタートアップでは残念ながらゼロからプログラムを教える余裕はないことが多い。だからこそ”僕らが何を与えられるのか”をすごく考えています。技術やビジネスマナーのイロハは十分に教えられないけれど、業界や技術の面白さはトレタだからこそ与えられることがあると思う。」(増井さん)

「今メドレーはエンジニアとデザイナー、ディレクター、医師で30人くらいの開発チームですが、職種間の隙間をなくすことを徹底していますiOSエンジニア、サーバサイド、フロントエンド、と担当を分けることで情報断絶が起きる。ミッションによって人をアサインし、職種を横断して取り組める環境を作っています」(平山)

 

最後に平山は「X-TechはWebエンジニアのものと思われがちですが、toB向けに広く展開しているプロダクトが多く、(デブサミの参加者に多いような)SIer系のエンジニアの方にも近しい匂いを感じてもらえる世界だと思う。ぜひ次のキャリアとして、インターネットの会社も選択肢にあるんだというのを思っていただけると嬉しいです!」と力強くコメントして、セッションを締めました。

f:id:medley_inc:20180222161519j:plain

2月には「日経 xTECH」が創刊されるなど、ますます注目のX-Tech分野。

どんなことができる業界なのか、メドレーはどんなビジョンに向けて動いているのかなど、もっと話を聞いてみたいという方は、ぜひご連絡ください!

www.wantedly.com

ComposableなUI設計を目指したフロントエンド開発

こんにちは、開発本部の舘野です。医療介護の求人サイト「ジョブメドレー」の開発を担当しています。

昨年、ジョブメドレーでは事業所が利用する採用管理画面のUIリニューアルを行いました。ユーザが使いやすいUIづくりを目指すために、長期間にわたり誰が開発しても一貫性あるUIを実現できるようなシステムが必要です。そこで今回は「Composable」なUIシステムの実現をテーマに、どのように開発を行ったのかについて、共有させていただきます。

背景:画面や機能追加のたびにUIの一貫性がなくなっていた

ジョブメドレーの採用管理画面とは、医療機関介護施設の採用担当者が求人情報の管理や応募者の選考状況の管理などを行う画面です。

この採用管理画面ですが、リニューアル以前はAngularフレームワークとして採用したSPAで、UIに関してはAngularUIのBootstrapを利用して、それぞれのエンジニアが実装を行っていました。

それなりのUIをスピーディーに実現できる点においては、BootsrapのようなUIフレームワークを利用することで受けられる恩恵は大きかったのですが、一方で、包括的にUI設計を行っているわけではなく、各人が局所的にUIを作っていくので、画面や機能を追加していく中で一貫性がないUIが増えていく状態になっていました。

実際にユーザインタビューなどを行ってみると、「ログインした後どうすれば良いのか分からない」、「〇〇という機能があることを今まで知らなかった」、「xxがどこにあるのか分からない」などの意見が多々あり、全面的なUIの見直しが必要になっていました。

医療や介護の現場での人材不足を解消するために採用担当者に提供するツールとして、今後さらに機能拡充していくことが求められていましたが、機能拡充していくことに耐えうる状態にはないというのがプロダクトチームのメンバーの共通認識でした。

そこで、全体的に情報設計から見直してデザインを刷新し、今後プロダクトを成長させていく上でスケール可能なUIを提供できるようにするため、UIリニューアルを決定しました。

フロントエンドで必要だったこと

Bootstrapを用いてエンジニアのみでUIを作っていたのとは異なり、リニューアルでは社内のデザイナーが現状のUI上の課題を整理したデザインを作成しました。

これに伴って、自前で全てのUIパーツを作成することになりましたが、Bootstrapに頼りきっていたときとは違い、堅牢性と柔軟性を伴ったUIシステムを自分たちで構築する必要がありました。

リニューアル前の採用管理画面のUIは一貫性に欠けており、ユーザは非常に多くの操作を学ぶ必要がありましたが、この責任はデザイナーだけでなくUI開発をするエンジニアにも大いにあります。 良いデザインができても、最終的にプロダクトのUIはコードによって作り上げられるものなので、エンジニア次第で一貫性に欠けるUIになってしまうことは十分にあり得ると思います。

往々にして起こり得るのは、目にする機会が比較的少ない画面であったり、改修対象ではない部分などが気づいたら崩れていたり、意図しないUIになってしまっていたりということですが、こういった状況に陥る大きな要因としてはフロントエンドの部分で一貫性に対する配慮ができてないことが1つだと思います。

そこで、すでにある採用管理画面を使いやすくするのはもちろん、今後スケールしていく中で一貫性のあるUIを担保し続けていくためには、リニューアルでフロントエンドも堅牢で柔軟なUIシステムへと変える必要がありました

UIリニューアルで開発上大切にしたこと

UIの一貫性を保つとなると、今のフロントエンドではもはや当然のことかもしれませんが、コンポーネント指向で構成することになると思います。

技術選定としては、上述の通りリニューアル以前はAngular(v1.4.11)を利用していましたが、リニューアルのタイミングでReactへ移行しました。

Reactを選択した理由としては、学習コストの点やコミュニティが活発でエコシステムが充実している点、単一方向のデータフロー、シンプルなAPIなどを総合的に判断してのものですが、目下の課題であるUIコンポーネントのメンテナビリティに関しても適切な選択肢であると考えました。

CSSの方はというと、リニューアル前はBootstrapでまかなえない部分はSassでそれぞれのエンジニアが書きたいように書くという状態でしたが、リニューアルでSassに加えて一部PostCSSという構成に変更して、設計はITCSS、Lintをstylelintで行う、という形にしました。

ITCSSを選択した背景としては、その詳細度順のレイヤー階層によってカスケードを管理しやすい点やレイヤーの増減で容易にスケールできる点などから選択しました。

CSS in JSも考慮はしましたが、リニューアルの時点ではこれという決定的な選択肢が無かったこともあり(まだstyled-componentsも正式リリースされてなかった)、classnamesを利用しました。

フレームワークやライブラリの選定も重要ですが、UIシステムを刷新する上で開発上最も重視したのは「Composability(コンポーネントの組み合わせが容易であること)」でした。

Composableであるということは、つまり様々な状況において組み込み可能な状態であり、再利用性が高いということになります。 それぞれのコンポーネントを組み合わせることが容易に出来るとともに、複数のコンポーネントを組み合わせた状態から1つ1つ分解することも容易な状態が望ましく、結果的にそれでUIが構築しやすく改修しやすい状態に自然となるはずです。

モーダルを例にあげると、モーダルの中で表示するコンテンツ要素やモーダルの背面に敷くオーバーレイコンポーネントは、モーダルコンポーネント自体には含まず別のコンポーネントとして切り出した方が再利用しやすく、組み合わせやすい、ということです。

<ModalFrame>
  <Modal>
    <ModalHead>...</ModalHead>
    <ModalBody>...</ModalBody>
  </Modal>
  <Overlay />
</ModalFrame>

上記の例でいうと、モーダルを画面の中央に配置することは<ModalFrame />が行い、<Modal />自体はモーダルに内包されるコンテンツのコンテナとしての役割だけを持ちます。<Overlay />も独立したコンポーネントの1つで、モーダル以外とも組み合わせて利用しています。

コンテナとなるコンポーネントとその子となるコンポーネントは、別コンポーネントに分離されていることで、お互いに依存しないようになります。

また、Sassファイルもこのコンポーネント構成に合わせて分けています。 ITCSSにおいて、<ModalFrame />のようなレイアウトのみの役割を持つ場合のスタイルはObjectsレイヤー(装飾を持たないUIパターンのレイヤー)となり、装飾を持つ<Modal /><Overlay />はComponentsレイヤーとして扱います。

@import “objects.modal-frame”;
@import “components.modal”;
@import “components.overlay”;

CSSはその特有のカスケードや詳細度によって決定されるスタイルがあり、依存関係を持たない状態を作ることが困難ですが、ITCSSの考えに則ってそれらのCSSの特徴に逆らわないように詳細度の低いものから順番に@importするようにしています。

Sassファイルの中身ですが、_objecst.modal-frame.scss<ModalFrame />のスタイルのみを記述するようにします。

.o-modal-frame {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: map-get($zIndexMap, modalFrame);
}

_components.modal.scssも同様に<Modal />のスタイルのみを記述します。

.c-modal {
  position: relative;
  margin: 0 auto;
  width: 900px;
  min-width: 640px;
  background-color: $JM-White;
  box-shadow: 0 1px 6px 0 rgba($JM-Black, 0.2);
  z-index: map-get($zIndexMap, modal);
}

このようにSassとReactコンポーネント毎に1対1の関係になるようにしています。 プレフィックスとして付与しているc-o-はITCSSのレイヤーのことを指します。 o-はObjectsレイヤーのプレフィックスで、c-はComponentsレイヤーのプレフィックスです。 基本的にReactのUIコンポーネント内では、コンポーネントの種別に応じてc-o-のプレフィックスを持つクラスと、状態によって付けたり外したりするStateレイヤーのs-プレフィックスのクラスのみを使用します。

話をReactに戻すと、下記のようなヘッダー要素を画面上部に固定表示するだけの役割を持つ<AppBar />コンポーネントは、props.childrenで子要素を受け取れるようになっているだけで、その内容には関知しないようになっています。

const AppBar = (props) => {
  return (
    <div className="o-app-bar">
      { props.children }
    </div>
  );
};

内包する子コンポーネントが何であれ、<AppBar />は自分自身の責任だけを果たせば良いので、開発上もシンプルに考えられます。

classNameに渡しているo-app-barはITCSSのObjectsレイヤーのクラスです。

.o-app-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: map-get($zIndexMap, appBar);
}

ヘッダー要素を画面上部に固定表示する、レイアウトのみの役割を持つコンポーネントなので、Objectsレイヤーとなり、o-app-barにはレイアウト目的のスタイルのみを持たせます。

ジョブメドレーの採用管理画面では、医療機関介護施設から求職者に向けた情報を入力していただくために多くのフォーム要素があり、非常に煩雑になりがちですが、それぞれの役割を果たすコンポーネントを組み合わせることで、UI開発上の堅牢性、柔軟性を高められるように努めました。

実際のリニューアル開発時には、全てのUIコンポーネントを実装する前に、開発側ではデザイナーが用意したSketchから、全てのUIパーツを洗い出す作業を行い、その中で分解不可能なレベルまでコンポーネントを分解していき、実装すべきコンポーネントを一覧化しました。

その後、作成したコンポーネント一覧から全UIコンポーネントをStorybookに実装していきました。

Storybookは、UIコンポーネント開発のサンドボックス環境として、ReactやVueを利用した開発では割と一般的に利用されるようになっていると思います。リニューアル時も各コンポーネントの開発環境として利用して、コンポーネントのパターンや組み合わせの確認などをStorybook上で行いました。

画面を作っていく段階では、用意したUIコンポーネントを組み合わせて利用すれば画面全体の大半のUIが出来上がるようになっていました。

細かい部分では、事前に用意するコンポーネントに不足があったり、実装した後で仕様の変更によりコンポーネント自体を削除することや、分解不可能な状態まで落とし込めてないコンポーネントが見つかったりと、様々な反省点はありました。ですがリニューアル全体を通して振り返ると、ComposableなUIコンポーネントで堅牢で柔軟性のある構成にするということに一定の成果は出せたかなと思います。

まとめ

UIリニューアル以降、採用管理画面ではリニューアル時のUIシステムを土台にして、継続的に機能を追加・改修しています。

プロダクトで設けているKPIも順調に遷移していて、顧客からの問い合わせもリニューアル以前のような、UI上の問題で利用が困難であるというものは減少し、ポジティブな結果が得られています。

開発をする上でもComposableになるようにコンポーネント群を作成したことで、リニューアル以降はUIの改修がシンプルに行えるようになり、開発メンバーのスキルセットに左右される部分が少なくなり、開発効率が上がりました

このような点からリニューアル自体は良かったと思うと同時に、一方でさらに良いUIを提供するために取り組むべきことは、少なくないと感じます。

例えば採用管理画面が十分にアクセシブルだとは言えないし、パフォーマンス面でもより一層の努力が求められます。もちろんUIコンポーネントの堅牢性もまだ十分とは言えません。

より良いプロダクトを提供するためにそういった課題に対しても継続して取り組んでいきたいと思います。

お知らせ

メドレーでは、エンジニア・デザイナーを募集しています。 メドレーでの開発にご興味ある方は、こちらをご覧ください。 www.medley.jp