私が初めて触れた Go WEB フレームワークは beego でした。これは非常に強力なフレームワークであり、あまりにも (bu) 強力 (go) なので、多くの人が最初に選択します。 ling) (huo) その後、マカロン (マティーニ) を試しました。 Macaron の設計は、多くのフレームワーク、ルーティング、ミドルウェア、HTTP コンテキストの主流のアイデアであり、一般的に使用されるいくつかのミドルウェアを実装しています (追記。一部のミドルウェア コードは beego から来ています)。マカロンさんの頭の中では、m.Map() で任意の型を注入し、Context へのリフレクションで型を取得できるとのことで、初めて試したときはとても嬉しくて、その設計を褒めました。
PHP を使用する場合、Phalcon というフレームワークがあり、その設計の中心となるのは、log、db、などのサービスを登録することです。キャッシュやメタデータなどを DI に保存し、使用する場合は DI から取り出してください。 Phalcon の使用姿勢は、まず APP を初期化し、その後、さまざまな DI を登録し、その後 RUN します。 疑似コードは次のとおりです。
<?php$di = new \Phalcon\DI\FactoryDefault();$di->set('router', new MyRouter());$di->set('logger', function () { return new LoggerFile('../apps/logs/error.log');});$di->set('db', function () { return new PdoMysql( array( "host" => "localhost", "username" => "root", "password" => "secret", "dbname" => "blog" ) );});$di->set('db2', ...);$di->set('mongo', new \MongoClient());// Create an application$application = new \Phalcon\Mvc\Application($di);// Handle the requestecho $application->handle()->getContent();
上記の初期化は、さまざまなセットに対応しています。の型で、lazyload などもサポートしており、使用方法は比較的簡単です。
<?php$di = new \Phalcon\DI\FactoryDefault();$db = $di->get('db');$mongo = $di->get('mongo');$mongo->selectCollection('xxx');
要約すると、set はサービス (インジェクション) を設定することです。 get は、使用するサービスを取り出すことです。もちろん、PHP は静的言語である Go とは異なり、型アサーションを必要としません。
マカロンを使用するプロセスでは、問題は基本的に明らかです。たとえば、2 つの db が必要な場合、リフレクションに依存しすぎると、同じタイプの登録が 1 つだけになってしまいます。ロガーのタイプは同じですが、異なるサービス目的を実行するのはより困難です。実際、私にとって最も痛いのは、マカロンフレームワークが独自のログパッケージを使用していることです。フレームワークで出力されるログはインジェクションに依存せず、ネイティブです。ログ。 Phalconでの経験を組み合わせて、Phalon DIのアイデアを移植するというアイデアを思いつき、他のアイデアと組み合わせてBaaを作りました。 DI は現在 Baa で書かれている最も単純なものですが、車輪の再発明の最も直接的な結果です。
Baa の DI のアイデアを見ると、set と get という非常にシンプルな内容になっています。使用姿勢は Phalcon と同じですが、遅延ロードなどの多くの姿勢をサポートしていません。 (無名関数) を呼び出すと初期化され、静的クラスは文字列を設定して new を使用します。シンプルではありますが、考え方に違いはありません。例を示します。
package mainimport ( "github.com/go-baa/cache" _ "github.com/go-baa/cache/redis" "github.com/go-baa/render" "gopkg.in/baa.v1")func main() { // new app app := baa.New() // register logger app.SetDI("logger", log.Logger) // register render b.SetDI("render", render.New(render.Options{ Baa: app, Root: "templates/", Extensions: []string{".html", ".tmpl"}, FuncMap: template.Funcs(b), })) // register cache app.SetDI("cache", cache.New(cache.Options{ Name: "cache", Prefix: "MyApp", Adapter: "memory", Config: map[string]string{}, })) app.SetDI("cache2", cache.New(cache.Options{ Name: "cache2", Prefix: "MyApp2", Adapter: "redis", Config: map[string]string{}, })) // router app.Get("/", func(c *baa.Context) { ca := c.DI("cache").(cache.Cacher) ca.Set("test", "baa", 10) v := ca.Get("test").(string) c.String(200, v) }) // run app app.Run(":1323")}
アプリの初期化では、必要に応じて、Context、context.DI() Get などのロガー、レンダー、キャッシュ、さらには DB 初期化を挿入します。または、baa.Default().GetDI() を使用して他の場所で取得します。上記で指摘したログを見てください。ここでは、フレームワークに組み込まれているロガーを置き換えるために app.SetDI("logger", xxx) を使用するだけです。これは、レンダリングを実装するレンダーを登録するだけです。 baa.Renderer インターフェイスをカスタマイズできます。
依存性注入 (DI) は、数行のコードしかありませんが、設計上のアイデア、コンセプト、問題解決の姿勢です。