0

我在这个问题中使用了 Scala,但我也可以用 Java 或任何其他语言回答。


我可以使用以下内容公开服务:

def doSomethingOnUser(user: User): Result

问题是:也许在实现中不需要加载完整用户,只需使用 userId 就足够了,因此客户端可能不必提供完整用户并避免不必要的数据库调用。

def doSomethingOnUser(userId: String): Result

问题是:也许接口客户端由于某种原因已经加载了一个完整的用户,然后它使用调用这个方法doSomethingOnUser(loadedUser.getId()) 所以在服务实现中我们现在只有 userId 而加载完整的对象可能是必需的:这会导致加载客户端和服务实现中的对象。

这两种可能性似乎都有缺点。一个简单的解决方案可能是公开这两种方法,以便根据上下文和您已经加载的数据,您可以使用其中一种或另一种。


在您添加许多方法属性之前,这可以正常工作。

您最终可以得到一个服务接口:

def sendDocumentToUser(document: Document,user: User): Result
def sendDocumentToUser(documentId: String,user: User): Result
def sendDocumentToUser(document: Document,userId: String): Result
def sendDocumentToUser(documentId: String,userId: String): Result

我只是想知道您对这个主题的看法是什么,根据您的经验,什么最有效以获得干净的界面,客户端不必知道哪种方法最适合出于性能考虑而调用,而无需进行不必要的数据库调用。

使用 Scala 或 Haskell 之类的函数式编程语言,是否有一些可用的数据结构,以便我们可以使这些事情变得更容易?

而Java,这可能吗?

我正在考虑在 Scala 中使用类似的东西:

def sendDocumentToUser(document: Either[Document,String],user: Either[User,String]): Result

正如 om-nom-nom 所说:使用起来并不是很优雅,所以任何更合适的数据结构都会受到欢迎(例如,如果它没有像客户端那样完全加载,那么从 DB 中延迟获取对象?)

4

2 回答 2

1

如果您无法在实现中强制执行某些内容,请将其留在接口之外(因此,使用 userId)。对我来说,doSomethingOnUser(loadedUser.getId())胜过千百倍

def sendDocumentToUser(document: Either[Document,String],
                       user: Either[User,String]): Result

您有义务让接口和实现的每个客户端都调用您的方法,只要

sendDocumentToUser(Right("doc"), Left(user))

这是难以理解的混乱,请不要。

将您的界面定义为

def sendDocumentToUser(document: String, user: String): Result

如果实现需要使用已经加载的文档和用户,他们可能会定义自己的重载,并使用 back off to stock sendDocumentToUser

class SomeImplementation extends YourInterface {
   def sendDocumentToUser(document: Document, user: User) = {
     this.sendDocumentToUser(document.getId, user.getId)
   }
   // ....
}

如果您真的不希望您的用户编写.getId,请定义两个隐式方法User => StringDocument => String,尽管我不会这样做。

于 2013-05-27T12:06:49.137 回答
0

另一种可能的解决方案是定义一个案例类,该类将用作函数的单个参数,然后在函数中进行模式匹配以确定如何根据提供的内容进行处理。可能看起来像这样:

case class Inputs(userId:Option[String], user:Option[User], documentId:Option[String], document:Option[Document])

然后是函数:

def sendDocumentToUser(inputs:Inputs):Result

这种方法的唯一缺点是无法强制您至少拥有最低要求的输入(即没有Inputs(None, None, None, None))。这意味着您必须在模式匹配中明确处理这种情况并返回失败结果或抛出异常。不是最佳的,但仍然是一个解决方案。

您还可以像这样稍微不同地构造函数:

def sendDocumentToUser(userId:String, documentId:String, user:Option[User] = None, document:Option[Document] = None):Result

这样,您需要 userId 和 documentId 并允许可选的 User 和 Document 对象(如果它们已经存在)。

于 2013-05-27T12:16:55.677 回答