環境
私は最近、より良いフォーマットのコードの作成に興味を持ちました。そして、「コードを実行するための独自の「最良の」方法はもちろんないため、「良い慣行と見なすのに十分な人々によって承認されたルールに従う」という意味です。
最近はほとんどRubyでコードを書いているので、リンター(Rubocop)を使ってコードの「品質」に関する情報を提供し始めました(この「品質」はコミュニティ主導のプロジェクトruby-style-guideで定義されています)。
場合によってはコードの効率がコードの記述方法によって実際に影響を受ける場合でも、コードの効率についてではなく、「フォーマットの品質」のように「品質」を使用することに注意してください。
とにかく、すべてのことをして、私はいくつかのことを実現しました(または、少なくとも覚えていました)。
- 一部の言語(特にPython、Rubyなど)では、優れたコードのワンライナーを作成できます。
- コードのガイドラインに従うことで、コードを大幅に短くすることができますが、それでも非常に明確です。
- ただし、これらのガイドラインに厳密に従うと、コードがわかりにくく/読みやすくなります。
- コードはいくつかのガイドラインをほぼ完全に尊重し、それでも品質が低い場合があります
- コードの読みやすさはほとんど主観的です(「私が明らかにすることは、仲間の開発者にとって完全に不明瞭かもしれない」)
これらは単なる観察であり、もちろん絶対的なルールではありません。また、コードの読みやすさと以下のガイドラインはこの時点では無関係に見えるかもしれませんが、ここでのガイドラインはコードの1つのチャンクを書き換える方法の数を絞り込む方法です。
次に、いくつかの例を挙げて、すべてをより明確にします。
例
単純なユースケースを見てみましょうUser
。「」モデルを持つアプリケーションがあります。ユーザーはオプションでありfirstname
かつsurname
必須とemail
アドレスを。
私は、メソッド「書きたいname
その後、名前を返します」(firstname + surname
少なくとも、彼の場合は、ユーザーのを)firstname
またはsurname
、本、またはそのemail
代替値としていない場合。
また、このメソッドでuse_email
パラメーターとして" "(ブール値)を使用して、フォールバック値としてユーザーの電子メールを使用できるようにします。このuse_email
パラメーターは(渡されない場合)デフォルトで" "になりますtrue
。
それをRubyで記述する最も簡単な方法は次のとおりです。
def name(use_email = true)
# If firstname and surname are both blank (empty string or undefined)
# and we can use the email...
if (firstname.blank? && surname.blank?) && use_email
# ... then, return the email
return email
else
# ... else, concatenate the firstname and surname...
name = "#{firstname} #{surname}"
# ... and return the result striped from leading and trailing spaces
return name.strip
end
end
このコードは、最もシンプルで理解しやすい方法です。Rubyを「話さない」人でも。
それでは短くしてみましょう:
def name(use_email = true)
# 'if' condition is used as a guard clause instead of a conditional block
return email if (firstname.blank? && surname.blank?) && use_email
# Use of 'return' makes 'else' useless anyway
name = "#{firstname} #{surname}"
return name.strip
end
これは短く、理解しやすいですが、簡単ではありません(ガード句は条件ブロックよりも読みやすいです)。また、Guard句により、使用しているガイドラインへの準拠が強化されるため、ここではwin-winです。また、インデントレベルを減らします。
次に、Rubyのマジックを使用して、さらに短くします。
def name(use_email = true)
return email if (firstname.blank? && surname.blank?) && use_email
# Ruby can return the last called value, making 'return' useless
# and we can apply strip directly to our string, no need to store it
"#{firstname} #{surname}".strip
end
さらに短く、完全にガイドラインに従っています...
質問を開始できるのはここです。本当に価値があるのでしょうか?「いいえ、読みやすくし、 ' return
' を追加します」と言う必要があります(これはガイドラインを尊重しないことを知っています)。それとも、「大丈夫、Rubyのやり方、気のいい言語を学んでください!」
オプションBを使用する場合は、さらに短くしてください。
def name(use_email = true)
(email if (firstname.blank? && surname.blank?) && use_email) || "#{firstname} #{surname}".strip
end
ワンライナーです!もちろん、それは短いです...ここでは、Rubyが値を返しますという事実を利用するか(電子メールは以前と同じ条件で定義されることになるので)1が定義されているの応じて、他の。
書くこともできます:
def name(use_email = true)
(email if [firstname, surname].all?(&:blank?) && use_email) || "#{firstname} #{surname}".strip
end
それは短く、読むのはそれほど難しくありません(つまり、私たちはallいワンライナーがどのように見えるかを見てきました)、良いRuby、それは私が使用するガイドラインに準拠しています...しかし、まだ最初の書き方と比較してそれは、読むのも理解するのもずっと簡単ではありません。また、この行が長すぎる(80文字以上)と主張することもできます。
質問
いくつかのコード例は、「フルサイズ」コードとその縮小版の多く(有名なワンライナーまで)を選択するのが難しいことを示しています。それでも、読みやすさの点で「フルサイズ」コードに勝るものはありません...
そこでここに本当の質問があります:どこでやめるか?短いとき、十分短い?コードが「短すぎ」、読みにくくなったことを知る方法(非常に主観的であることに留意してください)?そしてさらに:常にそれに応じてコーディングし、ワンライナーと「フルサイズ」のコードチャンクを混在させないようにする方法
TL; DR
ここでの主な質問は、「長くても明確で、読みやすく、理解しやすいコードチャンク」と「強力で短く、読みにくい1ライナーを理解する」のどちらかを選択する場合です。 2つの唯一のオプションではなく、スケールの最下部:「十分にクリア」と「本来あるべきほど明確ではない」の境界をどこで定義するか。
主な問題は、古典的な「ワンライナー対読みやすさ:どちらが良いですか?」ではありません。しかし、「これら2つのバランスを見つける方法は?」
編集1
コード例のコメントは「無視」されることを意図しており、何が起きているかを明確にするためにここにありますが、コードの可読性を評価する際には考慮されません。
return
バリアント3 が好きです。これらの7文字は、私の目にかなり明瞭さを加えます。
[firstname,surname,!use_email].all?(&:blank?) ? email : "#{firstname} #{surname}".strip
...と書くことができfalse.blank?
ます。なぜなら、trueを返し、三項演算子が数文字を節約するからです...¯\ _(ツ)_ /
return
キーワードはどのような明確さを追加することになっていますか?!情報は一切提供しません。それは純粋な混乱です。