プログラムの設計の過ちにいつ気付くのか

他の人から指摘を受けないと筋の悪いコードを書いていることに気づけなかったり、他の人が書いたコードのまずさをうまく言語化できなかったりしてモヤモヤするなぁと思ってこの文章を書いています。(※この文章に明確な結論はありません。)

プログラムを書くようになって3年くらい経過しましたが、よくない設計をして自分やチームを困らせたことが何度もあります。私が設計の過ちに気付くのは大きく分けて以下の4つのタイミングがあります。

  1. 人に指摘を受ける
  2. 新規の機能を追加する
  3. 既存の機能を修正する
  4. コードを読む

人に指摘を受ける

自分が書いたコードに対して他者から不適切な点を説明してもらい、理解できたときに設計の過ちに気づくということです。自分のようなキャリアが浅いエンジニアは何度か経験していると思います。

新規の機能を追加する

新しい機能を開発する際に、プログラム的にはただの追加にならず、もともとあった機能にもなんらかの影響を与えていると気づいくことがあります。既存のプログラムの修正のコストがやけに高く、見積りどおりに作業が進んでいないことに気づいた頃に「既存の〇〇が☓☓になっていたことで機能を追加しにくく、〇〇が△△だったら機能を追加しやすかった」と思うことがあります。

また、既存の機能に影響は与えないものの、新規の機能から既存のAPIや関数を呼ぼうとしたときに、やけに呼びづらいと感じることもあります。

既存の機能を修正する

バグを修正するときや機能を削除するときに既存の別の機能にも影響を与えていることに気づくことがあります。

「既存の機能を修正する」と「新規の機能を追加する」はオブジェクト指向の文脈でよく言われるopen/closed principleに反していることに気づいたとも言えます。ただ、拡張に対して開いているべき、修正に対して閉じているべきというのはクラスに限った話ではなく、マイクロサービスなどのより大きな概念に対しても当てはまるのではないかと考えています。

コードを読む

自分の書いたコードを読み直しているときに、書籍やブログを読んで得た知見と実際にコードを書いた経験から筋の悪さに気づくことがあります。前者の書籍やブログを読んで得た知見は「〇〇の原則といった一般的に良いとされている手法に反していて、☓☓なデメリットがある。」、「〇〇というアンチパターンに当てはまっていて、☓☓という問題が発生している」といった知識に基づくものです。後者の実際にコードを書いた経験は上で書いた「人に指摘を受ける」、「新規の機能を追加する」、「既存の機能を修正する」などのように実際に手を動かした経験に基づくものです。個人的には知識より経験から設計の過ちに気づけることが多いです。「知っている」と「1度やったことがある」では理解度に大きな差がある、もしくは印象の強さが異なるのかもしれません。(もちろん人によります。)

オブジェクト指向でのアプリケーションの設計やRDBの設計などは歴史が長く、本質はほとんど変わっていないはずです。しかし、キャリアを積んだエンジニアでも設計を誤ったり、エンジニアによって解釈が異なっていることはあると思います。また、優れたエンジニアでも設計の筋の良さみたいなものをうまく言語化できていないこともあると思います。個人的にはこのあたりがモヤっとしています。

正しいとされている原則を具体的なコードと共に理解しておいて、コードを書くときに都度何が正しいかを考え抜く、問題のあるコードを正しく修正するということを繰り返すことが、設計スキル向上の王道パターンなのでしょうか?

追記

いくつかフィードバックをいただいたので、以下追記です。

  • DB設計の場合、運用時(設計したものが成長した後)になるまで、設計が本当に適切だったのか、どんな時に問題になるのかを理解できないことがある。
  • 自分自身が考えて設計するのと、他の人に指示を受けて設計をするのでは残るものが異なる。自分で決断することがスキルにつながる。

Software engineer

Software engineer