When is it useful to separate state of behavior?

Asked

Viewed 231 times

12

In object orientation there is the concept of encapsulation: meet in the same state class and the functions operating in that state.

But there are situations where it is useful to separate state and behavior. The following example has come to me:

In an e-commerce purchase like Amazon, should there be a shipping fee? This decision is based both on the Customer object (it is an Amazon Prime customer or not) and on the items being purchased (if they are all from Amazon, there are no shipping costs, but if the item is from another supplier, then there is a shipping fee).

You cannot put these behaviors into the Client object or Item... so you put out of of both objects, in an object that checks constraints (restrictions) and that is part of the workflow of presenting the price to the user.

In Domain-driven design there is a particular object called "Constraint" or a specification. It is a very stylized interface, where you pass a business domain object and the object-Constraint answers one question ehSatisfeitaPor(objetoDeDominio) as a boolean result.

This is useful when you have several different checks on the state of the business object you want encapsulated in a single object (a Constraint) which has a very specific set of business rules.

You could likewise put these behaviors into the business object, but then you would have an ever-growing list of them. On the other hand, what’s wrong with that, you might ask yourself? Well, if you don’t want to cram a business domain object with specific processing rules (which may have to change dynamically based on different workflows), then it’s best to isolate these checks on different objects constraints.

Or, as recommended by Domain-driven design, you may also want to separate these methods ehSatisfaction() on separate objects when two business objects are involved and you do not want to arbitrarily place the behavior on one of the domain objects.

If at some point you find yourself writing code that is checking a thing before performing the work, then ask yourself if it would not be interesting to have an object-Constraint to answer the question.

The question I want to ask is: in what other situations is it useful to separate state of behavior? The end of the example already kind of answers the question, but does not cite any specific example.

Another example that apparently falls into the same case is the Embeddeddocument quoted by Martin Fowler in his article on the principle Tell Don’t Ask, but the example is in Ruby and I could not understand it.

P.S.: Anyone who wants to turn the examples into code to illustrate the situation, I believe it is also a useful contribution to the question.

1 answer

7


Merge X separate

I am in favor of separation, to the point that often the best form is not even object oriented, the more separate you can compose. This idea of putting everything together hinders the composition that is the basis for facilitating maintenance. All done to work well with different components, have easy and flexible fittings.

I don’t know how to talk like that in which situations it’s useful because it’s always useful to me. You put together what cannot be left out, where the behavior is very tied to the state, that the way it is done has to be very much object implementation detail, and that has no context.

I’ll even say I prefer leak abstraction and expose what should not separate certain parts, which goes against what OOP proponents say it is to do. It’s much easier to maintain it like this, even, or better yet, when you don’t know what’s coming, which is the most common.

It cannot radicalize, it cannot be ideological. Anemic model may be great, but it may not be the solution. It is often chosen to please a specific mechanism, not because modeling requires.

Example

The example quoted is great and people keep breaking their heads because it always changes something in the project. And I’ve seen crazy solutions to suit the theory you’ve created of how you have to do it, when often, and I’m not saying that’s the case with the example, a loose function is the solution.

The more DDD study I see the utility, and that the idea is very good and goes in the right direction, that is, goes against much of what OOP preaches (at least some points). But I also see that it’s so much code, so much layer, so much concept, so much clumsiness, that you waste too much time on it, you start to have too many mechanisms and too little business logic, which is the opposite that the DDD preaches. DDD should only be applied, and without the ideological part, which it has, if it has a framework very good, what I’m trying to find and did not appear to me until now.

ehSatisfeitaPor() is mechanism, does it need? Is it not just bureaucracy? Does it need this flexibility? Is it sufficient? It depends. Again I find too much concern with mechanism. It’s too abstract a case, so you have to do it and see if you need it, and you have to refactor. It is important to be easy to refactor when something didn’t work out. When you put it all together it’s more complicated to separate, and what’s separate it’s easier to put together.

Constraints can be contextual, which complicates. I know that DDD has something about context and this is cool, but it starts to complicate, will need?

I’m not saying you shouldn’t use it like this, just ask if it’s the solution, if it adds or is just following the cake recipe.

I think there is exaggeration in the dynamicity that occurs in many applications, often in the name of tests, of DDD, of principles that one can’t even say why one is using.

I often say that there are two reasons to solve something at runtime:

  • only has complete information at runtime, has nothing to do
  • there are many possible variations of the same algorithm or data structure, and so having a more dynamic mechanism helps to reduce the application size or even complexity.

A third reason is convenience, and it is valid in some cases, but is often abused.

The example seems to abuse a little of this, DDD seems to abuse. You end up doing a lot late Binding just because you want to follow the fashion. But if it’s useful, then use a language that encourages this.

New ways of doing

There are times when too much Lego starts to complicate too. That’s why I’m loving the languages that allow composition in an easier way, that allows more cohesion and less coupling. Thing that the procedural has always been good, so much so that these two concepts exist before OOP. Today who defends much OOP saw nothing else, heard that procedural was bad, and it was even, because it was badly done. So the middle ground is more interesting.

Peças de Lego

Metaprogramming is something that is beginning to facilitate maintenance, maintain performance and decrease complexity, but it is still early to celebrate.

Inclusive Generics often solves better. Allows for more composition. C++ staff say that if they had thought about it before they wouldn’t even need to have O in the language.

It is common to use lambda to inject behavior when it is known to exist, but the details must be configurable in the object.

And I’ve been more adept at a certain flexibility. I still am, under a certain line, but anything that relies on structure needs a very good engineer looking after it. There is a company that has an engineer and a committee to choose the code of a product, one by one, so important that it is to make good choices with things that you will "marry" forever. Today for me these examples in Ruby are horrible and unnecessary things indeed.

Flexibility has to come from architecture, not solution. It needs to be easy to adapt, not easy to metamorphosize :) Don’t even try this in Java, or at home :D The example of the embedded document is full of ideology and I don’t even know if it has anything to do with the question here.

More examples

Take the modern C++ library, almost everything there is trying to separate. Data structures are increasingly "naked" and there are libraries outside that manipulate them whenever it has a certain feature. Example.

Take the LINQ from C#, everything separate, it’s all composition, it’s all an abstraction to deal with many objects that have at least one thing in common. Documentation. The same goes for Streams from Java.

If people observe, a lot of things is naturally separated without realizing, because the decision must be natural, not imposed by a methodology or paradigm.

Do you realize that most best known design patterns, that everyone talks about, encourage separation and not joining? A very common example is the Strategy (where the exact behavior is not defined in the object), or the Visitor (that nor what behavior it may have), but all behavioral and structural are very strong in that.

Well done, some Dps are unnecessary. And have mechanisms that make them more unnecessary. Paul Graham and Peter Novig used to say that. Or at least have simpler ways to do.

See more about in Policy-based design.

That is why I say that Customer or Supplier are not derivations of Person, are facets of Person, are optional, occasional parts of Person. What can have hierarchy is Juridical and Physical Person, who are always Persons. And Person never really exists, is only taxonomy, is abstract.

Almost every inheritance must be abstract (some say all). Orientation to the object fold that must have something like a skeleton and derivations must contain the details. But there is too much combination, there does not work. I already told the AP another answer.

Note that this example is not only separate behavior, it has also been, for example: credit limit is a state that is in Customer, but not in Supplier, and not in Person. Now you might think it doesn’t matter. But as a Person can be a Customer and a Supplier at the same time, to reconcile the two into one object only becomes a complete mess, on the other hand if you separate the same person will exist twice in the system. All wrong because it does not model the real world, and the fundamental examples of OO encourage this error.

They’re even talking about not modeling the real world. When you do that, you flirt with disaster because the real world changes and your system isn’t ready for that. That’s what I always say, it’s hard to see the real world.

Article posted

The article is almost silly, at least for those who are not very new, and the novice will buy that as the holy Graal, which it is not. I also don’t know if it has to do with the question.

As far as I know, DDD preaches avoid getter/Setter :D

Completion

If the behavior is not viscerally linked to the state and cannot be separated without having a price to pay, it should be separated, except for some convenience, which requires great care. There are methodologies or guidelines who preach just that.

Does it all make sense in general? See other views, not just mine.

Note that perfect architecture does not exist, except in very trivial cases.

I find it kind of broad code transcribing and I don’t know if it serves something. For more concrete examples need more specific question.

  • Of the 7 (6 I don’t know who) who have already voted on the question, they could tell me if they have any reason not to have returned in the answer. I can think of a few reasons for this. Those who say nothing and do not vote on the answer I will consider that they voted and did not come back to see what they had found so good. I say this just to get a sense of what’s going on, I know a lot of people won’t want to vote because it’s an answer that goes out of the way that people think, if you wanted a vote, you just say what people want to hear.

  • I (vote 9) yet I did not vote for not having finished reading, despite being too inclined to vote already

  • Those who come later is normal :) The question is to understand how the staff votes as like or if in this case that’s not it. I think it’s common to vote and never be interested again. But it can only be the controversy of the answer. But you’ve already had 1 who either did the same as you, or decided not to vote because it’s controversial.

  • I gave my +1 but I confess that the examples "modern library of C++" and "LINQ of C#" do not help me much, it is my old limitation of only knowing Java that you already know, but if you want to detail them a little it can help. And another limitation is that I understand concrete examples better, so the question was specifically about providing examples. The answer for the most part seems well-grounded, the beginning is in my understanding a defense to the anemic model, what I find abstract for not knowing, but then part of me study this model. (continues...)

  • The recommendation to apply DDD sparingly is good, I would just like to recall a quote from Eric Evans that says that DDD is nothing new, it’s just the application of OO principles already known, so I don’t see why DDD contradicts OO (but it’s just a quote, you read a lot more about DDD than I do). "Most design standards encourage separation and not joining", could explain by giving examples? (continues...)

  • As for the Customer and Supplier, I agree that being papers (roles) the right is to avoid adopting inheritance, but I only have the superficial view of the problem, unfortunately I need to be pointed out what is being separated from what (maybe read the own paper I just linked help on this). About "There are methodologies or guidelines that preach just this", also, if possible, quote them. (continues...)

  • Fowler’s article talks about co-locating state and behavior, which to me is encapsulation, "But there are times when Objects collaborate effectively by providing information", what for me is an indication of sometimes violating this encapsulation, but I may have misinterpreted the article. Ready.

  • 1

    And that’s the problem with Java, still attached to ideologies. Everything modern is abandoning OOP, but without saying anything because ñ is good Mkt. Then I try to expand when organizing. I’ve had so much time to do everything I want. For concrete examples complicates, because it’s kind of doing everything, it’s clearly broad, I’d need something more specific, but I’m going to expand and something happens. Did you find it well founded? I don’t :D The anemic model is suitable in many cases, the Oopers say it’s a crime. DDD doesn’t know much yet. But he uses something of OOP, but overall he goes against it. It’s obvious...

  • ...He says to separate everything, not to encapsulate so much, to compose, of course not only that. Dps are class compositions, they are not heaping everything on the object. Just look at the examples.

  • 1

    DDD I only know of telephony. The description of the development did not captivate me, nor did I ever go after or work in singing that preached this model. About anemia in Java, I must say I’ve been quite happy. I do not use for everything, but almost all the secondary applications I work in the company have mainly used anemic model and simplicity. The use of lambda that language now provides helps a lot in DRY, and in some behavior injections in Runtime it makes sense to have this abstraction. (...)

  • 2

    (...) Even in the primary application, where there is more of this OO side, there were several scenarios where I defused an inheritance situation and put behavior injection. It became more elegant, easier to maintain and easier to extend (and the old guard who worked there moved on the inside seeing lambda, Function, Supplier, Consumer xD). The question is to find the right time to use each type of abstraction and go without fear (...)

  • 1

    (...) And, yes, this multiple types of abstraction, despite improving the quality of the code (measured in bugs by delivery) creates trouble even today because many of the company’s old guard want there to be "a standard" so that everyone can follow blindly. And my answer is always: "the standard is what is best in every situation". Sometimes OO (but rarely, much more in framework calls than in business class development), sometimes functional, sometimes behavior injection, sometimes anemic. What best fits is what should be used

  • 1

    Eric Evans doesn’t know the first thing about D.O.D.:D :D :D It’s serious! Of course, the DDD itself was something he invented and can understand, but what matters and is useful in the DDD is different from what he preaches. In fact OO in business doesn’t make as much sense as people think, so they make a lot of mistakes.

  • I think I’ve touched a nest of bums :P There’s a whole lot of fuss about separating state of behavior and I didn’t touch that when I asked the question. I didn’t think I was going to give so much up my sleeve. I’ll accept the answer, but it’s not what I expected to hear (not that this is bad) :)

  • You speak your mind

  • No, nothing relevant, I expected that in general it would be a rule to put things together except in some situations where the object collaborates better by sharing state. Something like this, a handful of loose examples of exceptional situations. But the answer answers the question, so it’s ok.

  • Trying to reconcile the answer and my understanding, I’ve always considered that joining state and behavior only makes sense for things that are viscerally connected. Status and operations affecting that state.

Show 12 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.