こんばんは、エリ狐です。
ITで仕事をしていると「美しいソース」、「美しくないソース」という言葉をよく聞きます。
今回はこれら「美しさ」についてまとめます。
雑誌のレイアウトには多くの考えが詰め込まれています。
段落の長さ、横幅、記事の順番、表紙などなど、優れた雑誌というのは、ページを飛ばして読めるようになっています。
また、順番に読めるようになっています。
優れたコードは「目に優しい」ものでなければなりません。
コードを読みやすくするための余白・配置・順序について説明します。
- ソースに一貫性を持たせる
- 似ているコードは「シルエット」を似せる
- 関連するコードをまとめてブロック化する
基本的にはこの3つなのです。
前編(この記事)では「美しいソースが必要なわけ」、「ソースの一貫性」、「シルエット」について説明していきます。
前編と後編に分けます!!
美しいソースが必要なわけ
■汚いソース例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class:class StatesTest{ public: // doubleを保存するクラス void Add(double d); // と素早く統計を算出するメソッド private: int count; /* それまでの 個数 */ public: double Average(); private: double minimum; list<double> past_items ;double maximum; }; |
■美しいソース例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// doubleを保存するクラスと // 素早く統計を算出するメソッド class:class StatesTest{ public: void Add(double d); double Average(); private: list<double> past_items; int count; //それまでの個数 double minimum; double maximum; }; |
これら2つを比較すると断然「美しいソース」の方が読みやすいですよね。
もちろん、このプログラムをあなたが再利用する場合においても、断然「美しいソース」を選択するでしょう。
このように、見た目が美しいコードの方が使いやすいのです。
したがって、さっさと流し読みができるようになれば、誰にとっても使いやすいコードだと言えます。
またプログラミングの時間は、コーディングする時間よりも「読む時間」が多いです。
そのため「ソースを理解するまでの時間」が短い方が作業が早く終わったり、間違いを少なくできます。
したがって、「美しいソース」を書くことはとても重要です。
一貫性のある記述について
ソースの一貫性は色々あります。
前半では「一貫性のある簡潔改行位置」についてみていきます。
ここでは、とある4つの引数があるコンストラクター(TestConnectionSimulator)を例に説明します。
- 通信速度(Kbps)
- 平均遅延時間(ms)
- 遅延時間(ms)
- ロス率
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class PerformanceTester { public static final TestConnectionSimulator wifi = new TestConnectionSimulator( 500, /* kbs */ 80, /* ms */ 200, /* ms */ 1/* % */); public static final TestConnectionSimulator test_fiber = new TestConnectionSimulator( 45000, /* kbs */ 10, /* ms */ 0, /* ms */ 0/* % */); public static final TestConnectionSimulator coll = new TestConnectionSimulator( 100, /* kbs */ 400, /* ms */ 250, /* ms */ 5/* % */); } |
企業のアプリケーションの開発に携わると「コーディング規約」というものがあります。
そこでは1行幅の文字数が決まっていることが多く、横幅を合わせるために余計な改行を入れなければならない時が出てきます。
このように「浮いてる」ソースは美しくありません…
つまり「イケてないソース」と言います。
最初の3ヶ条で述べた「似ているコードは「シルエット」を似せる」が守られていないので、一貫性を持たせるために適切な改行を入れる必要があります。
■美しくしたソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class PerformanceTester { public static final TestConnectionSimulator wifi = new TestConnectionSimulator( 500, /* kbs */ 80, /* ms */ 200, /* ms */ 1 /* % */); public static final TestConnectionSimulator test_fiber = new TestConnectionSimulator( 45000, /* kbs */ 10, /* ms */ 0, /* ms */ 0 /* % */); public static final TestConnectionSimulator coll = new TestConnectionSimulator( 100, /* kbs */ 400, /* ms */ 250, /* ms */ 5 /* % */); } |
いかがでしょうか。
このように「シルエット」を意識することで、一貫性を持たせることができ、楽に目を通すことができます。
しかも同じコメントが3回も繰り返されてるよ??
そーいう場合には、仮引数コメントを書いて横にしちゃいましょう!!
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class PerformanceTester { // TestConnectionSimulator("接続速度", "平均遅延時間", "遅延時間" , "ロス率") // [kbs] [ms] [ms] [%] public static final TestConnectionSimulator wifi = new TestConnectionSimulator(500, 80, 200, 1); public static final TestConnectionSimulator test_fiber = new TestConnectionSimulator(45000, 10, 0, 0); public static final TestConnectionSimulator coll = new TestConnectionSimulator(100, 400, 250, 5); } |
コメントを上部に移動して仮引数を1行書くことで、数値の右コメントが不要となりました。
一貫性がないのなら「シルエット」を作れ!
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DatabaseConneciton database_Conneciton; string err; assert(ExpandFullName(database_Conneciton, "エリ狐くん", &err)) == "Mr. エリ狐"); assert(err == ""); assert(ExpandFullName(database_Conneciton, "エリーヴァ", &err)) == "Mr. エリーヴァ"); assert(err == ""); assert(ExpandFullName(database_Conneciton, "名無しさん", &err) == ""); assert(err == "見つかりませんでした。"); assert(ExpandFullName(database_Conneciton, "エリ", &err) == ""); assert(err == "複数見つかりました。"); |
このパターンは、第一声「う●こ」って言いたくなるほど…見た目が汚いですよね。
また、1行が長すぎて折り返されているところもあります。
そして「シルエット」はブサイクだし、何より一貫性がありません。
「シルエット」を作ってしまえ!!
ということです!
■メソッド
1 2 3 4 |
CheckFullName("エリ狐くん", "Mr. エリ狐", ""); CheckFullName("エリーヴァ", "Mr. エリーヴァ", ""); CheckFullName("名無しさん", "", "見つかりませんでした。"); CheckFullName("エリ", "", "複数見つかりました。"); |
これなら引数の異なる4つのテストがあることがよくわかるね!
1 2 3 4 5 6 7 8 9 10 |
void CheckFullName( string part_name, string expect_full_name, string expect_err) { // database_Conneciton クラスのメンバー string err; string full_name = ExpandFullName(database_Conneciton, part_name, &err); assert(err == expect_err); assert(full_name == expect_full_name); } |
この記事の目標はソースの「美しさ」についてでしたが、このように構造を改善することも重要です。
このように、コードの見た目を意識することで…
- 重複行がなくなり、コードが簡潔になった
- 試験する際に重要な部分(名前、エラー文字列)がみやすくなった
- 試験パターンが減った
次回はその他の「ソースの一貫性」についてまとめていきます。
前半部分のまとめ
- 複数のコードブロックで類似処理があったら、シルエットも同じようにする
- コード列を整理すれば、全体の概要がわかりやすくなる
- コードの見た目を表面上を改善すると、構造も改善できる
誰でも美しいコードを見るのが好きです。
そのため一貫性を持たせることは素早く簡単に読むことができるので重要となります。
次回も引き続き美しいソースを書くための方法「関連するコードのブロック化」についてまとめていきます。