1

Let's say I have a class modeling some kind of object, for example a graph (in the graph theory sense).

I will have the graph structure and data inside the class, but what about other more complex behaviors? For example, I want to create a function that transforms the graph in a specific way, or that dumps the graph in a JSON format. Should these functions be inside or outside the class?

My first thought is to put these kinds of functions inside the class, but if I put a lot of functions, each graph object will take way more memory right?

Are there clear guidelines for this question? Also, is it language dependant?

3 Answers 3

4

if I put a lot of functions, each graph object will take way more memory right?

Wrong (at least for any language I'm aware of). There is likely a small overhead (of the order of bytes to tens of bytes) per class for adding more functions but not per object.

How much should go into your objects is to some extent a philosophical debate: the OOP "purists" will tell you everything should be a member function; other people will say that forcing everything into the class for the sake of it leads to bloated classes which violate the SRP - this can be particularly true for something like JSON serialisation which is very much an orthogonal concern from the main purpose of your class.

5
  • Just a minor point: I don't think even OOP purists would argue for bloated classes/objects (preference towards member functions doesn't imply that it should all go into the same object (or into a few mega-objects)). Dec 6, 2021 at 12:03
  • In that case, is it possible to split a class into several parts, by behaviors? For example having a class split into 2 files, one for the core class, and one for the input/output utility functions ? Do some languages propose such features? Dec 6, 2021 at 12:10
  • @FilipMilovanović Absolutely nobody directly argues for bloated objects, but rich domain models / "Tell, don't ask" can lead to that in my experience if applied too rigidly. Dec 6, 2021 at 12:13
  • 1
    @AlexisPister C# has partial classes which allow you to do precisely that. But I'd strongly advise against it, a huge class in 2 files is just as bad as a huge class in 1 file (or perhaps worse because you're hiding the badness). partial classes were to a very real extent a hack to allow the WinForms visual designer to work and you shouldn't use them for other things. See the 3rd bullet point here... Dec 6, 2021 at 12:16
  • 2
    @AlexisPister - You'd normally do something like that by making two distinct classes with different responsibilities and a well-defined way in which they can interact (communicate and collaborate to achieve a goal together). Every OO language allows you to do that. That's the whole point of OOP! But it seems to me that you're not thinking along those lines (you're not thinking in terms of interacting objects and in terms of how that interaction should happen), it looks like you are thinking about functions sharing data, and are treating classes as namespaces; if so, shift your thinking. Dec 6, 2021 at 12:16
1

It's actually not complicated. You put all behavior in a class that needs the internal data of that class to work.

Whenever you need to "get" some data from an object to do something, well, that something should likely be in that object in the first place.

Having additional behavior in a "class" does not use heap memory, so you'll be fine.

So here are some caveats. I lied. It is actually sometimes complicated, when you have different requirements, or you're building a library for which you don't yet know, or even can't know all use-cases. Obviously if you need to support behavior that will be added later, by somebody else, you need to make data available. For example you want to support somebody else implementing a graph search. Well, you'll have to make data available and you probably won't put those things where they would be in a closed application.

Also, you can actually refactor objects. That means push "data" elsewhere, or group data together, etc. So if you feel a behavior does not fit an object well (meaning you don't have everything for it in one place), you could actually move things around, so it does fit somewhere and also the data for it is co-located.

0

I was the sole maintainer of a Java application (molecular diagnosis) for 15 years, during which time the design evolved a lot. The original developers had answered your question "inside".

... I want to create a function that transforms the graph in a specific way, or that dumps the graph in a JSON format. Should these functions be inside or outside the class?

After a few years I noticed that there were more and more transforms and dumps, or their analogues, so I started to change:

void sometransform(parameters)

to

void transform(AbstractTransformer transformer, parameters)

I already had some unit tests in place, and made a point of covering any code with tests before I refactored. My experience with large systems is that one never gets it right the first time, because the client never gets it right the first time: the client makes educated guesses about the behaviour of the market, the listen to feedback (otherwise they will go broke and not be able to afford developers), and their requirements evolve. So change the code: if it protests that the change hurts too much, change the design.

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