OOPHP Advocacy arguments
Moderator: General Moderators
-
leenoble_uk
- Forum Contributor
- Posts: 108
- Joined: Fri May 03, 2002 10:33 am
- Location: Cheshire
- Contact:
OOPHP Advocacy arguments
As senior developer at my company I'm attempting to move the framework I've inherited towards a stricter OOPHP model. At the moment the sites mainly employ an arbitrary "page template/page class" pairing which I spent a considerable amount of time fighting. Now I'm making progress and we have a usable base class which will be applicable for most of our purposes, and the boss wants me to talk all the developers through it and start pushing for a little more thought before new systems are developed.
Developers are pretty much given autonomy in what they write which is where my problem lies. I've got one developer who "doesn't see the point" of OOPHP. Sure, he codes using class structures but that frankly is all they are, structures. The actual code logic is not far in advance of old style procedural code. It's not entirely his fault as this was how they've all been coding for years, and the framework is filled with bloated function dumps as a result. He does fully understand OO and indeed has knowledge of JAVA, but his arguments against OOPHP seem to be:
a) PHP was never meant to be OO
b) What's the point of creating objects for a web application where there is no persistence, and the second the page finishes loading all the objects are destroyed.
So although I'm supposed to be informing everyone about the new super-class, a certain amount of my time is going to have to be devoted to a sales pitch for OOPHP.
Anyone got any killer arguments I can use to shut him up?
Cheers
Lee
Developers are pretty much given autonomy in what they write which is where my problem lies. I've got one developer who "doesn't see the point" of OOPHP. Sure, he codes using class structures but that frankly is all they are, structures. The actual code logic is not far in advance of old style procedural code. It's not entirely his fault as this was how they've all been coding for years, and the framework is filled with bloated function dumps as a result. He does fully understand OO and indeed has knowledge of JAVA, but his arguments against OOPHP seem to be:
a) PHP was never meant to be OO
b) What's the point of creating objects for a web application where there is no persistence, and the second the page finishes loading all the objects are destroyed.
So although I'm supposed to be informing everyone about the new super-class, a certain amount of my time is going to have to be devoted to a sales pitch for OOPHP.
Anyone got any killer arguments I can use to shut him up?
Cheers
Lee
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Re: OOPHP Advocacy arguments
That is simply ridiculous. PHP has object functionality on par with other languages (and improving). "never meant" is an opinion, not a technical assessment -- so meaningless to your company. Either a language has OO or it does not.leenoble_uk wrote:a) PHP was never meant to be OO
I hate to sound harsh, but it sounds like the complaining programmer knows pretty much nothing about the current state of software design or development. And probably worse is it sounds like you know very little as well. The "super base class" gives you away. You're not doing OOP. Your just namespacing a procedural library using the class construct. You programmer doesn't know good design -- but he may know bad design. Give him that.leenoble_uk wrote:b) What's the point of creating objects for a web application where there is no persistence, and the second the page finishes loading all the objects are destroyed.
OO is counter-intuitive. You would never come up with the idea on your own. And programmers, like your stubborn one, who have intuited their way to knowing how to program are particularly resistant. It is not a question of whether you will convert to OO, but when and how well. Honestly, it is how professional applications are built today. It is not arguments that are needed. You, and your programmer, need to see OOP solutions solving your problems.
(#10850)
- allspiritseve
- DevNet Resident
- Posts: 1174
- Joined: Thu Mar 06, 2008 8:23 am
- Location: Ann Arbor, MI (USA)
Re: OOPHP Advocacy arguments
In my experience, OOP isn't really something you can force somebody to use. You have to think in terms of objects, and that is hard to do, if not impossible, for somebody from a purely procedural background. My suggestion would be to look at what code they use, and do some refactoring. Extract a couple useful objects, and show them how to use them with their existing code. Once they start using those, introduce a couple more. Show them the benefits, instead of trying to get them blindly convinced. That would be my advice.
-
leenoble_uk
- Forum Contributor
- Posts: 108
- Joined: Fri May 03, 2002 10:33 am
- Location: Cheshire
- Contact:
Re: OOPHP Advocacy arguments
Yeah, I know from experience that it takes a while to make that leap from procedural code which uses classes to actually using objects in a way which, when it happens, just feels "right". Everything clicked into place for me eventually and it was like an epiphany. Trying to explain that to somebody who hasn't got there yet isn't really helped when that person is resistant to change.
Some people just don't seem to realise that if you don't *want* to learn more about your chosen career after the point at which you qualified to do it, then you're gonna get stuck at that level while everybody else moves on - and one day you'll find yourself looking for a new job and finding that you no longer have the basic skills required.
I would just like to say that this...
The core feature of the class I've described is that it provides a universal getter/setter. Fed up finding myself repeatedly writing very similar get/set routines for objects describing clients, products, messages etc.like this:
I combined all the features of my getters/setters into a single routine, so the getters/setters of any new object which extends the class consist of a single line - a call to the base getter/setter method - a la:
It goes further than that in that if objects are created on the fly by passing an id into any of the getters/setters then it caches the newly created object and always checks the cache to see if the object has already been created and accesses its methods instead. It's a massive time-saver (and space saver) when it comes to writing new classes. Even that little get/set takes 14 lines of code, multiply that for each property and each class and you have a lot of very similar chunks of code. There's certainly no "library" of procedural code in the base class.
Anyway, gone off on one a bit there, that's not strictly relevant to the question I posed, don't mean to get "snippy", sorry.
Lee
Some people just don't seem to realise that if you don't *want* to learn more about your chosen career after the point at which you qualified to do it, then you're gonna get stuck at that level while everybody else moves on - and one day you'll find yourself looking for a new job and finding that you no longer have the basic skills required.
I would just like to say that this...
...was a bit of a wild assumption. I purposely didn't want to go into detail about what that meant and I perhaps used the wrong words to describe it but I'm pretty sure it's not what you've described.arborint wrote:The "super base class" gives you away. You're not doing OOP. Your just namespacing a procedural library using the class construct.
The core feature of the class I've described is that it provides a universal getter/setter. Fed up finding myself repeatedly writing very similar get/set routines for objects describing clients, products, messages etc.like this:
Code: Select all
class client {
private $name;
public function name($value=false, $id=false){
$v = false;
if($id){
$c = new client($id);
$v = $c->name($value);
}else{
if($value){
// validate $value
$this->name = $value;
}
$v = $this->name;
}
return $v;
}
}
Code: Select all
class client extends obj {
protected $name;
public function name($value=false, $id=false){
return $this->get_set(__FUNCTION__, $value, $id);
}
protected function valid_name($value){
// bespoke validation routine (if required), called by parent class if it exists.
return bool;
}
}
Anyway, gone off on one a bit there, that's not strictly relevant to the question I posed, don't mean to get "snippy", sorry.
Lee
- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
Re: OOPHP Advocacy arguments
After amateur hour, every developer I know of uses OOP in PHP. It's also a bit strange that the developers of a language never meant to be OO spend so much time making it OOa) PHP was never meant to be OO
Ignorance breeds silliness. Every major programming language used in web applications has OO. Ruby, Python, PHP, Javascript, Perl, [insert random language]... Most of them have rapid application frameworks which depend on the benefits of OO. Unfortunately you'll find it extremely difficult to sway a committed procedural programmer. It's extremely rare these days, but it was only a few years ago that procedural vs object-oriented flamewars were common in the PHP community.b) What's the point of creating objects for a web application where there is no persistence, and the second the page finishes loading all the objects are destroyed.
The suggestion of gradual refactoring is your best bet. Surely everyone working at your company has had experience at using libraries? Most libraries in PHP are OO, and the principle of refactoring code into reusable libraries is one of the most common use cases in procedural refactoring.
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Re: OOPHP Advocacy arguments
A focus on getters and setters also sounds procedural. It also sounds like you are implementing a fancy bit of magic, and trying to get your guys to use it, instead of starting with the basics. Reducing the use of getters/setters and explicitly coding them for clarity would be better in my opinion. You programmers need to walk before they can run. They really need to get over the hurdle of understanding OOP first.leenoble_uk wrote:It goes further than that in that if objects are created on the fly by passing an id into any of the getters/setters then it caches the newly created object and always checks the cache to see if the object has already been created and accesses its methods instead. It's a massive time-saver (and space saver) when it comes to writing new classes. Even that little get/set takes 14 lines of code, multiply that for each property and each class and you have a lot of very similar chunks of code. There's certainly no "library" of procedural code in the base class.
One of the best arguments to put to your programmers is about their careers. If you are a procedural programmer then you are self taught and self supporting at this point. There are thousands of books and articles published on OOP design and programming in PHP each year. You'd be hard pressed to find a book focused on procedural/structured design and programming in the last 5-10 years. They need to change for the company, but they really need to change for themselves. There is a whole, huge new world of design ideas, patterns, methodologies, etc. awaiting them.
(#10850)
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: OOPHP Advocacy arguments
Probably the biggest misconception about OOP. OOP is not about the languages OO constructs like class and access control as much as it is a "style" or "way" of developing software and seeing virtual objects.leenoble_uk wrote:a) PHP was never meant to be OO
Basically you can write OO code in C or Macro Assembler as the concept of a class or inheritence/composition can be emulated in any language. Some language constructs just force a best practice on you preventing lazy developers from shooting themselves in the foot.
This is like saying constants shouldn't be used in a language which doesn't support the "const" modifier. Smart developers work around this problem by following strict conventions, such as:
Code: Select all
CONST_PI = 3.1415This is probably where I struggled most in using objects in PHP, coming from C++ I simply didn't see the purpose at first. Then I figured WTH I'll make everything possible and object and see what happens. Initially it led to mega bloated tightly coupled code but after several years of refactoring and disscussing problems on these forums with other object enthusiasts...I can honestly say it has saved me tremendous amount of coding.b) What's the point of creating objects for a web application where there is no persistence, and the second the page finishes loading all the objects are destroyed.
I think this is much more personal choice than anything. If someone is uncomfortable about the overhead in creating and using objects in a PHP environment...there is little you can do to change their mind, other than argue hardware is easier to upgrade than keeping optimized code working. Some won't accept that arguement and rightfully so I guess.
Re: OOPHP Advocacy arguments
Code has two audiences. One is a machine which has a massive memory, can hold a million things in its head at once, and never gets confused no matter what kind of spaghetti mess you throw at it. So long as the code parses it will execute. In comparison, our feeble minds can only hold a few things in our heads at one time. We get very confused very easily.
When you start out you just want to make computers do stuff but programming is much more about writing code which people can understand (hence the importance of naming - the computer doesn't care). That's really what OOP is all about. It breaks an application up into easy-to-understand components which can be worked on without disturbing anything else. You can't eat a horse in one big gulp but if you break it down into bite-sized chunks it's much easier.
Test-driven design does the same sort of thing: tests are used to drive an OOP design forward in lots of small, easy-to-figure-out steps.
When you start out you just want to make computers do stuff but programming is much more about writing code which people can understand (hence the importance of naming - the computer doesn't care). That's really what OOP is all about. It breaks an application up into easy-to-understand components which can be worked on without disturbing anything else. You can't eat a horse in one big gulp but if you break it down into bite-sized chunks it's much easier.
Test-driven design does the same sort of thing: tests are used to drive an OOP design forward in lots of small, easy-to-figure-out steps.
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: OOPHP Advocacy arguments
Having read this thread again...
I think the general consensus is the same: There is no argument "only reason" to use OOP.
I think it's important to remember that few OOP developers start programming in OOP right from day one. Most start in procedural and eventually learn the better method and start using objects. That is to say, they have learned from experience and the school of hard knocks.
Anyone that shuns OO methods I would argue it's because they fail to understand OOP and programming in general. Like McGruff said, programming is about writing human readable code, and objects (when used right) clearly win that battle!
I think the general consensus is the same: There is no argument "only reason" to use OOP.
I think it's important to remember that few OOP developers start programming in OOP right from day one. Most start in procedural and eventually learn the better method and start using objects. That is to say, they have learned from experience and the school of hard knocks.
Anyone that shuns OO methods I would argue it's because they fail to understand OOP and programming in general. Like McGruff said, programming is about writing human readable code, and objects (when used right) clearly win that battle!
Re: OOPHP Advocacy arguments
Heh, that is exactly what I thought when reading the topicstart. There is no such thing as a "baseclass" (unless you're using the term to indicate a parent object) and it usually indicates a poor OO design. Objects have responsibilities, now what the hell would the responsibility of "Base" be? Considering it indicates poor design, it also tends to indicate a lack of OO comprehension, so I'm with arborint on this one.arborint wrote:The "super base class" gives you away. You're not doing OOP. Your just namespacing a procedural library using the class construct. You programmer doesn't know good design -- but he may know bad design. Give him that.If you don't really understand what OO is or why OO improves software development, then you will never be able to convince anyone to use OO.
As arborint accuratly stated, setter/getter fixation usually indicates the very same. It clearly indicates a lack of encapsulation. There should not be any reason to simply return the value of a particular classmember, because that means that you've misplaced functionality.
This sounds like the frontpage of RephactorMcGruff wrote:When you start out you just want to make computers do stuff but programming is much more about writing code which people can understand (hence the importance of naming - the computer doesn't care). That's really what OOP is all about. It breaks an application up into easy-to-understand components which can be worked on without disturbing anything else. You can't eat a horse in one big gulp but if you break it down into bite-sized chunks it's much easier.
- allspiritseve
- DevNet Resident
- Posts: 1174
- Joined: Thu Mar 06, 2008 8:23 am
- Location: Ann Arbor, MI (USA)
Re: OOPHP Advocacy arguments
Another thing to consider is in a web context, domain objects don't generally have all that much business logic... they are basically data holders that are virtually the same in the database as when displayed. In that sense, they're almost glorified arrays, and getters/setters are the best way to give access to those properties while still leaving room for future business logic. They aren't always an indicator of misplaced functionality though. I think shallow domain objects like that are one of the reasons people get so confused over this topic.webaddict wrote:As arborint accuratly stated, setter/getter fixation usually indicates the very same. It clearly indicates a lack of encapsulation. There should not be any reason to simply return the value of a particular classmember, because that means that you've misplaced functionality.
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Re: OOPHP Advocacy arguments
I agree, getters/setters are a code smell. They are not evil in themselves. They are useful in many instances. When you seem them in your code you should ask yourself if you are simply hiding procedural steps in multiple calls.
(#10850)
Re: OOPHP Advocacy arguments
They are a code smell indeed, but they are not evil per se. I was saying that the fixation on having setters and getters for everything can be an indication of misplaced functionality. Reading back, however, I can imagine that it is easy to misread. Still hard to express myself in English on some occasions, sorry 'bout that.arborint wrote:I agree, getters/setters are a code smell. They are not evil in themselves. They are useful in many instances. When you seem them in your code you should ask yourself if you are simply hiding procedural steps in multiple calls.
Your posts did get me to think it through a bit more though, so I have to thank you for it. Yes, getters and setters have their uses. Actually, I had an additional paragraph before I posted my message to this forum stating that although they could indicate misplaced behaviour, you really can't live without (some) setters/getters. But I figured that might confuse other readers, so I removed that paragraph.
Coming back to this topic however, if you don't mind, I'd like to ask you guys a question. I reckon most people reading this forum are actually separating logic according to the MVC pattern. In my case, an object residing in my model layer is a Domain Object. It _does_ have additional logic, it's not just mapping to a database table. Taking a User for example, a User has a method named resetPassword( $old, $new ) for example. It also contains a User's name, however.
Now, when displaying details of a user, the template will have to echo the user's name. By common standards, it would be bad practise to display it from a public member e.g. $user->name;, so we tend to write a getter for it (or worse yet, we generate it). That's not at all weird, because we don't want the view to know how the object _really_ gets the user's name (it might be lazy loaded, for example).
Public members are definitely out of the question. So, we tend to write a getter for this particular member, to make sure we're not breaking the rules of encapsulation. Problem with writing this particular getter though is that such a getter makes it very easy to misplace functionality that actually belong to the object itself. Some people therefore conclude that all setters and all getters are evil. I strongly disagree with that notion though, since there _are_ legitimate reasons for using setters/getters.
Martin Fowler, as always, has something to say about this too. He states that setters/getters are not evil, but they can be a rather big codesmell. If you get two members from an object to calculate something, or carry out an action with it, that behaviour is probable misplaced and should be placed in the object you're asking the values from. If that behaviour seems to vary, you should encapsulate it to a different object. That's really the essence of OOP (if you ask me
In the bliki-article Fowler wrote, there is a quote:
In my opinion, mister Fowler is right as usual and the code below should be considered bad encapsulation (and thus a bad design):If we're looking for a simple rule of thumb, the one I prefer is one that I first heard from Kent Beck, which is to always beware of cases where some code invokes more than one method on the same object. This occurs with accessors and more reasonable commands. If you ask an object for two bits of data, can you replace this with a single request for the bit of data you're calculating? If you tell an object to do two things, can you replace them with a single command? Of course there are plenty of cases where you can't, but it's always worth asking yourself the question.
Code: Select all
<?php
$user = $this->_usermapper->getUserById( 1 );
$bday = $user->getBirthday( );
$this->view->age = $this->calculateAge( $bday );
?>
But then, I can see a lot of situations where the +getBirthday( ) method is actually necessary. To accomplish layering, one would not output the details of a User in the same object that one uses to save this User to the database. That's the Single Responsibility Principle in effect and we've learned to adhere that quite some time ago, since it increases both maintainability, stability, flexibility and as a result, testability.
So, the View in MVC should be able to render proteced members from an object in the model layer. But how then? As we concluded, public members aren't an option, they will absolutely ruin encapsulation. Getters/setters _may_ potentially be abused and you might just miss it. Magic methods are... well.. not my preffered choice for the simple reason that they don't tell you what they do when skimming an object's interface. I'd rather have an object that shows what it does on the interface than having to open the file to see what __call, __get and __set are doing.
Those are the choices we have in PHP: public members, accessor/mutators and magic methods. We don't have properties like C# and Python do. But then... So, we'll have to write getters for each member we wish to output if we want to keep the encapsulation. I think that's the reason people write them. Aren't there other solutions?
One of the solutions is obvious: create a +render( ) method on the User object and pass that a UserRenderer object, which in turn can be used by the View to output the members. It'll probably take 20 minutes at most after you try this method before you start hating for even suggesting this
Another, in my humble opinion more decent and less tedious option, is to have the domain object throw a Data Transfer Object to the View. That is what it's meant for, right? I've not tried this approach yet, but I think I might be on to something here
This could obviously be enforced using an interface which has the method "exportData", and using an abstract class "DomainObject" which defines the behaviour to the call of that defined method. Still, I have my concerns. There aren't many, but a few, methods that are used for displaying values from the Domain Object. In the Netherlands, where I happen to live, names consist not only of a first name and a last name, it can also have a "tussenvoegsel", which most literally means "prefix". To everyone that isn't Dutch, one could compare it to "the". It's a word that exists, but hasn't any importance. By example: using Peter van Stuyvesant, Peter would be the first name, Stuyvesant is the last name, and "van" would be the prefix. Most literaly it means "Peter Of Stuyvesant".
So, when trying to display the name, there is some logic involved. If the name does have a prefix, the prefix plus an additional space should be shown. That logic should be in the model layer, so as to not repeat yourself. Thus, that logic can not be in a Data Transfer Object, since it's not just data, it should actually be in a method called +getName( ). And then what? Now, I tend to just pass on the Domain Object itself. I do wonder however if this is the best way to go, since that would mean I'd pass an object that has more behaviour than just displaying logic (such as logging in). It probably isn't, but I really look forward to reading to what you have to say on this topic.
I've read more of your topics than you would probably imagine (mostly on Sitepoint though), and I tend to agree with you a lot, but in this partical instance, I would like to beg to differ. A web context (assuming you're implying web-based PHP software) does not mean there is less bussiness logic. Worse yet, I'd say the amount of bussiness logic involved in a web application is the same amount as you would find in a desktop application. Zend Framework, Symfony, CodeIgnitor and other frameworks seem to have a tradition in braking the rules of SRP, but the logic is there nevertheless. They just tend to put it in the controller layer, which is a huge mistake in my opinion.allspiritseve wrote:Another thing to consider is in a web context, domain objects don't generally have all that much business logic... they are basically data holders that are virtually the same in the database as when displayed. In that sense, they're almost glorified arrays, and getters/setters are the best way to give access to those properties while still leaving room for future business logic.
Anyway, do you guys have any thoughts on how to pass an object to the View layer without that object being mutable while still being able to allocate the specific diplaying logic? I'd be really happy to read up on that.
PS: If some of the sentences don't seem to make sense: I'm not only Dutch, but it also happens to be my birthday which means I just had a party, with a lot of wine
- allspiritseve
- DevNet Resident
- Posts: 1174
- Joined: Thu Mar 06, 2008 8:23 am
- Location: Ann Arbor, MI (USA)
Re: OOPHP Advocacy arguments
By web context, I guess I meant website, moreso than web application... For simple content: pages, articles, blog posts, messages, etc., there's not much behavior involved. I think that is where people get confused a lot-- they have objects that are little more than arrays, and wonder why people tell them they can't access the properties directly. That is a case, that I think comes up often, in which accessors don't demonstrate a lack of encapsulation. There's no business logic being applied to those properties, only display logic.webaddict wrote:A web context (assuming you're implying web-based PHP software) does not mean there is less bussiness logic. Worse yet, I'd say the amount of bussiness logic involved in a web application is the same amount as you would find in a desktop application.
Re: OOPHP Advocacy arguments
Right.. but then we'd have to start a discussion on the differences between a website and a webapplication. When saying a website is little more than a few pages, I wonder why they started that in OO in the first place. The right tool for the right job?allspiritseve wrote:By web context, I guess I meant website, moreso than web application...
Well, pages can be published, unpublished, removed, updated, have attachments etc. etc. So can articles and blogposts. Messages (assuming these are comments from users or something like that) can be marked as spam, or marked as ham, or hidden, or shown. I'd say there is a lot of behaviour involved. Then, if the requirements are _really_ simple, again: you have to wonder why you started using OO for the task.allspiritseve wrote:For simple content: pages, articles, blog posts, messages, etc., there's not much behavior involved. I think that is where people get confused a lot-- they have objects that are little more than arrays, and wonder why people tell them they can't access the properties directly.
Except there should be bussiness logic applied to those properties (although I prefer the terms behaviour and data). Most of what I see people doing in controllers should really be in the Domain Object. But like I said before: in the case of displaying data from an object, accessors have to be there. Unless, of course, you know better solution, which brings me back to my questionallspiritseve wrote:That is a case, that I think comes up often, in which accessors don't demonstrate a lack of encapsulation. There's no business logic being applied to those properties, only display logic.