はじめに
ナイトウ(@engineer_naito)と申します。
昨年?のITエンジニア本大賞にも選ばれた『良いコード/悪いコードで学ぶ設計入門 保守しやすい 成長し続けるコードの書き方』(著者:仙塲大也)を読みました。
昨年10月にfindy様にいただいてからずっと「積読」状態でした。
勉強する時間が取れるようになったのと、紙の本を久しく読んでいなかったので読みました。
とても面白い本だったので、復習のためにも感想文を書きます。
感想
読みながら印象に残ったことをメモしていました。
-
isZero()
はどうなんだろ -
isDisabled()
はやりすぎなのでは? - 基底クラスに派生先についての記述や分岐が混じってしまっているのめっちゃ辛い
- 「#ミノ駆動本」ってハッシュタグは拡張性がないし設計ミスなのでは?(笑)
- もしかして三項演算子使いたくなった時点ですでに浅い?
- 引数だけ違くて、メソッド名は同じやつを何て呼ぶんだっけ
- ファーストクラスコレクションの概念は今まで全くなかった
- メトリクスってしたことなかったけどしてみたい
- "threshold" 名前で使ったことなかった
- そういえば学生時代は変数名の使い回しとか御法度だった気がする
- プログラミング始めたての頃は再代入って仕組みの意味が全くわからなかったな
- コンストラクタにバリデーション、今まで意識して書けてなかった
- 値ってスカラだけじゃなくて単位(次元)とかベクトルとかがやっぱり大事だよね
isZero()
はどうなんだろ
例コードに、ある値が最小値(private static final int MIN = 0
)を下回らないようにするために isZero()
なるプロパティを定義している箇所がありました。
これは少し言い過ぎな命名に見えます。
isMin()
とかにしたい気がします。
isDisabled()
はやりすぎなのでは?
可読性を向上させるために、 !isEnabled()
ではなく、 isDisabled()
を新しく定義して用いるという内容の記述がありました。
これをやるのはちょっと勇気いりそうだなと感じています。
まだこれはやりたくないです。
基底クラスに派生先についての記述や分岐が混じってしまっているのめっちゃ辛い
読んでてここの辺の内容はとても共感しました。
僕の場合はクラスの継承ではなくDjangoのテンプレートの継承ですが、共通化のためにした継承でエラい目に逢ったことがあります。
基底テンプレートに継承先のテンプレートのための分岐ロジックがあって、剥がすのに苦労しました。
継承という仕組みはできれば避けた方がいいというのはぼくも強く同意します。
「#ミノ駆動本」ってハッシュタグは拡張性がないし設計ミスなのでは?(笑)
本のカバーに「#ミノ駆動本」でSNS投稿に使ってねみたいなこと書いてありました。
ミノ駆動さんが書いた本は全て「ミノ駆動本」になってしまうのでは?
2冊目以降で困らないか?
これは設計ミスなのでは?(笑)
※disの意図はありません。
もしかして三項演算子使いたくなった時点ですでに浅い?
ぼくは現在4年目なので「良いコード」みたいなことにとても関心があり、三項演算子という記法が大好きです。
if-elseをこれを使って書き直すことでとても満足できます。
しかし「ミノ駆動本」を読むと条件分岐の記述を用いようとする時点で立ち止まりたくなりました。
interfaceを用いた実装に直せないかを考えたいです。
引数だけ違くて、メソッド名は同じやつを何て呼ぶんだっけ
public class OverloadExample {
// 2つのint型の引数を取る
public void display(int a, int b) {
System.out.println("Sum of two integers: " + (a + b));
}
// 2つのdouble型の引数を取る
public void display(double a, double b) {
System.out.println("Sum of two doubles: " + (a + b));
}
}
上記のような仕組みのことをなんと呼ぶのか思い出せませんでした。
オーバーロードでした。
オブジェクト指向の最も特徴的な要素の1つである多態性(ポリモーフィズム)を実現するための仕組みでした。
ファーストクラスコレクションの概念は今まで全くなかった
配列などのオブジェクトを扱う際にfor文などを用いた繰り返し処理を多く実装しますが、その記述がオブジェクトを用いる箇所に散り散りになってしまっていました。
ファーストクラスコレクションでは配列に対する操作についてもクラスに集約することで、上記の課題を解決低減することができます。
今までこの設計方法をまるで持ち合わせていなかったので非常に参考になりました。
ファーストクラスコレクションを使えないか、引き出しを増やしたいです。
メトリクスってしたことなかったけどしてみたい
これまでのプロジェクトで、なんとなく「コードの見通しが悪くなってきたので」、「このまま続けると困りそうなので」という感覚的な根拠でしかリファクタリングや設計の見直しを提案することしかできませんでした。
普段箇所の実装を行なっている開発メンバーにはおおよそ意図や問題意識を汲み取ってもらえましたが、マネージャーやお客様に「なんとなく」では話をできません。
メトリクスのようなコードの現在状況を数字にして出してくれる仕組みがあることを知ったので今後は積極的に活用して、提案の根拠をより強固にしていきたいです。
"threshold" 名前で使ったことなかった
"threshold" という単語は知ってはいたのですが、なぜかこれまでプログラミングにおいては使っていませんでした。
境界値、閾値などプログラミングの文脈においてとても有効なものなので今後の命名の引き出しに追加したいです。
そういえば学生時代は変数名の使い回しとか御法度だった気がする
プログラミング始めたての頃は再代入って仕組みの意味が全くわからなかったな
学生時代では変数を定義する際に同じ変数名を用いることは基本的にNGだったような気がします。
加速度は a
、 絶対温度は T
、運動量は p
、のようによく用いられる量については変数名の慣例があり、同じ量であっても対象が異なる場合は添え字などをつけて別の変数名を用いることが当たり前でした。
再代入という仕組みがなかったかどうかは覚えていませんが、少なくとも再代入を意識して式を書いていなかったですね。
コンストラクタにバリデーション、今まで意識して書けてなかった
今までバリデーションのロジックを多く書いていましたが、コンストラクタ内で書くということを意識できていませんでした。
これからはコンストラクタ内で書くことができるかどうかを意識して、不正な値を弾くような仕組みを実現したいです。
値ってスカラだけじゃなくて単位(次元)とかベクトルとかがやっぱり大事だよね
また学生時代の話になりますが、物理量は値とその単位がとても大事でした。
コードを書くようになってからあまり単位とか向きについて意識することがなくなってきている気がします。
単位(次元)が異なる量は足し算引き算できなかったり(?)、ある物理量を計算していたが、導かれた値の単位が求めたかった量の単位(次元)と異なっていたらどこかに間違いがあったりなど、単位(次元)を考えずに式を書くことはありませんでした。
最後に
とても勉強になりました。
経験則的に「この設計はよくない気がする」と予感がすることはできても、言語化することはできていませんでした。
この本を読んで言語化できることが増えたおかげで悩むことが減ったり、時間を削減できる気がしています。
設計についての正解(全てのケースに対応できる解決策)というのはないと思います。
しかし、いろいろな設計方法を知っておく(引き出しを増やす)ことで柔軟に対応することができると思いました。
最後まで読んでいただきありがとうございました!