本記事について
入社してから1年未満の私は、すでに多くのしくじりを行いました。
この記事では、これまでのしくじりを振り返り、今後の改善のために記録として残そうと思います。
主に、開発経験が浅い方々にとって参考になる内容になれば幸いです。
本記事の内容は組織やチームによって異なります。
ここで述べていることは個人的な見解に過ぎません。
しくじりエピソード
今回紹介するしくじりエピソードは以下の通りです。
- 名前の意味が広すぎ
- 気づいたらマジックナンバー
- スコープの広い変数を定義しすぎ
- YAGANI原則を無視
他にもありますが、しくじり影響度の高かった4つを取り上げました。
しくじり ① : 名前の意味が広すぎ
エピソード
クラスや構造体、列挙型、メソッド、変数など、どの局面において意味の広すぎる曖昧な命名になっていました。
class UserManager { // Manager=管理だが、管理の意味自体が広すぎる。
func updateUser() {}
}
影響
広すぎる意味を持つ曖昧な命名は、他のチームメンバーがコードを理解する際に障害となります。
また、仕様変更時のバグ発生のリスクも高まります。
このような命名を持つクラスに機能を次々と追加すると、結果として膨大なクラスが作成されてしまいます。
改善案
それぞれの単語を具体的に掘り下げるてみると、目的に合った命名が可能です。
ある図形の座標を計算することを目的とした構造体 ShapesPositionManager
は、
具体的にすると、PieChartPositionCalculator
になります。
- ShapesPosition → PieChartPosition (実際には円グラフ用)
- Manager → Calculator (実際には計算専用)
さらに、chatGPTを使ってアイデアを出し合うことで、具体的な命名の選択肢が増えると思います。
Q. ShapesPositionManagerという構造体を見て、どんな内容だと思いますか?
A. 図形の位置管理、配置制御、ユーザー入力に応じた図形の挙動管理などを担うと推測されます。
しくじり ② : 気づいたらマジックナンバー
エピソード
プレゼンテーションロジックの実装中に、意図せずマジックナンバーを使用してしまいました。
3とありますが、ある要素の選択可能な上限数を3に設定しています。
if selectedElementCount > 3 {
// 処理
}
影響
このような実装はレビュー時にレビュワーへの負担を増加させ、重要な問題の発見を妨げます。
また、現時点で問題が見られなくても、選択可能な上限数を他の箇所でも使用したい場合、数値の3がコードの至る所に散らばることになります。
他の開発者が機能を修正する際に、この数値を見落としやすくなるため、結果としてバグが発生するリスクが高まります。
改善案
あくまで一例ですが、以下のように修正することができます。
private let maxSelectionCount = 3
...略
if selectedElementCount > maxSelectionCount {
// 処理
}
しくじり ③ : スコープの広い変数を定義しすぎ
エピソード
クラス内で一箇所のみで参照されるにもかかわらず、複数のメンバ変数を定義していました。
具体的には、表示のみのラベル変数をメンバ変数として保持していました。
private let titleLabel = {
let label = UILabel()
return label
}()
private let subTitleLabel = {
let label = UILabel()
return label
}()
func configureView() {
titleLabel.text = "アールグレイフレーバー"
subTitleLabel.text = "ミルクフレーバー"
addSubView(titleLabel)
addSubView(subTitleLabel)
}
影響
この実装方法は、影響範囲を広げ、多くの箇所から呼び出される構造を作り出してしまいます。
また、コード量が増加し、クラスの内容を把握するのに時間がかかるようになります。
改善案
基本的にはスコープをできるだけ狭くすることが重要だと考えています。
そのため、個人的には以下のような実装方法を採用しています。
ただし、この例は細かいので、好みやチームの方針によって異なることがあります。
private func configureView() {
let titleLabel = makeTitleLabel(text: "アールグレイフレーバー")
let subTitleLabel = makeTitleLabel(text: "ミルクフレーバー")
addSubView(titleLabel)
addSubView(subTitleLabel)
}
private func makeTitleLabel(text: String) -> UILabel {
let titleLabel = UILabel()
titleLabel.text = text
return titleLabel
}
これによってクラスを把握するときに、メンバ変数を追う必要がなくなりました。
さらに、タイトルのラベルを作るメソッドを見るだけで済むようになりました。
しくじり ④ : YAGNI原則を無視
エピソード
YAGANIとは?
You ain't gonna need it.の略で、「必要なもの以外を実装するな」という考え方
仕様書には記載されていなかったものの、非機能要件として必要だと考え、タイトルラベルの表示を制御するロジックを独自に追加しました。
しかし、この実装は仕様の詳細を決めるミーティングが予定されていたにもかかわらず、そのミーティングでの確認を行わずに先に進めてしまいました。
影響
ミーティングの後、タイトルラベルの表示を制御するロジックは不要と判断されました。結果として、すでにマージされていたコードを後から削除する追加作業が必要になりました。
改善案
そもそも仕様が決定されてからコードを進めるのが基本的な流れです。
必要となる機能は、その必要性が明確になった時点で実装するようにしましょう。
最後に
今回のしくじりを踏まえ、コーディングや仕事の進め方の基礎を身につけられるように日々精進しようと思います。