Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Specification Pattern by Scala

DZone's Guide to

Specification Pattern by Scala

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

 Specification pattern is simple and clean solution to implement your business rules.  This pattern is mixture between composite and factory Gof patterns introduced by Eric Evans & Martin Fowler.

In this blog, we will not explain how this pattern works, but you can refer to wikipedia and Xebia  for more details. But, we try here to translate specification pattern using the Scala language.

Implementation :
UML diag

package me.jtunisie.specifications


trait TSpecification [T]{
def ->(candidate :T ):Boolean
def ||( specification : TSpecification[T]):TSpecification[T]
def &&(specification :TSpecification[T] ):TSpecification[T]
def unary_!():TSpecification[T]
//Addition
def | ( specification : TSpecification[T]):TSpecification[T]
def & (specification :TSpecification[T] ):TSpecification[T]
}

The last two methods has been added compared to the specification. Sometimes, we need to do full check as A || B is not always equal to B || A. {Take as example true || (1/0 == 0 ). "We have encountered this problem when we validate an old embedded compiler written in C and in some platform  like Solaris ( A || B ) starts by checking B and then A. }
 abstract class ASpecification[T] extends  TSpecification [T]{

def ->(candidate :T ):Boolean
def ||( s : TSpecification[T]):TSpecification[T] = OrSpecification(this,s)
def &&(s :TSpecification[T] ):TSpecification[T] = AndSpecification(this,s)
def unary_!():TSpecification[T] = NotSpecification(this)

// Recurssive Add-0ns
def | ( s : TSpecification[T]):TSpecification[T] = ROrSpecification(this,s)
def &(s :TSpecification[T] ):TSpecification[T] = RAndSpecification(this,s)

}

To implement recursive and not recursive behavior, we have used /: and \: .
According to documentation :
(z /: List(a, b, c)) (op)  equal to op(op(op(z, a), b), c)

and

(List(a, b, c) :\ z) (op)  equal to op(a, op(b, op(c, z)))

case class AndSpecification[T]( s: TSpecification[T]* ) extends ASpecification[T]{
override def -> (candidate :T ):Boolean= (true /: s) (_ -> candidate && _ -> candidate)

}
case class OrSpecification[T]( s: TSpecification[T]* ) extends ASpecification[T]{
override def ->(candidate :T ):Boolean= (false /: s) (_ -> candidate || _ -> candidate)
}
case class NotSpecification[T]( s: TSpecification[T] ) extends ASpecification[T]{
override def ->(candidate :T )= ! (s -> candidate )
}


case class RAndSpecification[T]( s: TSpecification[T]* ) extends ASpecification[T]{
override def ->(candidate :T ):Boolean= (s :\ true) (_ -> candidate && _ -> candidate)
}
case class ROrSpecification[T]( s: TSpecification[T]* ) extends ASpecification[T]{
override def ->(candidate :T ):Boolean= (s :\ false) (_ -> candidate || _ -> candidate)
}

This code will not compile. In fact, Boolean class doesn't have -> method (IsSatisfiedBy). By Scala, we can use open class tool ( adding this method to Boolean class).

Here is the implicit implementation :

package me.jtunisie

package object specifications {

class MyBool(b:Boolean){
def ->(candidate :Any ):Boolean = b
}
implicit def toMyBool(b:Boolean)= new MyBool(b)
}

source code is under  : http://github.com/ouertani/Rules

Mode of use ( with precedence checked ):

Object AlwaysOk extends ASpecification[Boolean] { override def -> (b: Boolean)= true } object AlwaysKo extends ASpecification[Boolean] { override def -> (b: Boolean)= false }

 

object AlwaysOk extends ASpecification[Boolean] {
override def -> (b: Boolean)= true
}
object AlwaysKo extends ASpecification[Boolean] {
override def -> (b: Boolean)= false
}


false mustBe ((AlwaysOk || AlwaysKo) && AlwaysKo)-> (true)
true mustBe (AlwaysOk || (AlwaysKo && AlwaysKo))-> (true)
true mustBe ( AlwaysOk || AlwaysKo && AlwaysKo)-> (true)

 

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}