1 年後に Python コードは理解できるが、XYZ コードは理解できないという人がいると聞きました。なんで?Python 構文の何が良いのか、別の構文の何が悪いのかわかりません。私は C# が好きですが、VB.NET コードの方が読みやすいと感じています。私は言語設計を行っていますが、コード/構文/言語を読み取り可能または読み取り不能にするものは何ですか?
19 に答える
経験。
IMO、大きなものの1つは重要な空白です。ブロックのインデントは長い道のりであり、Python や F# などの言語は、ある程度の有意な空白を提供し、読みやすさに役立ちます。
Java や C# のようなコードは構造化される傾向があり、読みやすさは、言語自体ではなく、最初にどのようにコーディングされたかに焦点を当てます。
コードは、明示的な「やりたいことを述べる」スタイルで書かれている場合に読み取り可能です。これはソファの言語にのみ依存します
- それはあなたが望むものを表現することを可能にします (関数型プログラミング!)
- 暗号的なステートメントを強調していません
残りは、コードの記述に使用するスタイルによって異なります (Perl でさえ理解できます!) が、特定の言語ではステートメントを簡単にハックすることができます。
クリア:
expr = if not (ConditionA and ConditionB) then ... else ...
不明:
expr = (!(conditionA && conditionB)) ? ... : ...
クリア:
foreach line in lines:
if (line =~ /regex/):
// code
不明:
... if /regex/ foreach(@lines);
クリア:
x = length [ x | x <- [1..10], even x ]
不明:
int x = 0;
for (int i = 1; i <= 10; ++i)
if ((i&&1)==0) ++x;
プログラマーは、言語ではなく、コードを読み取り可能または読み取り不能にします。そうでないと考えるのは、自分をだますだけです。可読性を判断する資格があるのは、その言語を知っている人だけだからです。プログラマーでない人にとって、すべての言語は等しく読めません。
一般に、Python が読みやすいと見なされるのは、標準化されたインデントを強制するためです。これは、if ブロックにいるのか関数にいるのかを考える必要がなくなることを意味します。それは明らかです。したがって、不適切に記述されたコードでさえ明らかになります。
私が一般的に読むのが難しいと考える言語の 1 つは、同じ理由 (というか、その逆) で PHP です。プログラマーは自由にインデントでき、変数をどこにでも格納できるため、すぐに複雑になる可能性があります。さらに、PHP には歴史的に大文字と小文字を区別する関数名がなかったので (PHP < 4.4.7 だと思います)、これはコア言語の実装にも一貫性がないことを意味します... (誤解しないでください) 、私はその言語が好きですが、悪いコーダーは本当に混乱する可能性があります)。
JavaScript はまた、規律のない開発者にとって多くの問題を抱えています。変数がどこで定義され、どのスコープにいるのか疑問に思うでしょう。コードは 1 つの統合された場所にあるのではなく、複数のファイルに分散し、予期しない場所に潜んでいることがよくあります。
ActionScript 3 は少し優れています。一般に、誰もが同様の構文を使用するようにする動きがあり、アドビは標準を定義し、それらをアクセス可能で一般的なものにすることまで行ってきました. 営利企業によってサポートされている ECMAScript の実装が、一般化されたものよりも優れていることを理解するのにそれほど時間はかかりません。
可読性は、多くの入力を必要とする機能です。言語の可読性に影響を与える可能性のあるものの完全なリストをコンパイルすることは、実際には不可能だと思います。それを説明する最も一般的な方法は、「認知負荷の最小化」です。いくつかの主な要因:
- 意味の機微。2 つのコード スニペットが一見非常に似ているように見えても、実行内容が異なる場合、読み手は立ち止まって実際に何が起こっているのかを推測しなければならないため、読みやすさが損なわれます。
- 意味のないコード — ボイラープレートとも呼ばれます。これは必ずしも何もしないコードを意味するわけではありませんが、実際に行っていることについて何も教えてくれないコードです。関数やオブジェクトの実際の意図を表現していないコードはすべて、可読性を大幅に低下させます。
- 意味を詰め込む - 別名ゴルフ。これはボイラープレート問題の反対です。コードを圧縮することで、読み手が停止して 1 文字ずつ調べなければならなくなる可能性があります。これが発生する正確なラインはいくぶん主観的です (Perl が好きな人もいれば嫌いな人もいる理由の一部です) が、これは間違いなく実際の現象です。
1 年後に Python コードは理解できるが、XYZ コードは理解できないという人がいると聞きました。なんで?
まず、構文だけに基づいてそれを言う人はいないと思います。考慮すべき要素は他にもたくさんありますが、いくつか例を挙げると、次のとおりです。
- 一部の言語は、何かを行うための 1 つの正しい方法 (Python など) のみを促進する傾向があり、他の言語はさまざまな方法を促進する傾向があるという事実 (たとえば、私が聞いたところによると、Ruby [免責事項: 私は Ruby プログラマーではありません])
- 言語が持つライブラリ。より優れた設計のものは、ドキュメントを必要とせずに信じられないほど簡単に理解できる傾向があり、これも覚えやすくなる傾向があります。したがって、優れたライブラリを備えた言語は、物事をより簡単にします。
そうは言っても、Python に対する私の個人的な見解は、多くの人がそれを「実行可能な疑似コード」と呼んでいるという事実です。疑似コードに表示されがちなさまざまなものをサポートし、拡張機能として、物事について考えるための標準的な方法です。
また、Python の非 C ライクな構文 (非常に多くの人に嫌われている機能の 1 つ) も、Python を疑似コードのように見せます。
それが、Python の可読性に対する私の見解です。
正直に言うと、何が言語を読みやすくするかということになると、単純さと個人的な好みの組み合わせに帰結するように思えます。(もちろん - 十分に努力すれば、どんな言語でも判読できないコードを書くことは常に可能です)。個人の好みは実際には制御できないため、表現のしやすさに帰着します。単純な機能を使用する言語が複雑になればなるほど、その言語は読みやすさの観点から一般的に難しくなる可能性があります。
1 文字で十分な場合に必要な単語 - パスカルと VB の庭の石。
比較:
Block ()
Begin
// Content
End
対。
Block
{
// Content
}
単語を読んでそれを概念と精神的に関連付けるには、追加の脳処理が必要ですが、単一のシンボルはそのイメージによってすぐに認識されます。
自然言語、通常のテキスト言語とヒエログリフを使った記号言語(アジア系)との違いと同じことです。最初のグループの処理は遅くなります。これは、基本的に、テキストが一連の概念に解析され、象形文字が概念自体を表すためです。あなたがすでに知っていることと比較してください - XML からのシリアライゼーション/デシリアライゼーションは、バイナリ形式のカスタム検索よりも高速ですか?
私見ですが、コンピューター言語が話し言葉に似ているほど、読みやすくなります。極端な例として、J、Whitespace、Brainfuck などの言語を取り上げます... 訓練されていない目には完全に判読できません。
しかし、英語に似た言語はより簡単に理解できます。COBOLが証明できるように、これが最高の言語になるわけではありません。
実際の言語そのものよりも、コードを書いている人に関係があると思います。どの言語でも非常に読みやすいコードを書くことができ、どの言語でも読めないコードを書くことができます。複雑な正規表現でも、読みやすいように書式設定してコメントを付けることができます。
私の同僚は、「どんな言語でもくだらないコードを書くことができる」ということわざを持っていました。私はそれが好きで、今日共有したいと思いました。コードを読みやすくするものは何ですか? ここに私の考えがあります
- 言語の構文を読み取る能力。
- 適切にフォーマットされたコード。
- わかりやすい名前の変数と関数
- 複雑な処理を説明するコメント。コメントが多すぎるとコードが読みにくくなる可能性があることに注意してください
- 短い関数は、長い関数よりも読みやすいです。
これらのどれも言語とは何の関係もありません。すべてはコーダーとその作業の質に関するものです。
構文に関しては、かなり説明的であることが不可欠だと思います。たとえば、多くの言語ではforeach
ステートメントがあり、それぞれが少しずつ異なる方法で処理します。
// PHP
foreach ($array as $variable) ...
// Ruby
array.each{ |variable| ... }
// Python
for variable in array ...
// Java
for (String variable : array)
正直なところ、私は PHP と Python が最も明確な理解手段を持っていると感じていますが、結局のところ、プログラマーがどれだけ賢く明晰になりたいかということにかかっています。たとえば、下手なプログラマーは次のように書くことができます。
// PHP
foreach ($user as $_user) ...
$user
私の推測では、追跡して何が何で、なぜそれを反復していたのかを突き止めようとしない限り、コードが一体何をしているのかほとんどわからないでしょう。明確で簡潔であるということは、プログラムをさかのぼって変数/関数名が何であるかを把握する必要なく、コードの小さなチャンクを意味のあるものにすることです。
また、空白には完全に同意する必要があります。タブ、改行、および演算子間のスペースは、本当に大きな違いを生みます!
編集 1:一部の言語には、物事をより明確にするための構文とツールがすぐに利用できるという点もあるかもしれません。Ruby を例にとります。
if [1,2,3].include? variable then ... end
詩、Javaを言う:
if (variable != 1 || variable != 2 || variable != 3) { ... }
これらの 1 つ (IMHO) は、確かに他のものより明確で読みやすいです。
コードはその単純さによって読みやすいと言ってみます。
それが何をし、その目的が何であるかを一目で理解する必要があります。ほんの数行で必要なことができるのに、なぜ何千行ものコードを書くのでしょうか?
これは、たとえば F# のような関数型言語の精神です。
クリーンなコードがすべてです。
小さく、シンプルに、適切な名前を付けて、書式設定してください。
class ShoppingCart {
def add(item) {
println "you added some $item"
}
def remove(item) {
println "you just took out the $item"
}
}
def myCart = new ShoppingCart()
myCart.with {
add "juice"
add "milk"
add "cookies"
add "eggs"
remove "cookies"
}
私にとっては、その主な問題は、その言語を使用すると、詳細が失われるのを防ぐ、より読みやすい抽象化を開発できるかどうかです。
これは、OOP が詳細を隠すことで非常に便利になるところです。共通の概念 (C++ のイテレータなど) の動作を持つインターフェイスの背後にあるタスクの詳細を隠すことができれば、通常は実装の詳細を読む必要はありません。
私は、言語設計(通常の言語の場合、頭脳明晰ではありません:))は問題ではないと思います。コードを読みやすくするには、標準やコード規則に従い、リファクタリングを忘れないようにする必要があります。
読者の識字率。
本当に、2つの異なる側面です。最初は構文と空白です。Python は空白の標準を強制し、不要な {、} および ; を削除します。文字。これにより、目にやさしくなります。第二に、そして最も重要なことは、表現の明確さです。つまり、コードを自分の考え方に戻すのがいかに簡単かということです。プログラミング言語には、後者の点に貢献するいくつかの機能 (および非機能) があります。
- ジャンプ禁止。Cのgoto文がその典型です。構造化ブロックが不足し続けないコードは読みやすくなります。
- 副作用を最小限に抑えます。グローバル変数は悪です、覚えていますか?
- よりカスタマイズされた機能を使用します。5 つの反復変数を使用してforループを追跡するにはどうすればよいでしょうか? Common Lispループははるかに読みやすい (ただし、書くのは非常に難しいですが、それは別の話です)
- レキシカルクロージャー。変数の値は、頭の中でコードを実行してから、どのステートメントがどのステートメントをシャドーイングしているかを把握するのではなく、ただ見るだけで把握できます。
いくつかの例:
(loop
do for tweet = (master-response-parser (twitter-show-status tweet-id))
for tweet-id = tweet-id then (gethash in-reply-to tweet)
while tweet-id
collecting tweet)
と
listOfFacs = [x | x <- [1 ..], x == sumOfFacDigits x]
where sumOfFacDigits x = sum [factorial (x `div` y) | y <- [1 .. 10]]