エッジケースが完璧なソリューションに穴を開けるとき
奇妙なテスト問題に対する完璧な解決策が見つかった。DEFAULT_HOST定数をオーバーライドするだけで、万事解決のはずだった。
ただし、あの醜い警告メッセージを消すにはwarningsをオフにしなければならない。でもこれですべてのテストが通るようになった。たった数行のコード変更で済んだのだ!
……ただし、ホストをオーバーライドしたくないテストがひとつだけある。まあ、定数を再オーバーライドして、また警告をオフにして、テストの最後に必ずリセットされるようにすればいい。完成まであと一歩、もうすぐそこだ!
ただし……ただし……ただし……。
そして数日後、27回目の行き詰まりに直面し、アプリが巨大なハックの塊と化していた頃、ふと立ち止まって自問するだろう。自分はいったい何をやっているんだ?この解決策は、元の問題よりも悪くなっていないか?
「賢すぎる問題」を解決する方法
最初のアイデアでは問題全体を解決できないことは明らかだ。では、どうすれば元のアイデアでは対応できなかったエッジケースすべてを解決できる、より良いアイデアを思いつけるのだろうか?
答えは——思いつけない。賢すぎるコードは、さらに賢いコードで打ち勝つことができない。少なくとも直接的には。むしろ逆方向へ進むのだ。シンプルに。素直に。
具体的にはどういうことか?
抽象化しようとしていたコードをインライン化するのだ。繰り返しを恐れず、コードを明示的に保つこと。
DEFAULT_HOST定数を別のデフォルトホストでオーバーライドしようとしていたなら、「デフォルト」という考え方自体を捨ててしまおう。必要なときに毎回、明示的に指定すればいい。
つまり、こう書くのではなく:
require 'test_helper'
silence_warnings do
Rack::Test::DEFAULT_HOST = "www.justinweiss.com"
end
class WelcomeTest < ActionDispatch::IntegrationTest
include Rack::Test::Methods
test "can visit the homepage" do
get "/"
# ...
end
# ...
end
こう書くのだ:
require 'test_helper'
class WelcomeTest < ActionDispatch::IntegrationTest
test "can visit the homepage" do
get "https://www.justinweiss.com/"
# ...
end
# ...
end
一見完璧な解決策が破綻するとき、その原因はいつも、最終的に処理すべきエッジケースを想像していなかったことにある。
大丈夫。未来を正確に予測できる人などいない。しかし、破綻に気づいたら、掘るのをやめること。パッチを次々と当て続けてはいけない。代わりに、元の解決策をいったんほどいて、そこからより良いものを抽出するのだ。
より良い解決策を抽出する方法
コードをすべて明示的で素直な形で書き出すと、自然と再編成のアイデアが浮かんでくるはずだ。
多くの場合、適切な場所に「メソッドの抽出(Extract Method)」や「クラスの抽出(Extract Class)」を適用するだけで十分だ。コツは「適切な場所」を見極めること。だが、目の前に大量の重複コードが並んでいれば、それを見極めるのはずっと簡単になる。
そして、継承と委譲にも頼ろう。これらは、賢くなりすぎることなくコードを整理するための、シンプルで基本的な構成要素だ。
もうひとつ大事なこと
ドキュメントを読むことを忘れないでほしい:
require 'test_helper'
class WelcomeTest < ActionDispatch::IntegrationTest
setup do
# This already exists:
host! "www.justinweiss.com"
end
test "can visit the homepage" do
get "/"
# ...
end
# ...
end
答えが常にこんなに明白に見つかるとは限らない。しかし、自分が3つのクラスと1つのgemを作ってまで解決しようとしていた問題に、組み込みメソッドひとつで対応できると気づくほど、開発者を謙虚にさせる経験はない。
最終的には、より良い解決策に
2番目に導いた解決策は、通常あらゆる面で最初のものより優れている。
なぜだろうか? 理由は次のとおりだ。
-
開発者としての経験が増えている。
だから、良いコードとは何かを、より正確に判断できる。
-
自分が構築したシステムへの理解が深まっている。
だから、書くコードがシステム全体にどう馴染むかについて、より良い意思決定ができる。
-
どの前提が間違っていたのかを知っている。
だから、解決策は空想上の問題ではなく、実際に存在する問題により適合するものになる。
そして最後には、あなたの最高の「賢さ」が活きる場所が見つかるかもしれない。今度こそ、ハックなしで。
掘るのをやめなければならない
賢いコードを書くのは楽しい。Rubyなら、なおさら書きやすい。そして、その道が間違った方向へ向かっていると分かっていながらも、突き進み続けるのは、もっと簡単だ。
しかし、「何かがおかしい」という漠然とした感覚を覚えたら、一度立ち止まること。コードをほどき、ドキュメントを読み、コードを素直で明示的なものにする。そして、より良い道を見つけるのだ。
あなたは、延々と終わらない穴を掘り続けた経験がありますか? どうやって抜け出しましたか? そして、最終的にどんなコードになったでしょうか? ぜひコメントで教えてください。
-
Wise Video Converter徹底解説!あらゆる動画形式を自在に変換できる万能ソリューション
Wise Video Converterは、世界中で高い人気を誇る動画変換ソフトウェアの一つです。あらゆるファイル形式の動画を、さまざまなマルチメディアデバイスで再生できる形式へ簡単に変換できる手軽さが最大の魅力です。ポータブル版も用意されており、USBメモリやメモリカードに入れて持ち運べば、外出先でも利用可能。スマートフォン、タブレット、ゲーム機、PCなどで動画をスムーズに再生したい方に最適なツールです。 主な特徴 直感的で使いやすいインターフェース シンプルかつ高速・効率的な操作感 ワンクリックでの動画変換に対応 Windows、スマートフォン、タブレットとの高い互換性 複数の
-
エッジコンピューティングはいつ導入すべき?判断に役立つ3つの重要ポイント
エッジコンピューティングは、クラウドコンピューティングを補完する技術として注目されています。しかし、多くの企業では「本当にエッジコンピューティングが必要なのか」「まだ導入には早いのではないか」という判断に迷っているのが実情です。適切な意思決定を行うためには、まず「なぜ自社にエッジコンピューティングが必要なのか」を冷静に見つめ直すことが大切です。単に話題になっているからという理由で導入すべきではありません。技術の本質を理解した上で、今すぐ必要かどうかを見極めましょう。 この記事では、エッジコンピューティングへの移行を検討すべきかどうかを判断するための、3つの重要なポイントを解説します。 1.