Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-organize the naming convention of module, type, product, and file to have consistent project structure #450

Merged
merged 7 commits into from
May 19, 2024

Conversation

omochi
Copy link
Contributor

@omochi omochi commented May 19, 2024

背景 

#420 で Carton のプロダクトには SwiftPM プラグインが追加されました。

従来の carton コマンドの実装は、
エンドユーザから利用される carton コマンドと
プラグインと、
プラグインから利用される CartonFrontend コマンドの
3層に分割されました。

この3層にはそれぞれ、 bundle, dev, test の機能のロジックが実装されています。
つまり、プロジェクトはおよそ 9個のコード群として実装されています。

課題

これら 9個のコード群について、
ソースコードの実装パターン、ファイル名、型名などに一貫した規則がないため、
プロジェクト全体のコードを読んで回るのが難しいと感じています。

Cartonには多くのOSSコントリビュータが協力することが期待されているため、
初めてソースツリーに触れる人が歩きやすい構造にしておくことが重要です。
特に、3層の構造は一般的に見られない実装パターンであるし、
ただのシンボル参照ではなく IPC が多用されているため、
コード同士の参照関係をIDEだけで追跡することができず、読解しづらいです。
そのため、ファイルツリーのコンベンションで構造のヒントを与えることが有効でしょう。

わかりづらいポイントの具体例を挙げます。

例えば Dev.swift というソースファイルを見かけたとして、
これが 3層のどれに関与するものなのかファイル名からわかりません。

例えば CartonCLI というディレクトリ名、つまりモジュール名を見たとして、
これも 3層との関係が不明です。
2つのコマンドだけではなく、プラグインも command plugin であり、つまり CLI です。

3つのプラグインは Plugin.swift と同じ名前が与えられており、
こちらについては逆にディレクトリ名を見ると 3機能 のいずれであるかがわかるようになっています。

Carton という型名が存在しますが、
これは一見 carton エンドユーザコマンドに関係しているように見えて、フロントエンドです。

CartonFrontend というコマンド名は、
ライブラリのように見えますが、実行可能ファイルです。

実行可能ファイルのエントリポイントも、
main.swift, Main.swift などがありますが、中身はトップレベルコードだったり、 @main 型だったりします。
後者については、ファイルに含まれる型がファイル名から予測できないので、
ファイルツリーからナビゲートしにくいです。

提案

以下のような原則を設けます。

実行可能ファイルは kebab-case にする

これは一般的な慣習です。

トップレベルコードでのエントリポイントは main.swift にする

これは、このファイルの中身にはトップレベルタイプが存在しないからです。

そのファイルが代表的な型を一つ含む場合は、ファイル名と型名を一致させる

こうすることによって、型名からファイルに辿り着きやすくなります。

@main 付きの型を含むファイルは、型名のファイル名にする

上記のルールのもとで、こうなります。

コマンドの実装のモジュール名は、コマンド名の PascalCase にする

こうすることによって、 command-name 実行可能ファイルの実装が、
CommandName モジュールによって提供されているという関係がわかりやすくなります。

コマンド型には Command suffix をつける

コマンド型とは AsyncParsableCommand に準拠する型と、
CommandPlugin に準拠する型の事です。

こうすることによって、その型がコマンドであることがわかりやすくなります。
機能名で型名サーチした時、名前からそれがコマンドなのか、ライブラリなのかわかりやすくなり、
目的のコードに辿り着きやすくなります。

プラグインモジュールには Plugin suffix をつける

こうすることによって、モジュールやディレクトリがプラグインを実装していることがわかりやすくなります。

コマンドプラグイン型には、 CommandPlugin suffixをつける

こうすることによって、
ある型がプラグインコマンドを提供していることがわかりやすくなります。

また Command をつけるもう一つの理由として、
プラグインモジュールと型名を異らせるためです。
これが同じだと Swift言語仕様上の不都合が生じます。

フロントエンドのコマンド型には Frontend をつける

コマンドは3層あるので、どの層なのかすぐわかることが重要です。

実際にはエンドユーザ層は main に書き下されているので2層しか実装はないのですが、
その暗黙の知識がなくとも名前でわかれば便利です。

変更

以上の原則に基づいて、以下のように変更します。

CartonFrontend モジュール

このモジュールは実行可能ファイルです。
モジュール名を carton-frontend に変更します。
CLIのコマンド名も carton-frontend に変わります。

Main.swiftmain.swift にリネームします。

CartonCLI モジュール

CartonFrontend にリネームします。

型名を以下のように変更します。

CartonCartonFrontendCommand
BundleCartonFrontendBundleCommand
DevCartonFrontendDevCommand
TestCartonFrontendTestCommand

また、それぞれのファイル名も同様に変更します。

CartonBundle モジュール

このモジュールはプラグインです。
モジュール名を CartonBundlePlugin に変更します。

CartonBundlePlugin 型は CartonBundlePluginCommand 型にリネームします。
また、それを含むファイルの Plugin.swiftCartonBundlePluginCommand.swift にリネームします。

CartonDev, CartonTest モジュール

CartonBundle プラグインモジュールと同様の変更をします。

carton-release モジュール

これには Main.swift が含まれていますが、
中身は @main のついた CartonReleaseCommand 型だけが含まれているので、
CartonReleaseCommand.swift にリネームします。

チートシート

変更内容を整理した手元のメモも貼っておきます。
内容は同じですがこちらの方が一覧しやすいかもしれません。

module CartonFrontend → carton-frontend
file Main.swift → main.swift

module CartonCLI → CartonFrontend
type Carton → CartonFrontendCommand
type Bundle → CartonFrontendBundleCommand
type Dev → CartonFrontendDevCommand
type Test → CartonFrontendTestCommand

module CartonBundle → CartonBundlePlugin
type CartonBundlePlugin → CartonBundlePluginCommand
file Plugin.swift → CartonBundlePluginCommand.swift

module CartonDev → CartonDevPlugin
type CartonDevPlugin → CartonDevPluginCommand
file Plugin.swift → CartonDevPluginCommand.swift

module CartonTest → CartonTestPlugin
type CartonTestPlugin → CartonTestPluginCommand
file Plugin.swift → CartonTestPluginCommand.swift

module carton-release
file Main.swift → CartonReleaseCommand.swift

@omochi omochi changed the title モジュール名、型名、プロダクト名、ファイル名に一貫した規則を与え、プロジェクト構造がわかりやすくする モジュール名、型名、プロダクト名、ファイル名に一貫した規則を与え、プロジェクト構造をわかりやすくする May 19, 2024
await Carton.main()
}
func main() async {
await CartonFrontendCommand.main()
Copy link
Contributor Author

@omochi omochi May 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

async版の main を呼び出すために async context の中で main を呼ぶ必要があったため、 main 関数に包んでいます。

元のような Main 型は不要な型であり、
他の場所でも生じうるとややこしくなるので、
型を作らないほうが見やすいと思います。

少しだけ行数も少ないし。

Copy link
Contributor Author

@omochi omochi May 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あーだめだこれ、ステータスコードが引き継げていない

Copy link
Contributor Author

@omochi omochi May 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

いやいいのか exitしてるか

@kateinoigakukun kateinoigakukun changed the title モジュール名、型名、プロダクト名、ファイル名に一貫した規則を与え、プロジェクト構造をわかりやすくする Re-organize the naming convention of module, type, product, and file to have consistent project structure May 19, 2024
public static let configuration = CommandConfiguration(
commandName: "carton-frontend",
Copy link
Contributor Author

@omochi omochi May 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

型名から自動設定されるコマンド名がうまくいかないので、手動設定します。サブコマンド3つについても同様です。

Copy link
Member

@kateinoigakukun kateinoigakukun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no opinion here, so let's move forward

@kateinoigakukun kateinoigakukun merged commit e7e0d11 into swiftwasm:main May 19, 2024
2 checks passed
@omochi
Copy link
Contributor Author

omochi commented May 19, 2024

@kateinoigakukun

テストが通ったので確認お願いします。

テストが落ちていたのは、swift-argument-parserがコマンド名を型名から自動設定するためでした。
手動でコマンド名を設定するように修正しました。

swift-argument-parser的には、コマンド名と同じ型名を使うのが推奨かもしれませんが、
これは小さなパッケージに限って有効な設計だと思います。

@omochi omochi deleted the rename-modules branch May 19, 2024 06:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants