81

Does an object have to represent an entity?

By an entity I mean something like a Product, Motor, a ParkingLot etc, a physical, or even a clear-cut non-physical conceptual object -- something that is well defined, with some core data clearly belonging to the object, and some functions/methods that clearly operate on the core data.

For example, I can have an object of a Demon, an entity in itself, an imaginary one perhaps and not physical but an entity nevertheless

Can an object be just a collection of methods, a common set of procedures that tie in with a common goal?

Example: can a class be called MotorOperations or MotorActions, where there is no entity, but methods inside the class do things like

  • getMotorDataFromHTMLForm()
  • getMotorManufacturers()
  • selectMotorFromUserRequirements($requirements)
  • canMotorCanHandleOperatingConditions($conditions)
  • computePowerConsumptionForMotor($id)

A class is typically defined as data central to the object + operations on data. So for a Motor there may be some motor variables relating to motor specifications, and there can be operations that combine those data to produce something.

In my case it is more like I have a class with operations on data + data that is passed through the class, there is no data centric to "Motor Operations", other than temporary pass-through-the-class data.

Question

Can classes represent entity-less objects? If not, why they are bad/incomplete/non-OOP-centric? Are there ways they need to be changed/improved conceptually to be in line with OOP?

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.

  • 2
    +1. But would "yes" mean that it does have to represent an entity, or would it mean that they can represent entity-less objects? – Panzercrisis Jul 7 '15 at 21:29
  • 1
    First thing that comes to my mind: java.awt and its "Op" classes (e.g.docs.oracle.com/javase/7/docs/api/java/awt/image/…), if that's what you mean. It represents an operation. Now, I'm not sure whether it's good practice (it does look weird and ugly), but it's included in Java standard library, and Java is OOP. For the most part. – Luke Jul 7 '15 at 21:49
  • 1
    No it doesn't, but that doesn't mean MotorActions or MotorOperations are good ideas or not. – immibis Jul 8 '15 at 9:26
  • 1
    This question could benefit from a further specification of can. – reinierpost Jul 8 '15 at 16:47
  • 3
    @Dennis I really feel like you're asking all the wrong questions. First because there's no one definitive definition of OOP, second because paradigms are only a means to an end. The only questions that matter are "does writing code this way make it easier to reason about its correctness?" and "does writing code this way make it easier to reuse?" – Doval Jul 8 '15 at 18:38

13 Answers 13

108

No, an object does not have to represent an entity.

In fact, I would argue that when you stop thinking about objects as physical entities is when you finally get the benefits that OOP promises.

This isn't the best example, but the Coffee Maker design is probably where the light started to come on for me.

Objects are about messages. They're about responsibilities. They're not about Cars, Users, or Orders.

I know we teach OO this way, but it becomes apparent after a few tries how fundamentally frustrating it is to figure out where things go when you try to do MVC, MVVM or MVWhatever. Either your models become ridiculously bloated or your controllers do. For navigability, it's great to know that anything that touches Vehicles is in the Vehicle.ext file, but when your application is about Vehicles, you inevitably end up with 3000 lines of spaghetti in that file.

When you have a new message to send, you have at least one new object, and perhaps a pair of them. So in your question about a bundle of methods, I would argue that you're potentially talking about a bundle of messages. And each one could be its own object, with it's own job to do. And that's ok. It will become apparent as you split things apart which things really, really need to be together. And you put them together. But you don't immediately drop every method in a vaguely appropriate drawer for convenience sake if you want to enjoy OO.

Let's talk about bags of functions

An object can be just a collection of methods and still be OO, but my "rules" are pretty strict.

  1. The collection should have a single responsibility, and that responsibility can't be as generic as "Does stuff to motors". I might do such a thing as a service-layer facade, but I'm acutely aware that I'm being lazy for navigability/discovery reasons, not because I'm trying to write OO code.

  2. All the methods should be at a consistent layer of abstraction. If one method retrieves Motor objects and another returns Horsepower, that's probably too far apart.

  3. The object should work on the same "kind" of data. This object does stuff to motors(start/stop), this one does things with crank lengths, this one handles ignition sequencing, this one takes an html form. This data could conceivably be fields on the object and it would seem cohesive.

I generally build objects of this sort when I'm doing transforms, composition, or just don't want to worry about mutability.

I find focusing on object responsibilities leads me towards cohesion. There has to be some cohesion to be an object, but there doesn't need to be any fields nor very much behavior for it to be an object. If I was building a system that needed those 5 motor methods, I would start out with 5 different objects that do those things. As I found commonality, I would either start to merge things together or use common "helper" objects. That moves me into open/closed concerns - how can I extract this bit of functionality so I never have to modify that particular file again but still use it where needed?

Objects are about messages

Fields barely matter to an object - getting and setting registers doesn't change the world outside the program. Collaborating with other objects gets the work done. However, the strength of OO is that we can create abstractions so we don't have to think about all the individual details at once. Abstractions that leak or don't make sense are problematic, so we think deeply (too much, maybe) about creating objects that match our mental models.

Key question: Why do these two objects need to talk to each other?

Think of the object as an organ in a person - it has a default purpose and only changes behavior when it receives a specific message that it cares about.

Imagine a scenario where you're in the crosswalk and a car is coming fast. As the brain object, I detect a stressor. I tell the hypothalamus to send corticotrophin-releasing hormone. The pituitary gland gets that message and releases adrenal corticotrophic hormone. The adrenal glands get that message and create adrenaline. When the muscle object gets that adrenaline message it contracts. When the heart get the same message, it beats faster. There's a whole chain of players involved in starting the complex behavior of sprinting across the street and it's the messages that matter. The brain object knows how to get the hypothalamus to send out the alert, but it doesn't know the chain of objects that will eventually make the behavior happen. Likewise the heart has no idea where adrenaline comes from, it just knows to do something different when that shows up.

So in this (simplified) example, the adrenal gland object only needs to know how to take ACTH and make adrenaline. It doesn't need any fields to do that, yet it still seems like an object to me.

Now if our application is designed only to sprint across the street, I may not need the pituitary gland and the adrenal gland objects. Or I only need a pituitary gland object that only does a small part of what we might conceptually see as the "pituitary gland model". These concepts all exist as conceptual entities, but it's software and we can make the AdrenalineSender or MuscleContractor or whatever and not worry much about the "incompleteness" of our model.

  • 4
    I agree with the actual content of this answer, but I feel like it misunderstands the question. Specifically, the question includes in entity "or a concept, something that is well defined". Counter-examples to this are "MotorOperations or MotorActions". From this, I'm pretty confident that both the original and final class designs from the CoffeeMaker example fall under the OP's definition of "representing an entity" – Ben Aaronson Jul 8 '15 at 12:37
  • 1
    The postmodern system architecture DCI handles this without the extreme abstractions created by structure-loving engineers. The computer should think what the user is thinking, not the other way around. fulloo.info/doku.php?id=what_is_dci – ciscoheat Jul 8 '15 at 15:29
  • @BenAaronson I feel like you can evolve to that object as cohesive concept with enough concerted effort, but I have found a tendency for an entity-focus to force things together that should be apart. Entities encourage boundaries in our names, which is good, but they also bring along this notion of correctness/completeness, which tends to hurt. In the most ridiculous terms, I'm for a FirstNameValidator object and against a Name object that also does validation for first and last names. – Steve Jackson Jul 8 '15 at 17:03
  • 1
    Another good example: ericlippert.com/2015/04/27/wizards-and-warriors-part-one – Moby Disk Jul 8 '15 at 19:09
  • 2
    Objects are about messages - Steve Jackson's answer - this is absolutely right on. MOP is not what is meant by "messaging" as conceived by The Father of OO Alan Kay who said the big idea is messaging. And further, I'm sorry that I long ago coined the term "objects" for this topic because it gets many people to focus on the lesser idea. – radarbob Jul 11 '15 at 22:32
21

Can classes represent entity-less objects? If not, why they are bad/incomplete/non-OOP-centric? Are there ways they need to be changed/improved?

In short, you can do anything, but this specific scenario would be against OOP principles :)

What you are describing is sometimes called a "utility" class - usually a sign of code smell. You want to avoid creating classes for the sake of keeping some methods together.

Not every object in your application has to be linked to a real-life entity like a motor, or car; those are business objects. In your application, you are likely to use many of your business objects, but you would also need some more segregation for other operations that are not part of business entities, like the ones you listed.

You should have a look at common architectural patterns - one of them is MVC (Model-View-Controller).

If I was to distribute the methods you listed using MVC, here is what I would do:

View Class:

  • GetMotorDataFromHTMLForm()

Model Class (Motor Essentially):

  • GetMotorManufacturer()
  • CanMotorHandleOperationConditions()
  • CalculatePowerConsumption()

Controller Class(MotorsController):

  • GetAllMotors()
  • GetMotorById()
  • GetMotorByUserRequirements()

It seems like you are using PHP; a good MVC framework to have a look at is Laravel. In their examples they illustrate well where what methods belong to.

Another, more generic source of information how to decide where the methods belong are GRASP and SOLID principles.

  • thanks. In essence, it looks to me that what I have is a Controller class with a few impurities mixed in (Model, View, etc). Does that mean that if I rename MotorOperations to MotorsController and clean it up a bit, my collection of functions will be in line with OOP? – Dennis Jul 7 '15 at 22:25
  • @Dennis, Not necessarily, have a look at my collection of methods under each class. Controller is not a class that contains it all :) It's the class that has operation on your models, and nothing more. The only dependencies of a controller would generally be DAL(Data Access Layer) directly, or services that provide you access to DAL. You never want to access View from the controller (example: getMotorDataFromHTMLForm), instead, your View should be the one dependent on the controller. – Alexus Jul 7 '15 at 23:00
  • 2
    Could you elaborate on why a Utils class would be an example of code smell? Just curious, as I have myself enjoyed having random util functions wrapped in a Utils class as opposed to just being stand-alone functions... in my experience it makes code a bit more readable, but my experience is limited. – HC_ Jul 7 '15 at 23:45
  • 3
    @HC_ Having a Utils class is the same as having a "Misc" folder in your picture collection. It indicates that you were lazy to assign responsibilities to your objects properly/potentially missing objects and use Utils to compensate for that. There is a room for Util classes, especially with static functions, and extensions to other classes, but before you create a collection like that, check if you can incorporate them into your proper OOP classes :) Another reason is sometimes a class can only have one method. But going forward, you need to add more and Utils class becomes a bigger mess. – Alexus Jul 8 '15 at 0:19
  • I often end up with a Utils LIBRARY, but I usually try to group and name my utils classes a bit more descriptively. These days, there are many open source "common utilities" libraries out there that already have general purpose utilities that most people need, so I'd look around a bit before writing your own. – Guy Schalnat Jul 9 '15 at 17:02
15

Can classes represent entity-less objects?

Can? Yes. Should? Probably not - or at least, not how you're phrasing things.

Objects actually are best when not representing a physical object directly since reality so infrequently maps nicely to code. But they do need to represent a cohesive concept or code-object. They need to represent a single cohesive responsibility.

Just bundling a bunch of tangentially related functions together is a namespace or a module - not an object in OOP parlance. Those can be useful, but they're not the same, and require a different sort of usage/thinking to work with effectively.

  • 3
    bundling a bunch of tangentially related functions together is a namespace: that sounds more like procedural paradigm rather than object oriented. – Dennis Jul 7 '15 at 20:42
  • @dennis - exactly (or functional if you call it a Module). Mixing paradigms can be powerful. Or it can be terribly messy. – Telastyn Jul 7 '15 at 20:43
  • Or both :) - - - - - – Alexus Jul 7 '15 at 20:59
  • @Dennis : Or neither - bundling together only tangentially related functions is a dubious practice in any paradigm. – sdenham Jul 8 '15 at 14:55
  • I am dealing with code that started out as a procedural codebase. At some point an effort to convert it to OOD was made but, mostly classes were created to "hold functions and methods", without any actual OO-design. I have been discovering quite a few things like this that try to bridge the gap between paradigms but are neither in one nor the other – Dennis Jul 8 '15 at 15:03
11

A class should model something - otherwise it's pointless. However, what's being modeled may not be a physical "thing"; instead, it may be a representation of something which is not 'real', but which is needed to control the system being modeled. For example, in a traffic light control system you could very well have some sort of ControlSignal class, representing a signal sent from one portion of the system to another to indicate that some action needs to be performed. In "the real world" these signals might consist of electrical impulses transmitted across wires from one box to another. The process of modeling something which isn't "real" as a concrete object is referred to as "reification".

Best of luck.

  • Yep, that's almost precisely what I would have said. A class is nothing more than a model for a noun. That's it. Nothing more, nothing less. A class is a noun, and methods are verbs (or messages if you prefer). A junior engineer who thinks in those simple terms can go a long way before those analogies break down (unlike trying to pretend that classes are descriptions of physical objects -- an analogy that starts to break down on almost your first project). – Calphool Jul 9 '15 at 21:05
7

No. (Title edited to ask the opposite question!)

eg:

Public class MyRepository
{
    public MyObject GetObject(string id)
    {
        //get data from the DB and build an object
    }
}

or

Public class MyService
{
    public MyObject3 ProcessData(MyObject1 obj1, MyObject2 obj2)
    {
         //perform a process which is not a sole responsiblity of obj1 or obj2
    }
}

However, in general the ideal behind OOP is to move away from

public struct Car
{
    public Wheel[] Wheels;
}

public int CountWheelsOnCar(MyCarStruct car)
{
   return car.Wheels.Length;
}

to

public class Car
{
    private Wheel[] wheels;
    Public int CountWheels()
    {
        return this.wheels.Length;
    }
}
  • Do you mean that they can represent entity-less objects? (See the comment I left on the question.) – Panzercrisis Jul 7 '15 at 21:31
  • 3
    I've been programming OO too long I guess--when I looked at MyRepository I immediately pictured a glass bowl on my dresser with a bunch of coins and crap in it. Reach in and grab out a penny, or a button.... – Bill K Jul 7 '15 at 22:58
  • @pan yes, like the service and the repo in my example – Ewan Jul 8 '15 at 5:36
  • @bill you crazy old fool!!! Thats the MyButtonAndOrPennyBowl class! clean coding ftw – Ewan Jul 8 '15 at 5:37
  • 1
    Your second example looks to me like a function dressed up as an object, which is not (in my opinion) justified for its own sake, though there may be some other justification (e.g. if functions are not first-class entities in the language.) – sdenham Jul 8 '15 at 14:10
5

I think that visualizing something in the real world is helpful when coding classes but not necessary.

In fact, depending on how literal you want to be, many objects we work with don't have physical representations at all. For instance--consider MVC architecture. In the real world there is no Model or Controller even though they are generally represented by classes. The three together often represent something, but not always--but as I said you could probably force a fit into something if you really want to (and being able to imagine SOMETHING helps! I visualize most objects in some way--just not anything you'd ever see in the real world).

Mostly these "Rules" you will learn about OO are just guidelines meant to get you oriented into thinking in OO not necessarily things you worry about much once you are using it to code on a daily basis.

By the way OO itself isn't some panacea and it doesn't help you much at all during your first pass at coding some solution, but I think that if done right it is a truly fantastic way to organize code so it can be more readily understood later. Writing maintainable code is probably one of the hardest tasks in software development and in many cases (anything that requires ongoing debugging/maintenance) it is by far the most important.

5

Does an object have to represent an entity?

Question: Which entity does a Logger represent?

Not metaphorically - literally.

When explaining OOP to students it is helpful to explain objects with analogies to the physical world.

Alan Kay - one of the fathers of OOP - wrote the following:

[...]

The original conception of it had the following parts.

  • I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages
  • I wanted to get rid of data.

[...]

OOP to me means only messaging, local retention and protection and

hiding of state-process, and extreme late-binding of all things.

almost unbelievable HW architecture. I realized that the

cell/whole-computer metaphor would get rid of data

source

From this, objects are best understood as

  • autarkic objects encapsulating / hiding data

  • communicating with other objects via messages

Can classes represent entity-less objects?

Definitely: Think of Math


Regarding your example:

Example: can a class be called MotorOperations or MotorActions, where there is no entity, but methods inside the class do things like

  • getMotorDataFromHTMLForm()

  • getMotorManufacturers()

  • selectMotorFromUserRequirements($requirements)

  • canMotorCanHandleOperatingConditions($conditions)

  • computePowerConsumptionForMotor($id)

To decide, where to put these methods, you have to take a look at responsibilities: who is respnsible for what.

getMotorDataFromHTMLForm()

The context of such a method would be constructing a motor-object. It is not the responsibility of the motor to create itself from Data retrieved via a form. There are at least two objects involved; one is the motor and the other is the creator of the motor.

getMotorManufacturers()

The typical context in which one would write such a method is a service.

selectMotorFromUserRequirements($requirements)

This would also be used in a service-context

canMotorCanHandleOperatingConditions($conditions)

This is a question to a motor-object

computePowerConsumptionForMotor($id)

This too is a question best asked a motor itself.


tl;dr

The metaphor of objects as physically objects is more irritating than helpful.

  • wow your answer breathes some life into OOP! I have to say that I didn't mean physical as an end to it all. intent of my question was more "does an object have to be a thing with data where data clearly belongs to the thing and functions that clearly operate on the data that belongs to the thing". So Logger in this case, while not a physical thing, it is a concept akin to that of a "physical log book". Whether it has data that is core to its state, and is not just transient to it, that may depend on implementation and interpretation .. and is more so where my question was going.. – Dennis Jul 8 '15 at 18:06
  • but yes, answers had to address my physical bias – Dennis Jul 8 '15 at 18:26
3

Yes, you can do this. But you're essentially creating a class to provide the same functionality as a procedural library. The only reason to do that is if your language lacks procedural modules (e.g., Java or Ruby).

In a language with procedural modules (I think PHP has procedural modules), you might consider just using a procedural module.

You could also consider re-designing your class so an instance of the class represents a coherent object.

But only use OO notation when it's giving you extra power, not just for the sake of being OO!

3

In layman's words

  • What you describe is called an utility class.
  • It has no state, meaning you will not ever really need to have several instances of it
  • All methods are static, meaning you have to pass everything as parameters

Such classes do exist, for example the Java SDK has the Collections class which consists exclusively of static methods that operate on or return collections.

So the answer would be no, not all classes need to be modelled from a domain entity.

In the other hand, such classes are only a few or should be only a few in a program made in a OOP language, since the real power of OOP lays in polymorphism and encapsulation.

It would be like using a plane to go from one place to another not by flying but by driving it around on freeways. Planes have wheels like cars do, but they are intended to fly.

2

No, a class merely represents something that can be instantiated, has members, and can be inherited from.

In fact, your language may have static classes, which are not even instantiated more than once.

.NET's Math is a great example of a "professional" class that represent no entity (unless you want to get philosophical about what math is...), and also happens to illustrate a legitimate use case of such a class. It has only methods and 2 fields (both representing individual constants).

The class hierarchy of a similar library, Math.Net, groups mathematical/numerical methods into classes by type. Here classes represent not an entity, but a logical category.

I myself often end up creating (static) classes which are nothing more than a bag of related (static) functions, or a bunch of constants conveniently grouped in one central place. I wouldn't claim that this is good design, but sometimes it's the most straightforward solution.

  • 1
    The fact that the math-related methods are placed in .NET/BCL into a separate class as static methods is not a necessity or design consideration but a consequence of a fact that there are no free-standing methods in C#. In C++ such functions could be just grouped into a namespace. – Vlad Jul 13 '15 at 20:41
1

The answers to your questions ultimately hinge on how precisely one defines terms like "class" and "entity." You did a good job of defining the latter, allowing both physical and conceptual entities. But the term "class" to purists will always be "a factory for instantiating objects with a particular internal representation" and to pragmatists the term will encompass those Java or C++ things despised by purists. Ditto for the term "OOP," which pragmatists might say Java and C++ do, but which purists would take to mean what Alan Kay meant when he remarked ["I invented the term object-oriented, and I can tell you I didn't have C++ in mind"]( So what *did* Alan Kay really mean by the term "object-oriented"?).

If you take the pragmatist view, you can accept your instance-less utility classes. But the purist view is more interesting. OOP, according to Kay, was always more about the messages than the classes. So to your questions:

Can classes represent entity-less objects?

No. Classes classify objects. Classes are by definition those entities to which you send a message such as new to produce an object. An object is an entity made from a class. Classes exist to manufacture, and indeed classify, objects. That's what classes do. Classes make objects. We use classes to classify objects. So if C is just a bundle of methods that does not permit instantiation or subclassing, there cannot be any objects classified by C, so C is not a class.

If not, why they are bad/incomplete/non-OOP-centric?

They're not bad. Just don't call them classes. A bundle of methods is OOPable: something you could send a message to in order to invoke a method, but it's not a class unless it can instantiate an object. Do you know Ruby? In Ruby a module is a bundle of methods. A class is a module that can instantiate objects. There is nothing bad about a module. But the thing that makes a class different from a module (in pure OOP terms) is that a class can have instances. A module is just some methods. The confusion is that C++ and Java and other languages use the term "class" for both class and module.

Now, to look at one of your specific examples, you ask about a MotorOperations class to which you could send the message computePowerConsumptionForMotor with argument id. Is that bad? At least it does not violate the Tell Don't Ask Principle. Do we have to make a motor class and send it the powerConsumption message? Maybe not 100% of the time, but maybe trying to do such things will lead to some nice insights about your code. Or, it can lead to an explosion of little classes which would be bad.

Are there ways they need to be changed/improved conceptually to be in line with OOP?

If "doing OOP" is important to you, then you will want to look for ways to architect a system into components that communicate by sending messages to each other. That is just what OOP is, or at least what the coiner of the term had in mind. Utility classes are not OOP in this view. But to some people, they may be.

Trying to make an entire large system out of millions of living, breathing, objects, all instantiated from classes, may work for some projects. But if you find yourself creating artificial, wrong-sounding classes, then modules should be introduced. Try to emphasize classes, and use modules when instantiable classes would be ridiculous.

TL;DR - method bundles are not always bad. Try to use instantiable classes first. Fall back to "modules" only when needed.

0

Taking the given examples:

getMotorDataFromHTMLForm()
selectMotorFromUserRequirements($requirements)

These look like "factory" methods, that would return a Motor object. The second implies that either you're creating a new object to meet requirements, or you have a database or in-memory collection of motors that you're examining. In which case it should be a method on that. Or it could be a method on the requirements object.

getMotorManufacturers()

From where are you getting them? That's what this should be a method of.

canMotorCanHandleOperatingConditions($conditions)
computePowerConsumptionForMotor($id)

These look like they should be methods on Motor.

  • Yes. it is a "bundle of possibly unrelated methods" (BOPUM for short). I agree with the Factory and Motor comments. getMotorManufacturers is to return all motor manufacturers from the database. I am not sure where that goes. It will take me some time to unravel this BOPUM to put things where they need to go.. – Dennis Jul 8 '15 at 14:13
  • I am getting getMotorManufacturers from the Database. Database cannot have a method ... Currently I have a DataMapper pattern that queries the database, initializes an array, and populates it with Motor Objects (also containing Manufacturer information), and then returns that array to the caller. The caller is my MotorOperations class, which in turn is called from a ProductSelection class (which contains an algorithm that is used to select Motors, and loaded motor information is the data for that algorithm) – Dennis Jul 8 '15 at 21:07
0

An object is a collection of methods and data that have high cohesion. They belong in a class because they are highly interrelated and state is retained.

This is true whether you use big up front design and attempt to model everything, or emergent design where you iterate and evolve the object into whatever fits the needs of the system at the time.

If you have no reason to retain state, you probably don't have any reason to instantiate an object which means there is probably no reason to have a class. Unless, the language your using doesn't have the ability to define a namespace other than using class. In which using class should be fine because it would be idiomatic.

I can't think of any negative aspects to using classes in this way other than the typical. Your inviting unnecessary cost and complexity by having to instantiate a "namespace". Anyone supporting this code will wonder where the data is costing additional cognitive load (most likely a one time cost per person). It's an unusual usage without any additional value.

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.