🏢

iOSアプリできちんと設計をするようになったら変わったこと

2021/12/11に公開

この記事はエンジニアと人生コミュニティのアドベントカレンダー#2 の11日目の記事です。

10日目は @ta_ka_tsu さんの ひたすら鉄を作っている人生。でした。

週末鉄塊を作ってらっしゃるのは知っていたのですが、動機が

さてさて、唐突ですが私は鉄を作りたいのです。
そしてその鉄で何かを作ってみたいのです。
たった一振りのナイフでもいい。
何かモノを作り上げてみたいのです。

「ゼロから。」

というのはあまりにかっこよすぎませんかね。

応援しています!🎉


1. はじめに

私の所属する会社のアプリチームでは、可能な限り新機能を実装したり、既存機能を改善したりする際はクラス図等を利用して設計[1]を実装前に行い、設計の概要をチーム内レビューにかけて承認が取れたら実装をするようにしています。


Figure1: チーム内レビューに出す設計のサンプル

設計を実装前にチームメンバーがレビューすることによって、実装してから実装方針に問題があったり、もっといい実装方針が判明した場合に実装にかけてしまった工数が無駄になってしまう確率を下げることができます。

またこのレビューにはプラットフォームの別け隔てなくレビューするようにしており、私が書いたiOSの設計をAndroidエンジニアがレビューすることもありますし、Androidの設計をiOSエンジニアがレビューすることもします。

直近2年ほどクラス図を作成してから実装に入るようにしており、経験がある程度まとまってきたので、良いと思っている点をまとめようと思います。

また私が経験してきたプロダクトでは雰囲気設計書のようなものだけがあるものが多く、きちんと設計をまとめてから実装するプロダクトは初めてだったため、設計にきちんと時間を書けるべきか悩んでいるエンジニアの方にも参考になる情報があるのではないかと思います。

2. 設計できるようになるまで

2.1 大変だったこと

前述したように、そもそも私は設計があるプロダクトに参加するのが初めてだったため、実装前に設計をまとめるという開発スタイルに慣れるのがとても大変でした。

なぜなら、ある程度のアプリであれば概ねどのように実装すればよいか頭の中にイメージできたため、単にアプリを作って動かすことのみを目的とすると僕にとってはあまりメリットがない作業だったためです。

2.2 設計がないと困っていた点

その一方で下記のような悩みを抱えていました。

  • 近視眼的に得られる情報をもとに実装プランを決めた上で、レビュー前に実装に着手してしまうため、実装を進めてから情報が足りなかったりするケースがある。
    • この問題が発生すると、場合によりますがアプリデータの取り回し方法を根本的に変えないといけない場合もあり、手戻りが大きくなりがち
  • 暫定的な仕様をもとに実装をする場合、実装が進んでいったあとに仕様が一部変わってしまうケースが有る。この場合に何をどこまで変更すればいいかがすぐにわからない。
  • 時間が立つと自分がどういう実装をイメージしていたかがわからなくなる場合がある
  • PRの単位が機能全体になるしかないので、レビュワーが機能全体をレビューする必要がある。結構大変。
    • レビューも大変だし、指摘内容によっては書き換える量が結構多かったりするケースも有り、レビュイー・レビュワーお互いにとってデメリットがでかい

2.3 設計をするようになって

入社してからしばらくの間は設計をまとめずに実装に着手することが多かったのですが、ちょっとづつ設計を行うようにしたところ、上記の悩みが解消する事がわかりました。
具体的には下記のように解消されました。

  • 近視眼的に得られる情報をもとに実装プランを決めた上で、レビュー前に実装に着手してしまうため、実装を進めてから情報が足りなかったりするケースがある。
    • この問題が発生すると、場合によりますがアプリデータの取り回し方法を根本的に変えないといけない場合もあり、手戻りが大きくなりがち

→ クラス図に設計を起こす際に、実際にコードに落とし込めるか、情報に過不足はないかなどをすべて検討するため、後から情報が足りなかったりするケースが激減しました。

  • 暫定的な仕様をもとに実装をする場合、実装が進んでいったあとに仕様が一部変わってしまうケースが有る。この場合に何をどこまで変更すればいいかがすぐにわからない。

→ アーキテクチャに則って設計している場合各クラス・構造体の責務は明確になっているため、仕様の変更内容を設計に当てはめて、どこを変更すればよいかを一発でイメージできるようになった。

  • 時間が立つと自分がどういう実装をイメージしていたかがわからなくなる場合がある

→ 設計図を見直せばOK。シンプル。

  • PRの単位が機能全体になるしかないので、レビュワーが機能全体をレビューする必要がある。結構大変。
  • レビューも大変だし、指摘内容によっては書き換える量が結構多かったりするケースも有り、レビュイー・レビュワーお互いにとってデメリットがでかい

→ 予め設計図を共有して、完成形についてレビュイーレビュワーの両方が合意できているため、PRの粒度を個別のクラス単位にまで落とすことができた。
このため、手戻りの量を最小限にすることができた。

また当初思っていなかった副次的な作用として、修正の全体像が着手前に見えているので進捗どうですか?が怖くなくなりました

設計をするだけで上記のようなメリットを享受できるのであれば、ぜひ設計したほうがいいです。

3. 設計するようになって

3.1 意識の部分・コードの改善点

ものすごい当たり前なんですが、「その処理はどこにあるのが正しいですか?」という設計の基本を意識するようになりました。

私の開発しているプロダクトではClean Architectureを採用しており、大まかに下記の分類になっています。

View -> Presenter -> UseCase -> Repository -> DataStore

設計するに当たり、どの処理をどのクラス・構造体に担当させるかを決める必要があるため、全体を俯瞰してどの情報がどこにあるか、どの処理はどこでする必要があるかを考えるようになりました。

たとえば、ViewControllerはViewに関わることをするべきであって、APIの実際のアクセスのような自分の責務に関係ないことをするべきではないですし、UseCaseがViewを操作するのもおかしいですよね。

このように処理を書く前にその処理はここにあるべきか?を意識するようになった結果各レイヤに記述されるコードが責務の範囲のもののみになり、コードが自然と疎結合になりました。

またこれは意図していなかった良い影響ですが、より良い設計を作りたい! と思うようになった結果、ドメインモデルやSOLID原則、他のアーキテクチャパターンだったりと今まで興味がなかったジャンルにも自然と興味が出るようになり勉強するようになり、視野が広がったと考えています。

3.2 実際にクラス図に何を書いているの?

僕の所属しているチームではクラス図を利用して設計をレビューしています。

クラス図には下記2つがわかるようにしています。

  • イベント伝播の肝となる関数・振る舞いの肝となる関数
  • データモデルの各プロパティ

Figure1を例に出すと、

  1. LoginDataModel構造体にはusernameとpasswordのプロパティがletで宣言されているんだな
  2. LoginUseCaseProtocolは、LoginDataModelを受け取ってログイン処理をする振る舞いを定義しているんだな
  3. LoginUseCaseがLoginUseProtocolに適合しているんだな

という点がわかるようにしています。

このときLoginUseCaseに実際に記載されるコードの詳細はわかりませんが、実際に書かれたコードが良いか悪いかを確認するのは実際のコードがないとわからないため、PRの方で確認したほうが良いと考えています。

上記がわかれば処理の内容と処理の粒度、及びモデルの区分などがわかるため設計のレビューを行うことができるようになると考えています。

4. レビューについて

4.1 レビューの流れ

下記流れでレビューしています。

  1. 新機能の要求仕様や画面仕様をGitHub Issueに登録する
  2. 担当者がIssueの情報をもとに設計
  3. クラス図をIssueに添付し、チームメンバがレビュー
  4. 問題なければAprooveされて実装する

僕がレビューするときには下記点を意識するようにしています。

  • iOS的に実現しにくいところはない?
  • 情報の粒度・分割の区切りは正しい?
  • View, Presenter, UseCase, Repository, DataStoreが持っている情報および実装している処理のうち、それぞれの責務を超えた処理があったりしない?

4.2 レビューをするようになってよかったこと

レビュイーレビュワーの両方の共通言語で指摘できるようになりました

「こっちの書き方のほうがいいです!」という抽象的な言い方ではなく、「その処理は責務的にPresenterにあるべきではないので、UseCaseとして切り出したほうがいいです」だったり、「その処理はドメインとして別ドメインであるべきなので、別のRepositoryを作ってそこに書きましょう!」という感じで、レビュイーレビュワーの共通言語で指摘・返答できるようになった事が良い点でした。

また実装前に設計方針についてフィードバックが得られるようになったのも良い点でした。

自分が開発しているアプリは比較的大規模なアプリで自分の知っている知識量には限界がるため、パラメータを見落としてしまうケースや、この処理をしたほうが早かったりと、自分で設計したと思っていても足りていない物があったりするケースが有りました。

自分以外の第三者が設計をレビューできることにより、上記のような改善点をより早い段階で気がつく事ができるようになったのも良い点でした。

5. 終わりに

簡単にではありますが、設計するまで辛かったことから設計大好きになるまで、設計して良いと思っていることをまとめてみました。

自分自身が設計をそこまで精力的にやっていなかったマンなのですが、前述のメリットを体感してからは、基本的に設計をしてから実装着手するようにしています。

これを設計あまりやってなかった頃の僕が読んでも設計をするようにはならない・・・と思ってはいるのですが、設計についてあまりやってない人であれば試しにやってみていただければ、とても嬉しく思います。


エンジニアと人生 #2 Advent Calendar 2021 明日12日はYoshitakaさんです。お楽しみに!

脚注
  1. ここで言う設計とは「そのとおりに実装すればもう何も考えず動くようになる」レベルの、実現可能性などをすべて考慮した設計です ↩︎

Discussion