Web制作、Web開発の歩き方

分かりやすいコードの書き方

第3話:適切な関数の分割

(最終更新日:2025.4.6)


分かりやすいコード

この記事は5分で読めます!
(絵が小さい場合はスマホを横に)

適切に分割しよう!

コードが読みにくくなる原因の一つが「関数が長すぎて、何をしているのか分からない」ことだ。 始めは短くて分かりやすいロジックだったとしても、 機能が追加され、ロジックを加えていくうちに分かりにくくなることはよくある。 今回は、そんな関数をどのように分割すれば、読みやすく、保守しやすく、再利用性の高いコードになるのかを解説する。



1.1つの関数は1つの責務

まず大前提として、関数は「1つの目的」だけを果たすように書くべきだ。 これを単一責任の原則(Single Responsibility Principle)と言う。 時と場合にもよるが、基本的には、1つの関数に処理を詰め込みすぎないことが重要だ。 コメントで省略している(実際にはif文、for文などの処理で非常に長くなる)が、下記のような関数は良くない。 1つの関数に複数の責務(チェック・計算・通知・更新)が含まれていて、テストしづらく、再利用も困難になる。

分割されていない関数

次に良い例を示す。関数の中に小さな関数で分割されているのが分かる。 1つの関数に1つの目的だけを果たすようにしているので、テストがしやすく、再利用も容易だ。 また、適切に関数が命名されていれば、どんな処理をしているのかも明らかになる。 先ほどのように、コメントで記さなくても関数が処理を示すので、非常に読みやすい。

分割された関数

2.適切な関数の長さと関数分割の基準

一概に「何行以内」と断言はできないが、10〜20行以内が適切な関数の長さの目安と言える。 ただ、長さよりも読み手への分かりやすさを重視した方が良い。あくまで分割の目安である。 画面にスクロールせずに収まり、各関数間の抽象度が揃っていることが大事だ。 テストや再利用をしやすくするためにも、小さくて明確な関数が良い。

次に関数分割を行うか否かの基準だが、次の三点を基準にすると良い。

  1. 処理が複雑になった(複数の処理を1つの関数に書いていると読みにくくなる)
  2. 同じ処理が複数箇所にある(重複コードは分割して共通化)
  3. 関数名がうまく付けられない(複数の責務が混在している)
3.命名、分割しすぎのリスクとその回避方法

関数名は「何をするか」を明確にするために動詞から始めるのが基本だ。 下記に悪い例と良い例を示す。悪い例(名詞、もしくは動詞だけ)だと何をどうするか分からない。 一方、良い例では「動詞+目的語」で書かれているので、何をどうするか(E-mailを送る)が明らかである。

悪い例 良い例
data() loadData()
email() sendEmail()
check() checkInventory()
update() updateUserProfile()

今まで、関数は分割するようにと言ってきたが、関数を小さく分割しすぎると、 かえって処理の流れが断片化してわかりにくくなることがあるので、注意が必要だ。 適切な粒度で分割することが求められる。 下記に悪い例と良い例を示した。名前にした時、処理の流れが想像できるのが理想だ。 「動詞+目的語」でスッキリ命名できない場合は、処理が小さすぎるか大きすぎると思っておこう。

分割しすぎ(悪い例)と適切な分割(良い例)


4.リファクタリングの実例

上記の集大成として、リファクタリングの実例を示す。 まずは、リファクタリング前の、分割されていない関数を示す。 「Welcomeメッセージの作成」と「E-mailの送信」、2つの処理が混在していて読みにくい。

リファクタリング前

次にリファクタリング後の実例を示す。 「ユーザー名を引用したWelcomeメッセージの作成」と「E-mailの送信」を分けたことで意味が分かりやすくなっている。 加えて、2つを合わせた場合よりも、各々の関数でテスト、再利用しやすくなったことが分かる。 例えばE-mailの送信は、今回のようなWelcomeメッセージが無い場合でも使える。また、変更もしやすい。

リファクタリング後

5.まとめ

今回は関数の分割方法について解説した。 関数は1つの目的だけ持たせて、長さはできれば20行以内が好ましい。 ただし、分割しすぎて使いづらい時は、長さと命名を再度考える。 重複コードや複雑な処理は分割のサインになる。そして、関数名は「動詞+目的語」で意味が分かるようにする。 このような創意工夫が、あなたのプログラムを読みやすいコードにしてくれるはずだ。

▼参考図書、サイト

 「リーダブルコード」 Dustin Boswell、Trevor Foucher 著、角 征典 訳 オライリー

How to Write Understandable Code Episode 3: Proper Function Decomposition (Last updated: 2025.4.6) Understandable Code Reading time: 5 minutes (Turn your phone sideways if the image appears small) Split smartly! One of the main reasons code becomes hard to read is because functions are too long and unclear. Even if the logic starts off simple, as features are added, functions often become cluttered. In this article, we’ll explain how to properly split functions to improve readability, maintainability, and reusability. [Contents] 1. One Responsibility per Function 2. Ideal Function Length and Split Criteria 3. Naming and Over-Splitting Risks 4. Refactoring Example 5. Summary 1. One Responsibility per Function As a basic rule, each function should serve a single purpose. This is known as the Single Responsibility Principle. While it depends on the situation, it’s generally best not to overload a function. Below is a bad example (commented code omitted), where one function contains multiple responsibilities: checks, calculations, notifications, and updates. This makes it hard to test or reuse. Poorly split function The following is a good example. The function is broken down into smaller ones, each with a clear single purpose. It becomes easier to test and reuse. Moreover, with proper naming, the purpose is clear even without comments. Well-split function 2. Ideal Function Length and Split Criteria There’s no strict rule, but 10–20 lines is a good target length for a function. Rather than length alone, prioritize clarity for the reader. It's ideal if a function fits on screen without scrolling and the abstraction level is consistent. Smaller, focused functions are easier to test and reuse. Here are three good indicators for when to split a function: The logic is getting too complex (multiple types of processing in one function) Duplicated code exists (common processing should be extracted) You struggle to name the function clearly (likely doing too many things) 3. Naming and the Risk of Over-Splitting Function names should start with a verb to clearly indicate what the function does. Below are examples of bad and good naming. Bad examples (nouns or vague verbs) are unclear. Good examples use a "verb + object" structure, making the purpose immediately obvious. Bad Example Good Example data() loadData() email() sendEmail() check() checkInventory() update() updateUserProfile() While splitting functions is encouraged, over-splitting can make the logic hard to follow. Maintain appropriate granularity. Below is a comparison of poor over-splitting and a good balance. If you can't give the function a clean "verb + object" name, it's likely too small or too large. Bad (over-split) vs. Good example 4. Refactoring Example Let’s look at a real example. Below is the original unrefactored code. It mixes creating a welcome message and sending an email, making it difficult to read. Before Refactoring Below is the refactored version. Separating "Create Welcome Message" and "Send Email" makes the code more understandable, testable, and reusable. For example, the email function can now be reused in other contexts and is easier to modify independently. After Refactoring 5. Summary In this article, we explored how to split functions effectively. Each function should serve a single purpose, ideally within 20 lines. Avoid over-splitting, and always reconsider both naming and size. Duplicated logic and complex processing are signs it's time to refactor. Aim for clear names in "verb + object" format. These practices will help you write more readable and maintainable code. ▼References  "Readable Code" by Dustin Boswell & Trevor Foucher, Japanese edition by Masanori Sumi, O'Reilly Japan