xfolch (1) [Avatar] Offline
#1
Hi Debasish

I am currently reading your book and I am not clear on why we should separate state and behaviour from the point of view of a functional domain approach. I mean, taking your own example about Account, what is the problem in adding behaviour related to?

Some things that I think about bundling both:

  • It does not break the immutability, because you does not change the state but returns a new object model

  • It allows the compositionality when functions are pure. In that case, the compositionality only depends on the arguments and return types of the function.

  • I agree that some behaviors that involve different domain objects could be in a kind of domain service.

  • I am just interested in learning what are the constraints in adopting the named object-oriented approach in contrast to your proposed one.

    Thanks in advance

    Congratulations for your excellent book!!
    Ilja Tollu (9) [Avatar] Offline
    #2
    Hello, colleagues!

    Let me suggest.

    You mean, why can't we define behaviour as objects' (entities and values) methods rather than functions?

    1. If you do that you supposedly are going to read some state and use some methods of
    this
    , not just method arguments.
    This makes methods impure, so they can't be passed to higher order functions like
    flatMap
    and the like.
    Also, you'll not be able to use function combinators
    andThen
    or
    compose


    2. Follows from the previous point: calling an object's method makes it execute immediately, so you can no more build computation, but rather you run a chain of evaluations. Besides, how'd you return something like
    Either[Err, Obj]
    , if you need to chain to your behaviour farther?

    3. Also follows from the first point. All these Lenses, Monads, Applicatives et cetera address the problem of abstracting context from its content. You can write and test it once, or better take some ready solution like Scalaz and then use it many times within your domain. But if you don't separate behaviour from objects, you'll have to build this context logic back into your objects making them unmanageable.

    4. Of course, you can couple object with behaviour as long as that is the object's exclusive behaviour, i.e. you don't need to reuse it, and if it makes code cleaner than decoupled version.

    This is just my humble opinion.
    I'm also waiting for Debasish to bring some light to this and sibling topics.

    Best regards!
    Ilja
    Debasish Ghosh (116) [Avatar] Offline
    #3
    One of the simple reasons I love to keep state and behavior decoupled is to encourage independent evolution of the two and exploit the compositionality properties of functions.

    Once u define the state of your domain object as an algebraic data type, you get a host of advantages out of the box:

  • Immutability (case classes are immutable by default)
    Built in abstractions that let you manipulate ADTs functionally without any boilerplates e.g. Lenses, Zippers etc.
    With an ADT you can enforce strict separation of algebra & interpretation (have a look at the Free monads chapter of the book)


  • When you keep the state separate from the behavior, it's much easier to have pure functions to model domain behaviors. The state can be passed with the function using State monads. So we avoid the huge problem of manipulating mutable state - this is a huge plus for designing concurrent abstractions.

    Finally, loosely coupled abstractions are easier to manage and test. With an implicit this pointer, we have an unnecessary coupling of methods with an object, which makes compositionality more difficult. Just think why we cannot have seamless pointfree implementations even in Scala while we can have them in Haskell. It has a lot to do with the this pointer.

    Let me know if this helps. Or you need more details on the subject ..

    Thanks.