美しく並べる:コードレイアウトの重要性
リーダブルなコードを書くための重要な要素の一つは、美しく整えられたレイアウトである。適切に整形されたコードは理解しやすく、メンテナンスも容易になる。
この記事では、コードを視覚的に美しく整理するための基本的なテクニックを紹介する。
適切なインデント
インデントはコードの構造を視覚的に表現する重要な要素である。以下は同じPlayerクラスを異なるインデントで表現した例である。どちらが読みやすいだろうか。
// インデントなし - 読みにくい
class Player {
public id: number | undefined;
public name: string | undefined;
constructor(id: number, name: string) {
this.id = id;
this.name = name;}
getName() {
return this.name;}
getId() {
return this.id;}}
// 適切なインデント - 読みやすい
class Player {
public id: number | undefined;
public name: string | undefined;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
getName() {
return this.name;
}
getId() {
return this.id;
}
}
適切にインデントされたコードは、クラスの構造、メソッドの定義、処理のブロックなどが視覚的に区別できるため、コードの理解が格段に容易になる。
改行の位置の一貫性
長い行や複雑な式を扱う場合、適切な位置で改行することでコードの可読性が向上する。特に重要なのは、改行の一貫性である。
以下は長い変数宣言の例である。どちらが読みやすいだろうか。
// 一貫性のない改行 - 読みにくい
const adminAuthenticationManager: UserAuthManagerFactory =new UserAuthManagerFactory(
config,
"admin",
options,
securityProvider,
database
);
const testAdminManagerAuthenticationManager: UserAuthManagerFactory =
new UserAuthManagerFactory(
config,
"testAdmin",
options,
securityProvider,
database
);
const userAuthenticationManager: UserAuthManagerFactory = new UserAuthManagerFactory(
config,
"normal",
options,
securityProvider,
database
);
// 一貫性のある改行 - 読みやすい
const adminAuthenticationManager: UserAuthManagerFactory =
new UserAuthManagerFactory(
config,
"admin",
options,
securityProvider,
database
);
const testAdminManagerAuthenticationManager: UserAuthManagerFactory =
new UserAuthManagerFactory(
config,
"testAdmin",
options,
securityProvider,
database
);
const userAuthenticationManager: UserAuthManagerFactory =
new UserAuthManagerFactory(
config,
"normal",
options,
securityProvider,
database
);
長い変数宣言では、各引数を独立した行に配置し、インデントを一貫させることでコードの読みやすさが大幅に向上する。また、後から引数を追加・削除する際にも変更箇所が明確になる。
縦の線を揃える
特に表形式のデータやオプション定義などでは、縦の線を揃えることで視認性が大幅に向上する。
// 揃っていない - 読みにくい
options[] = {
{ "ping", NULL, cmd_ping },
{ "servers", NULL, cmd_server_list },
{ "server", options.serverId, cmd_server_info },
{ "members", NULL, cmd_memeber_list },
{ "member", options.memberId, cmd_member_info },
}
// 縦の線が揃っている - 読みやすい
options[] = {
{ "ping", NULL, cmd_ping },
{ "servers", NULL, cmd_server_list },
{ "server", options.serverId, cmd_server_info },
{ "members", NULL, cmd_memeber_list },
{ "member", options.memberId, cmd_member_info },
}
このような整形は、データ構造の視覚的な把握を助け、情報の比較を容易にする。ただし、コードエディタによってはタブとスペースの混在に注意が必要である。
関連するコードをブロックにまとめる
関連する処理を論理的なブロックにまとめ、コメントで区切ることで、コードの全体像が把握しやすくなる。
// 整理されていない - 読みにくい
class Game {
private static FrontendServer frontendServer;
private static BackendServer backendServer;
private static Web3Server web3Server;
public static main void(String[] args) {
viewProfileHandle();
web3Server = Web3Server();
onStart();
saveProfileHandle();
onDamage();
onEnd();
frontendServer = FrontendServer();
findProfileHandle();
backendServer = BackendServer();
deleteProfileHandle();
onAttack();
}
}
// 論理的なブロックに整理 - 読みやすい
class Game {
private static FrontendServer frontendServer;
private static BackendServer backendServer;
private static Web3Server web3Server;
public static main void(String[] args) {
// ハンドラ
viewProfileHandle();
saveProfileHandle();
findProfileHandle();
deleteProfileHandle();
// イベント
onStart();
onEnd();
onAttack();
onDamage();
// 各サーバー起動
frontendServer = new FrontendServer();
backendServer = new BackendServer();
web3Server = new Web3Server();
}
}
段落による分割
長い関数内でも、関連する処理をグループ化し、空行で区切ることで「段落」を作ると読みやすくなる。
# 改善前のコード
def suggest_new_friends(user, email_password):
friends = user.friends()
friend_email = set(f.email for f in friends)
contacts = import_contacts(user.email, email_password)
contact_emails = set(c.email for c in contacts)
non_friend_emails = contact_emails - friend_emails
suggested_friends = User.objects.select(email_in=non_friend_emails)
display["user"] = user
display["friends"] = friends
display["suggested_friends"] = suggested_friends
# 段落で分けた改善後のコード
def suggest_new_friends(user, email_password):
# フレンドのメアドを取得
friends = user.friends()
friend_emails = set(f.email for f in friends)
# ユーザーアカウントから全てのメアドをインポート
contacts = import_contacts(user.email, email_password)
contact_emails = set(c.email for c in contacts)
# フレンドではない連絡先を抽出
non_friend_emails = contact_emails - friend_emails
suggested_friends = User.objects.filter(email__in=non_friend_emails)
# 表示データの設定
display["user"] = user
display["friends"] = friends
display["suggested_friends"] = suggested_friends
return display
段落による分割は、処理の論理的なステップを視覚的に表現し、各部分の役割を明確にする。
まとめ
コードの美しい整形は、単なる見た目の問題ではなく、可読性とメンテナンス性に直結する重要な要素である。この記事で紹介した以下のテクニックを意識すべきである:
- 適切なインデント:コードの論理構造を視覚的に表現
- 一貫性のある改行:長い行を読みやすく整形
- 縦の線を揃える:表形式データの視認性向上
- 関連するコードのブロック化:処理の論理的なグループ化
- 段落による分割:長い関数内での処理の流れの明確化
美しく整えられたコードは、チーム全体の生産性向上にも寄与する。コーディング規約を定め、チームで一貫したスタイルを維持することも重要である。
参考文献
- 『リーダブルコード』(Dustin Boswell, Trevor Foucher 著、角征典 訳、オライリー・ジャパン、2012年)