エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

スマホアプリ開発で採用している技術

【マルチデバイスチーム ブログリレー1日目】

イントロダクション

こんにちは、エンジニアリンググループ・マルチデバイスチーム(以下「マルデバ」)の星野です。

エムスリーのエンジニアリンググループは、サービス開発を行う「事業チーム」と、各事業チームを横断してサポート/開発する「横断チーム」とに分かれております。私が所属するマルデバは「横断チーム」に位置し、各サービスの iOS / Android アプリ(およびそのBFF)の開発を専門に行なっており、私は主にこの後に紹介する m3.com アプリ、Web 講演会アプリ、m3.com CAREER アプリの開発を行っています。

今日から6日間「マルチデバイスチーム ブログリレー」と題し、マルデバメンバーでリレー形式でテックブログを執筆し、マルデバがどのような開発をしているのか・どんなチームなのか・どんなメンバーがいるのかなど、ご紹介できればと思います。

トップバッターである私からは、マルデバのスマホアプリ開発で採用している技術についてご紹介していきます。

エンジニアリンググループ紹介資料でも多少触れられていますが、各アプリごとにもう少し深く掘り下げてご紹介していきますので、 エムスリーでのスマホアプリ開発がどのようなものか、イメージを掴んでいただければ幸いです。

speakerdeck.com

m3.com アプリ

m3.com アプリ

昨年の3月にリファクタリングの紹介をいたしました m3.com アプリです。 マルデバでは一番の主力アプリとして、今なお新規機能の追加やリニューアルなどを注力的に開発しています。

■ m3.com アプリの採用技術一覧

[iOS]
・設計: マルチモジュール、MVVM + Flux
・UI: UIKit(宣言的UIを採用し、コードのみで実装)
・DI: Needle
・ライブラリ管理: SPM
・リアクティブプログラミング: Combine
・非同期処理: Swift Concurrency
・通信: REST

[Android]
・設計: マルチモジュール、MVVM + Flux 
・UI: JetpackCompose、XML
・DI: Dagger Hilt
・非同期処理: Kotlin Coroutines
・通信: REST、GraphQL(一部)

リファクタリングのブログと内容が被る部分も多いため、軽く紹介する程度にとどめます。設計では iOS / Android ともに「アプリ本体」「ドメイン」「インフラ」「各サービス(UI)」とモジュール分割しており、さらに iOS 側は脱 CocoaPods、脱 XcodeGen を行い SPM によるマルチモジュールへと切り替えを進めている最中です。

SPM によるマルチモジュールについては、下記のサイトが参考になるかと思います。

www.notion.so

さらに、両 OS ともに Flux による一方通行のデータフローを完全に実現したことで、コードの保守がとても楽になりました。これを実現する前は、不具合が発生した際に原因箇所を特定するためにコードを行ったりきたりするハメになり、不具合修正がとても辛かったのですが、現在は一方向に読み進めていくだけで問題箇所を特定できるようになり、原因特定とコード修正の両面で不具合修正のスピードが格段に向上しました。

また、両 OS ともに DI を行い、ビジネスロジックのユニットテストを行っています。

Android が JetpackCompose を採用しているのに対し、iOS 側は UIKit を採用していますが、「View が表示する状態を Combine でストリーム化」+「宣言的 UI でコードでレイアウトを組む」など、今後の SwiftUI へ切り替えを見据えた実装となっています。

(2023/1/20加筆) UIKit での宣言的 UI には、下記の Carbon というライブラリを利用しています。

github.com

リファクタリングの成果もあり、m3.com アプリは7年という歴史があるにも関わらず、モダンな技術で構成され、開発がラクで楽しいアプリになっています。もし古いアプリ開発に疲れてしまった方は、エムスリーにきて私たちと一緒に楽しい開発をしてみませんか!?

ToDo Plus アプリ

ToDo Plus アプリ

こちらは、m3.com サービス内の「今日やること(ToDo)」に特化したアプリです。「記事を読む」や「Web講演会を視聴する」といった ToDo の一覧を確認したり、ToDo の進捗具合を簡単に確認できるアプリとなっています。マルデバが開発しているアプリの中では一番エンタメ色が濃く、クイズやクーポンくじなどもあり、さらにクーポンくじでは Lottie によるアニメーションをおこなったり効果音を鳴らすなど、アプリの規模(小ささ)に対して、さまざまなチャレンジをしております。

■ ToDo Plus アプリの採用技術一覧

[iOS]
・設計: MVVM + Clean Architecture
・UI: UIKit(宣言的UIによるコードでの実装、一部 Xib によるレイアウト)
・DI: Needle
・ライブラリ管理: CocoaPods、SPM(一部)
・リアクティブプログラミング: ReactiveSwift
・通信: GraphQL、REST(一部)

[Android]
・設計: MVVM + Clean Architecture
・UI: XML、JetpackCompose(一部)
・DI: Dagger Hilt
・非同期処理: Kotlin Coroutines
・通信: GraphQL、REST(一部) 

[共通]
・KMM による一部ビジネスロジックのフレームワーク化

Android Layer

両 OS 共に MVVM + CleanArchitecture で設計しており、Android 側はマルチモジュールとなっています。

このアプリは機能面だけではなく、 iOS での Needle(DI) の導入・宣言的UIでのレイアウト実装、Android での Dagger Hilt の導入、KMM による iOS / Android の処理の共通化など、技術的なチャレンジも数多く取り入れました。その経験をさらに m3.com アプリや Web 講演会アプリに横展開していくなど、マルデバの中でもターニングポイントとなったアプリと言えます。

KMM については以前に荒谷(@_a_akira)さんがブログを執筆していますので、是非こちらもご参照ください。

www.m3tech.blog

Web 講演会アプリ

Web 講演会アプリ

こちらはエムスリーの主力サービスである「Web 講演会」に特化したスマホアプリです。 医療従事者向けの講演会を動画で視聴したり、気になる講演会を事前に視聴予約することで、開演直前に Push 通知でお知らせする機能などがあります。

ファーストリリースが 2020 年と、比較的新しいアプリになります。

■ Web 講演会アプリの採用技術一覧

[iOS]
・設計: MVVM + Flux
・UI: SwiftUI
・DI: Needle
・ライブラリ管理: SPM、CocoaPods(一部)
・リアクティブプログラミング: Combine
・通信: GraphQL、REST(一部)

[Android]
・設計: マルチモジュール、MVVM + Flux 
・UI: XML
・DI: Dagger Hilt
・リアクティブプログラミング: StateFlow
・通信: GraphQL、REST(一部)

まず最初に Flutter を採用するかどうかの検討を行ったのですが、当時開発していた別のアプリで Flutter の WebView で特殊な処理をしようとしてバグを踏み抜いた経験がありました。このアプリの肝である動画視聴部分も WebView であったために、Flutter の採用は見送りました。

Flutter は採用しませんでしたが、先に iOS で MVVM + Flux で UI とロジックを完全に切り離した設計・実装を行い、その後 Android 側では、ロジック部分は iOS と同じ作り・UI のみ Android 用に実装するという形で進めることで、Flutter は不採用でもスピーディに開発を進めることができました。(iOS の初期開発が 3 ヶ月ほどだったのに対し、Android は 1.5 ヶ月ほどでした)

Android Web 講演会アプリ アーキテクチャー

アーキテクチャーは m3.com アプリと同様、「アプリ本体」「ドメイン」「インフラ」「各機能(UI)」の構成となっています。Android はマルチモジュールを採用していますが、iOS 側については当時、チーム内でも他にマルチモジュールを採用したアプリがなかったため、マルチモジュールは採用せずに開発を進めました。ただし、モジュールを意識したレイヤー構成や、各レイヤー間の依存関係が一方向になる様にしているため、今後マルチモジュールに移行する際も大きな問題はなく移行できるものとなっております。

SwiftUI

UI につきましては、iOS 側で SwiftUI を採用しております。ファーストリリースでは SDK 13 を利用していたため、SwiftUI もまだ使い勝手が悪く、 原因不明のバグに悩まされたり、UIKit をラッピングして利用したりと、試行錯誤しておりました。現在は SwiftUI 自体の改善や、ターゲット OS の切り上げなどもあり、今後の開発のしやすさへの期待が高まっています。

逆に Android 側は XML でレイアウトを組んでいるため、JetpackCompose の導入を進めたいところです。

m3.com CAREER アプリ

m3.com CAREER アプリ

m3.com CAREER は医師向けの求人アプリです。常勤・非常勤・スポットアルバイトの全ての勤務形態に対応し、希望科目・エリア・その他条件を指定することで、医療機関や紹介会社からの求人を探すことができるアプリとなっています。

ファーストリリースが 2021 年 1 月とマルデバの中では一番新しいアプリとなっています。機能的に特に難しい要件もなかったため Flutter を採用しました。

状態管理には riverpod を採用し、さらに freezed を組み合わせて MVVM の設計にしました。

github.com

github.com

freezed + riverpod による ViewModel の例

上記のコード例では、

  1. メニュー画面で表示する状態を MenuState というデータで freezed で定義する
  2. その状態を扱うクラスを MenuViewModel として StateNotifer を利用して定義する
  3. Widget はこの状態を監視して、描画する

形で ViewModel と View(Widget) を実装しています。m3.com CAREER アプリでは、アプリの仕様自体がシンプルなため、Flux は導入せずに各画面を MVVM で構成するのみといったシンプルな作りにとどめています。

最後に

エムスリーでは他にもアプリ開発をしていますが、マルデバで主に開発しているのはこの 4 つのアプリになります。 上記でご紹介した通り、各アプリ毎に特性が違うため、採用している技術も多岐に渡っています。

採用している技術が多岐に渡るのは良い面も悪い面もありますが、エンジニアとしてはとてもチャレンジしがいのある現場であることは間違いありません。

We are hiring!

マルデバではまだまだやりたいことが多く、スマホアプリエンジニアを絶賛募集しております! このブログや、この後に続くマルデバメンバーからのブログを読んで、多少でも興味を持ちまたしたら、ぜひカジュアル面談などでお話ししましょう!

jobs.m3.com