-
Notifications
You must be signed in to change notification settings - Fork 40
Home
Welcome to the scala-samples wiki!
There are the list Ideas or notes or more often takeouts about scala and not only - I would say more about Software Development in general. All will start with "I found that..."
I found that Domain Driver Design (DDD) concepts are quite useful, when it comes to domain modeling (surprise!).
Useful - to separate domain logic from the rest. To be simple (not talking about Aggregates or whatsoever for now): The separation part is crucial.
I found that thinking in terms of Algebra of API
and Laws of Algebra
fits better to Domain modeling comparing to the traditional terms like Code
and Test
of/for the domain logic. When we say Laws
that quite clear that those law should be obeyed then it is quite clear that you may not miss the to write it (in the form of unit test), and then it is quite clear that the law is also the code.
Example, Algebra of API
for the domain of ThingAdder (all about parameters and types):
trait ThingAdder[Thing] {
def add(thing1: Thing, thing2: Thing): Int
def takeAway(thing1: Thing, thing2: Thing): Int
}
The interesting part here is that we use generics, the Thing
does not exist yet. And it is quite powerful when you think about it from the very beginning, abstracting over - that I guess should be the first part one should do when she start modeling - describing the model. ( For me it is strange that GoLang
doesn't have generics. I understand that it could be slow on compilation or run-time or to mentally grasp what's going on with code. But human are quite complex too, but they still in use )
Example of Laws of Algebra
(using ScalaTest
integrated with ScalaCheck
):
import ThingAdder._ // the impl of of `ThingAdder` trait
forAll {things: (thing1: Thing, thing2: Thing) =>
add(thing1, thing2) should equal (thing2, thing1)
}
forAll{ (thing1: Thing, thing2: Thing) => {
for {
twoThings <- add(thing1, thing2)
result <- takeAway(thing1, twoThings)
} yield (result)
thing2 should equal result
})
The interesting part for me was that there is code - algebra of the domain - the interface
(as one may call it) and the law - the test
without any implementation just yet!
I think that using property based testing (with forAll
and such) should come first as one describes the laws of the domain. The last (second) that should come to mind is to write manual unit test. By far forAll
with generators.
Basically it's primary school math in action n+m = m+n; n+m-n = m. Where n, m is whatever. Where whatever depends on generators. For known types Int, String, Date - scalatest comes with predefined generators. So we can save time - concentration on the model testing. Quite nice I think.