自己紹介
職種:Androidエンジニア(最近は個人開発でiOSにも取り組み中)
年齢:23歳
学歴:高卒
資格:
- 基本情報技術者試験
- 応用情報技術者試験
- 情報処理安全確保支援士
- Google Cloud Digital Leader
- Google Cloud Associate Cloud Engineer
- Google Cloud Professional Security Engineer
- TOEIC LR 795
趣味:
- チェス
- ウィスキー(特にアイラ系好き)
- 個人アプリ開発
- 競技プログラミング(最近はLinked List勉強中)
本記事について
本記事は、若手エンジニア向けの設計シリーズの第1回目となります。
シリーズの予定は以下の通りです:
-
第1回:設計の基礎概念(本記事)
- 抽象的思考と具体的思考
- 目的と手段の分離
- 抽象化クラスの役割
-
第2回:具体的な設計例や共通化パターン
- コード例を用いた解説
- よくある設計や関数の共通化の失敗とその解決策
執筆をしようと考えた背景
まず、現時点でも設計で迷う時は数多くあります。
ただ、自身がエンジニアとして就職した当時を振り返ると"設計"に関してはそもそも概念を掴めなかったり、参考書やサイトを見ても理解が進みませんでした。
他の若手エンジニアの方も同様に苦しんでいる人がいるのでは?と思い、役立てればと思い執筆にいたりました。
これから執筆する内容は、あくまで個人の意見であり決して正解を意味したり、またそれを押し付けるようなことが目的ではありません。
対象としている読み手
- 若手エンジニア
- 設計が分からないエンジニア("チョットデキル"人は読む必要ありません!)
本質的に必要な思考能力
私が考えるに、クラス設計や関数の共通化をする上で理解しておきたい本質的な思考力がいくつかあります。
抽象的思考と具体的思考の操作
これが最も要求される思考であり、最も難しい思考であると考えてます。
あらゆる事象が、因果関係(原因と結果)から成り立つように"物"も全て具体と抽象で考えることが出来ます。
また、抽象化というものは縦方向と横方向に分けることが出来ます。
横方向
"りんご"・"ぶどう"・"れもん"を例として考えます。
これら3つは下記のように抽象化出来ると思いませんか?
- 食べられるもの
- 皮を剥けるもの
- 色味をもつもの
このように各物が持つ特性を並べたものは横方向の抽象化になりやすいです。
Appleが提唱している"プロトコルプログラミング"に近いですかね?
縦方向
また、物は縦方向に具体化及び抽象化することが可能です。
「スマートフォン」を例にして考えてみましょう。
スマートフォン
⇩
携帯電子機器
⇩
電子機器
⇩
機器
⇩
物(オブジェクト)
抽象化及び具体化は難しい
このように抽象化と具体化の操作は相当なバリエーションがあります。
クラス設計などを考える上では、この様々なバリエーションの中からどのように抽象化すればいいか?を見抜くことが一番大切なスキルです。
これを見誤ると悲惨なことになりやすいです。
- 過度に抽象的→抽象化の利点が無い
- 過度に具体的→抽象化クラスの使い回しが出来ない
そして、恐ろしいことに設計の正解/不正解は時と場合で無慈悲に変わります。
今まではこの抽象化で良かったのに急に新たな仕様のみ微妙に異なり抽象化が適用できないとか既存の仕様変更がガラッと入ったりとか...。
そのため、自身が作っているプロダクトの展開予測(ビジネス的視点)やSIerであれば顧客の特性(仕様変更依頼を頻繁に出すなど)の判断が必須になっているのです。こればっかりはAIも苦手だと思います...。
ではどのようにして抽象化する方向を決めるべきなのか?それが次の項目に絡みます。
目的と手段の分離
社会人になると度々指摘される内容です。
これが前項目の考え方を支える補助役としての思考の種類です。
そもそも、わざわざ設計において抽象化クラスを使い、抽象化及び具体化を行う目的はなんでしょうか。
本質は3つあると考えてます。
-
コードの共通化ができる
- 同じ振る舞いを抽象化クラスに閉じ込めることができる
- 例えば、for文で同じ抽象化クラスを持つ各インスタンスに同じ処理を適用できる
- これにより、コードの重複を減らし、保守性を高めることができる
-
ドメイン知識(業務知識のこと)が浅くても実装ミスを防ぐことができる
- 新しい機能を追加する際に、抽象化クラスが「ここに実装が必要」と教えてくれる
- これにより、実装時に必要な要素が明確になり、ミスを防ぐことができる
- 例えば、新しい種類の果物を追加する際に、「色」や「皮を剥く方法」などの必要な情報の実装が強制される
-
テストのしやすさ(テスタビリティの向上)
⚠️テストの話を持ち込むと長引いたり難しくなるので今回は簡単に紹介- 抽象化クラスを作っておくことでモックの挿入がやりやすい
- DI(依存性注入)の導入に役立つ
まとめ
設計において抽象化と具体化を考える際は、以下の点を意識することが重要です:
-
抽象的思考と具体的思考の操作
- 横方向と縦方向の抽象化を理解する
- 適切な抽象化の度合いを見極める
- ビジネス的な視点も考慮する
-
目的と手段の分離
- コードの共通化による保守性の向上
- 実装ミスの防止
- テストのしやすさの確保
設計は難しいですが、これらの基本的な考え方を理解しておくことで、より良い設計ができるようになると思います。
次回は、これらの考え方を踏まえた具体的な設計パターンについて解説する予定です。お楽しみに!