ビジネス ロジック全体を改善し、コードの重複を避けるために、クライアントの Web サイトの 1 つをゆっくりと、しかし確実にリファクタリングしてきました。私が取り組んできた主な分野の 1 つは、基本的なショッピング カート アプリケーションの製品です。
- データベースに対する SQL クエリを使用したアイテム検索
- 商品詳細テンプレート
- かごの中身を見る
- チェックアウト (住所を入力、注文を確認、送信)
製品に関する多くのビジネス ルールがあります。たとえば、次のとおりです。
- 閲覧可能な商品
- 特定のユーザーが表示できる製品
- 注文可能な製品
- 各製品はどの形式で注文できますか
- 等
何年もの間、これらのルールはすべて Web サイト全体で複製されていました。一部は SQL クエリで、一部はアプリケーション ロジックで、一部は両方で、一部のページでは実装方法が異なっていました。実際、一部のルールは特定のページに実装されていません (設計によるものではありません)。
異なるルールを持つ新しいサブアプリケーションも作成されました。
そのため、製品が表示される場合は常に、アプリケーション ロジック (つまり、Product.isViewable()、Product.isOrderable() など) のすべてのビジネス ルールを含む "Product" クラスの使用を実装しました。
これにより、Product クラスを拡張することにより、そのアプリケーション固有のルールを使用して、各サブアプリケーションで Product データを使用できるようになります。
私が現在抱えている唯一の問題は、ColdFusion アプリケーション ロジック (if/else など) と SQL 条件の組み合わせを使用して、データベースにクエリを実行し、多くの「古い」ビジネス ルールを含むアイテム検索ページです。SQL クエリのスニペットを次に示します。
WHERE (
LTRIM(RTRIM(UCASE(STATUS))) = 'ACTIVE'
OR UCASE(VIEWABLE_IF_RETIRED_FLAG) = 'Y'
)
<cfif SESSION.User.getSecurityLevel() LT 5>
AND (
UCASE(ORDERABLE_FLAG) = 'Y'
OR UCASE(ELECTRONIC_ORDERABLE_FLAG) = 'O'
OR UCASE(ELECTRONIC_ORDERABLE_FLAG) = 'V'
)
</cfif>
これらと同じルールが Product クラスに実装されています。
function isVisibleIfRetired() {
return getVisibleIfRetiredFlag() == "Y";
}
function isActive() {
return getStatus() == "ACTIVE";
}
function isDigitalViewable() {
return UCase(getIsProductOrderableFlag()) == "Y"
&& (
UCase(getElectronicOrderableStatus()) == "V"
|| UCase(getElectronicOrderableStatus()) == "O"
);
}
これは私を夢中にさせます。なぜなら、それは依然として本質的に重複したコードであり、ビジネス ルールが変更された場合に両方の部分を管理する必要があるからです。
一部のアイテムのみを表示する場所 (「類似アイテム」ウィジェットや「カートの表示」など) があり、単純にデータベースからプロダクト キーを選択し、それらの値をループしてProduct インスタンスを作成し、クラスのビジネス ルールを使用して、製品を表示するかどうか、または表示する方法を決定します。
ただし、アイテム検索クエリは最大 2000 件のレコードを返すことができ、2000 件のレコードをループして 2000 件のインスタンスを作成し、ビジネス ルールに基づいて表示を決定することは [現実的に] できません。
何か案は?