3

Based on some questions I asked (1, 2,3), I am frequently suggested to separate data from functions (because of changes in function, single responsibility, separation of concerns, adopting interfaces, immutability, ...).

Then my question is: In which situation functions should be encapsulated with data? what type of functions are they? Is representing an entity or a concept a single responsibility? if yes then I may conclude no function should be introduced in a class which represents an entity! Did I miss something?

According to the following approaches, what happens if I always follow the second approach! Please note in the second approach class Entity has no private state variable as it has no function, then its fields are accessible in class EntityOp1 and EntityOp23

class Entity
{ 
    public data;
    private s1, s2, s3;
    operation1;
    operation2;
    operation3;
}

vs.

class Entity
{
   public data;
}

class EntityOp1
{
     Entity e;
     private s1;
     operation1;
}
class EntityOp23
{
     Entity e;
     private s2, s3;
     operation2;
     operation3;
}
  • 4
    "I am frequently suggested to separate data from functions (because of changes in function, single responsibility, separation of concerns)." This statement is extremely dangerous and should not be taken as a rule. The main point of OOP is to group together data and operations on this data. – Euphoric Apr 6 '15 at 6:37
  • @Euphoric Maybe it is true for some type of functions, just I don't know which functions should be separated and which functions shouldn't be separated. Or What is wrong with second approach in the question. – Ahmad Apr 6 '15 at 6:39
  • 3
    @Euphoric In my opinion this is just as dangerous a statement, because it implies grouping data and operations is an end in itself. In reality it's just a means to creating abstractions. If a class has nothing to hide (e.g. when its sole purpose is to move a bunch of values from point A to point B) then there's no benefit to "grouping" the operations with that data; it's all public data anyways. – Doval Apr 6 '15 at 13:02
8

The main purposes of OOP is to limit scope in which fields (or properties) can be mutated. This makes reasoning and debugging of said code much easier. That is why 3rd question you are referencing talks about mutability. If your fields are immutable, then there is no need to limit scope of access to field, so separating data from operations makes much more sense. That is what all pure/functional languages do.

You probably misunderstood the SRP and separation of concerns. Data and functions are NOT separate concerns. They are parts of single concern. You should always model your functions and data as interconected parts, not as separate entities.

But the problems start when you include dependencies into the mix. Thats what first two referenced questions are about. Having dependency on some other code is a liability, so you should try minimize code that depends on something else. If you have class that depends on some complex library, but only 10% of that class actually needs that library, then it is good idea to separate those 10% into separate class/entity. But this make it problem, because the new class now cannot access the encapsulated fields it could access previously. Various languages give you various tools how to solve this problem. You could make them public, internal or make the class a "friend", or whatever.

The thing is that OOP modeling and design is extremely complex area with lots of unsubstianted "what to do" and "what not do" and every time you present a solution to a problem someone comes with similar problem where the solution doesn't work. It all comes down to experience. There have been written whole books, blogs and seminars about this topic. There is no way to answer your question with simple, few hundred words post.

  • Thank you, I got the difference, but if a class has only some public fields, is there any difference in approaches I shown in the updated question, I thought a class with no function has nothing to hide? – Ahmad Apr 10 '15 at 6:49
  • "but if a class has only some public fields" Then it is not a class, but a data structure. A bad one at that. – Euphoric Apr 10 '15 at 7:15
  • Yes, a class with no function is a data structure, the difference between first and second approach is to have all functions in one class or distribute them over classes, and as you said, its all depends on dependencies, SRP, and separation of concerns! then you mean separation of concerns is meaningful just when dependencies come to the problem? (Thanks anyway i think that's true if you have no comment) – Ahmad Apr 10 '15 at 7:30
  • @Ahmad No, SRP is meaningful all the time. Dependencies just give it another dimension, making it much more complicated. Operations and data are tightly connected. You should avoid creating artificial division between the two. – Euphoric Apr 10 '15 at 7:32
4

The easy answer is to mix data with functions that are responsible for that data. For instance, if you have a Document class, it makes sense to have a CalculateWordCount function in it, since it's the class that's responsible for the Words inside the Document. Alternately, you can have the Document responsible for Paragraph objects, which are in turn responsible for Paragraph-level functions, and so on.

The tricky part is modelling functions that seem to span several areas of responsibility. For instance, a Save method on that Document. Is is the responsibility of the Document to save itself, even though it will now have to be aware of a filesystem on which to save? Should we instead have a FileSystem class which receives the Document class and saves it (which allows us to switch it with a WebStorage later on), or pass the FileSystem into the Document.Save? Both are valid designs, and they're where experience can help you decide.

1

If your conclusion from previous answers is that you should separate function fron data, either

  1. You have misunderstood the answers
  2. Those answers are wrong.

This assumes that you are using an object oriented language, where the whole idea is to combine functions and data.

  • I need examples where I should mix them, and when I shouldn't – Ahmad Apr 6 '15 at 6:40
1

If you need examples when to bind data and behavior and when to separate, patterns books like GoF do have them. Important part: every pattern has a well-defined applicability area, telling when to use it.

Another basic design principle is "Low coupling (between entities), high cohesion (inside single entity)", the entities being objects or functions or pure data objects.

Together with patterns, you need a vision what to apply them to - that is, what to model. I recommend Martin Fowler's "Analysis patterns" book and Eric Evans' "Domain-driven design" AKA "DDD".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.