1.はじめに
他のプログラマの作業を制御する必要性に直面すると、人々がかなり迅速かつ簡単に学習することに加えて、修正に多くの時間を要する問題があることを理解し始めます。
比較的迅速に、必要なツールとドキュメント、顧客とチーム内での適切なコミュニケーション、正しい目標設定と優先順位付けを使用するように人をトレーニングできます(もちろん、すべてを所有している限り)。
しかし、実際のコードに関しては、すべてがはるかに単純ではなくなります。 はい、あなたは弱点を指摘することができ、それらのどこが悪いのかを説明することさえできます。 そして、次回はまったく新しい問題のセットでレビューを取得します。
プログラマーの職業は、他のほとんどの職業と同様に、数年間毎日、そして概して彼の生涯を研究しなければなりません。 最初に、N学期のコースの量に関する一連の基本的な知識を習得し、その後、さまざまな熊手を長々と踏みつけ、上級仲間の経験から学び、良い例と悪い例(何らかの理由で悪い例)を勉強します。
基本的な知識について言えば、美しいプロフェッショナルなコードを書く能力は、何らかの理由でこの基本的な知識に明確に含まれていないことに注意する必要があります。 代わりに、関連する機関や書籍で、アルゴリズム、言語、OOP原則、設計パターンについて説明されています...
はい、これはすべて知る必要があります。 しかし、同時に、実用的な(多くの場合1度または別のネガティブな)経験がある場合は、通常、適切なコードがどのように見えるかについての理解がすでに現れています。 そして、人生があなたに悪いコードのジューシーな例だけでなく、真似をする価値のある例にも「突っ込んだ」ことを条件にした。
これが全体の複雑さです。「価値のある」「美しい」コードのアイデアは、長年の個人的な経験に完全に基づいています。 今、このアイデアを、まったく異なる経験を持つ人、またはまったく経験していない人に短時間で伝えるようにしてください。
しかし、私たちと一緒に働いている人々によって書かれたコードの品質が私たちにとって本当に重要であるなら、それは試してみる価値があります!
2.なぜ美しいコードが必要なのですか?
通常、特定のソフトウェア製品を扱う場合、コードの美的品質はそもそも私たちには関係ありません。
私たちのパフォーマンス、機能実装の品質、その動作の安定性、変更や拡張の可能性などは、私たちにとって非常に重要です。
しかし、コードの美しさは上記の指標にプラスの影響を与える要因ですか?
私の答え:はい、そして同時に、最も重要なものの1つです!
これは、美の概念の主観的な解釈に関係なく、美しいコードには次の(ある程度まで相互に縮小可能な)最も重要な性質があるためです。
- 読みやすさ。 つまり コードを見て、実装されたアルゴリズムをすばやく理解し、特定のケースでプログラムがどのように動作するかを評価する機能。
- 管理性。 つまり さまざまな不快な予測可能および予測不可能な結果を回避しながら、必要な最短時間でコードに必要な修正を加える機会。
これらの品質が本当に最も重要である理由と、段落の冒頭に示した指標の改善にどのように貢献するのかは、プログラミングに携わる誰にとっても明らかであると確信しています。
そして今、一般的な言葉から特定の言葉に移るために、逆のステップを踏んで、私たちが美しくプロフェッショナルに書かれていると通常知覚するのは読みやすく管理可能なコードだとしましょう。 したがって、これらの品質を達成する方法の議論にさらに焦点を当てます。
3. 3つの基本原則。
私自身の経験のプレゼンテーションに戻ると、私は自分や他の人々のコードの可読性と制御性に取り組んでいる間に、次の理解に徐々に気づいたことに注意します。
解決する特定のプログラミング言語とタスクに関係なく、コードフラグメントがこれらの2つの品質を十分に備えているためには、次のことが必要です。
- 可能な限り線形。
- 短い
- 自己文書化。
コードをより美しくするためのさまざまなヒントとテクニックを際限なくリストできます。 しかし、これらの3つの原則に焦点を当てることで、最良の、またはいずれにしても、かなり良い結果が得られることを確認します。
したがって、それらの本質を詳細に説明するとともに、これらの原則に合わせてコードを作成するための一連の基本的なテクニックについても説明します。
4.コードの線形化。
3つの基本原則のうち、最も明白なのは直線性であり、ほとんどの場合無視されているように思えます。
おそらく、長年の研究(そして、おそらく科学活動)の間に、 O( n3) 、 O(nlogn)などの推定値を持つ非線形アルゴリズムを議論するために使用されているからでしょう。
もちろん、これはすべて重要で重要ですが、実際のプロジェクトでビジネスロジックを実装することについて話すときは、通常、子供のプログラミング本のイラストを連想させる、まったく異なるプロパティのアルゴリズムを扱う必要があります。 このようなもの( Googleから取得):
したがって、線形性では、アルゴリズムの漸近的な複雑さではなく、 相互にネストされたコードブロックの最大数、または最長のコードサブセクション全体のネストレベルに関連付けます。
たとえば、完全に線形の断片:
do_a();
do_b();
do_c();
:
do_a();
if (check) {
something();
} else {
anything();
if (whatever()) {
for (a in b) {
if (good(a)) {
something();
}
}
}
}
“” .
: , , C-like , , . , ( Java Javascript).
4.1. 1. .
.
“ ” :
- .
- .
- .
- .
- , .
- .
.
listen_client();
if (!is_clean()) {
...
}
check_cost();
if (!client_agree()) {
...
}
find_defects();
if (defects_found()) {
...
}
create_request();
take_money();
bye();
, , :
listen_client();
if (!is_clean()) {
...
}
check_cost();
if (client_agree()) {
find_defects();
if (defects_found()) {
...
}
create_request();
take_money();
} else {
...
}
bye();
, , .
4.2. 2. break, continue, return throw, else.
:
...
if (!client_agree()) {
...
} else {
find_defects();
if (defects_found()) {
...
}
create_request();
take_money();
bye();
}
:
...
if (!client_agree()) {
...
return;
}
find_defects();
if (defects_found()) {
...
}
create_request();
take_money();
bye();
, , else. -, break, continue, return throw ( ). -, , , else , - .
-, return , - ( : - ).
( ) , .
4.3. 3. .
.. “ ” , .
“” :
:
do_a()
if (check) {
something();
} else {
anything();
if (whatever()) {
for (a in b) {
if (good(a)) {
something();
}
}
}
}
:
procedure do_on_whatever() {
for (a in b) {
if (good(a)) {
something();
}
}
}
do_a();
if (check) {
something();
} else {
anything();
if (whatever()) {
do_on_whatever();
}
}
, , , , . , .
, , , . (. . 6.1).
4.4. 4. , , , , .
:
if (check) {
do_a();
something();
if (whatever()) {
for (a in b) {
if (good(a)) {
something();
}
}
}
} else {
do_a();
anything();
if (whatever()) {
for (a in b) {
if (good(a)) {
something();
}
}
}
}
:
do_a();
if (check) {
something();
} else {
anything();
}
if (whatever()) {
for (a in b) {
if (good(a)) {
something();
}
}
}
4.5. 5 ( ). try...catch , .
, try...catch , , .. , , .
, . .. , , . : , try..catch, .
, , , . , , .
4.6. 6. if-.
. :
if (a) {
if (b) {
do_something();
}
}
:
if (a && b) {
do_something();
}
4.7. 7. (a? b: c) if.
:
if (a) {
var1 = b;
} else {
var1 = c;
}
:
var1 = a ? b : c;
, , .
:
if (a) {
var1 = b;
} else if (aa) {
var1 = c;
} else {
var1 = d;
}
:
var1 = a ? b :
aa ? c : d;
, , .
, var1 , ( . 6.8).
4.8. , .
listen_client();
if (!is_clean()) {
wash();
}
check_cost();
if (!client_agree()) {
pay_for_wash();
bye();
return;
}
find_defects();
if (defects_found()) {
say_about_defects();
if (!client_agree()) {
pay_for_wash_and_dyagnosis();
bye();
return;
}
}
create_request();
take_money();
bye();
, , 3 bye() , , , , return (, return).
try...finally, , .. . .
( , . 5.1 , ):
procedure negotiate_with_client() {
check_cost();
if (!client_agree()) {
pay_for_wash();
return;
}
find_defects();
if (defects_found()) {
say_about_defects();
if (!client_agree()) {
pay_for_wash_and_dyagnosis();
return;
}
}
create_request();
take_money();
}
listen_client();
if (!is_clean()) {
wash();
}
negotiate_with_client();
bye();
, - , , , . , …
5. .
, , , , .
, — , , , . , , , , . .
5.1. 1. .
, , , - . , , , .
, .
. , : . . , - , .
, . 4.3.
if. , :
procedure proc1() {
init();
do1();
}
procedure proc2() {
init();
do2();
}
proc1();
proc2();
:
init();
do1();
do2();
. :
a = new Object();
init(a);
do(a);
b = new Object();
init(b);
do(b);
:
procedure proc(a) {
init(a);
do(a);
}
proc(new Object());
proc(new Object());
5.2. 2. .
— , . , , .
, , null. , NPE .
:
obj = new Object();
...
if (obj != null) {
obj.call();
}
, . (C , , new() null. ( .. Java) ).
( ) .
, , :
obj = factory.getObject();
obj.call1();
// obj null, )
if (obj != null) {
obj.call2();
}
, .
, , :
procedure proc1(obj) {
if (!is_valid(obj)) return;
obj.call1();
}
procedure proc2(obj) {
if (!is_valid(obj)) return;
obj.call2();
}
obj = factory.getObject();
if (is_valid(obj) {
proc1(obj);
proc2(obj);
}
, , . , (, proc1() proc2() API), .
:
- , . . Java, , “” @Nullable. , , / null.
- ! , . , , . , .
, , - , , .
NullObject, , , “” null. null - .
null-safe , apache-commons Java. , null.
5.3. 3. “”. .
— : , , . .
, , , 2D long-polling Javascript. , , , .
, , - , , . , , “” -.
, , , “” . , , , , .
, , , (, apache-commons guava Java) .
5.4. 4. , .
“” , ; , ; , , — , , , , .
, , , .
, , , , , .
, , , , , .
5.5. 5. .
, : , , ..
, , Javascript.
:
if (obj != null && obj != undefined && obj.s != null && obj.s != undefined && obj.s != '') {
// do something
}
, “ - ”. , Javascript, :
if (obj && obj.s) {
// do something
}
, boolean, if (obj) {} :
- false
- null
- undefined
- 0
, , . , , , - “” .
, :
if (!a) {
a = defaultValue;
}
a = a || defaultValue;
, .
6. .
“” , XML JSON. , , , .
XML , , , , , , .
, “” , , , .
“” , . , , , , .
6.1. 1. , . , .
, — .
name, , , , . compare(), , , - 1000 . NetworkDevice, , , .
, , , . , , .
, , . , , , .
, , “”.
, i, j, k, s. . i, j, . , , foreach .
ii, i1, ijk42, asdsa ., . , … , - .
6.2. 2. , — -.
, — . , , , , . , , . , .
“” — // . .
: .
6.3. 3. “ ”. , .
. 5.4., , , , , , , ( ) .
: , .
“” :
...
int sum = counSum();
int increasedSum = sum + 1;
operate(increasedSum);
...
, increasedSum , .. , (sum + 1) , . (“” ):
...
int sum = counSum();
operate(sum + 1);
...
, :
...
operate(countSum() + 1);
...
— , .
, , . :
double descr = b * b - 4 * a *c;
double x1 = -b + sqrt(descr) / (2 * a);
descr , .. , , , , “ ” .
, , : //, . , . 6.1, , . , , // , .
6.4. 4. , — .
: , . . . , - .
, , .
:
if (i == abs(i)) {
}
:
if (i >= 0) {
}
, , .
6.5. 5. , private (protected), . — .
.
, . , “ ”, . . , , . , , , .
6.6. 6. ( ) .
, .
:
Object someobj = createSomeObj();
if (some_check()) {
// Don't need someobj here
} else {
someobj.call();
}
, someobj , . . , .
, - :
if (some_check()) {
// Don't need someobj here
} else {
Object someobj = createSomeObj();
someobj.call();
}
, , . 6.3:
if (some_check()) {
// Don't need someobj here
} else {
createSomeObj().call();
}
, . , . :
Object someobj = createSomeObj();
for (int i = 0; i < 10; i++) {
someobj.call();
}
createSomeObj() — , , .
, , .
6.7. 7. . , , .
— , .
, . — .
, , .
6.8. 8. .
, . .
, , , - .. , , .
, , apache CollectionUtils guava Collections2 Java foreach — .
:
// getting “somestrings” collection somehow
...
Collection<String> lowercaseStrings = new ArrayList<String>();
/* collection is uninitialized here, need to investigate the initializion */
for (String s : somestrings) {
lowercaseStrings.add(StringUtils.lowerCase(s));
}
c:
// getting “somestrings” collection somehow
...
Collection<String> lowercaseStrings = Collections2.transform(somestrings, new Function<String, String>() {
@Override
public String apply(String s) {
return StringUtils.lowerCase(s);
}
}));
Java 8, :
... Collection<String> lowercaseStrings = somestrings.stream() .map( StringUtils::lowerCase ).collect(Collectors.toList());
, . finally catch (, - ). , try, try.
6.9. 9. , .
, Java .
Javascript ( : http://habrahabr.ru/post/154105).
:
var str = "mentioned by";
for(var i =0; l= tweeps.length; i < l; ++i){
str += tweeps[i].name;
if(i< tweeps.length-1) {str += ", "}
}
c:
var str = "mentioned by " + tweeps.map(function(t){
return t.name;
}).join(", ");
, … .
6.10. 10. , , .
, . , :
- .
- , (“comments lie”).
- , .
- .
, . .. , . , , .
// , ( . 5.2).
7. .
, , : . — .
. .
, , , , (, , ), . . , .
, : , , ( ). .
, , (, , ).
, , . , .
, , . , .
, — . “” , , , . . .
, , ( , ) , IDE.
. . , .
!