APIを設計する時、静的クラスは少し悩みの種である。きわめて頻繁に機能を公開するために静的関数とインスタンスメソッドの両方が議論されてきた。
静的関数の主な主張はシンプルなことである。インスタンスの作成と管理、依存性注入などを心配することなくコードのどこででも使うことができる。そして、新しいインスタンスを作成しないためガベージコレクト、パフォーマンスの面で優位だ。
それはあなたが状態を管理している場合を除いてだ。そしてすべての静的関数は、負荷の高いロックや同期技術を伴う可能性のあるスレッドセーフに作る必要がある。また個々の呼び出しはスレッドセーフであっても、一連の呼び出しをひとつのアトミックトランザクションとして呼び出す必要がある。これはAutoMapperの物語への入り口である。
もともとは静的関数をベースにしながら時間をかけてAutoMapperはますます構成可能になってきた。そしてそれぞれの新しい構成オプションは、さらに多くの状態を管理し、さらに潜在的なスレッドの問題を引き起こしていた。1月にJimmy Bogard氏はAutoMapper 4.2で静的関数を非推奨としてマークし、最終的にそれを削除することにした。
AutoMapperの4.2リリースに向けて、私は小さなインスピレーションを得ました。過去1年ほどに私は長くいるオープンソースコードベースに関して話したりpodcastしたりする機会がありました。私の最大の後悔はAutoMapperが最初から静的APIを提供していたことでした。最初のAutoMapperのテスト/プロトタイプは“Mapper.CreateMap”と“Mapper.Map”からはじまりました。私は上司のJeffrey Palermoに見せてどう思うかを聞くと、彼は“すばらしいが、それを静的にするべきではないと思う”そして私は“けっ、そんなわけない!”と言いました。
私は静的で問題を見てきたし、それを後悔しました。今後のリリースで私は静的を除いて見えるプロトタイプを作る機会があり、それはうまく動いていて、すべての静的APIを非推奨にする準備ができています。
この変更はいくつかの問題を引き起こす。AutoMapperの機能のひとつ、LINQ式チェーンで動作するfluent APIのサポートである。この機能は常に静的関数として定義された拡張メソッドが必要である。
これを回避するためにLINQのサポートをするが、グローバルの状態を使用しないようにする。その代わり、LINQ式にAutoMapper構成情報を渡す。これは少し冗長だが、いくつかの点でより柔軟だ。
これは静的APIからの移行ガイドからの例である。
public class ProductsController : Controller { public ProductsController(MapperConfiguration config) { this.config = config; } private MapperConfiguration config; public ActionResult Index(int id) { var dto = dbContext.Products .Where(p => p.Id == id) .ProjectTo(config) .SingleOrDefault(); return View(dto); } }
1ヶ月後、Jimmy Bogard氏は静的関数からの復元を決めた。彼は次のように書く
静的APIからの大きな痛みは、構成をいつでも変更できるため、明確な構成ステップを適用できないことでした。それについて考えましたが、静的APIはマッピング前に初期化を強要すること以外はなにも問題がありませんでした。それは今後許可されるものであり、インスタンスAPIは完全に排除され、静的APIはその上にある薄いベニアとなり、コンストラクタの代わりに静的な初期化メソッドを呼び出します。
このリリースではいくつかのobsolete属性を削除し、静的構成を使ったLINQ射影を復活させた。
InfoQは尋ねる。状態を持った静的関数とインスタンスメソッドのみの許可のどちらを支持するだろうか?