いくつかの再利用可能なコードのアーキテクチャ
-
23-08-2019 - |
質問
私は、共通の構造を共有し、同じ方法で同じ事のいくつか(例えば、ロギング、データベースの接続設定、環境設定)を行う必要があり、小さな、簡単なアプリケーションの数を書いていますし、私はいくつかのアドバイスを探しています再利用可能なコンポーネントを構成しました。コードを強くし、静的型付け言語で書かれている(例えば、JavaやC#が、私は両方でこの問題を解決するために持っていました)。現時点では私はこれを持ってます:
abstract class EmptyApp //this is the reusable bit
{
//various useful fields: loggers, db connections
abstract function body()
function run()
{
//do setup
this.body()
//do cleanup
}
}
class theApp extends EmptyApp //this is a given app
{
function body()
{
//do stuff using some fields from EmptyApp
}
function main()
{
theApp app = new theApp()
app.run()
}
}
より良い方法はありますか?おそらく、次のように?私はトレードオフを計量トラブルを抱えている...
abstract class EmptyApp
{
//various fields
}
class ReusableBits
{
static function doSetup(EmptyApp theApp)
static function doCleanup(EmptyApp theApp)
}
class theApp extends EmptyApp
{
function main()
{
ReusableBits.doSetup(this);
//do stuff using some fields from EmptyApp
ReusableBits.doCleanup(this);
}
}
1つの明らかなトレードオフは、オプション2で、「フレームワーク」はtry-catchブロックでアプリをラップすることができないということです...
解決
私はいつも構図(2番目のオプション)ではなく、継承(あなたの最初のオプション)を介して再使用することを支持してきます。
クラス間ではなく、コードの再利用のための関係が存在する場合、の継承のみが使用されるべきである。
あなたの例のために、私は複数のReusableBitsクラスごとやって1つの事を持っているでしょうので、各アプリケーションのメイク使用など/必要なときます。
これは、各アプリケーションが個々のアプリケーションより多くの自由を許可、すべてを取ることを余儀なくされることなく、その特定のアプリケーションに関連するあなたのフレームワークの再利用部品を可能にします。あなたは正確にあなたが今日心を持っている構造に適合しない将来にいくつかのアプリケーションを持っている場合は再利用継承によって、時には非常に制限的になることができます。
あなたが別のユーティリティにあなたの枠組みを壊す場合は、また、ユニットテストとテスト駆動開発がはるかに簡単に見つかります。
他のヒント
なぜ、あなたのカスタマイズ可能なコードの上にフレームワークのコールを作ってみませんか?だからあなたのクライアントは、いくつかのオブジェクトを作成し、フレームワークにそれを注入します。フレームワークの初期化し、setup()
などを呼び出し、その後、クライアントのコードを呼び出します。終了時(あるいはスローされた例外の後に)、フレームワークは、次にcleanup()
と終了を呼び出します。
だからあなたのクライアントは、単純な(Javaで)
とのインタフェースを実装しますpublic interface ClientCode {
void runClientStuff(); // for the sake of argument
}
とフレームワークコードは、この実装で構成され、必要なときはいつでもrunClientStuff()
を呼び出している。
は、の派生アプリケーションフレームワークからの、単に特定の契約に準拠したクラスを提供します。あなたがアプリから派生していないので、あなたの依存関係が静的ではありませんので、あなたは(例えば、どのようなクラスのクライアントがアプリケーションに提供します)、実行時にアプリケーションの設定を構成することができます。
上記のインタフェースは、複数のメソッドを持つように拡張することができ、アプリケーションが(クライアント固有のセットアップ/クリーンアップを提供するために、例えば)のライフサイクルに異なる段階で必要なメソッドを呼び出すことができますが、それが機能クリープの例です: - )
は、継承が継承されているすべてのオブジェクトは、その類似性のために、コードのデュオを再利用する場合にのみ良い選択であることを覚えておいてください。またはあなたが発信者が同じ核分裂でそれらと対話できるようにしたい場合。 私が今述べたことは、あなたに適用される場合、その常により良いお使いのベース/抽象クラスに共通のロジックを持っている私の経験に基づいています。
これは私がC#でサンプル・アプリケーションを再書き込みする方法をされています。
abstract class BaseClass
{
string field1 = "Hello World";
string field2 = "Goodbye World";
public void Start()
{
Console.WriteLine("Starting.");
Setup();
CustomWork();
Cleanup();
}
public virtual void Setup()
{Console.WriteLine("Doing Base Setup.");}
public virtual void Cleanup()
{Console.WriteLine("Doing Base Cleanup.");}
public abstract void CustomWork();
}
class MyClass : BaseClass
{
public override void CustomWork()
{Console.WriteLine("Doing Custome work.");}
public override void Cleanup()
{
Console.WriteLine("Doing Custom Cleanup");
//You can skip the next line if you want to replace the
//cleanup code rather than extending it
base.Cleanup();
}
}
void Main()
{
MyClass worker = new MyClass();
worker.Start();
}