Help us understand the problem. What is going on with this article?

ソースコードを美しくデザインする

More than 3 years have passed since last update.

はじめに

以前こんな記事を投稿しました。ノンデザイナー・デザイン初心者向け、デザイン虎の巻

上記記事では、デザインという漠然とした問いに対して、キモとなりそうな点をツラツラと挙げています。その中でレイアウトを知るという項目があります。これはプログラミングにおいても役に立つ重要な知識ではないかと思いました。
そこでレイアウトという1デザインメソッドをベースに、ソースコードの整形について具体的に考えてみました。もし何かの参考になれば幸いです。

前提条件

  • ここでのデザインとは設計のような上流・大きなものではなく、コードの見た目に関すること、表面的で単純なものです
  • 名前コメントの整形もある意味デザインとしても考えられますが、ここではレイアウトのみを取り上げたいと思います
  • サンプルコードはJavaScriptになります(考え方なので他言語でも応用できるかと思います)

目次

  • デザインのおさらい
  • 良いコードとは
  • 美しさを表現するための基本メソッド
  • 何を置いても一貫性が大事
  • 視線の誘導を意識する
  • ルールによって要素を整列させる
  • グルーピングで概要を素早く掴む
  • 優先順位をつける
  • 終わりに

デザインのおさらい

良いデザインとは、一体どういうものでしょうか。
概要とポイントをまとめてみます。

良いデザインとは

  • デザインとは思いを相手に伝えるための1手段(自己表現であるアートとは異なる)
  • 良いデザインとは思いを理解してもらいやすい・伝わりやすいもの
  • 美しく機能的であるものは、(意識・無意識問わず)人に伝わりやすい
  • つまりそれがデザインの目指すべき方向の1つとも言える

伝えたい思いが明確にされているという大前提がありますが......

また美しさという単語はやや抽象的なので、ここでは次のように定義します

ターゲットに対して、優しい・使いやすい・理解しやすい・予測しやすい・安心できる・楽しい、といった正の感情をおおよそ包括して与えられるもの

良いコードとは

良いデザインとして考えられるものが、適用できるのではないかと思いました。
優れたコードは、機械だけでなく人に対しても機能的です。機能的かどうかの判断は、他者から見て美しいかどうかという基準でできそうです(ここでの他者とはプロジェクトにおいてコードに直接関わる人、未来の自分を指す)。

例え最高のパフォーマンスを発揮する処理があったとしても、高度すぎて他者がじっくり時間を掛けないとまず理解できないものであれば、残念ながら優れているとは言えないかもしれません。複雑なものが避けられないのであれば、概要となぜそのコードを書いたのかの理由・背景が明確化されていることが望ましいです(そういった情報の補足として使われるコメントアウトは非常に美しいものです)。

美しさを表現するための基本メソッド

レイアウトには美しさを表現するための基礎知識・セオリーといったデザインメソッドが存在します。

  • 一貫性
  • 視線の誘導
  • 整列
  • グルーピング(まとめる・離す)
  • 優先順位

これらはコードにも当てはめることができそうです。
以下、簡単な説明とコードでデザインメソッドを具体的に考えてみたいと思います。

何を置いても一貫性が大事

既に決められたルールがあれば、まずこれを守ることが最も重要となります。例え「ここはイマイチ」「こうした方が美しいのになぁ」と思ったとしても、それを行うことで一貫性を損なってしまうようであれば、それは多くの場合正しいものではありません。一貫性が無いこと自体が最高に美しくないからです

もちろんルール自体に問題がありそうな場合は、再検討して改めて修正し直すことが望ましいですが......(理想論)

どれが正しい見た目かよりもまずは一貫性が大事.js
// どれもやりたいことは同じようなものだが・・・
function hoge(){}
function fuga () {
}
function moge()
{
}

// どれも数値型への変換で結果は同じだが・・・
var num1 = Number(str);
var num2 = Number(str);
var num3 = parseInt(str, 10);
var num4 = str - 0;
var num5 = Number(str);
var num6 = +str;
var bool = num1 === num2 && num2 === num3 && num3 === num4 && num4 === num5 && num5 === num6; // true

<追記>
あえて処理方法を使い分けている箇所があり、その意図がコードからだけでは読み取れなそうな場合は、コメントとして残すべき情報になります(もしくはコードからでも分かるよう名前を工夫する)。
例えば、ここではコレコレこういった値が渡される可能性があるため、parseInt()を使用している、など。

本記事のコメント参照&コメントありがとうございます!

<追記2>
レイアウトしか取り上げないと言いつつ、いきなり上記のvar num1 = ...以下のコード例自体がレイアウトという観点からズレてました。しまった笑

視線の誘導を意識する

縦長のコンテンツを見るとき、視線は左上から右下へ移動していきます。それを想定してコンテンツを置くことは、デザインの基本となります。左上にまずは見せたいタイトルを置き、右下に次に進んで欲しいリンクを置く、など。

コードでは、改行を工夫することでストレスが少なくなるような視線の動きを表現してみます。

右に行ったり来たり忙しい.js
var bool  = num1 === num2 && num2 === num3 && num3 === num4 &&  num4 === num5 && num5 === num6;
var bool2 = hoge !== fuga && fuga === moge;
var bool3 = hoge === fuga || fuga === moge || a === b && b === c;
var bool3 = hoge !== moge;
var bool4 = hoge() === fuga() && moge() === fuga() || abc !== def;
ある程度長さがあるものは改行を挟んだほうが美しいかもしれない.js
var bool = (
    num1 === num2 &&
    num2 === num3 &&
    num3 === num4 &&
    num4 === num5 &&
    num5 === num6
);
var bool2 = (
    hoge !== fuga &&
    fuga === moge
);
var bool3 = (
    hoge === fuga ||
    fuga === moge ||
    a    === b    &&
    b    === c
);
var bool4 = (
    hoge() === fuga() &&
    moge() === fuga() ||
    abc    !== def
);

他者の環境を意識する

自分一人が満足するだけでなく、他者にとっても美しく見えるか(美しく見えない可能性はないか)、想定することも重要です。

同じような値が並んでいるのなら、一列のほうが分かりやすいかも.js
hoge('aiueo', 'kakikukeko', 'sasisuseso', 'tatituteto', 'naninuneno');
hoge('AIUEO', 'KAKIKUKEKO', 'SASISUSESO', 'TATITUTETO', 'NANINUNENO');
hoge('AIueo', 'KAKIkukeko', 'SASIsuseso', 'TATItuteto', 'NANInuneno');
ただし、コードの折り返し制限を定めておらず、エディタ(他者)によってはこう見えるかも.js
hoge('aiueo', 'kakikukeko', 'sasisuseso', 'tatituteto', 
'naninuneno');
hoge('AIUEO', 'KAKIKUKEKO', 'SASISUSESO', 'TATITUTETO', 
'NANINUNENO');
hoge('AIueo', 'KAKIkukeko', 'SASIsuseso', 'TATItuteto', 
'NANInuneno');

ルールによって要素を整列させる

要素を一定のルールで整列させることで、統一感を生み美しさを表現してみます。

問題はないけど分かりにくいかも.js
var $window = $(window);
var $hoge = $('.hoge');
var isFuga = true;
var i = 0;
var aiueo = 'aiueo';

var arr = [100, 1, 10000, 10, 5, 1000];
var arr2 = [1, 100, 10, 10, 5000, 1];
インデントの桁数がバラバラ.js
for (var i = 0; i < 10; i++) {
  for (var l = 0; l < 10; l++) {
      for (var j = 0; j < 10; j++) {
        console.log(j);
      }
    //...
    //...
    //...
    for (var k = 0; k < 10; k++) {
      console.log(k);
    }
  }
}
縦のラインを意識して整列させてみる.js
// = の位置を全て合わせてみる
var $window = $(window);
var $hoge   = $('.hoge');
var isFuga  = true;
var i       = 0;
var aiueo   = 'aiueo';

// 各要素ごとに右揃えしてみる
var arr  = [100,   1, 10000, 10,    5, 1000];
var arr2 = [  1, 100,    10, 10, 5000,    1];
特定の切り口で整列を分けてみる.js
// 注) 上記とコードが違うのはご愛嬌
var $window  = $(window);
var $section = $('section');
var $hoge    = $('.hoge');
var $list    = $('.list');

var isFuga     = true;
var isFuga2    = false;
var isHogeFuga = false;

var num  = 100;
var num2 = 1;
var num3 = 10000;

var i = 0;
var k = 0;
var l = 0;
バランスも重要.js
// これは分かりにくい
var nandakaSugokuNagaiHensuuGaHitsuyouNiNatta = '';
var i                                         = 0;
var tottemoNagaiHensuuDesune                  = '';
var k                                         = 0;

Tabキーは環境によって余白が異なるため、Tabを扱う際は桁数が異なっても崩れないよう配慮が必要です。


<追記>
整列はすべきではないとの考えもあります。整列の作成自体およびメンテナンスには多少なりとも手間が掛かりますし、本質とは関係ない箇所の差分が出るのも困るかもしれません。いずれの場合でもこうすべきとは言い難いので、状況に応じたルール(一貫性)を作れれば良いかと思います。

<参考リンク>
- 変数や配列とかの縦位置を揃えないほうがいい?
- 私がコーディングで垂直方向にそろえるインデントをとる理由

グルーピングで概要を素早く掴む

関連するものは近くに、関連性の薄いものは離します。人はブロック単位で物事を認識するため、論理的なグループや階層によって物理的な距離を分けてやると概要把握の手助けになります。

どこで何をしているのか分かりにくい.js
var height = 100;
var width = 100;
var x = 10;
var calc = function(a, b) {
    return a + b;
};
var showLog = function(log) {
    console.log(log);
};
var y = 10;
var isCheck = false;
var $btn = $('button');
$btn.on('click', function() {
    btnFnc(isCheck);
});
function btnFnc(bool) {
    var val;
    if (bool) {
        val = calc(height, width);
    } else {
        val = calc(x, y);
    }
    showLog(val);
}
目的ごとにブロックを分けてみる.js
/* 変数宣言 */
var $btn    = $('button');
var height  = 100;
var width   = 100;
var x       = 10;
var y       = 10;
var isCheck = false;


/* 関数定義 */
var calc = function(a, b) {
    return a + b;
};
var showLog = function(log) {
    console.log(log);
};
function btnFnc(bool) {
    var val;
    if (bool) {
        val = calc(height, width);
    } else {
        val = calc(x, y);
    }
    showLog(val);
}


/* イベントハンドラ */
$btn.on('click', function() {
    btnFnc(isCheck);
});

ここでは単純に「変数」「関数」「イベント」でのみブロックを分けましたが、更にブロック内でも同じように小グループ単位で整理していくと分かりやすいかと思います

優先順位をつける

デザインでは何を見せたいか、コンテンツに優先順位を付けて、伝えたいものを優先的に見せていくことが重要です。

コードでは動作という面では順番が必須のものも、そうでないものもあります。ここでは順番が必須ではないものに対し、あえて意味を見い出して並べ替えることで一貫性・美しさを表現してみます。

例えばアルファベット順に並べてみる.js
var fuga = 'fuga';
var hoge = 'hoge';
var moge = 'moge';
var x    = 'x';
var y    = 'z';
例えばDOM上の順番に合わせてみる.js
var $win    = $(window);
var $doc    = $(document);
var $body   = $('body');
var $wrap   = $('#contents-wrapper');
var $sec    = $('section');
var $form   = $('form')
var $select = $('select');
var $input  = $('input');
例えば重要度を決めて並べてみる.js
var man = {
    living    : true,    /* まずは生存確認 */
    fName     : '山田',  /* 次に姓+名が重要 */
    lName     : '太郎',
    height    : 170,     /* 身長+体重の順番で */
    weight    : 60,
    hasBrother: true,    /* あまり重要ではない */
    bType     : 'A型'    /* 無くても良い */
};

終わりに

ここではレイアウトに絞ってコード整形を考えてみました。根底は他の人がすんなり理解できるかな、安心してコードを触りたいと思えるかな、というちょっとした気遣いにあります。こういったことが息を吐くようにできる方、きっとデザインも向いているでしょう!!

追記(2015/10/18)
改めて読みなおしてみると上手く表現できていない箇所もある気がするので、本稿の意図を補足します。

美しくデザインするという意味でも、まだまだ考えるべきことはたくさんあります。「誤解を生まない名前にする」「よりシンプルなロジックに書き換える」etc...。またコードという特性上、動作しなければ意味がありませんし、効率的で保守性に優れてパフォーマンスが出ていないと、やはりプログラムとして優秀とは言えません。

ここで取り上げたレイアウトとは小手先のものです。本当に重要なのは、単に改行することでも、整列させることでもなく、どうやったら見やすく・見てもらいやすくできるのかを意識して状況に応じた工夫をすることだと思っています(繰り返しになりますが、ターゲットには将来の自分も含めています)。

それがプログラミング本来の価値を高める「ロジックを精査する」「パフォーマンスを追求する」といったクリエイティビティな作業に繋がる最も近道なのではと考えました(=ケアレスミスを防ぐ、稚拙なロジック・低パフォーマンスに素早く気づくには)。

以上、何かの参考にでもなれば幸いです。
※意図を表現するための記事内のコード例がもっと上手く書ければよかった

nekoneko-wanwan
Webデザイン、フロントエンド開発を主にやっています。真面目なものから、変なものまで。色々な記事を投稿していければと思います。
hotstartupinc
「ペライチ」を開発する会社です。
https://peraichi.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした