想象一下class Purchasablescala中看起来像这样

case class Purchasable(product: ProductData,store: StoreData,seller: UserData){
  require {
    //seller is active &&
    //seller has defined personal info &&
    //seller has defined means of accepting payment
    //product contains a price in seller's current currency
    //product has defined shipping policies for atleast on of the store's locations
    //product is not past expiration date
    //product is either new or has uploaded images
    //and so on!
  }
}

object Purchasable {
  def validate(p: ProductData,s: StoreData,u: UserData): Either[String,Purchasable] = {
    Try(Purchasable(p,s,u)).toOption.toRight("unpurchasable.product")
  }
}


类型ProductDataStoreDataUserData来自3个数据库表的所有相关行。

当买家想要购买产品或将其添加到购物车中时,必须可以从这三个获取的行中获取成功的Purchasable实例。

但是自然而然地,在买家将此商品添加到购物车中之前,她必须首先在我们的数据库中查询可购买产品的列表。

显然,查询这些可购买项会使SQL中产生非常复杂的concontintin子句(这不是我的主要担心)。我主要关心的是必须使用两种完全不同的语言编写的重复逻辑。我从db中传输了三行,在scala中使用purchasables对其进行了验证,并将其插入到新表中。所以现在我有两个好处:


我的查询变得如此简单:


select * from products p
join stores s on p.storeId = s.id
join users u on s.userId = u.id
join purchasables pur on pur.productId = p.id



没有重复的逻辑和可维护性问题。如果业务需求发生变化,我只需要在代码中更改一位。


我看到的缺点是,我的可购买产品现在具有最终一致性,而不是即时一致性。因为Purchasable.validate表仅定期刷新(即使每2分钟刷新一次)。

我的问题:我在这里所做的是既定做法吗?我在互联网上进行搜索,所有有关最终一致性的讨论和技术都针对分布式系统问题。我还没有找到关于讨论该选择的文章或stackoverflow问题。在这种情况下,我感觉自己完全偏离了轨道,对自己的工作一无所知。

最佳答案

我可能错过了一些东西,但是我认为您的第一种方法更简单且步入正轨。

您说您需要用两种语言复制逻辑,但是我不知道为什么会这样。

据我了解,验证产品是否可购买,找到所有可购买的产品实际上是同一回事。它是find all purchasables in this source table源表,它可能与单个元素表一样小,也可能与完整项目表一样大。因此,您应该为此使用一个功能,并且相同的代码将处理这两个用例。

例如,如果您使用光滑,则可能具有以下功能

def findPurchasablesIn(table: Query[ProductTable, ProductRow, Seq])


并用不同的源表调用它?

09-29 20:56