CakePHP’s Hacker, Felix Geisendörfer really dislikes private methods. Although throughly disagree with him, he made a really interesting point on setting up a challenge and pointing out concise reasons for his thoughts, but what really bugs him is exactly what bugs me:
The previous programmers seemed to love private methods. They made sure to put 4-5 in at least every controller for good measure. I refactored this code, at least a lot of it. And I noticed a consistent pattern: 9 out of 10 times private methods were used as a rug that shit the programmers didn’t want to architect properly was swept under.
What’s happening nowadays is that more and more amateur programmers are landing on the OOP – Object Oriented Planet – without having even scripted before, what is nice because they are starting in a well known and mature concept wich rules most of great application’s design, but is also evil, because they don’t really know something, and so they can’t tell what is really going on in the whole application, and as they arrive in this planet coding all around and reading newbie tips but no single conceptual idea/text/article – they think it’s so boring – they just go messing and hacking with bad code, ending up in misconceptioned usage of concepts
Now, glueing pieces, take this and move to a CakePHP application. What is the first thing you see in a AppController when it’s app has some sort of authentication/authorization system?
-
function beforeFilter() { if(!empty($this->Auth)) { // config Auth sets $this->Auth->userModel = 'User'; [...] } } -
or... function beforeFilter() { $this->__setupAuth(); } function __setupAuth() { if(!empty($this->Auth)) { $this->Auth->userModel = 'Employee'; [...] } }
Why should you use the first approach when it would make your beforeFilter callback so big that it wouldn’t even pass on Tarique’s Sniffs? So, should you use AppController::__setupAuth(), so you wouldn’t clutter your api and app clients wouldn’t be allowed to access this method as an action? No. Both approaches are based upon outdated and non-oop techniques, after all the case we have here is the following:
- We have an object that does exactly what we want, but we have to override it’s defaults properties so it will fit our needings.
So override it:
App::import('Component', 'Auth');
class AppAuthComponent extends AuthComponent {
function __construct() {
parent::__construct();
$this->userModel = 'Employee';
$this->loginAction = '/quit-off';
}
}
And in your controller change ‘Auth’ to ‘AppAuth’ in $components var.
What has just happened is that we made usage of a OOP concept to make things happen in a smarter and cleaner way. Going deeply in concepts and ending up in a real world CakePHP’s MVC architecture we would see that what really happens is that controllers shouldn’t have private methods at all – after all they are meant to encapsulate application’s action logic, like this:
controller: user
action: create
description: When a user is created send an email to all admin users. Tell user if he was succeeded or not.
Things should run this way all across controllers, all reusable logic needed should go on components and there’s no needing for private methods, if any I would say that it’s a bad design.
But Private Methods Are Needed
Crawling around CakePHP’s source, you’ll find some private methods on Model. Model::_find{$type} methods are just for api concistency purposes and to centralize default operations on find options – so you don’t have to call a __setupFind() before each custom find method you write, so here is a case where a private method is really needed, because calling those _find{$type} methods would have no usage, as all they do is a query setup and it’s results manipulation. And it is just one example – it’s just one source of a 80+ (?) files framework – here’s another: http://cakebaker.42dh.com/2008/07/08/not-everything-has-to-be-public/
So as you can see there are real world approaches and use cases where a private method does make sense and does make your code more ellegant. The problem is that people care more about making things happen than about concepts, and use them in a random/dumb way that makes us think that concepts are old-crappy-jokes – and that the market is filled up with bad developers, what actually is truth.
Finally, Felix, no offense intended, insult CakePHP Model class code – sure you’re not going to show up with a handy solution!
-> Why when talking about OOP concepts people always end up talking about Java? What’s Java? Isn’t it that COBOL’s cousin? BASIC’s young sister? Come on.
2 responses so far ↓
Daniel Hofstetter // August 24, 2008 at 6:56 am |
I think it is not necessarily a bad design if you have private methods in controllers. If you use private methods to make your code more readable, then it is often overkill to move such methods to components. On the other hand, if there are too many private methods, it’s probably a sign you do too much in the controller.
rafaelbandeira3 // August 24, 2008 at 1:47 pm |
@Daniel Hofstetter : I don’t think that make your code more readable is the real purpose of private methods. Helper methods are needed when they encapsulate critic logic operations and are repeated over the method code.
A good usage of helper methods is made on Model class from CakePHP – yes, same file – where saveAll() method uses _save() to achieve a goal that require some logic and is needed more than once. So it is not about readability or beautifulness, it’s about logic encapsulation.