Had a discussion with a colleague about wether this is bad practice or not. Now I can not find immediate examples of this online.
We have a lot of database object mappers and call it's functions like so
(example) - the setId method get's the row from the database and set's it to predefined propertys
class Person {
public static function get($id) {
$object = new Person;
$object->setId($id);
return $object;
}
}
Using it like this we can use simple constructions like this: (where we got the id from for-example a post)
$person = Person::get($id);
instead of
$person = new Person;
$person->setId($id);
Now, my instinct tells me this is bad practice. But I can not explain it. Maybe someone here can explain why this is, or is not bad practice
Here are some other examples how we use it. we mainly use it for getters. (just the names, not the code. Almost all of them just run a query, which can return 1 object and then use the id of the result to use the setId method)
class CatalogArticle {
public static function get($id) { }
public static function getByArticlenumber($articlenumber) {} //$articlenumber is unique in the database
public static function getRandom() {} //Runs a query returning a random row
}
This isn't horrible persay. It's an implementation of a Factory Method design pattern. It's not bad at all in principle.
However, in your specific example, it's not really doing anything significant, so I'm not so sure if it's necessary. You could eliminate the need by taking a (perhaps optional) parameter to the constructor for the id. Then anyone could call $foo = new Person($id); rather than needing an explicit factory.
But if the instantiation is complex, or you want the ability to build several different people types that can only be determined by logic, a factory method may work better. For example, let's say you need to determine the type of person to instantiate by some parameter. Then, a factory method on Person would be appropriate. The method would determine what "type" to load, and then instantiate that class.
Statics in general are hard to test and don't allow for polymorphic changes like an instance would. They also create hard dependencies between classes in the code. They are not horrible, but you should really think about it if you want to use one. An option would be to use a Builder or a Abstract Factory. That way, you create an instance of the builder/factory, and then let that instance determine how to instantiate the resulting class...
One other note. I would rename that method from Person::get() to something a little more semantically appropriate. Perhaps Person::getInstance() or something else appropriate.
This blog post should tell you why people don't like static methods better than i could:
http://kore-nordmann.de/blog/0103_static_considered_harmful.html
The question that strikes me most about your current code snippet: Is a Person allowed to NOT have an Id ?
I feel like that should be an constructor argument if it's representing a real Person. If you use that class to create new persons that ofc might not work.
The difference between the 2 calls is minor. Both "create" a Person class and set the Id so you are not winning / loosing anything there when it comes to 'hard wired dependencies'.
The advantage only shows when you want to be able to pass a Person into another object and that objects needs to change the ID (as an example, the blog post should explain that better than i did here).
I'm only adding to edorian's post, but I've used static get methods in the past, where there is a caching engine in place, and (for example) I might have a given Person object in memcache, and would rather retrieve it from the cache than going off to the database.
For example:
class Person {
public static function get($id) {
if(Cache::contains("Person", $id))
{
return Cache::get("Person", $id);
}
else
{
//fictional get_person_from_database, basically
//getting an instance of Person from a database
$object = get_person_from_database($id);
}
return $object;
}
}
In this way, all cache handling is done by the class in question, rather than the caller getting a person calls having to worry about the cache.
long story short, yes, they are bad practice:
http://r.je/static-methods-bad-practice.html
http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/
A good reason apart of everything is that you 'should' be testing your code. Static methods cause issues, so there you have a good reason:
if you want to follow good practices, test your code
Ergo, if static causes testing issues, static prevent writing tests so it prevents to follow good practices :-)
time goes things changes.
just in case you have problems with testing you can use AspectMock library
https://github.com/Codeception/AspectMock
any way static is not so bad at all. to use static you should just know what you are doing and why. if you will place static only as fast solution it is bad idea in 99% of variations. in 1% time it is still bad solution but it gives you time when you need it.
Related
I am quite new to OOP, so this is really a basic OOP question, in the context of a Laravel Controller.
I'm attempting to create a notification system system that creates Notification objects when certain other objects are created, edited, deleted, etc. So, for example, if a User is edited, then I want to generate a Notification regarding this edit. Following this example, I've created UserObserver that calls NotificationController::store() when a User is saved.
class UserObserver extends BaseObserver
{
public function saved($user)
{
$data = [
// omitted from example
];
NotificationController::store($data);
}
}
In order to make this work, I had to make NotificationController::store() static.
class NotificationController extends \BaseController {
public static function store($data)
{
// validation omitted from example
$notification = Notification::create($data);
}
I'm only vaguely familiar with what static means, so there's more than likely something inherently wrong with what I'm doing here, but this seems to get the job done, more or less. However, everything that I've read indicates that static functions are generally bad practice. Is what I'm doing here "wrong," per say? How could I do this better?
I will have several other Observer classes that will need to call this same NotificationController::store(), and I want NotificationController::store() to handle any validation of $data.
I am just starting to learn about unit testing. Would what I've done here make anything difficult with regard to testing?
I've written about statics extensively here: How Not To Kill Your Testability Using Statics. The gist of it as applies to your case is as follows:
Static function calls couple code. It is not possible to substitute static function calls with anything else or to skip those calls, for whatever reason. NotificationController::store() is essentially in the same class of things as substr(). Now, you probably wouldn't want to substitute a call to substr by anything else; but there are a ton of reasons why you may want to substitute NotificationController, now or later.
Unit testing is just one very obvious use case where substitution is very desirable. If you want to test the UserObserver::saved function just by itself, because it contains a complex algorithm which you need to test with all possible inputs to ensure it's working correctly, you cannot decouple that algorithm from the call to NotificationController::store(). And that function in turn probably calls some Model::save() method, which in turn wants to talk to a database. You'd need to set up this whole environment which all this other unrelated code requires (and which may or may not contain bugs of its own), that it essentially is impossible to simply test this one function by itself.
If your code looked more like this:
class UserObserver extends BaseObserver
{
public function saved($user)
{
$data = [
// omitted from example
];
$this->NotificationController->store($data);
}
}
Well, $this->NotificationController is obviously a variable which can be substituted at some point. Most typically this object would be injected at the time you instantiate the class:
new UserObserver($notificationController)
You could simply inject a mock object which allows any methods to be called, but which simply does nothing. Then you could test UserObserver::saved() in isolation and ensure it's actually bug free.
In general, using dependency injected code makes your application more flexible and allows you to take it apart. This is necessary for unit testing, but will also come in handy later in scenarios you can't even imagine right now, but will be stumped by half a year from now as you need to restructure and refactor your application for some new feature you want to implement.
Caveat: I have never written a single line of Laravel code, but as I understand it, it does support some form of dependency injection. If that's actually really the case, you should definitely use that capability. Otherwise be very aware of what parts of your code you're coupling to what other parts and how this will impact your ability to take it apart and refactor later.
I have some pattern that works great for me, but that I have some difficulty explaining to fellow programmers. I am looking for some justification or literature reference.
I personally work with PHP, but this would also be applicable to Java, Javascript, C++, and similar languages. Examples will be in PHP or Pseudocode, I hope you can live with this.
The idea is to use a lazy evaluation container for intermediate results, to avoid multiple computation of the same intermediate value.
"Dynamic programming":
http://en.wikipedia.org/wiki/Dynamic_programming
The dynamic programming approach seeks to solve each subproblem only once, thus reducing the number of computations: once the solution to a given subproblem has been computed, it is stored or "memo-ized": the next time the same solution is needed, it is simply looked up
Lazy evaluation container:
class LazyEvaluationContainer {
protected $values = array();
function get($key) {
if (isset($this->values[$key])) {
return $this->values[$key];
}
if (method_exists($this, $key)) {
return $this->values[$key] = $this->$key();
}
throw new Exception("Key $key not supported.");
}
protected function foo() {
// Make sure that bar() runs only once.
return $this->get('bar') + $this->get('bar');
}
protected function bar() {
.. // expensive computation.
}
}
Similar containers are used e.g. as dependency injection containers (DIC).
Details
I usually use some variation of this.
It is possible to have the actual data methods in a different object than the data computation methods?
It is possible to have computation methods with parameters, using a cache with a nested array?
In PHP it is possible to use magic methods (__get() or __call()) for the main retrieval method. In combination with "#property" in the class docblock, this allows type hints for each "virtual" property.
I often use method names like "get_someValue()", where "someValue" is the actual key, to distinguish from regular methods.
It is possible to distribute the data computation to more than one object, to get some kind of separation of concerns?
It is possible to pre-initialize some values?
EDIT: Questions
There is already a nice answer talking about a cute mechanic in Spring #Configuration classes.
To make this more useful and interesting, I extend/clarify the question a bit:
Is storing intermediate values from dynamic programming a legitimate use case for this?
What are the best practices to implement this in PHP? Is some of the stuff in "Details" bad and ugly?
If I understand you correctly, this is quite a standard procedure, although, as you rightly admit, associated with DI (or bootstrapping applications).
A concrete, canonical example would be any Spring #Configuration class with lazy bean definitions; I think it displays exactly the same behavior as you describe, although the actual code that accomplishes it is hidden from view (and generated behind the scenes). Actual Java code could be like this:
#Configuration
public class Whatever {
#Bean #Lazy
public OneThing createOneThing() {
return new OneThing();
}
#Bean #Lazy
public SomeOtherThing createSomeOtherThing() {
return new SomeOtherThing();
}
// here the magic begins:
#Bean #Lazy
public SomeThirdThing getSomeThirdThing() {
return new SomeThirdThing(this.createOneThing(), this.createOneThing(), this.createOneThing(), createSomeOtherThing());
}
}
Each method marked with #Bean #Lazy represents one "resource" that will be created once it is needed (and the method is called) and - no matter how many times it seems that the method is called - the object will only be created once (due to some magic that changes the actual code during loading). So even though it seems that in createOneThing() is called two times in createOneThing(), only one call will occur (and that's only after someone tries to call createSomeThirdThing() or calls getBean(SomeThirdThing.class) on ApplicationContext).
I think you cannot have a universal lazy evaluation container for everything.
Let's first discuss what you really have there. I don't think it's lazy evaluation. Lazy evaluation is defined as delaying an evaluation to the point where the value is really needed, and sharing an already evaluated value with further requests for that value.
The typical example that comes to my mind is a database connection. You'd prepare everything to be able to use that connection when it is needed, but only when there really is a database query needed, the connection is created, and then shared with subsequent queries.
The typical implementation would be to pass the connection string to the constructor, store it internally, and when there is a call to the query method, first the method to return the connection handle is called, which will create and save that handle with the connection string if it does not exist. Later calls to that object will reuse the existing connection.
Such a database object would qualify for lazy evaluating the database connection: It is only created when really needed, and it is then shared for every other query.
When I look at your implementation, it would not qualify for "evaluate only if really needed", it will only store the value that was once created. So it really is only some sort of cache.
It also does not really solve the problem of universally only evaluating the expensive computation once globally. If you have two instances, you will run the expensive function twice. But on the other hand, NOT evaluating it twice will introduce global state - which should be considered a bad thing unless explicitly declared. Usually it would make code very hard to test properly. Personally I'd avoid that.
It is possible to have the actual data methods in a different object than the data computation methods?
If you have a look at how the Zend Framework offers the cache pattern (\Zend\Cache\Pattern\{Callback,Class,Object}Cache), you'd see that the real working class is getting a decorator wrapped around it. All the internal stuff of getting the values stored and read them back is handled internally, from the outside you'd call your methods just like before.
The downside is that you do not have an object of the type of the original class. So if you use type hinting, you cannot pass a decorated caching object instead of the original object. The solution is to implement an interface. The original class implements it with the real functions, and then you create another class that extends the cache decorator and implements the interface as well. This object will pass the type hinting checks, but you are forced to manually implement all interface methods, which do nothing more than pass the call to the internal magic function that would otherwise intercept them.
interface Foo
{
public function foo();
}
class FooExpensive implements Foo
{
public function foo()
{
sleep(100);
return "bar";
}
}
class FooCached extends \Zend\Cache\Pattern\ObjectPattern implements Foo
{
public function foo()
{
//internally uses instance of FooExpensive to calculate once
$args = func_get_args();
return $this->call(__FUNCTION__, $args);
}
}
I have found it impossible in PHP to implement a cache without at least these two classes and one interface (but on the other hand, implementing against an interface is a good thing, it shouldn't bother you). You cannot simply use the native cache object directly.
It is possible to have computation methods with parameters, using a cache with a nested array?
Parameters are working in the above implementation, and they are used in the internal generation of a cache key. You should probably have a look at the \Zend\Cache\Pattern\CallbackCache::generateCallbackKey method.
In PHP it is possible to use magic methods (__get() or __call()) for the main retrieval method. In combination with "#property" in the class docblock, this allows type hints for each "virtual" property.
Magic methods are evil. A documentation block should be considered outdated, as it is no real working code. While I found it acceptable to use magic getter and setter in a really easy-to-understand value object code, which would allow to store any value in any property just like stdClass, I do recommend to be very careful with __call.
I often use method names like "get_someValue()", where "someValue" is the actual key, to distinguish from regular methods.
I would consider this a violation of PSR-1: "4.3. Methods: Method names MUST be declared in camelCase()." And is there a reason to mark these methods as something special? Are they special at all? The do return the value, don't they?
It is possible to distribute the data computation to more than one object, to get some kind of separation of concerns?
If you cache a complex construction of objects, this is completely possible.
It is possible to pre-initialize some values?
This should not be the concern of a cache, but of the implementation itself. What is the point in NOT executing an expensive computation, but to return a preset value? If that is a real use case (like instantly return NULL if a parameter is outside of the defined range), it must be part of the implementation itself. You should not rely on an additional layer around the object to return a value in such cases.
Is storing intermediate values from dynamic programming a legitimate use case for this?
Do you have a dynamic programming problem? There is this sentence on the Wikipedia page you linked:
There are two key attributes that a problem must have in order for dynamic programming to be applicable: optimal substructure and overlapping subproblems. If a problem can be solved by combining optimal solutions to non-overlapping subproblems, the strategy is called "divide and conquer" instead.
I think that there are already existing patterns that seem to solve the lazy evaluation part of your example: Singleton, ServiceLocator, Factory. (I'm not promoting singletons here!)
There also is the concept of "promises": Objects are returned that promise to return the real value later if asked, but as long as the value isn't needed right now, would act as the values replacement that could be passed along instead. You might want to read this blog posting: http://blog.ircmaxell.com/2013/01/promise-for-clean-code.html
What are the best practices to implement this in PHP? Is some of the stuff in "Details" bad and ugly?
You used an example that probably comes close to the Fibonacci example. The aspect I don't like about that example is that you use a single instance to collect all values. In a way, you are aggregating global state here - which probably is what this whole concept is about. But global state is evil, and I don't like that extra layer. And you haven't really solved the problem of parameters enough.
I wonder why there are really two calls to bar() inside foo()? The more obvious method would be to duplicate the result directly in foo(), and then "add" it.
All in all, I'm not too impressed until now. I cannot anticipate a real use case for such a general purpose solution on this simple level. I do like IDE auto suggest support, and I do not like duck-typing (passing an object that only simulates being compatible, but without being able to ensure the instance).
I'm trying to design some class hierarchy and I got "stuck" at this part.
Lets say that I have following classes
abstract class Video
{
const TYPE_MOVIE = 1;
const TYPE_SHOW = 2;
abstract public function getTitle();
abstract public function getType();
}
class Movie extends Video
{
// ...
public function getType()
{
return self::TYPE_MOVIE;
}
}
class Show extends Video
{
// ...
public function getType()
{
return self::TYPE_SHOW;
}
}
In the diffrent part of the system I have (Parser) class that encapsulates creation of
movie and show objects and returns obj. to the client.
Question: What is the best way to get a type of a obj. returned from parser/factory class, so that client can do something like
$video = $parser->getVideo('Dumb and Dumber');
echo $video->getTitle();
// Way 1
if($video->getType == 'show') {
echo $video->getNbOfSeasons();
}
// Way 2
if($video instanceof Show) {
echo $video->getNbOfSeasons();
}
// Current way
if($video->getType == Video::TYPE_SHOW) {
echo $video->getNbOfSeasons();
}
Is there a better way than my solution (read as: does my solution suck?)?
Is there a better way than my solution (read as: does my solution suck?)?
Your solution does not suck, per se. However, whenever someone is trying to determine the subtype to perform some actions, I tend to wonder; why? This answer might be a little theoretical and perhaps even a little pedantic, but here goes.
You shouldn't care. The relationship between a parent and a child class is that the child class overwrites the behaviour of the parent. A parent class should always be substitutable by it's children, regardless which one. If you find yourself asking: how do I determine the subtype, you're usually doing one of two things "wrong":
You're attempting to perform an action based upon subtype. Normally, one would opt for moving that action to the class itself, instead of "outside" of the class. This makes for more manageable code as well.
You're attempting to fix a problem you've introduced yourself by using inheritance, where inheritance isn't warranted. If there is a parent, and there are children, each of which are to be used differently, each of which have different methods, just stop using inheritance. They're not the same type. A film is not the same a tv-serie, not even close. Sure, you can see both on your television, but the resemblance stops there.
If you're running into issue number 2, you're probably using inheritance not because it makes sense, but simply to reduce code duplication. That, in and on itself, is a good thing, but the way you're attempting to do so might not be optimal. If you can, you could use composition instead, although I have my doubts where the duplicated behaviour would be, apart from some arbitrary getters and setters.
That said, if your code works, and you're happy with it: go for it. This answer is correct in how to approach OO, but I don't know anything about the rest of your application, so the answer is generic.
I'd go with way 2. It abstracts you the need to add another constant at Video in case you may want to add class SoapOpera extends Show (for instance).
With way #2, you are less dependent on constants. Whatever information you can gain without hardcoding it, means less problems to likely happen in the future in case you want to extend. Read about Tight an Loose Coupling.
I think the second option is better, using instanceof. This is in general common to all OOP design and not just PHP.
With your first option, you have specifics about derived classes in the base class, and thus must modify the base class for each new derived class you add, which should always be avoided.
Leaving the base class as-is when adding new derived classes promotes code reuse.
If there is a "right" way, and everything is subjective in coding of course (as long as it doesn't adversely impact performance/maintainability ;) ), then it's the second way as "Truth" and "Brady" have pointed out.
The upside of doing things the way you're doing them now (class constants in the abstract) is that when you're working with other developers it can provide hints as to how you expect the abstract class to be interacted with.
For instance:
$oKillerSharkFilm = Video::factory(Video::MOVIE, 'Jaws', 'Dundundundundundun');
$oKillerSharkDocumentary = Video::factory(Video::DOCUMENTARY, 'Jaws', 'A Discovery Shark Week Special');
Of course, the downside is that you have to maintain the "allowable extensions" in the abstract class.
You could still use the instanceof method as demonstrated in your question and maintain the list of allowable extension in the abstract predominantly for control/type fixing.
My code is located here: https://github.com/maniator/SmallFry
Should I make it so that that the App class does not have to use static functions but at the same time be able to set and set variables for the app from anywhere?
Or should I keep it how it is now with App::get and App::set methods?
What are the advantages and disadvantages of both?
How would I accomplish that 1st task if I was to undertake it?
Related Question
Sample code:
//DEFAULT TEMPLATE
App::set('APP_NAME', 'SmallVC');
//END DEFAULT TEMPLAT
//
//DEFAULT TEMPLATE
App::set('DEFAULT_TEMPLATE', 'default');
//END DEFAULT TEMPLATE
//DEFAULT TITLE
App::set('DEFAULT_TITLE', 'Small-VC');
//END DEFAULT TITLE
//LOGIN SEED
App::set('LOGIN_SEED', "lijfg98u5;jfd7hyf");
//END LOGIN SEED
App::set('DEFAULT_CONTROLLER', 'AppController');
if(App::get('view')){
$template_file = $cwd.'/../view/'.App::get('view').'/'.App::get('method').'.stp';
if(is_file($template_file)){
include $template_file;
}
else {
include $cwd.'/../view/missingview.stp'; //no such view error
}
}
else {
App::set('template', 'blank');
include $cwd.'/../view/missingfunction.stp'; //no such function error
}
I think you have a feeling that static is bad. What I am posting may seem fairly crazy as it is a massive change. At the very least hopefully it presents a different idea of the world.
Miško Hevery wrote static methods are a death to testability.
I like testing, so for that reason I don't use them. So, how else can we solve the problem? I like to solve it using what I think is a type of dependency injection. Martin Fowler has a good but complicated article on it here.
For each object at construction I pass the objects that are required for them to operate. From your code I would make AppController become:
class AppController
{
protected $setup;
public function __construct(array $setup = array())
{
$setup += array('App' => NULL, 'Database' => NULL);
if (!$setup['App'] instanceof App)
{
if (NULL !== $setup['App'])
{
throw new InvalidArgumentException('Not an App.');
}
$setup['App'] = new App();
}
// Same for Database.
// Avoid doing any more in the constructor if possible.
$this->setup = $setup;
}
public function otherFunction()
{
echo $this->setup['App']->get('view');
}
}
The dependancies default to values that are most likely (your default constructions in the if statements). So, normally you don't need to pass a setup. However, when you are testing or want different functionality you can pass in mocks or different classes (that derive from the right base class). You can use interfaces as an option too.
Edit The more pure form of dependency injection involves further change. It requires that you pass always pass required objects rather than letting the class default one when the object isn't passed. I have been through a similar change in my codebase of +20K LOC. Having implemented it, I see many benefits to going the whole way. Objects encapsulation is greatly improved. It makes you feel like you have real objects rather than every bit of code relying on something else.
Throwing exceptions when you don't inject all of the dependencies causes you to fix things quickly. With a good system wide exception handler set with set_exception_handler in some bootstrap code you will easily see your exceptions and can fix each one quickly. The code then becomes simpler in the AppController with the check in the constructor becoming:
if (!$setup['App'] instanceof App)
{
throw new InvalidArgumentException('Not an App.');
}
With every class you then write all objects would be constructed upon initialisation. Also, with each construction of an object you would pass down the dependencies that are required (or let the default ones you provide) be instantiated. (You will notice when you forget to do this because you will have to rewrite your code to take out dependencies before you can test it.)
It seems like a lot of work, but the classes reflect the real world closer and testing becomes a breeze. You can also see the dependencies you have in your code easily in the constructor.
Well, if it was me, I would have the end goal of injecting the App dependency into any class (or class tree) that needs it. That way in testing or reusing the code you can inject whatever you want.
Note I said reuse there. That's because it's hard to re-use code that has static calls in it. That's because it's tied to the global state so you can't really "change" the state for a subrequest (or whatever you want to do).
Now, on to the question at hand. It appears that you have a legacy codebase, which will complicate things. The way I would approach it is as follows:
Create a non-static version of the app class (name it something different for now) that does nothing but proxy its get/set calls to the real app class. So, for example:
class AppProxy {
public function set($value) {
return App::set($value);
}
}
For now, all it has to do is proxy. Once we finish getting all the code talking to the proxy instead of the static app, we'll make it actually function. But until then, this will keep the application running. That way you can take your time implementing these steps and don't need to do it all in one big sweep.
Pick a main class (one that does a lot for the application, or is important) that you easily control the instantiation of. Preferably one that you instantiate in only one place (in the bootstrap is the easiest). Change that class to use Dependency Injection via the constructor to get the "appproxy".
a. Test this!
Pick another class tree to work on, based on what you think will be most important and easiest.
a. Test!!!
If you have more calls to App::, Go to #3
Change the existing App class to be non-static.
a. Test!!!!!!!!!!
Remove the AppProxy and replace with App in the dependency injectors. If you did it right, you should only have one place to change to make this switch.
Pat yourself on the back and go get a drink, cause you're done.
The reason that I segmented it out like this is that once a step is completed (any step), you can still ship working software. So this conversion could take literally months (depending on the size of your codebase) without interrupting business as usual...
Now, once you're done, you do get some significant benefits:
Easy to test since you can just create a new App object to inject (or mock it as needed).
Side effects are easier to see since the App object is required wherever it could be changed.
It's easier to componentize libraries this way since their side effects are localized/
It's easier to override (polymorphism) the core app class if it's injected than if it's static.
I could go on, but I think it's pretty easy to find resources on why statics are generally bad. So that's the approach I would use to migrate away from a static class to an instance...
If you don't want to have static functions but global access from everywhere WITHOUT passing the object to the places where it is actually needed then you pretty much can only use one thing:
A global variable
So you are not really better of doing that. But that is the only thing i can think of that would fulfill your requirements.
If you App object is something like an application config a first possible step would be to pass it to the objects that need it:
class Login {
public function __construct() {
$this->_login_seed = App::get('LOGIN_SEED');
self::$_ms = Database::getConnection();
}
changes into:
class Login {
public function __construct(App $app) {
$this->_login_seed = $app->get('LOGIN_SEED');
self::$_ms = Database::getConnection();
}
I'm kind of new in PHP. For some reason in other types of programming languages like JAVA I have no problem with using setters and getters for every single variable, but when I'm programming in PHP probably because it is so flexible it feels kind of like a waste of time. It feels simpler to just set the class attributes as public most of the time and manipulating them like that. The thing is that when I do it like this I feel like I'm doing something wrong and going against OO principles.
Is it really that wrong not using setters and getters? Why or why not? How do you guys do it most of the time?
The main problem with not using property accessors is that if you find out you ever need to change a field to a property later on – to make it a computed property in a subclass, for instance – you’ll break clients of your API. For a published library, this would be unacceptable; for an internal one, just quite a lot of work fixing things.
For private code or small apps, it could be feasible to just wing it. An IDE (or text editor) will let you generate accessor boilerplate and hide it using code folding. This arguably makes using getters and setters mechanically fairly easy.
Note that some programming languages have features to synthesise the default field+getter+setter – Ruby does it via metaprogramming, C# has auto-implemented properties. And Python sidesteps the issue completely by letting you override attribute access, letting you encapsulate the attribute in the subclass that needs it instead of having to bother with it up front. (This is the approach I like best.)
The point of getters or setters is that you can still add logic to your modifications of the field in one place instead of everyplace you want to modify or retrieve the field. You also gain control at class level what happens with the field.
If we're talking strictly about PHP here and not about C#, Java, etc (where the compiler will optimise these things), I find getters and setters to be a waste of resources where you simply need to proxy the value of a private field and do nothing else.
On my setup, I made two crappy classes, one with five private fields encapsulated by five getter/setter pairs proxying the field (which looked almost exactly like java code, funnily enough) and another with five public fields, and called memory_get_usage() at the end after creating an instance. The script with the getter/setters used 59708 bytes of memory and the script with the public fields used 49244 bytes.
In the context of a class library of any significant size, such as a web site framework, these useless getters and setters can add up to a HUGE black hole for memory. I have been developing a framework for my employer in PHP (their choice, not mine. i wouldn't use it for this if i had the choice but having said that, PHP is not imposing any insurmountable restrictions on us) and when I refactored the class library to use public fields instead of getters/setters, the whole shebang ended up using 25% less memory per request at least.
The __get(), __set() and __call() 'magic' methods really shine for handling interface changes. When you need to migrate a field to a getter/setter (or a getter/setter to a field) they can make the process transparent to any dependent code. With an interpreted language it's a bit harder to find all usages of a field or method even with the reasonably good support for code sensitivity provided by Eclipse PDT or Netbeans, so the magic methods are useful for ensuring that the old interface still delegates to the new functionality.
Say we have an object which was developed using fields instead of getters/setters, and we want to rename a field called 'field' to 'fieldWithBetterName', because 'field' was inappropriate, or no longer described the use accurately, or was just plain wrong. And say we wanted to change a field called 'field2' to lazy load its value from the database because it isn't known initially using a getter...
class Test extends Object {
public $field;
public $field2;
}
becomes
class Test extends Object {
public $fieldWithBetterName = "LA DI DA";
private $_field2;
public function getField2() {
if ($this->_field2 == null) {
$this->_field2 = CrapDbLayer::getSomething($this->fieldWithBetterName);
}
return $this->_field2;
}
public function __get($name) {
if ($name == 'field')) {
Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
return $this->fieldWithBetterName;
}
elseif ($name == 'field2') {
Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
return $this->getField2();
}
else return parent::__get($name);
}
}
$t = new Test;
echo $t->field;
echo $t->field2;
(As a side note, that 'extends Object' bit is just a base class I use for practically everything which has a __get() and a __set() declaration which throws an exception when undeclared fields are accessed)
You can go backwards with __call(). This example is quite brittle, but it's not hard to clean up:
class Test extends Object {
public $field2;
public function __call($name, $args) {
if (strpos($name, 'get')===0) {
$field = lcfirst($name); // cheating, i know. php 5.3 or greater. not hard to do without it though.
return $this->$field;
}
parent::__call($name, $args);
}
}
Getter and setter methods in PHP are good if the setter has to do something, or if the getter has to lazy load something, or ensure something has been created, or whatever, but they're unnecessary and wasteful if they do nothing other than proxy the field, especially with a few techniques like the ones above to manage interface changes.
I am probably not going to get many upvotes on this one, but personally getters and even more so setters feel like a code smell to me. Designs should be behavior driven, not data driven. Of course, this is just an opinion. If you have an object that depends on a particular data field of another object this is very tight coupling. Instead it should depend on the behavior of that object which is far less brittle than its data.
But yes, property like getters and setters are a step up from a dependency on a field directly for this very reason. It is less brittle and loosens up the coupling between the objects.
Did you consider to use magic functions __set/__get? Using them you can easily merge all getter/setter function in only 2 functions!
There is a way to emulate get/set without actually using get/set function class, so your code remains tidy:
$person->name = 'bob';
echo $person->name;
Take a look at this class I have coded.
Typically, when using this class, you would declare all your properties protected (or private). In the event where you'd want to add a behaviour on a property, say strtolower() + ucfirst() on the "name" property, all you'd need to do is declare a protected set_name() function in your class and the behavior should get picked up automatically. Same can be accomplished with get_name().
// Somewhere in your class (that extends my class).
protected function set_name($value) { $this->name = ucfirst(strtolower($value)); }
//
// Now it would store ucfirst(strtolower('bob')) automatically.
$person->name = 'bob';
P.S.
Another cool thing is you can make up non-existing fields such as
echo $person->full_name;
without having such fields (as long as there is a get_full_name() function).
If you access these variable in your script lots of time and if you update yoru class often you should use setters and getter because but if you dont this , when you improve your class you have to update all files which uses this variable .
Secondly main reason why you do this is you should not access variable directly because class structure may change and this data can be providen differently.While you are getting data from class you should not care about how this data is generated .Class have to care about this data proccessing so you only should care what will you get.