タスクは、OOP単一責任の原則)を使用して、古いDBから新しいDBに移行することです。
私の問題は、コントローラーを神のクラスにしたり、単一の責任を壊したりせずに、どうすればこれを作成できるかです。
これを実装する2つの方法を考えました
各プロパティ行を反復処理し、コントローラーのサブディビジョンと所有者にカスケードし、エンティティタイプごとに行移行を呼び出します
各エンティティ内に反復を追加します(例:プロパティはサブディビジョンを反復し、サブディビジョンは所有者を反復します)
今のところ、私が考えることは、ルールを複雑にしすぎたり、破ったりしているように感じます。多分私は間違った原則を理解したか、または3番目の方法があります。
通常、これはスクリプトで行いますが、新しいDBが別のプラットフォームにあり、addAddress()およびaddOwner()ロジックがAPIコンポーネントにあるため、APIを使用する必要があります。
OOPは常にETLタスクに最適な選択であるとは限らないため、ここでは「純粋」に固執しませんOOPここで。モデルが3つのテーブルのみの例に示すように単純である限り移行するには、これを過剰に設計することを避けます。3つのテーブルの移行を調整し、異なる「行移行」クラスを使用する1つのコントローラーがあるだけでは、コントローラーが「多すぎる」ようには見えません。責任」。
それにもかかわらず、責任を分散するためのいくつかのオプションがあります。 ETLプログラムの場合、移行の「E(xtract)」、「T(ransform)」、「L(oad)」の部分に責任を分割することをお勧めします。接続するのは「Extractor」クラスだけです。古いDBに移行し、移行するデータを提供します。「Load」クラスは新しいデータベースに接続する/ APIを使用する唯一のクラスであり、「Transform」クラスは変換作業を行いますが、ソースについては何も知りません。またはデータの宛先。さらに、例に示すように実際のモデルがはるかに大きい場合は、「Transform」クラスを小さな「サブトランスフォーマー」に分割することを検討してください。
2番目のオプションが理にかなっている場合、IMHOはエンティティクラスを移行コンテキストで排他的に使用するか、または異なるコンテキストで再利用および維持できるようにするかによって異なります。後者の場合、この非常に特殊なユースケース「移行」にのみ役立つビジネスロジックを追加しません。
「コントローラー」は必要ありません。「サービス」が必要です。
Controllerは、ユーザー入力や下位層で発生するその他のイベントに基づいて、アプリケーションのフローを制御します。 Serviceは、言われたとおりにビジネスを行うだけです。
移行サービスオブジェクトには、古いスキーマからデータをプルし、必要に応じてWebサービスまたはまったく異なるAPIを介して新しいスキーマにデータを永続化するためのインテリジェンスがあります。このサービスには、ジョブを実行するための最小限の依存関係が必要です。
PropertyMigrationService
には、次の責任があります。
必要なもの:
OldDataAccess
-古いDBでのCRUD操作用のクラスProperty
-古いDBの「プロパティ」のドメインモデルSubdivision
-古いDBのサブディビジョンのドメインモデルOwner
-古いDBの所有者のドメインモデルNewDataAccess
-新しいDB/WebサービスでのCRUD操作のクラスAddress
-新しいDBのプロパティのドメインモデルOwner
-新しいDBの所有者のドメインモデルPropertyToAddressMapper
-古いDBのProperty
オブジェクトを新しいDBのAddress
オブジェクトにマッピングするSubdivisionToAddressMapper
-古いDBのSubdivision
オブジェクトを新しいDBのAddress
オブジェクトにマッピングするOwnerToOwnerMapper
-所有者オブジェクトをあるDBから別のDBにマップします次のオブジェクト階層になります。
PropertyMigrationService
OldDataAccess
NewDataAccess
PropertyToAddressMapper
SubdivisionToAddressMapper
OwnerToOwnerMapper
移行サービスには、移行を実行するvoid migrate()
という単一のパブリックメソッドを含めることができます。
従来のスキーマを扱ってきたので、どのような狂気と混乱に遭遇するかはわかりません。この方法でソリューションを設計し、データアクセスクラスにインターフェイスを実装させ、PropertyMigrationService
にインターフェイスを介してこれらのオブジェクトを使用させることで、この移行プロセス全体をユニットテスト可能にすることができます。
これで、既知のエラー条件についてこれに一連のテストを実行し、これを実際に完全な証拠(十分な耐性)にすることができます。
これがサービスオブジェクトにラップされた後、いつ、どこで呼び出されるかについてある程度の柔軟性が得られます。
移行プロセスは、プロアクティブ(ユーザーがWebページのボタンをクリックして移行を実行する)またはパッシブ(スケジュールタスクが深夜に実行され、これらのレコードをたとえば1,000のバッチで実行する)の両方になります。