増田亨さんによる「設計の考え方とやり方」勉強会 書き起こし4ページ目です。最初からお読み頂く場合は、こちらから御覧ください。
資料
書き起こしリンク
- パート1「良い設計を目指す」
- パート2「設計スタイルの選択とクラス設計のスタイル」
- パート3「テーブル設計のスタイル」
- パート4「開発のやり方と設計スキルと補足資料」(本記事)
- パート5「質疑応答」
目次
開発のやり方
開発のやり方の分かれ道
簡単に言うと、目的の固定から出発する分解思考の開発のやり方がかつての潮流でした。タスク分解して、工程分解して分業体制にして、その結果実際に作っている人間の後半の工程に全部の問題のしわ寄せが来て、プログラムを書いている者が一番苦労するみたいな。前半の工程はゆるゆるの品質管理と納期管理でやっている。我々からすると「ふざけるな」と言いたくなるようなことをやってきた(笑)。
それに対して、目標の仮決めから出発する組み立て思考の開発とやり方。とっとと作り初めてとっとと成長させましょう、そのために変更を楽で安全にしているのだから、まず一旦作って、それをどんどん変えていく。安全に楽に変えていけるんだったらそうやっていきましょう、という考え方です。
実際に動くコードでやるとやっぱり一番いいなと思うのは、事実を積み上げて認識を合わせられるんですね。いくら理屈の上ではこっちがいいとか、理屈の上ではこうすべきと言っていても、なかなか結論がでない。だけど、実際に作ってみたら答えが出るということは嫌になるほど経験してきました。要するに長々と議論するくらいだったら作ってみましょうと。A案とB案で決められないんだったら両方作ってみればいいじゃないか、そして比較したら一発ですよ。
「二重に作るんですか?」ということではなくて、単価の高い人間達がただただ会議をして時間をつぶしているくらいだったら、コードを書ける人間がA案とB案をポンと作って比較してしまったほうがコストパフォーマンスがいい、そういう話です。
あとは仮決めの目標との差異をすぐ検出できるということ。仮決めの目標というのはあくまでも絵に描いた餅なんだけど、それと実際に作った餅を見比べて、絵に描いた餅に近づけていこうという調整もできるし、作ってみたら「絵に描いた餅自体はもうちょっとこうなんじゃない?」みたいな絵のほうの調整もできるわけです。
固定のゴールがどこかにあるわけではなくて、常に新たなゴールを見つけ出しながら、ゴール設定もバージョンアップしながらソフトウェアもバージョンアップしていく、そういう感じの作り方です。
組み立て思考の開発のやり方
目標は変わります。変えるべきです。構想を長い目で見たり、理想的な姿を思い描くということはとても大切だし、そこの方向性の認識合わせというのはとても大切なことです。しかし構想は状況や将来の見通しが変われば変化する。実際に作ってみて知見が増えても変化する。目標は変わっていくんです。そういう構想、最終目標の変化を前提にソフトウェアを作っていく。そもそも変化していくという前提なんだから、変更しやすい構造が当たり前です。
それからソフトウェアを変えやすい環境を整備するということ。それはプロセスであったり、開発環境であったり、運用環境であったり。最近はいろいろクラウド系のサービスを使えるようになったので、この辺に関してはやりやすくなったなと思います。
あとはソフトウェアを変え続ける開発のやり方に習熟するということ。これもひと昔前だったらけっこう難易度が高かったと思います。しかし今は登る気になれば誰でも登れる初心者向けの山ぐらいには難易度が下がってきていると思うんで、ちゃんとそこそこの準備をして、ある程度経験者に連れていってもらえばみんなで出来るぐらいの山登りにはなったと、そんなふうに理解しています。
変化しやすい構造を作る
変化しやすい構造ということで言うと、ツリー構造、ピラミッド構造、ネットワーク構造あたりが選択肢になってくるんですけど、結局ツリー構造とかピラミッド構造というのは部分の差し替えがとてもやっかいで危険になっちゃうんですね。ある一部だけ抜き出して作り直すとか。それに対してネットワーク構造というのは、ある部分を切断してそこに別のものを繋ぎ込むとかということをやっても、全体が破綻することはないんです。
トップダウンとかボトムアップだとそのある部分、特に根幹になるような部分を引っこ抜くと、ガタガタと全てが崩れたりということになりかねないんで、基本的にはネットワーク構造を志向していくという考え方です。
とっとと作る
あとは何度も言ったように、とっとと作るということ。その上で、コードファーストで書いていくということです。動くものを書きながらも、後で確認するために、当然設定だとか仕様だとかということをドキュメント化していかなければいけませんが、それはとっとと作るというアプローチにおいては、コードを書きながらコードの中に必要な情報を埋めこんでいって、ドキュメントとして見たくなる、たとえば一覧とか要点だけみたいなものを抜き出したい場合には、ツールを使って引っこ抜いて可視化して、そういうものを別のビューで見られるようにする。
そんな感じの技術を使いこなせるようになれば、とっととコードを書いて動くソフトウェアを作りながら、ドキュメントもしっかりしている、設計レビューもしっかりしている、みたいなことを担保できますね、という考え方です。
設計スキルを身につける
私自身はこう考えている、という程度で聞いておいてください。なるほどと思う人もいるかもしれないし、なんのこっちゃと思う人もいるかもしれないんですけども。
設計スキル
設計スキルの実体は、私は経験則の脳内データベースだと思ってます。しかも単なるデータベースに入っていればいいんじゃなくて、相当高速で、瞬間的にパッとパターンマッチで見つけてくるみたいな脳内検索ができる人のことを、設計スキルがある人と言えると思います。
脳内データベースに書き込まれた時の文脈と、目の前にある課題とは似ていても文脈が微妙に違っていたりするんだけど、そこを人間がいい感じにマッチングさせながら、過去の経験則を活用していくということ。それが設計スキルの実体なんだろうなと思います。
そういう観点に立つと、設計のスキルアップの法則というのは割と単純で、まずデータベースを拡充しましょうということ。経験則を増やしましょうということです。 そして経験則を増やしながら、検索速度も上げる、脳内キャッシュとか脳内のパーティショニングをするとか、検索速度を上げる方法がいくつかあるので、そういう訓練を必ずやるということ。
あとはパターンマッチ能力。文脈差異、経験と目の前の問題の状況の微妙な違いをうまくいい感じにマッチングできるようなスキルを意識して上げていくと、かなり設計スキルは上がってきます。
設計スキルアップの行動計画
経験則を増やす方法は3点セットです。実際に作ってみること、他人の経験則を知識・言葉として学ぶこと、他人の経験則と目の前の課題と自分自身の体験した知識から新たな経験則を導き出すこと。この三つを意識的にやることによって経験則は増やせます。
知識は使わないと期限切れでキャッシュから消えていくものなので、脳内キャッシュの最適化という意味では、適時リフレッシュすることが必要です。設計について考えるということを常に途切らせないように、キャッシュから消えないようにする。
そういうリフレッシュを繰り返していると、だんだん長期の記憶として忘れないようなところに書き込まれるという、人間の脳はそんなメカニズムになっているらしいです。更に、大脳の記憶だけではなくて、小脳にキャッシュされるらしいんです。脳の中の論理判断まで待たずに、大脳ではなくて小脳にキャッシュされて、目で見た瞬間に手が動くみたいな。
冗談みたいな話なんだけど、私はリファクタリングに関しては、ある部分に関してはけっこう小脳にキャッシュされてやっているなと実感しています。コードをぱっと見ただけで、リファクタリングのキーボードショートカットを無意識に叩ている、みたいな。
脳内の経験則データベースはただ量が増えているだけじゃ駄目で、パーティショニングを調整することによって保存量も増えるし、検索もしやすくなります。そのためには整理の軸とか、知識全体の枠組のバリエーションを絵にしてみたりとか、体系だった説明をされている書籍を読むことが必要です。どういう構造、目次立てになっているか、どういう関連付けになっているかを鑑賞するというか眺めるだけでも、自分の脳内に経験則データベースの構造、パーティショニングが変わります。そうすると参照経路が変わるんで、検索スピードが上がってくるみたいな感覚があるんですよね。
経験則と目の前の課題のマッチング精度を上げることに関しては、微妙なパターン「アンマッチ」があります。自分の持っている経験則と目の前の新しい課題というのは何かちょっと違和感があるので、その「何か違うな」ということを感じ取るということ。そして「ちょっとパターンを変形してみたらどんな結果になるかな?」ということをいろいろトライアルしてみながら、マッチ度を学習していく。これらをやることによって、目的とか状況とか、「今回はこういうことを重視した方がいいのかな?」と判断基準が微妙に違う文脈でも、マッチング能力が上がっていくみたいな感じです。
まとめ
ではまとめです。
良い設計は悪い設計より変更が楽で安全であるということ。
ソフトウェアの変更が楽で安全であれば、事業活動のスピードを上げられ、コストを下げられます。
そして開発者の学びと成長をソフトウェアに活かせる、あるいはその成長の機会自体を増やせます。もっともっと費用対効果の高い技術に移行していくことができる。そういうプラスの面があります。
補足資料
ここからは、資料にはこんなことが書いてありますよ、ということだけ紹介させてください。
実際に図書館の蔵書貸出アプリケーションというのはGitHubで公開していて、そこでどういうふうに、自己文書化とJIGというツールを使って設計内容を可視化するというような具体例を見られるようになっています。 こういう設計ドキュメントを、手作業で作るんじゃなくて、ソースコードから自動生成できます。興味のある人は経験してみていただきたいです。
これもそうです。ソースコードからドキュメント形式で、意図としてはどちらかというと技術者ではない人たちにビジネスルールがどういうふうに記述されているかというもの。これもソースコードから可視化してありますから、ソースコードの構造であり、関連付けの通りになっています。 こういう絵でチェックしてもらえれば、ソースコードの構造のほうにもすぐ反映できます。
これはあちこちで使った資料でもあるんですけど、「ビジネスで使うクラスの基本パターンってこんな感じだよね」「メソッドってこんな感じだよね」というようなものです。
次は、クラス設計の実装パターンみたいな話です。私がクラス設計をする時に参考にしている設計のひな形みたいなものです。
もうちょっと複雑になった時の組み立て方のパターンとか、あるいはコレクションを使った、ビジネスによく出てくるような、割と役に立つようなコレクション操作です。
これは、事業活動を大局的に理解してアプリケーションを開発していくための、モデル駆動設計のアプローチです。
事業活動を理解するといってもいろいろな切り口があるんですけれども、時系列で業務イベントとして、連鎖としてとらえるみたいなとらえ方についてです。
業務イベントが見つかればそこに必ず業務上の決め事、ビジネスルールがあるので、そこからビジネスルールを表現するコアドメインのクラスを作っていきます。
「業務の関心事を表現するクラスってこんなのもありますよね」というものです。出発点としてパッとこういうようなクラス名が使えると楽というか、こういうのを出発点として流用して、そのあとの改善活動に早く進む。参考にしてください。
事業活動とテーブル設計、さっき言った業務イベントのモデリングは当然イミュータブルで事実を記録するというテーブル設計のインプットに直接なりますから、そういう事業活動のイベントの連鎖としてモデリングするというのは役に立ちます。
複雑さの主因の第一は金額・数量・日付の計算判断で、それはカプセル化しましょうということ。値オブジェクトで語彙を作っていきましょうねということと、もう一つの大きな複雑さの主因は当然条件分岐なので、分岐する条件の特定と整理、そのためにどういうクラスをどういうふうにするかということです。 実際問題としては単純な条件分岐で済むのではなくて、条件分岐の組み合わせが複雑さの原因になるので、そういうものをどうやって整理していくか、そのへんが主戦場になります。
これは私もパターンとしてはいっぱい自分で経験則を持っていますけど、やっぱりアプリケーションを作る度に、常に新しいことに迷ったり、チャレンジしたりしながら設計しているというのが、今の私の日常です。
それでは私の話はここまでにしたいと思います。どうもありがとうございました。
パート4は以上です。パート5の 「質疑応答」は2022/08/26に公開予定です。
asken では、サーバーサイドエンジニアを大募集しています!