過去のLaravel JP Conferenceで発表された、Takeru Hiroseさんの「SimpleとEasyは違う / Simple is not Easy」がとてもわかりやすかったです。
Simple is not Easy
スライドの主張をまとめると1、次の通りです。
- イージー(Easy)は「簡単かどうか」を示すもので、主観的な評価である
- シンプル(Simple)は「単純かどうか」を示すもので、計測可能な評価である
- イージーを達成するために複雑にする、つまりシンプルを犠牲にするケースは多い。つまりイージーとシンプルはトレードオフの関係にあることが多い
「創味のつゆ」の例が完璧なので、ぜひスライドを先にお読みください。
「イージー」と「シンプル」は混同しやすい
さて。開発やコミュニケーションなど、ありとあらゆる仕事の現場で「シンプル」という表現は使われます。
- シンプルな実装にしてみました
- こうすればシンプルになるね
- もっとシンプルに考えようよ
自分も、上記のような表現を、正しいかどうかよく考えずによく使ってしまっています。
しかしこれらは本当に「シンプル」なのでしょうか?
もしかしたらそれは「イージー」なのかもしれません。
以下、開発にしぼって考えてみましょう。「シンプルな実装でいきますね」と言った場合の開発事例です。
シンプルな実装...?
たとえば次のような「シンプルな」実装があります。2
実装例
def calculate_average(students):
"""
下記の条件を満たす学生の数学と科学の平均成績を計算する関数。
* 数学の成績が50点以上
* 科学の成績が60点以上
* 出席日数が180日以上
"""
total_math = 0
total_science = 0
count = 0
# 外側のfor文: 学生のリストを反復処理する
for student in students:
# 1つ目のif文: 数学の成績チェック
if student['math'] >= 50:
# 2つ目のif文: 科学の成績チェック
if student['science'] >= 60:
# 3つ目のif文: 出席日数チェック
if student['attendance'] >= 180:
total_math += student['math']
total_science += student['science']
count += 1
# countが0でない場合、平均を計算。それ以外の場合、エラーメッセージを返す
if count > 0:
average_math = total_math / count
average_science = total_science / count
else:
raise Exception("条件に合致する学生がいません")
return average_math, average_science
# 実行例
students = [
{'math': 55, 'science': 65, 'attendance': 190},
{'math': 40, 'science': 70, 'attendance': 170},
{'math': 60, 'science': 75, 'attendance': 200},
{'math': 45, 'science': 55, 'attendance': 185},
]
average_math, average_science = calculate_average(students)
print("数学の平均成績:", average_math) # 出力: 57.5
print("科学の平均成績:", average_science) # 出力: 70.0
イージーな実装
しかしこの関数は、上述の定義に照らし合わせて考えると「シンプルな実装」ではなく「イージーな実装」と表現すべきです。
理由は簡単で、「単純かどうか」という観点では、この関数はどう見ても複雑だからです。
代わりに「簡単かどうか」という観点では、簡単だと感じる人も多いかもしれません。あらためてトレードオフの関係が見えますね。
大切なのは、やはり「イージー」であるものを「シンプル」と言わないこと、であると思います。
シンプルな実装
一方で下記は、そんな「イージーな実装」を「シンプルな実装」にしたものです。
def is_math_score_valid(student):
return student['math'] >= 50
def is_science_score_valid(student):
return student['science'] >= 60
def is_attendance_valid(student):
return student['attendance'] >= 180
def is_valid_student(student):
return is_math_score_valid(student) and is_science_score_valid(student) and is_attendance_valid(student)
def filter_valid_students(students):
return [student for student in students if is_valid_student(student)]
def calculate_total_math(valid_students):
return sum(student['math'] for student in valid_students)
def calculate_total_science(valid_students):
return sum(student['science'] for student in valid_students)
def calculate_average(students):
valid_students = filter_valid_students(students)
if len(valid_students) == 0:
raise Exception("条件に合致する学生がいません")
average_math = calculate_total_math(valid_students) / len(valid_students)
average_science = calculate_total_science(valid_students) / len(valid_students)
return average_math, average_science
それぞれの関数は単純なので「シンプル」です。
代わりに「イージー」であるかどうかは評価が分かれるところでしょう。元の関数のほうが簡単だと感じても不思議はありません。
まとめ
念のため、本エントリは「シンプルが良く、イージーが悪い」という結論ではありません。「シンプルとイージーを混同しないように注意しよう」という主張です。
なんとなく、それこそイージーに「シンプル」という言葉を使ってしまいそうになったとき、
- それはシンプルなのか?
- それともイージーなのか?
というセルフレビューを挟むと、さまざまな面で正しく情報を伝えることができると感じました。