Oop 当从数据库中获取具有Id的对象时,是否使用Option作为结果?

Oop 当从数据库中获取具有Id的对象时,是否使用Option作为结果?,oop,scala,functional-programming,playframework-2.0,slick,Oop,Scala,Functional Programming,Playframework 2.0,Slick,我已经做了一个从数据库中获取用户的定义 def user(userId: Int) : User = database withSession { (for{ u <- Users if u.id === userId} yield u).first } def user(userId:Int):user=database with session{ (用于{ u不,请求失败是不好的: def user(userId: Int) : Option[Us

我已经做了一个从数据库中获取用户的定义

 def user(userId: Int) : User = database withSession {
    (for{
      u <- Users if u.id === userId} 
    yield u).first
  }
def user(userId:Int):user=database with session{
(用于{

u不,请求失败是不好的:

def user(userId: Int) : Option[User] // is OK
def user(userId: Int) : Either[String,User] // is OK
def user(usedId: Int) : User // is not OK
或者你可以创建一个类型(一个概念),封装一个整数,确保它是一个有效的用户ID(在出生时)

在创建def时,必须确保函数的域(this和args)与代码域(result)之间存在正确的关系

无论如何,不要犹豫键入(创建概念),它将帮助您对代码进行推理


为什么
def user(userId:Int):user
不正常

因为
Integer
的元素与
User
的元素之间不存在关系。如果userid都是正整数,但您要求
User(-10)
?(不会发生,对吧?)此调用是否引发异常?或返回null

如果您认为它应该返回null,然后返回一个选项,那么它将封装潜在的缺失对应

如果您认为它应该引发异常,则返回:

  • a
    验证[somethingrepresentingangerror,User]
    (scalaz)
  • 一个
    或[something representingangerror,User]
    (scala 2.7、2.8、2.9)
  • 或a(scala 2.10)
拥有丰富的返回类型将帮助您正确使用API

顺便说一句,Scala不使用checked exception,所以您不能将exception用作替代结果。对于真正的异常行为(如运行时异常),应保留exception

另见:

  • http://www.scala-lang.org/api/current/index.html#scala.util.control.Exception$

    • 我认为返回选项总是个好主意[]当通过id获取数据时。您无法确定具有此类id的用户是否存在。例如,另一个请求删除了此用户,或者有人试图篡改您的输入数据。数据库是应用程序的外部系统,如果您知道如何从此类故障中恢复,则应该这样做。特别是在Scala中,Option是用于或者这样的任务。

      选项
      是表示某些可能失败的计算返回值的最简单的方法。只有在处理Java代码时,抛出异常或返回
      null
      才是可以接受的,并且您的手被现有的API(以及从Java代码调用代码时)束缚着

      选项
      的下一步是
      或[FailureIndication,SuccessValue]


      另一个改进是ScalaZ的
      验证

      是否愿意详细说明为什么它不好?SLICK的官方文档使用了这种方法。这是一个关于函数编程基本原理的长期讨论。类型是概念,函数是概念之间的关系。它也适用于良好的oop编程。(我在乎,但我正在忙着)我必须保留文档的声明,因为它被嵌入了一些模板代码中
      sealed case class UserId(u:Int) //extends AnyVal // If it's scala 2.10.0
      
      object UserId {
          def get(i:Int) : Option[UserId] = //some validation
      
      } /// ....
      
      def  user(userId:UserId) : User //is OK // well it depends on the semantic of user destruction.