はじめに
こんにちは!今年の4月に新卒で入社しました、
AXLBIT株式会社開発課の@ax-ueharaです!
今回は、2026年6月の社内勉強会において発表した内容を備忘録も兼ねて、まとめさせていただきます!
内容としては、『10分でわかるリーダブルコード』と題して、リーダブルコードを駆け出しPythonエンジニアの視点で大切だと思ったポイントをまとめたものとなります。

読みやすいコードとは?
そもそも、読みやすいコードとはいったいどんなコードなのでしょうか?
リーダブルコード内では以下のように定義されていました。
他の人が最短時間で"理解"できるようなコード
また、ここで「理解する」というのは、コードを変更したり、バグを修正したりできる状態を指すとされていました。
そんなコードを書くにはいったいどうすればいいのでしょうか?
今回はリーダブルコードの考え方やテクニックを抜粋して、駆け出しPythonエンジニア的視点から紹介させていただきます!
情報を伝える
ここでは、名前の付けかたについて紹介します。
名前は「短いコメント」である
リーダブルコードでは上記のように言われているくらい、名前は重要です。
短い名前でも、うまく情報を詰め込むことができれば、それだけ多くの情報を伝えることができます!
ここから、その名前への情報の詰め込み方のポイントを3つ紹介します!
①具体的な単語を使う(抽象を避ける)
以下の例を見てみます。
# 悪い例
def get_data():
# 良い例
def fetch_active_subscription_users():
悪い例のget_data()は何かを取得する以上の情報を持っていません。これでは、読み手は
中身を読みに行かないと、何をしている処理なのか推測すらできません。
一方で、良い例のfetch_active_subscription_users()は、
- 何を取得するか:アクティブなサブスクリプションユーザー
- どこから取得する処理か:
fetch=外部から取ってくるイメージ
まで一目でわかります。関数の中身を読まなくても、呼び出し元のコードを読むだけで
「ここでは何が起きているか」が推測できるようになります。
②名前に情報を追加する
以下の例を見てみます。
# 悪い例
timeout = 30
response = result
# 良い例
timeout_secs = 30
raw_response = result
悪い例のtimeout = 30は単位がミリ秒、秒なのか名前からはわかりません。
同様に、response = resultもresultが何らかのレスポンスを表す変数として、加工前のデータなのか、すでに何らかの処理を経たデータなのかが名前だけでは判断できません。
一方で、良い例のtimeout_secs = 30は変数名にsecsを加えることで単位(秒)が名前から読み取れます。
raw_response = resultも同様に、raw(加工前)という属性を加えることで、まだ何も処理していないレスポンスであることが一目でわかるようになっています。
③省略・頭文字を避ける
以下の例を見てみます。
# 悪い例
pu = get_pu()
svc = get_svc()
# 良い例
provider_user = get_provider_user()
service = get_service_qs()
悪い例のpuやsvcは書いた本人にはわかっても、他の人がコードを読んだときに何を指しているのか推測できません。特に、自分だけがわかる略語、チーム・プロジェクト固有の省略ルールは、他のメンバーや新しくプロジェクトに参加したメンバーにとっては意味不明な記号になってしまいます。
一方で、良い例のprovider_userやserviceは省略せずに書くことで名前だけで意味が伝わります。
ただし、すべての省略が悪いわけではありません。queryをqry、stringをstr、documentをdocのように、一般的によく使われていて意味が広く理解されている省略形であれば、新しいメンバーも理解できるため、使っても問題ありません。
実行の流れをわかりやすく
ここでは、条件やループなどの制御フローについて読みやすくする方法を、紹介します。
制御フローをできるだけ『自然に』読みやすくすることで、実行の流れがわかりやすくなり読みやすいコードにつながります。
①if/elseブロックの並び順
以下の例を見てみます。
# 悪い例
if not is_admin_user:
show_default_page()
else:
show_admin_page()
# 良い例
if is_admin_user:
show_admin_page()
else:
show_default_page()
悪い例は、is_admin_userでなければデフォルトページを表示し、そうでなければ(=管理者であれば)管理者ページを表示するという処理です。
条件が否定形(not)から始まっているため、読み手は一度頭の中で否定を反転させてから理解する必要があり、読みづらくなっています。
一方で、良い例は、is_admin_userであれば管理者ページを、そうでなければデフォルトページを表示するという処理になっています。
これは、肯定形の自然な流れになっていて、読み手にとって理解しやすい形となっています。なお、条件が複数ある場合は、単純な条件や、目を引きやすい条件を先に書くことでも読みやすさが変わります(ただし、これは優先度や状況によって判断が必要です)。
②関数から早く返す(ガード節を使う)
「ガード節」というテクニックを紹介します。関数の対象外となるケースを先に処理して早めにreturnすることで、ネストが浅くなり読みやすいコードになります。
# 悪い例
def send_email(user):
if user:
if user.is_active:
if not user.is_banned:
if user.email_verified:
send(user)
# 良い例
def send_email(user):
if not user:
return
if not user.is_active:
return
if user.is_banned:
return
if not user.email_verified:
return
send(user)
悪い例は、if文を4段ネストしており、「userが存在する」「is_activeである」「is_bannedでない」「email_verifiedである」という4つの条件を全て満たしたときだけsend(user)が呼ばれる処理になっています。
ネストが深いため、send(user)にたどり着くまでにどの条件を満たす必要があるのか、読み手が追いづらくなっています。
この例では条件が4つなのでまだ追える範囲ですが、条件がさらに増えると読み解くのが難しくなります。
一方で、良い例は各条件を「対象外なら即return」という形に並び替え、成功処理であるsend(user)を一番下に置いています。これにより、ネストがなくなりそれぞれの行が独立した「除外条件」として読めるようになっています。
特に、コードを書いた時点ではネストが浅くても、機能を追加・変更していく過程で気づかないうちに深くなりがちです。ネストが深いコードは読みにくいだけでなく修正もしにくくなるため、変更を加えるときは一歩下がって全体を見直す意識も大切です。
理解しやすい大きさに
コードの塊が大きすぎると、それだけ理解するのに時間がかかり、周りに悪影響を及ぼします。ここでは、巨大なコードを『飲み込みやすい大きさ』に分割する方法を紹介します。
①説明変数を使う
以下の例を見てみます。
# 悪い例
def can_access_admin(user):
if user.username == "root" and user.is_active and not user.is_deleted:
return True
return False
# 良い例
def can_access_admin(user):
username = user.username
is_available = user.is_active and not user.is_deleted
if username == "root" and is_available:
return True
return False
悪い例はif文の条件式にuser.username == "root"、user.is_active、not user.is_deletedという3つの条件がandで連結されたまま1行に詰め込まれています。
1つ1つの条件自体は難しくありませんが、まとめて読まされることで結局何を判定しているのかを一度に把握するのが大変です。
一方で、良い例は、式の一部をusernameやis_availableといった「説明変数」に置き換えています。特に、is_availableはis_activeとnot is_deletedという2つの条件をまとめて「利用可能かどうか」という1つの概念に集約しており、if文の条件式はusername == "root" and is_availableというシンプルな形になります。
②関数も分割する
以下の例を見てみます。
# 悪い例
def update_user_ui_flags(user):
if user.status == "active":
user.is_active_badge = True
user.is_inactive_badge = False
else:
user.is_active_badge = False
user.is_inactive_badge = True
# 良い例
def update_user_ui_flags(user):
if user.status == "active":
active_user_ui_flags(user)
else:
inactive_user_ui_flags(user)
def active_user_ui_flags(user):
user.is_active_badge = True
user.is_inactive_badge = False
def inactive_user_ui_flags(user):
user.is_active_badge = False
user.is_inactive_badge = True
悪い例は、update_user_ui_flagsという1つの関数の中に、状態がactiveのときの処理とそうでないときの処理がすべて詰め込まれています。関数名からは「UIフラグを更新する」ということしかわからず、具体的に何が行われているかは中身を読まないとわかりません。
一方で、良い例は、activeの時とそうでないときの処理をそれぞれ、active_user_ui_flagsとinactive_user_ui_flagsという別の関数に分割しています。update_user_ui_flagsは「状態に応じてどちらの関数を呼ぶか」を判断するだけのシンプルな関数になり、実際の処理内容は関数名を見るだけで推測できるようになっています。
今回は、処理があまり複雑でないため、そこまで効果を感じないかもしれませんが、関数が複雑になればなるほど威力を発揮します。関数として切り出しておくことで、修正やテストもしやすくなります。
まとめ
ここまで、リーダブルコードの中から3つのテーマを紹介してきました。
- 名前に情報を詰め込む:名前は『短いコメント』です。名前を見ただけで情報を読み取れるように意識することが大切です
- 制御フローを読みやすく:条件やループなどを『自然な流れ』で書くことで、実行の流れがわかりやすくなります
-
理解しやすい大きさに:巨大な式や関数は、『飲み込みやすい大きさ』に分割することで理解しやすくなります
これらのポイントを意識するだけでも、理解しやすいコードにつながります!
実際の業務で意識したいこと
ただ、今回紹介したテクニックを実際の業務に取り入れる際は、以下の2点も意識すると良さそうです。
- プロジェクトやPEP8などのコードの規約を確認する
- 読む人の立場になって考える(今の自分ではなく、半年後の自分や、これから参加する新しいメンバーがそのコードを読む場面を想像してみる)
特に、プロジェクトのコードが今回紹介したテクニックと異なる書き方をしていることもあると思います。処理上の理由などで、あえてそうしていることも考えられるため、疑問に思ったときは先輩などに確認し、その背景を含めて理解し、臨機応変に対応していくことが大切だと思います。
おわりに
『リーダブルコード』には、今回紹介した内容以外にも、コメントの書き方、タスクを小さくする方法、読みやすいテストの書き方など、理解しやすいコードに繋がるトピックがまだまだ紹介されています。
駆け出しエンジニアの方や、これからリファクタリングをするという方に非常におすすめです!
気になった方は、ぜひ本を手に取ってみてください!!
参考文献