「なんか変」と感じるコードは設計改善のチャンス――違和感を活かすソフトウェア設計術
やりたいことは分かっているのに、コードがなかなか言うことを聞いてくれない——そんな経験はありませんか?インデントが深すぎたり、メソッドチェーンが何重にも続いたり、どこか非対称だったり。原因を言葉にできなくても、「何かがおかしい」という違和感だけは残るものです。
そのまま無視して先へ進むこともできます。バックログにはまだ実装したい機能が山ほどありますし、「それほどひどいわけではない」と自分に言い聞かせることもできるでしょう。しかし、それはもったいない判断です。コードの違和感は、あなたに何かを伝えようとしているサインだからです。
違和感に気づけることが、設計力向上の近道になる
コードの「変な感じ」を正確に察知できるようになれば、ソフトウェア設計のスキルは短期間で大きく向上します。ただし、この直感は経験・メンターシップ・コードレビューの中で少しずつ育つもので、一朝一夕には身につきません。
そこで役立つのが、syntactic vinegar(構文的な酢)という考え方です。これは「悪い書き方をしたコードが、書いた本人に『気持ち悪い』と感じさせるようにする」手法のこと。こうした思想を持つライブラリを活用すれば、悪いコードをより速く、確実に検知できるようになります。
syntactic vinegar の具体例:minitest/mock
Rubyに標準で付属するモック/スタブライブラリ minitest/mock を例に見てみましょう。
require 'minitest/mock'
class CartTest < MiniTest::Test
def test_error_message_set_on_charge_failure
cart = Cart.new(items)
cart.stub(:charge!, false) do
cart.checkout!
assert_equal "The credit card could not be charged", cart.credit_card_error
end
end
end
このテストを実行すると、Cart の charge! メソッドがスタブ化されるため、実際の決済プロセッサにはアクセスしません。ブロック構文のおかげで、スタブの有効範囲を必要な箇所だけに限定できるのも良い点です。
ところが、スタブしたいメソッドが複数になったらどうなるでしょうか?
require 'minitest/mock'
class CartTest < MiniTest::Test
def test_error_message_set_on_charge_failure
payment_processor = PaymentProcessor.new
cart = Cart.new(items, processor: payment_processor)
payment_processor.stub(:charge!, false) do
payment_processor.stub(:login!, true) do
payment_processor.stub(:logout!, true) do
cart.checkout!
assert_equal "The credit card could not be charged", cart.credit_card_error
end
end
end
end
end
うっ……。インデントがかなり深くなってしまいました。しかもこれは1つのテストだけの話。同じようなネストが他のテストにも繰り返し現れることを想像すれば、問題の大きさが分かるでしょう。
もちろん、このネスト全体をテストヘルパーメソッドに包んで隠すこともできます。しかし、コードの声に本当に耳を傾けているなら、それは「もっと良い方法があるはずだ」と教えてくれているのです。
解決策:テストダブル(Test Double)への置き換え
ここで登場するのがテストダブルです。スタブの連鎖ではなく、本物のクラスを継承したテスト用クラスを用意してみましょう。
class TestPaymentProcessor < PaymentProcessor
def login!(account_id, key)
true
end
def charge!(amount, credit_card)
credit_card.can_be_charged?
end
def logout!
true
end
end
class CartTest < MiniTest::Test
def test_error_message_set_on_charge_failure
test_payment_processor = TestPaymentProcessor.new
cart = Cart.new(items, processor: test_payment_processor)
cart.credit_card = failing_credit_card
cart.checkout!
assert_equal "The credit card could not be charged", cart.credit_card_error
end
end
どうでしょうか? テストは格段に読みやすくなりました。さらに嬉しいのは、TestPaymentProcessor が他の多くの場面でも再利用できる点です。開発環境で実際のサーバーにアクセスしたくない場合に使う、といった応用も可能です。
悪いコードは「悪い」と感じられるべき
悪いコードを明確に見える化してくれる、主張の強い(opinionated)ライブラリを使う習慣をつければ、悪いコードにはるかに速く、確実に気づけるようになります。その結果として、将来書くコードはよりクリーンで、読みやすく、保守もしやすいものになっていくのです。
あなたのお気に入りの「主張の強いライブラリ」は何ですか? それがどのように悪いコードの発見と修正に役立っているのか、ぜひコメント欄で教えてください!
-
確認コードを使ってGmailのパスワードをリセットする方法【初心者向け完全ガイド】
Gmailのパスワードをリセットしたい理由は人それぞれです。セキュリティ攻撃の疑いから、プライバシーへの意識の高まりまで、さまざまなケースが考えられます。特別な理由がなくても、アカウントの安全を守るために数ヶ月ごとにパスワードを変更するのは良い習慣です。また、パスワードを忘れてしまった場合にも再設定が必要になります。なお、パスワードの「変更」と「再設定(復元)」では手順が少し異なる点に注意しましょう。この記事では、Gmailのパスワードをリセットする具体的な手順をステップごとに詳しく解説します。 Gmailアカウントを安全に保つためのポイント セキュリティ専門家によると、パスワードは3ヶ月ご
-
Webデザインの質を高める:HTMLとCSSコードを美しく整理する方法
Web開発には大きく分けて2つのアプローチがあります。1つはテキストエディタを使う方法、もう1つはGUIエディタを使う方法です。 テキストエディタ方式は、主に上級者向けの手法です。コードを深く理解し、自分が何を作りたいか明確で、視覚的な補助なしでもページを構築できる開発者が選びます。Vim、Emacs、Notepad++、Kateなどのテキストエディタで作業し、完成度を確認したくなったときだけブラウザでページを読み込みます。このアプローチはミニマルで効率的ですが、そのぶん難易度も高いのが実情です。 WYSIWYGエディタの落とし穴 一方、多くの人が利用するのはGUIエディタ方式です。コードを