読者です 読者をやめる 読者になる 読者になる

自由課題

学んだり、考えたり、試したりしたこと。

リーダブルコードを書くこと、あるいはコードをデザインすること

リーダブルコードという書籍を読みました。
私はデザイナというわけでは全くないのですが、視覚デザイン(知覚心理学)におけるゲシュタルトの法則と類似点を感じたのでまとめておきます。

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

ゲシュタルトの法則とは、人間はあるルールに従った「まとまり」単位でものを認識するということを示しています。 具体的には下記の法則があるそうです。
(法則自体の詳細はリンクを参照してください)

  • 近接の法則
  • 類同の法則
  • 共通運命の法則
  • 良い連続の法則
  • 閉合の法則
  • 面積法則
  • 対称性の法則

この逆を取る、つまり上記の法則で表される「まとまり」として認識しやすいようにコードを整理するとリーダブルになるのではないかと思っています。

次のような(おそらく読みにくい)C++のコードを例にとって説明します。これにゲシュタルトの法則を適用してみたいと思います。なお、コード自体にはあまり意味はありませんので悪しからずご了承ください。

class Member;
static const int MembersMax = 10;
class TeamMembers
{
public:
Member& get_member_at(int index);

private:std::map<int, Member&> members;
public:
bool IsInTeam(
  const Member &member
  );
~TeamMember();

TeamMember& addMember(Member &member);
    TeamMember();};

ここに類同の法則を(逆)適用してみます。本来の類同の法則とは、色や形状が似たものはまとまりとして認識しやすいというものです。
コードには色や形はないので、ここではpublicとprivateのかたまりに分けてみます。(説明がしやすいように、改行含めなるべくそのままの状態で分けます)

class Member;
static const int MembersMax = 10;
class TeamMembers
{
public:
Member& get_member_at(int index);

bool IsInTeam(
  const Member &member
  );
~TeamMember();

TeamMember& addMember(Member &member);
    TeamMember();
private:std::map<int, Member&> members;};

さらに類同感(?)が出るように、メソッドの記法を統一し、コンストラクタ/デストラクタと通常のメソッドを並べかえます。

class Member;
static const int MembersMax = 10;
class TeamMembers
{
public:
  Member& get_member_at(int index);
  bool IsInTeam(const Member &member);

  TeamMember& addMember(Member &member);
  TeamMember();
  ~TeamMember();
private:
  std::map<int, Member&> members;
};

次に近接の法則を考えてみます。
上記で分けたかたまり同士を近接させ、かたまりの間に改行を入れて距離を空けます。

class Member;
static const int MembersMax = 10;
class TeamMembers
{
public:
  Member& get_member_at(int index);
  bool IsInTeam(const Member &member);
  TeamMember& addMember(Member &member);

  TeamMember();
  ~TeamMember();

private:
  std::map<int, Member&> members;
};

だんだんムリヤリ感が漂ってきますが、共同運命の法則を考え、クラス外の関連する定数をクラス内に入れて、関連性を強調します。ここでも類同の法則・近接の法則を意識して配置します。

class Member;

class TeamMembers
{
public:
  Member& get_member_at(int index);
  bool IsInTeam(const Member &member);
  TeamMember& addMember(Member &member);

  TeamMember();
  ~TeamMember();

private:
  static const int MembersMax = 10;

  std::map<int, Member&> members;
};

ということで、まだまだ改良の余地はありますが、たったこれだけの工夫でもそれなりに リーダブルなコードになったのではないでしょうか。

個人的にはなるべく少ない法則から多様な結果を導くのが美しいと思うので、 このような基本的な法則から読みやすいコードとはどういうものかを考えるのも有益だと考えています。 リーダブルコードの書籍には、このような物理的な美しさ以外にもコードをリーダブルにするための いろいろなノウハウが詰まっているので、興味がある方はぜひご一読を。

ちなみに、色分けすることでも類同の法則を強調できるので、

class Member;

class TeamMembers
{
public:
  Member& get_member_at(int index);
  bool IsInTeam(const Member &member);
  TeamMember& addMember(Member &member);

  TeamMember();
  ~TeamMember();

private:
  static const int MembersMax = 10;

  std::map<int, Member&> members;
};

のようにカラースキームを適用することは、人間の認知の仕組み上でも有効であるといえそうです。

ノンデザイナーズ・デザインブック [フルカラー新装増補版]

ノンデザイナーズ・デザインブック [フルカラー新装増補版]