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;
}
Ahmad
  • 1,866

4 Answers4

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.

Euphoric
  • 38,149
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.

user949300
  • 9,009
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".