プログラミングの話を聞いていると「モジュール」という言葉が出てくるけど、なんだかよくわからない…そんなことありませんか?実は「モジュール」は、身の回りにもたくさん存在していて、プログラムをつくる時に超重要な考え方なんです。この記事を読めば、モジュールが何なのか、どうして必要なのか、そしてどうやって使うのかがスッキリわかりますよ。
- モジュールとは、プログラムを機能ごとの小さな部品に分けたもの。レゴブロックのような考え方です。
- モジュールに分けることで、バグの修正が簡単になり、コードの再利用ができるようになります。
- モジュール化することで、プログラムがわかりやすく、管理しやすくなり、複数人での開発も効率よくできます。
もうちょっと詳しく
モジュールの考え方は、実は昔からあります。自動車だって、エンジン、ブレーキ、ハンドルというように部品が分かれていて、壊れた部品だけ交換できるようになっています。プログラムも全く同じで、「ユーザー管理機能」「購入処理」「メール送信」というように、機能ごとに分けておくんです。そうすることで、ある機能を修正する時に、他の機能に影響が出にくくなります。また、「このプログラムでメール送信機能が必要だな」となったら、前に書いたモジュールを再利用すればいい。わざわざ一から書き直す必要がないんです。これが「モジュール設計」の大切さです。
モジュールは「黒い箱」。中身がどうなっているか気にしなくて、入力と出力だけ知ってれば使える!
⚠️ よくある勘違い
→ モジュール化は、学びたての初心者こそやるべき基本的な考え方です。プログラムが大きくなったら誰もがやります。
→ 小さなプログラムでも、機能ごとに分ける習慣をつけることが大事。そうすることで、後で大きなプロジェクトに対応できるようになります。
[toc]
モジュールって実は身近にあった
モジュールの考え方は昔からある
モジュールという言葉は、プログラミングから生まれたものじゃないんです。実は、製造業やものづくりの世界で、昔からありました。たとえば、スマートフォンを想像してみてください。内部には、通信機能、カメラ、バッテリー、ディスプレイなど、いろいろなパーツが入っています。それぞれのパーツは、別々の会社が得意な技術で作られていることもあります。カメラの部分に問題があったら、カメラの部分だけ交換すればいい。バッテリーが古くなったら、バッテリーだけ交換すればいい。全部一緒くたに設計されていたら、1つの部分が壊れたら、スマートフォン全体が使えなくなってしまいます。だから、パーツごと、機能ごとに分けるという考え方が大事なんです。
プログラムも同じ理屈です。大きな機能を全部1つのファイルに書いてしまうと、どこにバグがあるのか分からなくなります。変更したコードが思わぬ所に影響を与えることもあります。だから、機能ごとに分けて、独立した単位として管理するんです。これがモジュール化です。
日常生活の中のモジュール
実は、モジュールの考え方は、プログラムより日常生活の方が分かりやすいかもしれません。たとえば、クローゼットの中を考えてみてください。「上着」「ズボン」「靴下」というように、種類別に分けて置いてあったら、朝、着る服を選ぶのが楽ですよね。全部ごちゃ混ぜだと、欲しい服を探すのに時間がかかる。これがモジュール化です。
キッチンもそうです。「調理道具」「食器」「調味料」というように、用途別に分けて置いてあると、料理がしやすい。全部1つの引き出しに入っていたら、大変です。学校の図書館だって、本が「国語」「数学」「社会」というように分類されているから、読みたい本を見つけやすいんです。このように、モジュールの考え方は、生活のあらゆる場所にあります。
プログラムでモジュールはどう使われているか
プログラミング言語の中のモジュール
プログラミング言語を使ってコードを書く時、モジュールは様々な形で登場します。Pythonという言語では、「import」という命令を使って、他のモジュールを使うことができます。つまり、誰かが作った便利な機能が詰まったパッケージを、自分のプログラムに組み込むことができるんです。
例えば、「日付を扱う計算が必要だな」という時に、わざわざ一から日付計算のプログラムを書きません。既に誰かが作った「dateutil」というモジュールを使えばいい。これが「コードの再利用」です。JavaScriptでも同じです。「このプログラムでファイルを読み込む機能が必要だな」となったら、「fs」というモジュールを読み込めば、その機能が使える。このように、言語ごとに、モジュールの仕組みが用意されています。
関数もモジュールのような役割をする
関数って、学校の授業で習ったと思います。「足す」「かける」といった、ある処理をまとめたものですね。実は、関数もモジュールの一種だと考えることができます。なぜなら、関数は「入力(引数)を受け取って、処理を実行して、出力(戻り値)を返す」という、モジュールの特徴を持っているからです。
例を出してみます。学校の成績を計算するプログラムを書いているとします。テストの点数、提出物の点数、授業態度の点数を合計して、最終成績を出すという処理が必要だとしましょう。この処理を関数にまとめてしまえば、何度も繰り返し使えます。
関数 calculate_grade(テスト点, 提出物点, 態度点):
合計 = テスト点 + 提出物点 + 態度点
return 合計
こんな感じで、ある処理をまとめておくと、別のプログラムでも、同じ計算を何度も何度も書かずに済むんです。これが、モジュール化のメリット、「コードの再利用性」です。
モジュール化すると、なぜ便利なのか
バグを直すのが簡単になる
大きなプログラムを書いていて、バグが発生したと仮定してください。プログラム全体が1つのファイルに、ぎゅっと詰まっていたら、どこにバグがあるのか、探すのに時間がかかります。でも、モジュール化されていて、機能ごとに分かれていたら、「ああ、このバグは『ユーザー認証』モジュールにありそうだな」と、見当をつけやすくなるんです。
それに、『ユーザー認証』モジュールを修正する時、他のモジュールに影響を与える心配が少なくなります。なぜなら、モジュール同士は、決められた接続部分(インターフェース、つまり「入出力」の仕組み)でしか繋がっていないから。1つのモジュール内での変更が、他のモジュールに波及する可能性が低いんです。
複数人での開発がスムーズになる
大きなプロジェクトになると、複数人が同時にプログラムを書くことになります。モジュール化されていないと、皆が同じファイルを編集することになって、どの編集が誰の編集なのか、分からなくなったり、編集が衝突したりします。でも、モジュール化されていて、それぞれが「自分はAさんはユーザー認証を担当、Bさんは購入処理を担当」という風に役割が決まっていたら、別々のモジュールを編集できます。それぞれが独立して作業を進められるから、効率がすごくいいんです。
プログラムを大きくする時も楽
最初は小さなプログラムだったけど、「新しい機能を足したいな」ということになることがあります。モジュール化されていたら、新しいモジュールを足すだけでいい。既存のモジュールに大幅な変更を加える必要がないんです。例えば、最初は「ログイン機能」だけのシステムだったけど、「ユーザーの購入履歴機能」を足したいなら、新しいモジュールを作ればいい。ログイン機能のコードには一切手を加えなくていい。このように、システムの拡張が簡単になるんです。
モジュール設計のコツと注意点
何を基準にモジュールを分けるか
モジュール化する時に大事なのは、「どこで機能を分ければいいのか」を決めることです。間違ったやり方をしてしまうと、逆に複雑になってしまいます。基本的には、「関連した処理をまとめる」というのが原則です。
例えば、オンラインショップのシステムを作るとします。次のようにモジュールを分けるといいでしょう。
- 「ユーザー管理モジュール」:ユーザーの登録、ログイン、プロフィール管理などを一緒にまとめる
- 「商品管理モジュール」:商品の表示、検索、詳細情報などを一緒にまとめる
- 「購入処理モジュール」:買い物かごに入れる、購入手続き、決済などを一緒にまとめる
- 「配送管理モジュール」:住所の入力、配送状況の確認などを一緒にまとめる
こんな風に、関連する処理をグループにしてまとめるんです。」もしくは、「どのモジュールに何が属しているか、一目瞭然だな」という感覚になればいい目安です。
モジュール同士の繋がりを単純にする
モジュール化するもう1つの大事なポイントは、モジュール同士の繋がり(依存関係)をシンプルにすることです。いろんなモジュールが、バラバラに別のモジュールを使っていたら、複雑になってしまいます。
理想的なのは、「AモジュールはBモジュールを使って、Bモジュールはシステムの基本部分を使う」というように、順序が一方向になっていることです。「AはBを使って、BはAを使う」みたいに、グルグル回ってしまうと、バグの原因を特定するのが難しくなります。
モジュールの「約束」を明確にする
モジュールを作る時は、「このモジュールは、こういう形で入力を受け取って、こういう形で出力を返す」という約束(仕様)を決めておくことが大事です。そうすると、他の人が「このモジュールを使いたい」という時に、中身を理解しなくても、使い方が分かるんです。
スマートフォンで例えると、アプリは、「通知」という機能で、スマートフォン本体に「メッセージが来たよ」と伝えます。アプリが、スマートフォンのどの部分を使っているか、細かい中身は気にしなくていい。決められた方法で通知を出せばいい。それが「約束」です。プログラムでも同じことをするんです。
モジュールが小さすぎたり大きすぎたりしないようにする
モジュールの粒度(大きさ)も大事なポイントです。1行のコードをモジュール化するのは、逆に複雑になります。でも、1000行の巨大なモジュールも、管理しづらいです。一般的には、「1つのモジュールで、1つの明確な役割を果たす」くらいの大きさが目安です。
学校でいうなら、「数学の関数」なら、「足し算だけのモジュール」じゃなくて、「四則演算全般を扱うモジュール」くらいがちょうどいい。でも、「学校のすべての勉強」を1つのモジュールにしたら、大きすぎる。そうなると「数学」「国語」「社会」みたいに、さらに分ける必要があります。
