Am I using a parameter as a result when retrieving an object from the database with an id?

I made a definition that fetches the user from the database.

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

      

The database could potentially return an empty list if used with a non-existing userId.
However, I can't see when a non-existing userId will be provided. For example, my userId is retrieved from the logged in user. And if a non-existent userId is provided, I think it is okay to complete the request.

Any thoughts?

+3


source to share


3 answers


No, it is not ok if you cannot complete the request:

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

      

otherwise, you could create a type (concept) that encapsulates an integer that must be a valid UserId (at birth).

sealed case class UserId(u:Int) //extends AnyVal // If it 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.

      

When you do def, you must make sure that there is a correct relationship between the domain (this and args) of your function and the code (result).

Anyway, feel free to type (create concepts), it will help you understand your code.


Why def user(userId: Int) :User

doesn't it work?



Because there is no relationship between elements Integer

to elements User

. What if the UserIds are positive integers but you are asking user(-10)

? (it won't happen, right?) Should this call throw an exception? Or return null?

If you think it should return null then return the parameter, it encapsulates the potentially missing match.

If you think this should throw an exception, return:

  • a Validation[SomethingRepresentingAnError, User]

    (scalaz),
  • a Either[SomethingRepresentingAnError, User]

    (scala 2.7, 2.8, 2.9)
  • or Try[User]

    (scala 2.10)

Having rich return types will help you use your API correctly.

Btw Scala does not use checked exception, so you cannot use exception as an alternative result. The exception must be keept for truly exceptional behavior (like Runtime exceptions).

See also:

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


source


I think it's always useful to return Option [] when retrieving data by id. You cannot be sure that a user with this ID exists. E. g. another request deleted this user, or someone tried to tamper with your login. The database is an external system for your application, and if you know how to recover from such failures, then you should. Especially in Scala where Option is a good tool for such a task.



+1


source


Option

is the most minimal way to represent the return value of some computation that can fail. Throwing exceptions or returning is null

only acceptable when working with Java code, and your hands are somehow tied to an existing API (and when you call code from Java code).

The next step from Option

will be Either[FailureIndication, SuccessValue]

.

Further improvement - ScalaZ Validation

.

+1


source







All Articles