Hi there,
I've had for years a dillema that i just couldn't figure out. At some point in time i had to search for frameworks and CMSs, so i've taken a look at most major PHP frameworks and some C++ as well (not implying that they are related). I've also taken a peek at various open source projects out there, written in various languages, just to see what they're made of.
I've come to see that there's a trend that i like to call "OOP Overkill"; that is programmers tend to throw lots and lots of classes in their source code, everywhere, for every possible reason. And they also tend to create complex hierarchical structures of base classes : derived clases, and so on, alot of times for no apparent reason. I remember the first time i saw this, it was in MFC (Microsoft Foundation Classes), where for every possible window that you wanted to use, it automatically created a class for you. In web frameworks, this translates to at least a class being made for every web page that the application needs to deliver. OpenCart, for instance, uses 3 classes for each web page: one for model layer, one for controller and one for view. And that is on top of a plethora of other system classes that handle core functionalities.
There are even entire languages, like Java and C#, that force this design principle on you, making the entire application one big class (well ok, not so big, but still, instead of having only a main() function to start with, you get your application encapsulated in a class and there's nothing you can do about it).
And even if the language itself doesn't force this, there are lots of programmers who are verry eager to create an application class from the first lines of code and then just quickly instantiate a single object, spreading the logic all over tens of other files, inside member functions (methods) that you litteraly have to chase if you need to do something or to understand how everything works.
Personally, i don't see OOP as a "look, this is how everything should be done and look like". In my opinion, it's more like "look, this is a powerful tool; use it to give life to abstract ideas, encapsulating data and operations in a single object, whenever you need and it makes sense to have such thing". Therefore, as with any other tool, it's your freedom to use it or not.
In my ~15 years of doing all sorts of programs (desktop, web applications, etc.), i've never ever felt the need to take this approach. I've also never ever felt the need to use class inheritance, abstract classes, interfaces or anything the like. And i've taken quite complex projects but still, in languages like PHP, where you have arrays which are verry powerful and versatile, working with data cand be done at a simple level, without the need of complex encapsulation.
But, maybe there's something i'm missing. So my question is: what are the objective benefits of choosing such a design, encapsulating everything, including the application itself, into classes over classes over classes ? Is there, maybe, a security reason i'm not aware of ?
Thanks alot !
Cheers :)
Top comments (35)
I really don't get why the concept of a class upsets so many people, even experienced programmers as in this case. A class is a very lightweight container. Complaining about classes feels to me like complaining about having to use files to contain code.
Classes will give you no benefit if all you do in them is to declare "public static" methods. In OOP, you embrace abstraction and polymorphism. If you don't, there is no benefit. It's like using functional programming without immutability or pure functions - it makes no sense.
The reason why people are arguing so much about OOP and so little about other paradigms (e.g. functional programming) is that the benefit of OOP is much more subtle and less apparent as other paradigms. A good OOP design starts to pay off when you are dealing with large applications, large teams and numerous cross-cutting business requirements. That's why Java and C# are the most popular languages for application servers.
Modularity, abstraction, encapsulation, composition and polymorphism are the core ideas of OOP. Can you build software without them? Sure. Can you do all these things without an OOP language? Sure. OOP is an idea, a concept - not a language or an implementation. If you look at the linux kernel source code, I'm sure you will find plenty of these concepts, even though it's implemented in C.
Thanks for your input. I perfectly agree with you. But i feel that some people have misunderstood me. I wasn't asking the benefits of using OOP at all, just the benefits of exagerating with it.
Like, let's take for instance, the idea of a car. One might create a class Car with all it needs, while many others would create class Car + class SteeringWheel: derived from Car + class Wheels: Car + class Engine: Car + class OnlyThePlayButtonFromTheRadioPlayer: Car and so on and so forth.
That's what i'm questioning.
Oh I see, I didn't get that part - sorry.
I would say it really depends on the use case. If you are dealing with, say, an E-Bay like second hand shop, then modeling the steering wheel of a car as a separate class is definitly overkill. But if you are writing software for a car manufacturer, then it could be totally fine.
I'm not saying that this overkill never happens. Sadly it happens all too often. However, there are two things to consider here:
1) OOP does neither protect you from, nor does it encourage, over-engineering. You can over-engineer a C program, a Haskell program, you name it.
2) An experienced software engineer will not overdo it with classes - and in particular inheritance - when there is no need for it. The most over-engineered code I've seen is coming from junior developers and students. More experienced programmers tend to be pragmatic about it, and that's a good thing. Thankfully, we have very powerful refactoring tools these days. So even if your initial solution turns out to scale badly (e.g. maybe you used an Enum that you now have to constantly expand) you don't have to stick with it forever, you refactor the problematic part into a more elaborate solution. When people come looking at this code afterwards, they may think that it is over-engineered. But they were not aware of all the cases which caused you to refactor the "simple" code in the first place. It's often easy to call a solution over-engineered by looking at it for 5 minutes. But to give a definitive answer requires a very deep dive into all the use cases.
There is also a very large "gray zone" here where it isn't always clear at all if an abstraction is necessary or not. Some people would say that, for example, the Spring Framework is a total overkill in this regard. As somebody who uses a very large portion of it in my day-to-day work, I would argue that it is perfectly on point.
And sometimes your program just needs to do enough things to warrant the number of classes.
Yes, I agree with this. It's important to strike a balance between the extensibility of the program and the mental overhead of numerous classes.
I would like you to Google a book titled Head First Design Patterns and read the first chapter on singleton pattern. You can probably find it on Amazon and read it in the preview. You're definitely missing the point of design patterns and principles if you don't understand why some developers write endless and meaningless single file classes that do less than one thing. What are your thoughts on test driven development if I may ask?
I agree...I have seem overkill use of OOP, specially when people over abstract or do dynamically things that should be static, but everytime I read people questioning OOP (and not doing functional programming) I cringe and hope to never come near their code. How do they TDD? They can't...
I would rather "navigate" through 400 classes 30 lines each then through 10 classes 400 lines each. And I'm being nice when I say 400 lines...I've seem true Megazord classes, with rocket lunchers and everything.
I am so using the term "Megazord classes with rocket launchers" from now on.
OOP and FP (Functional Programming) were invented to help developers adhere to SOLID principles while writing readable code. These are great tools and everyone should be well-versed in their use.
But Yes, anything can be overkill. For example, there is a rule of thumb to keep your methods small. The reason for this is to keep the code focused on a single purpose. However, in many cases it is better (more readable and maintainable) to have one long method (say filling out a large reporting structure with many fields) than to write a complex set of nested methods and classes to accomplish the same thing.
IMHO, Writing understandable, efficient and maintainable code is a blend of art and science. The more experience you have (esp. in picking up other people code and understanding it) the better you will be at it.
You mention using arrays (or stdClass objects I suppose), well the problem with passing arrays to a method or function is you then have to perform a bunch of checks to make sure you have all the elements you need.
and repeat for however many elements you need to validate. And what if you have to pass that array to more than one function? Do you repeat all the validation, or do you abstract it, or do you rely on only being passed valid arrays from trusted callers?
What I do instead is write a dumb little class. It might only be 30 lines long but it'll be instantiated through a static method (or multiple static methods)
Then back in my original function I change the definition to:
My function will only accept valid input.
This is how Swift works basically. You can trust your input and get on with writing clean code.
Massive additional benefit: My IDE (PHP Storm) understands what my object is and will tell me if I type any of the properties wrong. With an array you're on your own.
Thanks alot for the input ;)
OOP can be overkill, especially if used as you described, with complex inheritance hierarchies. Python even supports multiple inheritance so you can really do wild things if you want so.
Want is the key though, you can NOT use complex hierarchies in your code or (as many do in many non functional language) try to use a functional style as possible.
My favorite features of OOP are composition and dependency injection I guess.
To answer your last question: I think that many people just don't think much about it and tend to follow the mass. If, as you highlighted, the framework you incorporate in your app uses objects and encapsulation heavily and the documentation does too, there's a high chance you're going to do the same. The framework might not even work without them :D
My personal experience is that forced encapsulation (aka really private methods or attributes you can't access from outside) can be an issue in the presence of bugs in the "private" logic.
The language I know best, Python, doesn't even really have the concept of private attributes. You can use
_foo
to tell the user that they are looking at a private attribute, you can use__foo
to tell the user that they are looking at a really private (LOL) attribute but they can just access them or even change them if they really want to do so.It's more of a convention than an actual barrier.
Python thinks programmers are grown ups ;-)
There are lots of reasons to use OOP for designing an application, though I am far from an expert.
When it comes to most personal projects or school projects, OOP style development is rarely necessary. There's usually not much repeating of code, the code isn't too complex and separated into many layers and modules. That's where OOP becomes useful.
However, in the workplace OOP becomes a bigger deal. When you've got dozens of project files, thousands of lines of code, and a complex workflow, OOP helps keep it all comprehensible. It allows for easier organization, less repetition of code, more readability, etc. Applications built on .NET MVC are a good example of this. Keeping things in separate layers of data (model), front-end (view), and function (controller) makes sure the code stays organized and that different modules don't overstep their boundaries.
For your last question, yes it can be a security issue. Part of application security is ensuring each module/segment of your code can only access the resources that it needs to access. Encapsulating your classes, keeping methods and variables private, etc. is a basic measure of security that can have catastrophic results if not implemented. This is actually the basis of a buffer overflow exploit, accessing resources that the module shouldn't be able to access.
You should listen to some Mike Acton stuff sometime. He dives into how oop shouldn't be the end all be all approach for everything. He's a big advocate of data oriented design. He can be a bit abrasive about it sometimes, but he's a pretty entertaining speaker. I think he's working for Unity now, which should be interesting to see if Unity starts embracing a bit of the data oriented design process down the road.
I'll look into this. Bit of searching, for something non-video, is this good introduction? gamesfromwithin.com/data-oriented-...
On OO, I read the following articles a while ago:
I am more in enterprise-development (sigh) than game-development, where Java is used a lot. The observations and critique on OO I found very recognizable.
When you strip away everything that sucks about OO, you end up with dynamic binding and a nice module system.
Thanks for the suggestion. I've found <CppCon 2014: Mike Acton "Data-Oriented Design and C++"> on Youtube, i'm listening now :)
If you follow the principle that a class should do only one thing then they often naturally become rather small and in a larger application there can be quite a few.
I personally find that approach appealing, yes there will oftentimes be small classes, but on the other hand once you get familiar with them its often easy to figure out what they're doing and how you should use them without looking inside them. And when you want to add some new feature/ability etc it's often easy also. I need another view, oh just add a class here, then use it in the code wherever you want.
I've also seen examples in production code where the powerful data structures of PHP have been used in functions thousands of lines long to build up to 8 dimensional arrays if not more. Try then to figure out what that code is doing without spending a few hours deciphering it.
Not saying that the code was good by any standard or programming paradigm, but it's what tends to happen if you do architectural decisions as an afterthought.
You brought a hot topic here my friend :)
I start with the basics :
The mistake that can be seen very often is people thinking that methods calls are free or that every bit of their code needs a state.
Many classes should have their methods as static ones.
Many methods, especially from unexperienced programmers are useless or add performance or complexity issues just because they think OOP is the only way to go.
As examples :
completely useless and a perf drop for no other reason than "i'm doing OOP"
or
again: completely useless : if your setter and getter that do nothing then the property IS public by its use.
You can access class prop a lot more efficiently directly than through methods call.
Again something that few people think about: they learned "a way' to OOP and don't question it anymore.
So , OOP is useful, no douvt on this BUT is very OFTEN misused.
Actually, your second example isn't useless.
For sake of argument, your getter/setter is used in multiple locations throughout your application.
You've changed something/discovered a bug/etc. with that variable within your class when it's set to specific values. You can safely put in some input validation into your setter to only allow correct input values (you could even make it a boolean/return a success condition).
If you had direct access to the variable, not only would you have to create some sort of validation after the fact. You'd also have to change all references to the variable to now use your getters/setters.
This might be fine on smaller projects but in a large project or some sort of Framework/Library could cause lots of extra work.
In short, it's better to future proof in that case.
i got to disagree on the principes of future proof.
That is a conception key point :
The point you make that maybe in the future you'll need validation is very interesting: it confirms another OOP situations where developpers overlook properties roles and visibility.
But that is not an OOP requirement or practice it's a conception mistake that needs to be fixed.
My point is that many devs think setting private AND writing setter/getter is "the way to go" in all situations, that's wrong on many occasions.
Visibility/validation is an important part BUT of the conception phase.
I don't even mention security 'cause if it was not thought in conception something's wrong.
I've been lately viewing it as having a gathering of different experts. I need to deliver some
Mail
. Then i need to request aMailman
todeliver(Mail mail)
. That expert may check that theMail
has all the information it needs to be sent. I don't do that checking, i just do my best to provide all the information that theMailman
can do it's job.I don't need to know how the mail is delivered, it's not my expertise. It's actually nobody else's problem to know how to deliver mail.
A lot of folks dread
Manager
classes in code. Also in real life: i should know best HOW to do the thing i'm requested. I have those properties in me to do the job.