『具体と抽象』で学んでも、抽象化を実務で忘れてしまう|設計の失敗から考える

恥ずかしいけど、『具体と抽象』(細谷 功 著)を読む前は、「抽象化」をよく分かっていませんでした。

オブジェクト指向を勉強していると、抽象化という言葉はよく出てきます。当時の理解は、「似たものから共通部分を抜き出してまとめる」くらい。共通クラスやインターフェースを作って、重複した処理をまとめることだと思っていました。

この理解のまま、私は「何でも管理できるテーブル」を作って失敗しました。『具体と抽象』を読んで、抽象化は共通化だけではないと知り、ほかの設計で困った経験も振り返るようになりました。今は、目的や責務を考えたら、具体的な仕様や動作に戻って確かめたいと思っています。

抽象だけでも駄目。具体だけでも駄目。この往復を忘れないための、自分への備忘録です。

失敗談1:使われない備考欄を先回りして作った

後から何にでも使えるように、500文字まで入るような文字列型の備考1、備考2を用意しました。文字項目1から文字項目10まで並べて、何でも設定できるようにしたこともあります。とりあえず文字列で保存できれば、後から何にでも使える。柔軟な設計のつもりでした。

でも、後から必要になったのは数値の管理。用意していたのは文字列型の項目です。数字を文字列として入れられても、数値として扱いたい要求とは型が合いません。何でも入るつもりで作ったのに、必要になったデータに合わなかった。使わないままの項目も残りました。

何を管理したいのか分かってから、必要な項目を足す。その方が自分には合っていました。まだ用途も分からないものを何でも受け止めようとしても、うまく抽象化できたわけじゃありませんでした。

本から受け取った「抽象化」の意味

著者は公式サイトで、本書の思考の根本を「具体と抽象の往復」と説明しています。目次にも「往復運動」の章があります。読んで残ったのは、抽象化して終わりじゃない、ということです。具体例から共通する特徴や仕組みをつかんだら、もう一度具体に戻して、別の事例や実際の設計に当てはまるか確かめる。そこまでで一往復。

私は記憶力に自信がなく、仕様を全部覚えようとすると、時間が経つにつれて曖昧になります。そこで、「なぜこの仕様なのか」「何が共通していて、どこが違うのか」と構造を考えるようにしています。細部を忘れても、仕組みを手がかりに考え直せるからです。

話が噛み合わない時は、見ている段が違う

この考え方は、システム開発の会話にもかなり当てはまります。

利用者と話していると、

  • 「この画面のこの項目をこうしたい」
  • 「このファイルにこの項目を追加したい」

といった、かなり具体的な話になることがあります。一方、開発側としては、

  • 「そもそもどんな運用をしたいのか」
  • 「誰がこのデータを使うのか」
  • 「何を実現したいのか」

と、もう一段上の話を聞きたい。どちらも真面目に話しているのに、噛み合わない。今振り返ると、見ている抽象度が違っていたのだと思います。

これは開発者同士でも起こります。ある画面で不具合が起きたとき、

  • 「とりあえずこの画面を直そう」という人
  • 「関連する処理にも同じ問題がないか」「そもそもの原因は何か」「データ設計に問題はないか」まで確認しようとする人

緊急なら、まず目の前の画面を直すこともあります。どちらがいつも正しい、とは言えません。ただ、

「今、自分たちはどのレベルの話をしているのか」

が分からないままだと、話が噛み合わなくなります。

施策の一段上にある目的を見る

「この業務を改善したい」の一段上には、「チームの生産性を上げたい」があり、さらに上には「ユーザーに価値を届けたい」という目的があるかもしれません。具体策だけを見ると、その施策自体が目的になってしまうことがある。

一度上がって「本当は何のためにこれをやっているのか」を考えると、別の選択肢が見えることがあると思う。

失敗談2:人が作った処理を、ステップ実行で追うしかなかった

人が作った処理を読み解く時にも、抽象化の難しさを感じました。

保存処理や帳票作成、画面の初回読み込みでも、共通化に手を焼いた記憶があります。コードの細かいところまでは思い出せませんが、前処理・本処理・後処理という共通の流れに合わせると、その場では要らない処理まで付いてきました。

ちょっとしたいだけなのに、100やらないといけないような感覚。

どのファイルが何の処理をしているのか分からない。どこをいじれば、どこが直るのか、何が変わるのかも直感的につかめない。

「この処理は一体どこで決まっているんだ?」

という状態になりました。素直にできないからすごいイライラする。

何をしたら、具体的に何がどうなるのかが見えない。ドキュメント類もなくて、仕組みをつかむ手がかりも少なかったと思います。

結局、デバッガーでステップ実行して、どこを通って何が起きるのかを追うしかありませんでした。高度に抽象化された仕組みと、実際のファイルや動作が自分の中で結び付かない。読み解くだけで時間がかかりました。

この経験から、自分で設計する時は、

  • 似ているという理由だけで共通化しない
  • 現在の処理が同じでも、変更理由が違うなら分ける
  • 共通化する前に、本当に同じ業務概念なのか考える

といったことを意識しています。共通化した後も、やりたい処理を素直に書けるか、要らない手順まで付いてこないかを確かめたいです。読む人が「ここを変えると、この動作が変わる」と追えるかも、忘れたくないです。

失敗談3:逆に「具体」に寄りすぎて起きた問題

反対の失敗もあります。

以前、メール通知をアプリケーションの処理の中からそのまま呼び出していました。やることは分かりやすい。処理が終わったらメールを送る。

悩んだのは、保存はうまくいったのにメール送信が失敗した時、どうリカバリーするかです。保存のトランザクションとメール送信の制御まで考えると、「保存してから送る」だけでは済みませんでした。

今考えると、「メールを送る」という具体的な処理だけを見ていたのだと思います。一段上から、

「この通知は、本処理から分けられるんじゃないか」

と考えると、キューに登録して別サービスやバッチから非同期で処理する、という選択肢も見えてきます。

次の実装では、この非同期化を進めています。通知をキューに登録して、後からバッチ的に送る。保存側はメールの送信完了を待たずに終えて、送信に失敗した時は通知側でやり直せるようにする。メールはメールの責務にする。保存処理もサクサク終わらせたい。ただ、今は実装中なので、そこはこれから確かめます。

テストでも、何をこの処理に任せて、どこを切り離すかで困りました。処理を愚直につないで書いてしまうと、外部データやDBに依存して、単体テストが難しくなる。実行も遅いし、データによって結果も変わる。

当時はインターフェースやスタブを使って依存を切り離すという考え方が弱かった。これも、目の前の具体的な実装だけを見るのではなく、

  • 「この処理の責務は何か」
  • 「どこまでを一つとして扱うのか」

という一段上の視点が必要だったのだと思います。

設計でも、抽象と具体を行き来する

その後、DDD(ドメイン駆動設計)やオブジェクト指向を学び直し、この考えはさらに強くなりました。

以前は、「何を一つの集約として扱うか」など考えたこともありませんでした。

  • Entityとは何か
  • Value Objectとは何か
  • どこまでを同じコンテキストとして扱うのか
  • どこで整合性を守るのか
  • どこまでを同じトランザクションにするのか

こういうことを考え始めると、クラスをどう作るかだけでは足りません。業務として、

「何が一つのものなのか」

「何を同時に守らなければならないのか」

まで考えることになります。コードを書く前にモデリングする意味も、前より分かってきました。

読書や設計では、いまいる場所を観測地点にする

「一段上を見る」と言うだけだと、何を見ているのかがぼんやりします。そこで、いま読んでいる主張や、目の前の設計で気になったところを観測地点に置いて、左に上位の抽象、右に下位の具体を並べて考えます。

左へ動くと、目的や共通する仕組みが見えてくる。右へ動くと、その見方が個別の事例やコードに当てはまるか、次に何をすればよいかを確かめられます。これは本に載っていた図ではなく、私が読書や設計で具体と抽象を行き来するための見取り図です。上位・下位は固定の段ではなく、どこを観測地点にするかで変わります。

左に上位・抽象、中央に今いる位置としての観測地点、右に下位・具体を置き、両側へ行き来する考え方
本書の図解ではなく、私が読書や設計で使うために描いた見取り図です。

毎回この見方ができているわけではありません。それでも、観測地点を決めて左右を行き来すると、抽象的な話を自分の問題に戻しやすくなります。

上位の話を、作業の具体に結び付ける

仕事をしていると、役職が上の人ほど抽象的な話をすることが多いように感じます。その話を具体的な作業まで降ろして、「この作業は全体のどこにつながるのか」をつかむのが速い人もいます。目の前の依頼が何につながっているのかを考えるのも、具体と抽象の往復なんだと思います。

AIにコードを任せても、解く問題は自分で考える

以前はプログラミング言語そのものを学ぶ時間が多くありました。今も必要ですが、コードを書く作業はAIが手伝ってくれる場面が増えました。その分、設計や運用、利用者にどう価値を届けるかを考える時間も増えたと感じています。

具体化にはAIを使えても、「そもそも何を解決したいのか」を決めるのは自分です。まず一段上から問題を捉え、必要な具体へ戻ることを忘れないようにしたいです。

まとめ:一段上がって、目の前に戻る

『具体と抽象』を読んでも、急に抽象化が身についたわけじゃありません。何でも入るつもりのテーブルが数値の要求に合わなかったことも、人が作った処理をステップ実行で追うしかなかったことも、今も覚えています。

迷った時は、まず何を観測地点にしているのかを確かめる。左へ一段上がって目的や共通する仕組みを見て、右へ戻り、目の前の仕様やコードに合うか確かめる。上がりっぱなしでも、目の前だけを見ても足りません。

まだ毎回この往復ができるわけじゃありません。だから、仕事でも読書でも忘れないようにしたいです。

確認した情報

コメント

タイトルとURLをコピーしました