DUICUO

Guarding: オープンソースの多言語アーキテクチャデーモン

[[408185]]

ガーディング入門

Guardingは、Java、JavaScript、Rust、Goなどの言語で使用できるアーキテクチャデーモンツールです。ArchUnitに着想を得たGuardingは、わかりやすいDSLを用いてデーモンルールを記述します。Windows、macOS、GNU/Linuxシステムをサポートしています。

使用

簡単に言えば、読みやすいDSLを使ってアーキテクチャルールを記述できます。これらのアーキテクチャルールは、主流の言語で使用できます。以下は、Guardingを使用して記述したルールの例です。

  1. package( "." )::file.len は 200 未満である必要があります。
  2. package( "." )::file.len は 50 より大きい必要があります。
  3.  
  4. クラス( "java.util.Map" )のみアクセスされます([ "com.phodal.pepper.refactor.staticclass" ]);
  5. クラス(実装"BaseParser" )::len = 2
  6. class ( implementation "BaseParser" )::名前 含む  「レクサー」 ;
  7.  
  8. struct( "..myapp.." ):: function . name には( "Model" )が含まれている必要があります
  9. struct( "..myapp.." )::関数.名前  ( "" )を含む

上記の例から、次のことがわかります。

  1. ArchUnit に慣れている方は、すぐに Guarding コードを書き始めることができます。もちろん、構文の多くはまだ開発中です。
  2. Guardingは中国語を非常によくサポートしています。ただし、英語と中国語のテンプレートの切り替えが問題だと思います。
  3. ガーディングは、Rust または Golang の class を struct に置き換えるなど、より多くの構文をサポートできます。

走る

Guarding の実行も非常に簡単です。`guarding .` を実行するだけです。

インストール

もちろん、インストールも非常に簡単です。GitHub(https://github.com/inherd/guarding)からダウンロードするだけです。あるいは、Rust環境をお持ちの場合は、「cargo install guarding」と入力するだけでインストールできます。

伸ばす

では、ガーディングを拡張するにはどうすればよいでしょうか?

建築を守る

次の図は、ガーディングのプロセスを示しています。

建築を守る

  1. つまり、ガーディング手順は次の 3 つの部分で構成されます。
  2. ガードルールパーサー。
  3. 多言語対応パーサー。解析ツールとしてTreesitterを使用し、S式と組み合わせて解析を行います。

ガードルール実行者。

多言語ソースコード解析

言語解析に関しては、一連の試みを行ってきました。

分析方法の選択

これはAntlrの標準言語解析に基づいています。当初Guardingを設計する際には、Antlrが公式にメンテナンスしているサードパーティ製の貢献文法ライブラリをベースにしたCocaに似た手法を使用する予定でした。しかし、私にとってこれは古い解析手法なので、おそらく使用しません。

Ctagsに基づく構文解析。もう一つの選択肢は、設計およびモデリング段階でCtagsを使用することです。Ctagsは、プログラムのソースコードツリーからインデックスファイル(またはタグファイル)を生成するユーティリティであり、テキストエディタで情報を素早く見つけやすくします。しかし、Ctagsを使用するにはバイナリパッケージをインポートする必要があります。そのため、まずctags-sysをビルドし、その後、長いCtags解析メソッドを記述する必要があり、非常に時間がかかりました。

LSPベースの構文解析。LSP(Language Server Protocol)の使用を簡単に評価しましたが、LSPを使用すると言語依存の要素がさらに増えるため、依然として実現不可能なアプローチです。

Uncodeの設計を改良しているうちに、Tree-sitterで同じ機能を実現できることが発見されました。Tree-sitterは当初、Atomエディターに導入された実験的な機能でした。Tree-sitterはRust、JavaScript、Python、Ruby、Haskellをサポートしています。HaskellやRubyのようなニッチな言語と比べると、比較的馴染みのないRustはまあまあといったところです(笑)。しかし、パフォーマンスに関しては、Rustはそれらの中で最高です。

解析例

以下は簡単な C++ クラスの例です。

  1. クラス MyClass {
  2. 公共
  3. 整数myNum;
  4. 文字列 myString;
  5. };

TreeSitter は上記の CPP コードを構文ツリー (部分的に) に解析します。

  1. 翻訳単位 [0, 0] - [6, 0]
  2. クラス指定子 [0, 0] - [4, 1]
  3. 名前: type_identifier [0, 6] - [0, 13]
  4. 本体: フィールド宣言リスト [0, 14] - [4, 1]
  5. アクセス指定子 [1, 2] - [1, 9]

次に、対応するクエリ構文ツリーの S 式を記述します。

  1. (クラス指定子
  2. 名前: ((type_identifier) @クラス)

S 式は構文ツリーから対応するノードを識別し、ここでは @class-name のようにノード情報を変数に割り当てます。

TreeSitter が提供するオンライン プレイグラウンドから試すことができます: https://tree-sitter.github.io/tree-sitter/playground

ガーディング構文解析と設計

GuardingはRust言語で開発されています。LalrpopやAntlrといったパーサーは既に使用しているため、今回はpestを使用します。これらのパーサーの学術的な違いについては深く掘り下げていませんが、私はニーズに基づいて、あまり使用しない方を選んでいます。以下はguarding.pestのコード例です。

  1. 通常のルール = {
  2. ルールレベル ~ ( "(" ~ スコープ ~ ")" )? ~ (use_symbol ~ 式)? ~ すべきか? ~のみ? ~ 演算子 ~ アサート ~ ";" ?
  3. }
  4.  
  5. ルールレベル = {
  6. 「パッケージ」 |
  7. 「クラス」 |
  8. 「構造体」 |
  9. 「機能」 |
  10. "ファイル"  
  11. }

ドキュメントと例には、Guarding 構文とキーワード情報の開発プロセスの記録が含まれています。

パッケージパスの解決

パッケージ パスの解決については言及する価値があるため、私たちのパッケージ解決方法は ArchUnit の設計に基づいています。

アーキテクチャ保護のためのガーディングの使用方法

GuardingはRust言語を使用しているため、バイナリはすべての主要なオペレーティングシステムに直接対応しています。また、CLIメソッドを使用しているため、以下のようなあらゆる段階で使用できます。

  • Git フックを使用してローカルでコードのコミット前チェックを実行します。
  • これは、継続的インテグレーション フェーズ中にパイプライン操作と組み合わせて使用​​されます。
  • IDEA/エディター プラグインによるリアルタイム検査 (まだ実装されていません)。

もちろん、このアプローチは単一のチームに適用されます。より大規模なチームの場合は、異なるアプローチを取ることができます。

  1. テンプレートの継承 (もちろん、まだ実装されていません)。

他の

Guarding の開発への参加を歓迎します: https://github.com/inherd/guarding

この記事はWeChat公式アカウント「phodal」から転載したものです。以下のQRコードからフォローできます。転載の許可については、「phodal」公式アカウントにお問い合わせください。