ライブラリ化するとファイルサイズが肥大化した。 そこで、ライブラリ化せずに分割する方法を探した。
入手
方法 | GitHub | MEGA |
---|---|---|
.lib分離 | ||
VC++proj内分割 | ||
ディレクトリ分割 |
前回、.libに分割して実装した。 今回は同じソースコードを.libに分割しない方法で分割してみた。 すると.libファイル分のファイルサイズが丸々なくなった。 理由はわからない。 ファイルを軽くしたいなら.lib化せず、exeプロジェクトに含めたほうがいい。
ライブラリ化の問題
ライブラリ化するとファイルサイズが一気に肥大化する。
ライブラリにせず、別のプロジェクトにすることはできない。 VC++でプロジェクト作成すると、プロジェクト単位でバイナリファイルを作成しようとする。 Winアプリ、コンソールアプリ、静的ライブラリ、動的ライブラリ、いずれかを作成してしまう。
対策
1つのWinアプリプロジェクトで、アプリ機能ごとにフォルダ分けする。
前々から気に食わなかったディレクトリ構成
- プロジェクト
- ソースファイル
- ヘッダファイル
- リソースファイル
- 外部依存関係
VC++でプロジェクトを作成すると、こんな感じでファイルが分けられる。 これが気に食わない。
ソースファイルとヘッダファイルの部分が嫌。 こんな分け方じゃ、規模が大きくなったときにまったく意味がない。
こんな感じにしたい
アプリ機能ごとに分離したい。 とりあえず、前回のプロジェクトを参考にすると、以下のように分けたい。
- プロジェクト(Windowsアプリ)
- Main
- Program.cpp
- Window1
- Window1.h
- Window1.cpp
- Initialize
- InitializeWndProc.h
- InitializeWndProc.cpp
- Keyboard
- KeyboardWndProc.h
- KeyboardWndProc.cpp
- Framework
- MultiWindow
- IWndProc.h
- WndProcMapper.h
- WndProcMapper.cpp
- WndClassRegister.h
- WndClassRegister.cpp
- PartWndProc
- IPartWndProc.h
- Window.h
- Window.cpp
- MultiWindow
- Main
方法を考えてみた
方法1
すべてWindowsアプリのプロジェクト配下に入れてしまい、プロジェクトのディレクトリ構成だけ変えてしまう方法がある。
メリット
- 参照設定が一切不要
- ファイルサイズが肥大するライブラリを作らずに済む
問題1
ファイラでプロジェクトファイルをみたら全部一つのディレクトリ内にあるから探すのに苦労する。 いちいち重たいIDEを起動せねばディレクトリ構成がわからない。 すでに完成したプロジェクトで、ちょっと中身を見たいときはテキストエディタで開きたい。 でも、フォルダ構成がないからごちゃ混ぜになってファイルを探すのが大変。
問題2
ファイル名が重複せぬよう工夫を強いられる。
問題3
1ディレクトリに含められるファイルの上限内である必要がある。
NTFSは無制限っぽいが、USBメモリに入れるならFAT32の上限65534にひっかかる可能性もある。 ふつう、そんなにたくさんファイルを作らないから問題にはならないだろうけど。
方法2
メリット
ファイルシステム上も同様のディレクトリ構成でファイルを探せる。
問題1
参照設定が面倒。 アプリ機能が追加されると、その都度、参照設定も追加せねばならない。
問題2
分類なんて曖昧なもの。 そのうち整合性がとれなくなったりしてやり直したりすることがよく起こる。 その都度、ファイルシステム上の構造を変えたり、インクルードパス文字列を生成して設定することになる。
問題3
コンパイラにインクルードするヘッダを参照するパスを渡す必要がある。
しかし、多すぎるとコマンドプロンプトの文字数制限にひっかかる可能性がある。 Windows2000だと2047文字、XP以降だと8191文字。
指標
規模における分割の指標
コード量が多すぎると見づらくなる。小分けにしたい。 分ける単位と量の指標を考えてみた。 あくまで上限の指標。実際はもっと小さくなると思う。
単位 | 最大値 |
---|---|
1ファイル | 1class |
1ファイル | 300行 |
1ディレクトリ | 1機能 |
1ディレクトリ | 8class |
1ディレクトリ | 8ディレクトリ |
1ディレクトリ | 4階層 |
1プロジェクト | 1Windowsアプリ |
1プロジェクト | 1Consoleアプリ |
1プロジェクト | 16参照ライブラリ |
1ソリューション | 4プロジェクト |
1プロジェクト8ディレクトリ4階層。 1prj = 84 = 4096 dir 1dir = 8class * 300行 = 2400行 1prj = 4096 dir * 2400行 = 9830400行
1class300行以内
- 1classをヘッダ(.h)とソース(.cpp)に分離した場合
- 各ファイルが300行以内であればいい
- 1classのヘッダ(.h)とソース(.cpp)の合計が300行を超えてもかまわない
参照ライブラリ
- C++はC#と違い、ライブラリ化してもヘッダファイルが必要
- 1ファイルにまとめられないから、ライブラリ化のメリットが下がる
- 何かの拍子にヘッダファイルを削除したら使えなくなってしまう
- ディレクトリ構成や参照設定も考える必要がある
ユーザとデベロッパの都合
開発では小分けにしたほうが好都合。 開発やテストがしやすい。
でも、エンドユーザに配布するときはexeファイルひとつにまとめたほうが好都合。 間違って削除したり変更したりできてしまうことを防ぎたい。
この辺、どうするのがいいんだろう。 そもそも何が好都合かなんてケースバイケースか。
exeだけにしてアップデートやロールバックまでユーザが制御できるのが一番いいのだけど。 もはやライブラリの話を超えてしまうか。
再利用性における分割の指標
再利用できそうな部分はライブラリ化する。
プロジェクトのソースコードは大きく分けて以下の3つに分けたい。
分類名 | 内容 |
---|---|
Main | 本プロジェクト固有の実装 |
Library | 本プロジェクト固有の機能の実装 |
Framework | 本プロジェクトが利用する抽象化のための実装 |
ただしLibraryはMainの一部ならMainに含めたほうがわかりやすいかもしれない。
ファイルサイズ
分割方法 | exeファイルサイズ | Window1.lib | MultiWindowCreatorClass.lib | PartWndProcClass.lib |
---|---|---|---|---|
.lib分割 | 19 | 2189 | 1729 | 752 |
VC++prj内分割 | 19 | - | - | - |
ディレクトリ分割 | 19 | - | - | - |
.libに分割すると、.lib分だけ増えている。 .libに分割せずexeだけの場合でも、同じソースコードなのに…。 なぜ.libに分けるとこんなにファイルサイズに差が出るのか。
所感
ぜんぜんまとまらない記事になった。 ライブラリのことなど諸々をよくわかっていないからかもしれない。
分割する方法の是非はともかく、単にフォルダ分けすることができるとわかった。 それだけでも収穫。
.libや.dllの話はかなり難しそう。 もっと調べる必要がある。