- ソフトウェアには不確実なことが多い。
- なぜ不確実なのか?
- 最大の理由は、ビジネスの複雑性が存在するため
- 複雑性によって状況は継続的に変化し、その結果、開発者の予測は高い確率で外れる。
- 丹念に積み上げた塔が崩れ、そのまま技術的負債へと変わる。
- 小さな理由としては、知識と経験の不足がある
- 知識と経験がなければ、開発者自身が生み出した技術的負債を作ってしまうことがある
- ビジネスの複雑性は開発者が制御できない外部要因である一方、知識と経験は開発者が制御できる内部要因
- 開発者には3つの道がある
- 複雑性に対抗するのは無意味だと考える悲観主義的な道
- 「どうせ変更されるのだから、とりあえずやろう」「技術は無意味だ」といった言葉を口にするようになる
- 楽で快適な道なので、気づかないうちにこの道を選んでしまうことがある
- 複雑性から目を背け、理想的な空想だけを考える道
- 自分が理想だと思う1つの技術で、すべてを解決できると信じる
- 硬直的で画一的な思考を持つようになる
- 開発者が陥りやすい道だが、抜け出すのは難しい
- 複雑性を受け入れ、それに立ち向かって戦う道
- 完璧にはなれないことを受け入れても、なおより良い道を探し続けようとすること
- 困難で耐え抜かなければならない道
- ソフトウェア開発は、これまでも複雑性と戦い続けてきた
- アーキテクチャ、方法論、アジャイルなど…
- 次には何が登場するのだろうか?
- 破壊指向開発
- 現実を見ると、どうせ消されるのだという悲観的な考えに陥りやすい。
- 私たちが一生懸命書いたコードが失敗作だと感じ、自ら消すのはとても苦痛だからだ
- いっそ 逆に考えて、むしろうまく消せるように作る のはどうだろうか?
- 破壊は良いことなのか?
- 破壊がなければ、新しいものは生まれない
- ソフトウェアで見られる破壊は、大きく2つある - ピボットとリファクタリング
- ピボットは、組織と製品がより良い道を選べるようにしてくれる
- リファクタリングは、ソフトウェアの寿命をさらに延ばすために不可欠な作業
- では、破壊指向開発とは?
- いつかコードが破壊されるという事実を受け入れ、それを志向して開発する方法論
- 3つの大原則を志向する
- 不確実性があるなら、可能な限り不確実性を減らす。
- 複数の方法を選べるなら、破壊しやすい方を選ぶ。
- 必要なものだけを維持する。したがって、不要なものはすべて消す。
- 分析 -> 境界の分離 -> コード実装 -> 複雑性の除去
- 内部要因による不確実性を減らし、避けられない外部要因による破壊に備えることが核心
- 境界の分離
- 不確実性は変化率であり、これを基準に分離することが可能
- 開発者は外部要因に備えつつ、可能な限り内部要因による変化率を下げなければならない
- 各要因の変化率は組織ごとに異なりうるため、固定的な数値で表現することは不可能 -> ヒューリスティックな方法で測定する
- 何を基準に分離するのか、抽象化レベルを決めなければならない
- 破壊可能性
- 実装するときは、大原則に従って破壊しやすい方を選ぶ
- 独立性、認知可能性、制御可能性を考慮して、破壊可能性を判断できる
- 独立性は、結合度と凝集度の程度、単一責任原則をどの程度守っているかで判断する
- 認知可能性は、開発者がコードを見て理解できる程度
- 制御可能性は、開発者が制御できる領域かどうかを判断すること
- 複雑性の除去
- 不要なものがあるか確認して取り除かなければならない。つまり、最終的にコードベースには必要なものだけを残すべき
- 締め切りなどの問題で作業が難しいなら、記録だけ残して後で作業しても問題はない
- 破壊に備えて、可能な限り単純性を維持することが核心
- コード破壊の技術
- コードをうまく消すためのさまざまな原則と方法がある
- 段階を分ける(リファクタリングパターン)
- 参照透過性を守る
- 単一責任原則を守る
- インターフェース分離原則を守る
- ストラングラーフィグパターン
- メソッドの特化
- 重複コードを書く
- 変化率の記録
6件のコメント
知識や経験が不足しているからコード負債を生む、という話にはあまり共感できませんね。
-> 要求事項の実装に与えられた時間が足りないこともあるでしょうし、協業する場合には他人との調和のために多少の技術的負債を受け入れることもあり、状況はさまざまだと思います。
知識や経験を開発者が統制できる内部要因と見ることにも、いまひとつ納得がいきません。
-> ビジネスは複雑で、どんな状況が訪れるか予測できないので、あらゆるケースをその都度学べるわけではないですよね。その状況に直面して学んだとしても、次にはまったく新しい問題が発生して、その知識が役に立たなくなることもありますし。
こんにちは。ご意見をお寄せいただきありがとうございます。
私は、極端な状況を見つめたときにこそ本質が見えると考えています。そういう観点から見ると、もし「知識と経験」を完全に備えていたなら、時間内に負債ではないコードを生み出せるはずだと考えました。
時間が足りないというのは、2つに分けられます。1つ目は、文字どおり実装に必要な時間が不足している場合です。この場合は、知識や経験とは別に、コードを書くための物理的な時間が足りなくなります。したがって、そもそも目標達成が不可能な条件です。2つ目は、何が良いのかを見極める時間が足りない場合です。この場合は、実装方法を調べたり、より良い選択肢を探したりする時間が不足しているため、いま持っている知識だけでコードを書いて仕事を終えます。こうして仕事を完了すると、「どこかおかしい」ということは分かっていても、正確にどう直せばよいのかは分かりません。もし正確な知識があり、それに対する経験によって自信を得ていたなら、このような問題は起きないはずです。
上に書いた時間不足の話は、私の意見を裏づけていると思います。もちろん、現実的には非常に難しい問題です。私はただ理想的なことを述べただけです。知識と経験を完璧に備えた状態はまれですし、おっしゃるように、組織のためにあえて受け入れる場合も確かにあります。不条理さを感じることはあるかもしれませんが、私はこの問題を「極端に見るなら」、知識と経験が不足していたために生じた問題だと考えました。
2つ目におっしゃっていた内部要因については、話は簡単です。「ビジネスは複雑で、どんな状況が起こるか予測できないのに……」という部分は、私が書いた文章でいう「ビジネスの複雑性」の話です。つまり、外部要因による問題です。外部要因だからこそ、開発者は制御できず、恐れを感じるのです。これもまた極端に考えて、ビジネスの複雑性がないと仮定するなら、開発者が書いたコードだけが残ります。そうであれば、内部的に制御できる「知識と経験」の問題だけが残ります。
もちろん、私が書いた文章もまた、あくまで私の意見にすぎません。十分に反例はあり得ます。意見を交わすことは、より良い道へ進むための機会だと思います。これからも多くのご意見をお寄せください。ありがとうございます。
ご丁寧にお返事いただき、ありがとうございます。
興味深く読みました。組織のステージによって、何が早すぎる最適化で何がオーバーエンジニアリングなのかも変わってくるように思います。どうせ書き直すことになるコードでもありつつ、実際に書き直す瞬間が来るのか来ないのかも分からないコードだというのが難しいところですね。私は
xxxサービスで機能がなくなるとしたら、yyyのコードやデータはどこに置くのが適切か? という問いで判断することもあるのですが、ほかの方々のやり方も気になります。コードだけでなく、データやスキーマも消えたり変更されたりしうるかを考えるようにしています
データに関する内容も入れたかったのですが、なかなかうまく思い浮かばなかったんですよね。クリティカルな部分なので簡単には手を入れにくく、下手をするとマイグレーション地獄に陥る可能性もあって慎重になりました。
おっしゃる通り、最初の設計段階が非常に重要な気がしますが、RAWをできるだけうまく蓄積できるようにするのが鍵になりそうです。あるいは、イベントソーシングアーキテクチャは削除という観点では有利かもしれませんね。もちろん、そのアーキテクチャをきちんと使ったことがないので、本当に有効かどうかはよく分かりません。