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 :)
Oldest comments (35)
Code less do more, reusability, single responsibility, less tests. If your class has great namings, I think you can understand everything. Nothing is complex.
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.
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 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.
Thanks for the suggestion. I've found <CppCon 2014: Mike Acton "Data-Oriented Design and C++"> on Youtube, i'm listening now :)
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.
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.
It's a valid paradigm for managing a large amount of state in an application. I consider that to be a flaw in itself and in that case the application should be split up.
You have to ask your self why is OOP so popular? What is it good for? The key here is polymorphism. This is what allows us to be able to have inversion of control and in turn allows us to use SOLID.
With polymorphism I can build an application with extensions, allowing others to extend my application with out knowing or caring. I can also do things like composition to reuse code between various parts of my application. I can use inversion of control to insert a mock implementation of my datalayer allowing my tests to run fast. Or test any other part of my system in isolation. This is all possible in statically type languages using OOP.
I use interfaces and abstract types to define my contracts and I can easily replace the implementations with mocks or test doubles when writing tests.
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 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 ;)