Skip to content
This repository was archived by the owner on Sep 27, 2022. It is now read-only.

Commit 9de20fd

Browse files
committed
Added code for an article "Scala: How to return a result code in a concise way"
1 parent c5fec94 commit 9de20fd

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.komanov.business.example
2+
3+
import java.util.UUID
4+
5+
import com.komanov.business._
6+
7+
import scala.util.Try
8+
9+
class BusinessExample {
10+
11+
def processRequestOld(userId: UUID, requestId: UUID): BusinessResult = {
12+
val userOpt = getUser(userId)
13+
if (userOpt.isEmpty) {
14+
return BusinessResult.UserNotFound
15+
}
16+
17+
val requestOpt = getRequestById(requestId)
18+
if (requestOpt.isEmpty) {
19+
return BusinessResult.RequestNotFound
20+
}
21+
22+
if (checkAccess(requestOpt.get, userOpt.get).isFailure) {
23+
return BusinessResult.NotOwner
24+
}
25+
26+
BusinessResult.Ok
27+
}
28+
29+
def processRequestWithException(userId: UUID, requestId: UUID): BusinessResult = {
30+
case class BusinessException(result: BusinessResult) extends RuntimeException
31+
32+
try {
33+
val user = getUser(userId).getOrElse(throw new BusinessException(BusinessResult.UserNotFound))
34+
val request = getRequestById(requestId).getOrElse(throw new BusinessException(BusinessResult.RequestNotFound))
35+
checkAccess(request, user).toOption.getOrElse(throw new BusinessException(BusinessResult.NotOwner))
36+
BusinessResult.Ok
37+
} catch {
38+
case be: BusinessException => be.result
39+
}
40+
}
41+
42+
def processRequestCollections(userId: UUID, requestId: UUID): BusinessResult = {
43+
getUser(userId).fold(BusinessResult.UserNotFound)(user => {
44+
getRequestById(requestId).fold(BusinessResult.RequestNotFound)(request => {
45+
checkAccess(request, user).toOption.fold(BusinessResult.NotOwner)(_ => BusinessResult.Ok)
46+
})
47+
})
48+
}
49+
50+
def processRequestEither(userId: UUID, requestId: UUID): BusinessResult = {
51+
val result: Either[BusinessResult, BusinessResult] = for {
52+
user <- either(getUser(userId), BusinessResult.UserNotFound)
53+
request <- either(getRequestById(requestId), BusinessResult.RequestNotFound)
54+
_ <- either(checkAccess(request, user).toOption, BusinessResult.NotOwner)
55+
} yield BusinessResult.Ok
56+
57+
result.fold(identity, identity)
58+
}
59+
60+
private def either[T](opt: Option[T], result: BusinessResult) =
61+
opt.fold[Either[BusinessResult, T]](Left(result))(Right(_)).right
62+
63+
def processRequestNew(userId: UUID, requestId: UUID): BusinessResult = {
64+
for {
65+
user <- getUser(userId) orResult BusinessResult.UserNotFound
66+
request <- getRequestById(requestId) orResult BusinessResult.RequestNotFound
67+
_ <- checkAccess(request, user) orResult BusinessResult.NotOwner
68+
} yield BusinessResult.Ok
69+
}
70+
71+
private def getUser(userId: UUID): Option[String] = None
72+
73+
private def getRequestById(requestId: UUID): Option[Request] = None
74+
75+
private def checkAccess(request: Request, user: String): Try[Unit] = Try(throw new RuntimeException)
76+
77+
}
78+
79+
case class Request(id: UUID,
80+
owner: UUID)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.komanov.business.example;
2+
3+
public enum BusinessResult
4+
{
5+
Ok, UserNotFound, RequestNotFound, NotOwner,
6+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.komanov
2+
3+
import scala.language.implicitConversions
4+
import scala.util.Try
5+
6+
package object business {
7+
8+
implicit final class ModelOrResultFromOption[M](private val opt: Option[M])
9+
extends AnyVal {
10+
// converts Option to Either.RightProjection
11+
def orResult[R](result: => R) =
12+
opt.fold[Either[R, M]](Left(result))(Right(_)).right
13+
}
14+
15+
implicit final class ModelOrResultFromTry[M](private val opt: Try[M])
16+
extends AnyVal {
17+
// converts Try to Either.RightProjection
18+
def orResult[R](result: => R) =
19+
(if (opt.isFailure) Left(result) else Right(opt.get)).right
20+
}
21+
22+
implicit def toResult[R](e: Either[R, R]): R =
23+
e.fold(identity, identity)
24+
25+
}

0 commit comments

Comments
 (0)