ルートのファイル構造


ファイル情報

.NETでは、一つのソリューションに複数のプロジェクトファイルを格納し、依存設定に基づいて順次ビルドするようなプロジェクトが構築できるので、そのスタイルを採用しています。

  • fishbornas.sln
ソリューション本体。ArchiveShelfプロジェクト、Hamelnプロジェクト、Pickerプロジェクトへの参照設定が含まれており、これらを編集するためにfishbornas.slnを開いてください。SolutionSandBoxは、ArchiveShelf/Hameln/Pickerの各機能を、同ソリューション内から参照・テストしたい時などに適当に使うためのフリースペースです。お互いに荒らしあう前提で利用してください。
  • BuildTask.sln
BuildTaskプロジェクト用のソリューション。 ArchiveShelfのビルド時に使う、独自のカスタム処理をコンパイルするBuildTaskプロジェクト用のソリューションです。 .NET環境では、Microsoft.Build.Utilities.Taskを継承したクラスを作ると、簡単にプロジェクトファイルのビルドイベントで自動実行する処理を自作する事が出来ます。 (URLからファイルをダウンロードしてくる、という処理を作ってみたのですが、今のところ使っていません)


ディレクトリ構造

  • ArchiveShelf
ArchiveShelfプロジェクトが格納されています。
  • BuildTask
BuildTaskプロジェクトが格納されています。
  • Hameln
Hamelnプロジェクトが格納されています。
  • Picker
Pickerプロジェクトが格納されています。
  • SolutionResource
ソリューション全体に関わるようなリソースのコピー元などをバックアップしておくスペース。
  • SolutionSandBox
好きに使ってください。ただコミットする時コンパイルだけは通るようにしといてね!


プロジェクトの名前空間

主要なオブジェクト指向言語では、クラス型定義の中にクラス型定義が入れ子になるように記述されていきます。 ノード構造を持つことで、言語自体の予約語との衝突を回避しつつ、同じ目的の機能に対して同じ名前を繰り返し用いることが出来るようにして、 可読性を上げる事が出来ます(例えば既存の別のクラスと同じネーミングパターンを近似する事で、その仕様をエミュレーションする事を暗黙に示し、仕様検討のコストも省いたり出来ます)

VB.NETの場合、純粋な名前空間を示すNamespaceは今のところかなり制約が多いので、ArchiveShelfでは、Classを代わりに用いています。

各プロジェクトとも、共通してルート名前空間にTTMT.FASを採用しています。雑な命名なので、修正はしたほうが良いと思います。 短さを保ちたいのですが、ガイドラインによるとかなり長いものになってしまいますね…。 http://msdn.microsoft.com/ja-jp/library/ms229026%28v=vs.100%29.aspx

ArchiveShelfプロジェクトの構成と設計規約

ArchiveShelfでは、それほど厳しいコーディング規約は設定していません…極端な話、読みやすければ全てヨシ、としています(と言うのも、マルチプラットフォームではなく.NET環境を前提にする以上、ある程度必然的に.NET風の記述に集束するからです)。またソースコードを編集するときに「新入りは末端だけ書いてシステムに手をつけちゃいけない!」なんて意識は必要ありません。一方で、平等な自由と設計保守を両立するために、少しユニークな3つのルールを設けてあります。

構成のルール

ArchiveShelfでは各ソースコード・モジュールがまずどんな具体的な機能であるか、よりも前に、おおまかな3つの層によって分類・構成されます。これらはそのままネームスペースを意味するクラスと一致し、またArchiveShelf配下のフォルダ構成にも合致します。まずどこに何を書くかを守ってください。

  • Logic
製品に依らない抽象的な実装を記述する層です。データ構造やアルゴリズムといった準標準ライブラリの役割を果たします。 当然、「かなり具体的に目的を持った機能の名前」ではなく、純粋にふるまいを意味する技術的、学術的な単語が多数見受けられることになります(例:統計解析クラス、ファイルパス文字列クラス)。なお、Logicクラスそのものはクラスとして定義されていますがただのネームスペース的クラスです。
  • AppBase
製品(この場合はArchiveShelfシリーズ)のための実装を記述する層です。この層で、Logicやライブラリの部品を複合して、具体的な機能名を割り当て、ArchiveShelfの基本的な機能全般を格納します。AppBaseクラスは、他の2つの層同様にネームスペース的クラスでもありますが、AppBaseだけはコンストラクタを持ち、AppBase自体をオブジェクトとして利用する事が想定されています。なお、この層のAppBaseという名前は、将来的にArchiveShelfオブジェクトと改名し、表面的な機能仕様と操作方法を文書化して丸ごとエクスポート公開する予定があります(.NETアプリはExeをDll同様にリンクできます)。
  • GUI
フォームデザインや、AppBase各機能とユーザー入出力との関連付けを行います。なおVisualStudioデザイナー機能の都合などGUI部品をGUIネームスペース配下に置けないときは、必ずしもGUIクラス下に配置しなくても良いとしています。実際、現状のところGUIはクラス・ネームスペースとしては存在せず、ただのディレクトリ構造にとどまっています。


■ LogicとAppBaseの区別
まずはAppBaseにいくつか機能を実装するとします。その実装のうち、さらに抽象化して繰り返し共用できる部分を抽出できるなら、それをまたAppBaseかLogicに記述して、プロジェクト全体の再利用率を上げる方法を検討してください。抽象化した再利用部をAppBaseかLogicのどちらに置くのかは曖昧な場合もありますが、そういう時は「もしLogicパートのみをユーティリティライブラリとしてLogic.dllのように単独リリースしたら?」と仮定してみてください。例えばLogicとAppBaseのどちらにもThreadingネームスペースクラスがあります。LogicのThreadingには汎用スレッド機能のみがあります。AppBaseのThreadingにはLogic.Threadingを再利用しつつArchiveShelfのために具体的に実装されたスレッド処理機能があります。難しい時はMLで質問してください。


GUIについて掘り下げる前に、構成のルールを補足するもう1つのルールを示します。

コメントは英語のルール

  • コメントは英語で書く。日本語は禁止。

頑張って英作文するのか、またはちゃんと構造を設計するのか、その二択にします。そして多くの場合、設計と型名と変数名をきちんとしてしまえば、ほとんどはコメントに頼らなくても英文ライクに読める素直なソースコードが出来上がります。とどのつまりは、コメントがなくても読めるのがベストです。そして一度、Grepやジャンプといったソースコードならではの読み進めテクニックを習得してしまえば、意外とコメントというのは有っても無くても、時に長いコメントはとくに、無駄に行が増えて読みにくいだけの存在になってしまうものです。

日本語のコメントを書いて良い例外

文書化ツールのためのコメント(関数説明など)は日本語で記述しても良いとします。
また、文字列定数などはコメントではないので、日本語で書くのは問題ありません。ただ、ユーザーへの視認性などがあまり関係なく、簡潔に書ける定数グループであれば、英語で統一するなどしてください(将来的なローカリゼーションコストもある程度考えていただけると幸い)。

そしてGUIのルール。GUIは、印象や気分次第で最も再配置が頻繁に起こる部分です。なので、ArchiveShelfではGUI層だけに特別な制限を課します。

GUI愚直のルール

  • 実装らしい実装を書かない。
  • 気の利いたソースコードも書かない。

ようするに、GUIだけは思わず蔑んでしまいそうなほど愚直なコードを上から下までダラダラと書き連ねてください、という事です。書き換える時に、手間を惜しむ以上の無念の舌打ちがあってはなりません。GUIは主にフローの実装を行うことになりますが、フロー制御とは、例えばフラグ管理ひとつとっても構造的な安全設計を行いにくく最もヒューマンエラーが起こるシーンになってきます。しかもGUIは気まぐれに仕様変更が起こるものです。愚直のルールとはつまり、そんなGUI製造で、どう転んでもスパゲティを回避するための重要なルールです。リッチな実装を要するGUIを書く唯一の方便は、AppBaseやLogic層に記述する理由を作りそこから呼び出す事です(例えば、何度も再利用できるコンポーネントをAppBaseに記述する、あるいは独立しても再利用できる汎用GUIコンポーネントをLogicに記述するなど)。なお、次の内容に限ってはGUI層にもそれなりに高度な実装が許可されます。

GUIに気の利いた実装を書いて良い例外
  • ArchiveShelfのGUIにしか関係せず、どうしても必要だけど一回しか使わないロジック。
機能らしい機能は原則的にAppBaseクラスの担当です!ただこの場合は他のいずれにも該当しないので仕方ありません。
  • メモリオブジェクトの寿命管理
ユーザー入力は、処理の開始や終了といったフロー制御に対して強い権限を持つため、GUIに書かれる実装のほとんどはメモリの寿命管理になるようにしておいて下さい。


これらのルールを組み立てるにあたり、重要な基準となっているのが「そのソースコードはいつメンテを要するか」という点です。大きく分けて、ソフトウェアのソースコードは「環境に依存するとき」「個別の製品仕様に依存するとき」修正・拡張されます。この2属性の組み合わせに従う時は4つの層に分かれますが、.NETの場合は.NET環境が暗黙に約束されるので「環境依存するかどうか」は系統立てるほど考えなくても良い点になっています。なので、個別の製品仕様に依存するかだけで区分けされます。またもう一点、GUIだけはどうしても気まぐれに仕様変更を呼びます。なので、GUIもまた層として独立させ、フローと実装の境界を明確にします。このプロジェクトでは誰にでも全ての層に等しい編集のチャンスがあります。鉄壁のデグレード対策よりも、例えば新要素の開発工数がどうであれ、それを現況にコミットするための影響範囲や必要な工数だけは、誰にでもすぐに算定しやすいことを重要視しています(なお、エクストリームスタイルに近いため、自動文書化ツールとユニットテスト導入を検討しています)。


最後に、ルールというほどではありませんがお願いがあります。

命名するときのお願い

  • 全角文字はやめて!
  • もっと空気を読んで!

舌を巻くようなネーミングは歓迎します。ただ、日本語型名とか、同じ目的の機能を示す単語の言い回しが場所によって何通りも変わったりするのは、さすがにヤメテ!

これは、一部の人間にとっては本当に当たり前すぎる話なんですが、もし、この言わんとすることがチンプンカンプンな時は、ハッカーになろう How To Become A Hacker というドキュメントをチラと読んでみると、ニュアンスをつかむ助けになるかもしれません。

本当の最後に

もっと合理的で効果の出せる方法があれば、これらのルールもアプリケーションの構造も議論して適宜修正していきましょう。なにぶん、プロジェクト創始者が完全なオープンソース初心者(?)ですので、そのへんはヨロシクお願いしたいと思います。