The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

xfolch (1) [Avatar] Offline
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 (12) [Avatar] Offline
    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
    , not just method arguments.
    This makes methods impure, so they can't be passed to higher order functions like
    and the like.
    Also, you'll not be able to use function combinators

    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!
    Debasish Ghosh (116) [Avatar] Offline
    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 ..