Jump to content

How to "think" OOP?


NotionCommotion

Recommended Posts

I've been reading about OOP and am starting to get a grasp of some of the principles such as encapsulation, inheritance, polymorphism, prefer composition over inheritance, SOLID, etc, but still am not "thinking" OOP but only somewhat applying these principles to my current procedural oriented brain.  I expect I am overly thinking this, but I recently wrote an application using primarily inheritance and it become a convoluted mess, and I really need to change my way of thinking (I will write up some specifics to follow).  I have listed a couple of my newfound inklings below: 

 

I had an epiphany yesterday when I questioned who is responsible to specify the interface.  Previously, I would write some class which did something, and then write an interface which enforces it.  While this might provide a little value, I now think I had it wrong, and this viewpoint prevented me from thinking OOP.  Instead, I should have started from the parent class's prospective and asked "what do I want?" or "what you must provide" and not "what I can deliver".  Is this a better way of thinking?

 

If that need is overly specific, then I should make it more abstract and think "VERB ANYTHING" or "VERB YouTellMe".  I still question how abstract is enough (i.e. drawCircle() is too specific, draw() is more abstract, makeArt() is very abstract) but expect I will come to grasp with this over time.  In addition, I suspect one might try to decouple adjectives and/or adverbs from the action, but haven't yet generated any ideas how or really even why.

 

I think domain classes represent the thing and is the authority of what the thing can do (methods) and what data it has (properties), and implementation classes control what we want to do with the thing.  I've read that domain classes shouldn't extend implementation classes and neither the reverse and each should be separate classes, but I was never certain the correct definition of domain and implementation classes.

 

UML are to OOP as ERD is to relational databases.  Question:  How important is it to create UMLs, and do you do so?

 

Polymorphism, prefer composition over inheritance, and open-closed principle are all related to the same concept.  Yes, I suppose polymorphism can be archived by inheritance but most seem to imply that it is archived by combining objects differently (i.e. composition).  OCP requires that the functionality be changed without modifying the code, and if I extend the class and modify the code, well then it doesn't meet this principle.  The use of the world "extension" is a little confusing in OCP's definition "Objects or entities should be open for extension, but closed for modification" as it implies that one class is "extended" by inheritance, but I suppose I am just misinterpreting the word "extend". 

 

"Prefer composition over inheritance" does not mean only use composition, but only when all things are equal, use composition.  Inheritance is the better choice when taking a "thing" and making it more specific.  For instance, circle extends (is inherited from) shape is more appropriate than inserting circle characteristics into a generic shape.  Inheritance is preferred when dealing with a single logical domain where a sub-class's abilities are primarily additive to that of the superclass.

 

Classes should be small, and if they get big, they are likely doing to much and have multiple "reasons to change" and should be sub-divided into multiple smaller classes.

 

Inheriting some super grab bag utility class (i.e. more specialized array operations, cURL, rendering a prepared statement for troubleshooting, etc) is not a good idea (but is something I have always done).  Instead I should either inject this class or make them static, or maybe if I reduce class sizes enough, not use them at all (not sure if I like this idea), and probably should break them into sub-classes. 

 

Sorry for kicking a dead horse, but I really need to make this sink in and would appreciate any comments whether I am "thinking" correct, or whether there are addition important ways I should alter my thinking.

 

Thanks

Link to comment
Share on other sites

rambling ahead

 

 

 

I had an epiphany yesterday when I questioned who is responsible to specify the interface. Previously, I would write some class which did something, and then write an interface which enforces it. While this might provide a little value, I now think I had it wrong, and this viewpoint prevented me from thinking OOP. Instead, I should have started from the parent class's prospective and asked "what do I want?" or "what you must provide" and not "what I can deliver". Is this a better way of thinking?

I start by thinking about how I want my classes to be used and what's needed to allow that. I'll use my Gearman library as an example here. When I started this project, I created pseudo-code regarding how it would be used before anything else. That pseudo-code (after some tweaks) essentially became the examples in the read me file. Once I was happy with that pseudo-code I knew what sort of public methods and classes I would need so I wrote those up. In this instance I just went straight to a class, but in some cases I might make an interface instead. It depends on if I think I may need to have multiple implementations with the same API or not.

 

After that it was a matter of implementing those public methods so they did what they needed to do. The process can be repeated at the next level if needed. For example I needed to have some objects to manage the socket connection and data communications with the gearman server so I again wrote up some pseudo-code for how I thought that should work then implemented it that way.

 

I find working like this makes the process easier as you can think about the problem on a high level and design how you want the code to work without worrying about how to actually make the code work. Once it comes time to implement your design you may find it needs some changes, but they are generally minor in my experience.

 

UML are to OOP as ERD is to relational databases. Question: How important is it to create UMLs, and do you do so?

I've never bothered with UML. The pseudo-code / interface approach I use works well for designing. If things are then named and categorized well then it's generally not hard to figure out how everything relates by just looking at the code.

 

 

Inheriting some super grab bag utility class (i.e. more specialized array operations, cURL, rendering a prepared statement for troubleshooting, etc.) is not a good idea (but is something I have always done). Instead I should either inject this class or make them static, or maybe if I reduce class sizes enough, not use them at all (not sure if I like this idea), and probably should break them into sub-classes.

Indeed, you should only be inheriting if the two classes are largely related. Because you can only inherit from one parent, you don't want to be wasting that on some utilities functions. What happens when one day you are say developing a plugin for something and your plugin has to extend a certain class? Now you can't extend your SuperUsefulUtilities base class and all those fancy utility functions are not usable.

 

If your utilities are worthy of a class, it's best to make them into a class you can make an instance of. If they are are just random useful functions, leave them as simple functions and include them.

 

Traits can kind of be abused to simulate extending multiple classes, but it's a slippery slope I think. I've yet to come up with anything that I'd consider to be a good use of traits, but I have abused them a bit as a way to share some common code between classes before when I don't have time to do some proper refactoring.

 

 


 

As for your title question "How to think OOP?", that's mostly just something you'll need to develop over time. As you've already noticed there are several opinions out there as to what's right or wrong and so with each tutorial or code base you study you'll find sometimes conflicting statements about what to do and not to do.

 

The best thing to do is to learn about what is possible, then try and find reasons why people think such things are good or bad and decide if you are with those reasons or not. For example, some people think that things like Singleton classes are the devil and should never be used. Other's find them to be quite useful and think outlawing them is absurd. I come down somewhere in the middle of that debate. There are reasons you'd only want a single instance of something and a singleton class is a great way to accomplish that. On the other hand, just because you only want a single instance right now doesn't necessarily mean you won't need a second in the future.

 

 

Not sure if the above is helpful in any way, kind of came out like incoherent rambling imo. I spent some time on it though and don't want to just delete it, so there you go.

Link to comment
Share on other sites

I'm going to quote myself from your other thread:
 

It should be easy. It should be logical. That's it.
 
If I am tasked to change something in the registration process. It should not take me more than 2 seconds to figure out where I need to make the changes.


I use the same process kicken uses. Keep it simple, above all else. Software means nothing, if it's filled with fancy terms, and none of your co-workers can maintain it.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.