The title is maybe not too clear, so here's an example.
abstract Class A {
public static $property = null;
}
Class B extends A {
}
Class C extends A {
}
I want to have a "None" method in all classes extending A, and this method should return an instance - always the same - of the called class. So:
B::None() // Returns a "default" B
C::None() // Returns a "default" C
Why is this: I have (simplifying) several Slots which may or may not be assigned to Activities of several kinds. So I can have a Slot for Surfing and one for Swimming. And that Slot may be null. In my code, when reporting, I could of course do something like
if (Slot.Surfing == null) {
println "Not surfing anywhere";
} else {
println Slot.Surfing.Location;
}
But I'd like to not check at all and just write
println Slot.Surfing.Location;
and pre-assign the slot to Surfing::None(). Actually I'd do that in a superclass and have it automatically assign the "proper" instance of None.
This way, Slot.Surfing(nowhere) is a different null from Slot.Swimming(nowhere), but that for me now would actually be a feature.
The problem is that if I really want to check I'm swimming somewhere, I must be sure that
if (Slot.Surfing == Surfing::None()) {
works. For that, None() must always return the same object. I could run the check on a field of Surfing, maybe a non-i18n-ed integer value... 0 or -1 being a typical choice... but adding a property for that purpose seems ill designed.
NOTE: this has many similarities with the Singleton (anti)pattern, but it is not actually a Singleton (see at bottom).
If I implement the None() method in A, though, I have to handle the fact that any static property will "live" only once, in A, and not in each of the child classes. So I create a default instance of B, save it in A, and then all subsequent calls to other subclasses of A will find and return that one instance -- and C::None() will be an instance of B.
I can make the None() method create a new default instance every time. This works, but now I have several "default" Bs, and in some circumstances two properties both set to B::None() will be, quite correctly, considered different.
In the end I came up with this workaround (PHP 5.3.+):
private static $nones = array(); // array of already created "null" instances
protected static function None() {
// If I do not already have an instance for this class...
if (!isset(self::$nones[$ChildName = get_called_class()])) {
// ... I create a default instance.
self::$nones[$ChildName] = new $ChildName(/*...*/);
}
// And I return the default instance.
return self::$nones[$myClass];
}
I have checked some questions and answers on Stack Overflow and elsewhere, and the most relevant one employs what amounts to the same approach (notice the $instance array indexed on the called class's name):
class A {
public static function getInstance(){
// Maybe use this function to implement the singleton pattern ...
return self::$instance[get_called_class()];
}
public function className(){
return get_class(self::getInstance());
}
}
Yet maybe because I'm still a wet-behind-the-ears OOPer, to me this approach smells. I would think there ought to be a way of declaring a child static property in the parent, and accessing it from the superclass (of course, then I would have to ask myself: if A declares a "downstream" static property, B inherits from A, and C from B, where does that property live, or where should it live, now? -- and I have no satisfying answer).
Addendum - Singletons
The above approach is in practice not too different from a Singleton. It seems (thanks to Touki for pointing me there) that I can get rid of Singletons through dependency injection. Yet in this case it would require to pass around, say, None_C to all methods that may require a default value for a reference to an instance of C. I would then have to push None_C into my Configuration object, and have it know about any subclasses of A that I might declare. At first sight, this smells even more (although in fact adding another subclass of A amounts to changing the system's configuration... which would be the reason for changing Configuration).
TL;DR
So to make a long story short, granted that the above approach does work,
is having the parent class maintain a static array of its "active" children acceptable from an OOP point of view?
is there a better and/or cleaner way to do it?
If memory is not an objection (nowadays, it rarely is), the solution is simply to get a step further into OOP land.
The real problem for which the "child singleton" was needed was that I wanted comparisons to be reliable. Of course two different "nulled" objects, while being both "nulled" and therefore identical in this respect, are not the same object. If they have identical properties too, then the == operator will return TRUE, but if one of them gets slightly changed for some reason (i.e., due to a bug), == will return FALSE. The use of === PHP5 operator in singleton context will solve this problem, but introduces more complexity.
The (not so obvious to me) simple solution is to discard comparisons altogether and simply replace:
if (Slot->Surfing == Surfing::None())
with a suitable
Slot->Surfing->isNull() // or maybe isEmpty() depending on semantics
Then I can declare the isEmpty method in the parent class, and this reveals that I really needed also a more specific equals and comparison operators:
abstract Class A {
...
public static function createNull() {
$nulled = new A();
$nulled->setNull(); // Whatever is needed to nullify an object
return $nulled;
}
public function setNull() {
$this->nullFlag = true; // Example
return $this;
}
public function isNull() {
return (true === ($this->nullFlag)); // Or whatever else
}
abstract function equals($obj);
abstract function compareTo($obj);
}
Class Surfing extends A {
public function equals($obj) {
if (null == $obj) {
return false;
}
if ($this === $obj) {
return true;
}
if (!($obj instanceOf Surfing)) {
return false;
}
// Properties
foreach(array('property1','property2',...) as $val) {
if ($this->$val !== $obj->$val) {
return false;
}
// Maybe some other check
...
return true;
}
}
...
Slot->Surfing = Surfing::createNull();
...
if (Slot->Surfing->isNull()) {
...
}
An additional big advantage of this approach is that now every activity is an independent object and can be safely updated without altering other instances (if Slot->Surfing was a nulled object, to set it to something else I needed to reassign, I couldn't simply go ahead and modify it -- this actually introduced horrid coupling and had a tremendous potential for subtle bugs).
Related
I am reading an article about constructors doing too much work.
One paragraph reads
In the object oriented style, where dependencies tend to be inverted, the constructor has a different and more Spartan role. Its only job is to make sure that object initializes into a state where it satisfies its basic invariants (in other words, it makes sure that the object instance starts off in a valid state and nothing more).
Here is a basic example of a class. On creation of the class I pass in the HTML which needs parsed to then set the class properties.
OrderHtmlParser
{
protected $html;
protected $orderNumber;
public function __construct($html)
{
$this->html = $html;
}
public function parse()
{
$complexLogicResult = $this->doComplexLogic($this->html);
$this->orderNumber = $complexLogicResult;
}
public function getOrderNumber()
{
return $this->orderNumber;
}
protected function doComplexLogic($html)
{
// ...
return $complexLogicResult;
}
}
I'm calling it using
$orderparser = new OrderHtmlParser($html);
$orderparser->parse()
$orderparser->getOrderNumber();
I use a parse function because I dont want the constructor to be doing any logic as both the article above and this article state this is terrible practice.
public function __construct($html)
{
$this->html = $html;
$this->parse(); // bad
}
However if I don't use the parse method, then all my properties (in this example just the one) would return null.
Is this known as an object in an 'invalid state'?
Also, it somewhat feels like my parse method is an initialise function in disguise, which is also deemed bad by the other article (although im not sure if that is only when a constructor calls that method, when it is manually called or both). Regardless, the initialise method is still doing some complex logic prior to setting a property - which needs to happen before the getters can be reliably called.
So either I am misunderstanding these articles or these articles are pushing me to think that maybe my overall implementation of this simple class is incorrect.
Generally, it's a code smell to perform work in a constructor, but the reason behind the practice has more to do with the programming language than an opinion about best practices. There are real edge cases that will introduce bugs.
In some languages derived classes have their constructors executed from the bottom up, and in other languages from the top down. In PHP they are called from top to bottom and you can even stop the chain by not calling parent::__construct().
This creates unknown state expectations in base classes, and to make matters worse PHP allows you to either call parent first or last in a constructor.
For Example;
class A extends B {
public __construct() {
$this->foo = "I am changing the state here";
parent::__construct(); // call parent last
}
}
class A extends B {
public __construct() {
parent::__construct(); // call parent first
$this->foo = "I am changing the state here";
}
}
In the above example class B has it's constructor called in different orders and if B was doing a lot of work in the constructor, then it might not be in the state the programmer was expecting.
So how do you solve your problem?
You need two classes here. One will contain the parser logic and the other the parser results.
class OrderHtmlResult {
private $number;
public __construct($number) {
$this->number = $number;
}
public getOrderNumber() {
return $this->number;
}
}
class OrderHtmlParser {
public parse($html) {
$complexLogicResult = $this->doComplexLogic($this->html);
return new OrderHtmlResult($complexLogicResult);
}
}
$orderparser = new OrderHtmlParser($html);
$order = $orderparser->parse($html)
echo $order->getOrderNumber();
In the above example you could have the parse() method return null if it fails to extract the order number, or throw an example. But neither class ever enters into an invalid state.
There is a name for this pattern, where a method yields another object as the result in order to encapsulate state information, but I remember what it's called.
Is this known as an object in an 'invalid state'?
Yes. You're exactly correct that the parse method is an initialise function in disguise.
To avoid the initialization parsing, be lazy. The laziest approach is to eliminate the $orderNumber field and parse it from the $html inside of the getOrderNumber() function. If you expect that function to be called repeatedly and/or you expect the parsing to be expensive, then keep the $orderNumber field but treat is as a cache. Check it for null inside of getOrderNumber() and parse it out only on the first invocation.
Regarding the linked articles, I agree in principle that constructors should be limited to field initialization; however, if those fields are parsed from a block of text and the expectation is that clients will utilize most or all of the parsed values, then lazy initialization has little value.
Furthermore, when the text parsing does not involve IO or newing up domain objects, it should not impede blackbox testing, for which eager vs. lazy initialization is invisible.
One of the common problems that occurs when the constructor does "too much" is that two objects that are somewhat closely linked need to reference each other (Yes, the close linking is a bad smell, but it happens).
If Object A and Object B must reference each other in order to be "Valid", then how do you create either?
The answer is usually that your constructor makes objects that are not fully "Valid", you add the reference to the other invalid object and then you call some kind of finalize/initialize/start method to finish and make your object valid.
If you still want to be "Safe", you can protect your business methods by throwing a not initialized exception if it's called before the object is "Valid".
Dependency Injection has a generalized version of this problem, what if you had a circular loop of injected classes? Following the construct/initialize pattern solves the general case too, so DI just always uses that pattern.
Addressing the question in the title I have always viewed an object as being in a valid state when it can perform its work without any issues; that is to say, it works as expected.
In looking at the linked article what jumped out at me was that the constructor logic was creating a lot of objects: I counted 7. All of these objects were tightly coupled with the class in question (ActiveProduct) as they were referenced directly and the constructor was passing the this pointer to the other objects constructors:
VirtualCalculator = new ProgramCalculator(this, true);
DFS = new DFSCalibration(this);
In this case ActiveProduct has not yet completed its initialization yet ProgramCalculator and DFSCalibration can call back into ActiveProduct via methods and properties and cause all sorts of mischief so for this reason the code is highly suspect.
In general in OOP you want to be passing objects to the constructor not instantiating them in the constructor. Also you want to employ the Dependency Inversion Principle and use interfaces or abstract / pure virtual classes when passing objects to constructors which would allow for dependency injection.
In the case of your class OrderHtmlParser this doesn't seem to be an issue as the complex logic at issue doesn't appear to go outside of the OrderHtmlParser class. I was curious as to why the doComplexLogic function was defined as protected, implying that inheriting classes can call it.
That said how to deal with initialization may be as simple as making the Parse method static and using it to construct the instance of the OrderHtmlParser class and make the constructor private so that the caller has to call the Parse method to get an instance:
OrderHtmlParser
{
protected $html;
protected $orderNumber;
private function __construct()
{
}
public static function parse($html)
{
$instance = new OrderHtmlParser();
$instance->html = $html;
$complexLogicResult = $instance->doComplexLogic($this->html);
$instance->orderNumber = $complexLogicResult;
return $instance;
}
public function getOrderNumber()
{
return $this->orderNumber;
}
protected function doComplexLogic($html)
{
// ...
return $complexLogicResult;
}
}
I fully agree with the comment from #trincot:
When you create the Parser with the Constructor, there is no need to pass the html.
Maybe you want to use the Parser Object a second Time with another Input.
So to have a clean constructor, I use a reset() Function, which is also called in the Beginning and which resets the initial State of the Object.
Example:
class OrderHtmlParser
{
protected $html;
protected $orderNumber;
public function __construct()
{
$this->reset();
}
public function reset()
{
$this->html = null;
$this->orderNumber = null;
}
/**
* Parse the given Context and return the result
*/
public function parse($html)
{
// Store the Input for whatever
$this->html = $html;
// Parse
$complexLogicResult = $this->doComplexLogic($this->html);
// Store the Result for whatever
$this->orderNumber = $complexLogicResult;
// return the Result
return $this->orderNumber;
}
public function getOrderNumber(){}
protected function doComplexLogic($html){}
}
Like this, the Parsing Object can do, what it is supposed to do:
Parse as often as you want:
$parser = new OrderHtmlParser();
$result1 = $parser->parse($html1);
$parser->reset();
$result2 = $parser->parse($html2);
Thank you for the excellent question!
This is an error-prone design to pass extensive data to the constructor that will merely store it inside the object to process this large data later.
Let me quote your beautiful quote again (the bold mark is mine):
In the object oriented style, where dependencies tend to be inverted, the constructor has a different and more Spartan role. Its only job is to make sure that object initializes into a state where it satisfies its basic invariants (in other words, it makes sure that the object instance starts off in a valid state and nothing more).
The design of the parser class in your example is troublesome because the constructor takes the input data, which is real data to process, not just “initialization data” as mentioned in the quote below, but does not actually process the data.
According to professor Ira Pohl from the University of California, Santa Cruz, the main roles of constructors are: (1) initialize the object, (2) convert values when a class has different constructor each having a different list of arguments - this concept is known as constructor overloading, (3) check for correctness - when the constructor parameters are checked to belong to a legal range.
Anyway, even if constructors are meant to initialize, convert and check, it happens very quickly, without significant delays.
In the very old programming courses, in 1980-s, we were told that a program has input and output.
Think of the $html as of the program input.
The constructors are not supposed to accept the program input. They are only supposed to accept the configuration, initialization data like character set name or other configuration parameters that may not be provided later. If they accept large data, they will likely be needed to sometimes throw exceptions, and exceptions in a constructor is a very bad style. Exceptions in constructors should better be avoided to make the code easier to fathom. For example, you may pass a file name to the constructor, but you should not open files in the constructor, and so on.
Let me modify your class a little bit.
enum ParserState (undefined, ready, result_available, error);
OrderHtmlParser
{
protected $orderNumber;
protected $defaultEncoding;
protected ParserState $state;
public function __construct($orderNumber, $defaultEncoding default "utf-8")
{
$this->orderNumber = $orderNumber;
$this->defaultEncoding = $defaultEncoding;
$this->state = ParserState::ready;
}
public function feed_data($data)
{
if ($this->state != ParserState::ready) raise Exception("You can only feed the data to the parser when it is ready");
// accumulate the data and parse it until we get enough information to make the result available
if we have enough result, let $state = ParserState::resultAvailable;
}
public function ParserState getState()
{
return $this->state
}
public function getOrderNumber()
{
return $this->orderNumber;
}
protected function getResult($html)
{
if ($this->state != ParserState::resultAvailable) raise Exception("You should wait until the result is available");
// accumulate the data and parse it until we get enough information to make the result available
}
}
If you conceive the class to have an evident design, programmers who use your class will not forget to call any method. The design in your original question was flawed because, contrary to the logic, the constructor did take the data but didn’t do anything with it, and a particular function was needed that was not obvious. If you make the design simple and obvious, you will not need even states. The states are only needed for classes that accumulate data for a long time until the result is ready, like state machines, for example, asynchronous reading of the HTML from the TCP/IP socket to feed this data to a parser.
$orderparser = new OrderHtmlParser($orderNumber, "Windows-1251");
repeat
$data = getMoreDataFromSocket();
$orderparser->feed_data($data);
until $orderparser->getState()==ParserState::resultAvailable;
$orderparser->getResult();
As for your initial questions about object states: if you design a class in such a way that the constructor only gets initialization data while there are methods that receive and process the data, so there are no separate functions to store the data and parse the data that may be forgotten to call – no states are needed. If you still need states for long-living objects that collect or supply the data sequentially, you may use the enumeration type like in the example above. My example is in abstract language, not a particular programming language.
I am confused whether to use static method or just simple method.
Lets me give an example, I am using Zend framework 1 project.
I have class like
class Example1
{
public static function getVariable() {
return is_numeric(Zend_Registry::get('config')->Variable) ? Zend_Registry::get('config')->Variable : 0;
}
public function calculateSome($param1, $param2) {
$response = array();
if($param2 == 0) {
$response = number_format(($param1 * self::getvariable()) /100);
} else {
$response = $param1;
}
return $response;
}
}
Usage :
Currently i'm getting variable value like Example1::getVariable() in whole project.
And Calculating like first instantiating a class $class1 = new Example1(); and then calling the function like $class1->calculateSome(1, 0);
I am confused whether it is good to change calculateSome() to public static and call like this Example1::calculateSome(1, 0) or left as it is.
I Have found link when to use static =>
When to use static vs instantiated classes
But I can't understand what it says.
You can find the long answer here: How Not To Kill Your Testability Using Statics
The TL;DR version of it is:
A static method is nothing more than a namespaced function, Foo::bar() does not significantly differ from foo_bar().
Whenever you call a static method, or a function for that matter, you're hardcoding a dependency. The code that reads $bar = Foo::bar(); has a hardcoded dependency to a specific Foo class. It is not possible to change what Foo refers to without changing that part of the source code.
An object is a "soft" dependency. $bar = $foo->bar(); is flexible, it allows room to change what $foo refers to. You use this with dependency injection to decouple code from other code:
function baz(Foo $foo) {
$bar = $foo->bar();
...
}
You can call Foo::bar() anytime from anywhere. If Foo::bar has some dependency it depends on, it becomes hard to guarantee that this dependency is available at the time you're calling the method. Requiring object instantiation requires the object's constructor to run, which can enforce requirements to be set up which the rest of the methods of the object can depend on.
Constructors together with dependency injecting objects into other functions are very powerful to
create seams in your codebase to make it possible to "take it apart" and put it together in flexible ways
put checks into strategic places to ensure requirements are met for certain parts of the code (at object instantiation time the constructor enforces a sane state of its little part of the world, its object), which makes it a lot easier to localise and contain failures.
Think of it like compartmentalising your app and putting firewalls between each compartment with a supervisor in charge of each one; instead of everyone just running around in the same room.
Any time you write new Class, you may as well write Class::staticMethod(), the hardcoded dependency is the same.
So the decision comes down to:
What are the requirements of this class? Does it need to ensure certain preconditions are met before any of its code can run (e.g. a database connection needs to be available), or are all methods just self-contained little helper methods?
How likely are you to maybe want to substitute this class for another class? Does this class produce side effects (e.g. writing to a file, modifying some global state) which may not always be desirable and hence a different version of it may be useful under some circumstances?
May you need more than one instance of this class at the same time, or is the nature of the class such that there are no individual instances needed?
Start using unit tests, which require you to take your app apart and test each little part individually to ensure it works, and you'll see where the advantage of object instantiation and dependency injection lie.
When the method involve instance-based properties/changes u should keep it non-static.
If its a method that is needed for the whole type then use static.
For example u can keep tracks of created instances by this snippet:
class Product {
static $count;
private $name;
public function __construct($name) {
$this->name = $name;
self::$count++;
}
public function getName() {
return $this->name;
}
public static function getCount() {
return self:$count;
}
}
$productA = new Product('A');
$productB = new Product('B');
echo $productA->getName(). ' and ' . $productB->getName(). '<br />'. PHP_EOL;
echo 'Total made products :' . Product::getCount();
I see quite often (ie within the Slim framework) that single function accessor style (like in [1] below) is deprecated in favor to classical Java-ish 2 functions accessors (get/set) (like in [2] below).
Personally I rather prefer less lines of code (in [1]) and less typing (get/set) than being able to chain setter calls like in [3] (which I consider awful).
Am I missing something?
class Test {
protected $body;
// [1] single function accessor
public function body($body = null)
{
if (!is_null($body))
$this->body=$body;
return $this->body;
}
// [2] dual function accessors
public function getBody()
{
return $this->body;
}
// [2] dual function accessors
public function setBody($body)
{
$this->body=$body;
//[3] ok, you could return $this for chaining
}
}
Are Single Function Accessors A Bad Habit?
They are not a good idea. The reasons are simple:
They have multiple responsibilities (setting and getting data). Good functions have a single responsibility and do it well.
They mask intent. You can't look at the method call and understand what's going to happen.
What do you think the body() method does? Well, body is a noun. And having a method (which should be a verb) being a noun is confusing.
But what if the method was age(). Age is both a verb and a noun. So when you see $obj->age(), are you telling the object to give you its age? Or are you telling the object to age itself?
Whereas $obj->getAge() is crystal clear what you're trying to do. And $obj->getBody() is equally clear.
It adds complexity to methods.
Your overall complexity will stay the same (because the same logic exists), but it shifts to fewer methods. Which means that instead of having 2 dead simple methods, you have one more complicated method.
So yeah, I'd avoid it.
But let's step back a minute. Rather than asking the question if "Single Function Accessors" are a bad habit, let's ask the same question about accessors in general...
Are Property Accessors A Bad Habit?
My answer is: yes.
Depends on Role of Object:
What it depends on is the role of the object, and the role of the specific property. It's a case-by-case basis.
There are tons of different types of objects (domain objects, services, proxies, collections, etc). Some are stateful, and some are not.
If the object isn't stateful, it has no properties and hence we can ignore it.
For those objects that have state, why do they have that state?
If it's because they represent the state, then the state should be public (not saying the property should be public, but the state should be exposed to the outside world). So domain models which represent business entities should have public state.
class User {
public $name;
}
But if the role of the object isn't to represent the state, but to do something with it, then it shouldn't be exposed.
class UserMapper {
protected $pdo;
public function __construct(Pdo $connection) {
$this->pdo = $connection;
}
public function findUserById($id) {
...
}
In the mapper case, $pdo is incidental state. The mapper's job isn't to represent the data of the database connection, but it needs it to work.
The Bottom Line
The bottom line is never expose state that the object isn't directly representing.
Just because you have a property, doesn't mean you should expose it. In fact, often times you shouldn't expose it. This is known as Information Hiding.
Depends On Type Of State:
But what about types of objects that are stateful? Well, as it turns out there are two fundamental types of state:
Application State
Think Configuration and things like that. Basically state that's not defined at build time, but is known at runtime.
It's important to note that this state shouldn't change through the course of a request. And it also should be reasonably the same request-to-request (aside from deploys, etc).
User State
Think state and data that's derived or dependent upon user input. An obvious example would be data that was submitted from a form.
But a less obvious example would be if you use different renderers for different types of representations. So if a user requested a JSON response, the JSON rendering code being set in a property would be considered user state.
My assertion:
Property accessors for application state are bad. There's no reason that application state should change mid-run, therefore there's no reason that you should have to propagate the state.
Property accessors for user state may be OK. But there's more to it than that.
Depends On What The Accessor Does
In the case of your example:
public function setBody($body)
{
$this->body=$body;
}
You're essentially making $body a public property.
And there's nothing wrong with that. But why do you need a method? What's wrong with: public $body; in the first place?
Some people will say "properties are evil, they must never be public!". And that's hogwash, since that's exactly what you did with that accessor.
Now, if the accessor did some typing information (through type hints), or other validation logic (minimum length, etc), then that's a different story...
Or is it?
Let me give an example.
class Person {
public $name;
public $age;
}
vs
class StrictPerson {
protected $name;
protected $age;
public function setName($name) {
if (!is_string($name)) throw new BlahException();
if (strlen($name) < 10) throw new InvalidException();
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function setAge($age) {
if (!is_int($age)) throw new ....
if ($age < 0 || $age > 150) throw new ...
$this->age = $age;
}
public function getAge() {
return $this->age;
}
}
Now, it should be clearly obvious that those properties are always valid. Right? Right? Right?
Well, no. What would happen if I created a child:
class LoosePerson extends StrictPerson {
public function setName($name) {
$this->name = $name;
}
public function setAge($age) {
$this->age = $age;
}
}
All of a sudden, all of our validation disappears. Now you could argue that was intended and it's the programmer's problem. Or you could simply change the properties to be private instead, to hold them always being valid. Right? Right? Right?
Well, no. What would happen if I did this:
$a = new StrictPerson;
$r = new ReflectionProperty($a, 'name');
$r->setAccessible(true);
$r->setValue($a, 'Bob');
I've just set an invalid value onto an object that's supposed to always validate.
The Bottom Line
Using accessors as validators only works if you always use them. And every tool that you use always uses them. Things like mysqli and PDO and Doctrine and PHPUnit which set the property directly rather than calling setters can cause massive problems.
Instead, you can use an external validator:
class PersonValidator {
public function validate(Person $person) {
if (!is_string($person->name)) {
throw new Blah...
}
if (strlen($person->name) < 10) {
throw new Blah...
}
if (!is_int($age)) throw new ....
if ($age < 0 || $age > 150) throw new ...
return true;
}
}
So, Are Property Accessors A Bad Habit?
I argue that yes, often times they are a bad habit.
Now, there are some cases where you should use them:
When you must represent that state in an interface
Properties are not specifiable in an interface. So if you must represent that the object exposes state in an interface, then you should use a getter and a setter.
I'd strongly urge you to consider why you are creating the interface. For simple data objects, it's often better to rely on the core object type (since polymorphism can't benefit due to there being no logic on the data object).
When you need to hide the internal representation for some reason.
An example would be a class that represents a unicode string. You may have an accessor method to get the raw value. But you'd want that to be a method so that you could convert the internal representation to a string of the proper character set.
That brings up an interesting point.
When you create an accessor, you should never create a property accessor. You should instead create a state accessor. The difference is that property accessors must always return a property or set it).
A state accessor on the other hand can "fake it" if it needs to. So our example above about the unicode string class, could internally represent the string as an array of code points. Then when you access the "string" state, it will convert the array into an actual string.
Objects Should Abstract
If you're going to use an accessor, it should be to abstract state. Not to represent it.
The Bottom Line / TLDR
Property accessors are a bad habit. If you're going to do that, make the properties public and use a validator object.
State accessors are not a bad habit. They are quite useful for maintaining useful abstractions.
Pass all your objects dependencies in the constructor and just have getters to access them, no need for setters most of the time.
Further to #Kleskowy and #marty answers, the best possible solution for doing this is like the following:
class Test {
protected $body;
public function body()
{
$args=func_get_args();
if (count($args)==1) //simple setter
$this->body=$args[0];
elseif (count($args)) //setter for an array
$this->body=$args;
else //getter
return $this->body;
}
}
The #marty's idea ends up in a nice way to create an array which is equivalent to PHP 5.4 [] syntax (except assoc arrays). But still compatible with PHP 5 to 5.3 ;-)
You can then write:
$a->body("a"); //a value
$a->body(null); //set to null is possible
$a->body("this","is","an","array"); //convenient way to initialize $body as an array
$a->body(); //get the value
I know this is probably subjective but I read this optimization page from Google for PHP and they suggest use the variable property directly without the need of getters and setters. Understandably I see the performance gain in this but is this really a good design practice to follow?
Their Example using getter/setter:
class dog {
public $name = '';
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
$rover = new dog();
$rover->setName('rover');
echo $rover->getName();
Suggested Optimization:
$rover = new dog();
$rover->name = 'rover';
echo $rover->name;
This would be a welcome change in my design process as I see the need for getters/setters going away, but what other hurdles/benefits might occur in doing this?
This would be a welcome change in my
design process as I see the need for
getters/setters going away, but what
other hurdles/benefits might occur in
doing this?
You lose the ability to implement special get/set logic on a particular property. For properties that are scalars (strings, integers, booleans) maybe this is no problem. But what if you have a property that is a lazy-loaded class instance?
class Document
{
protected $_createdBy;
public function getCreatedBy()
{
if (is_integer($this->_createdBy)) {
$this->_createdBy = UserFactory::loadUserById($this->_createdBy);
}
return $this->_createdBy;
}
}
That trick only works in a method. You could use __get and __set for this logic but as you add properties you end up with a big nasty switch() block:
public function __get($name)
{
switch ($name) {
case 'createdBy':
// blah blah blah
case 'createdDate':
// more stuff
// more case statements until you scream
}
}
If you just want to avoid or put off writing getters and setters, use the __call magic method to trap method calls that follow the getProperty() and setProperty() naming convention. You can put all the default get/set logic in __call and never touch it again:
abstract class Object
{
public function __call($method, $args)
{
$key = '_' . strtolower(substr($method, 3, 1)) . substr($method, 4);
$value = isset($args[0]) ? $args[0] : null;
switch (substr($method, 0, 3)) {
case 'get':
if (property_exists($this, $key)) {
return $this->$key;
}
break;
case 'set':
if (property_exists($this, $key)) {
$this->$key = $value;
return $this;
}
break;
case 'has':
return property_exists($this, $key);
break;
}
throw new Exception('Method "' . $method . '" does not exist and was not trapped in __call()');
}
}
This approach is very fast from a development standpoint because you can just extend the Object class, define some properties, and you're off to the races:
class Foo extends Object
{
protected $_bar = 12345;
}
$foo = new Foo();
echo $foo->getBar(); // outputs '12345'
$foo->setBar(67890); // next call to getBar() returns 67890
$foo->getBaz(); // oops! 'baz' doesn't exist, exception for you
It's slow from an execution standpoint because magic methods are damned slow, but you can mitigate that later by defining explicit getBar() and setBar() methods (because __call is only invoked when you calling a method that isn't defined). But if a particular property doesn't get accessed very often, maybe you don't care how slow it is. The point is, it's easy to add special get/set methods later on and the rest of your code never knows the difference.
I cribbed this approach from Magento and I find it to be very developer-friendly. Throwing an exception when calling the get/set for a property that doesn't exist helps you avoid phantom bugs caused by typos. Keeping property-specific logic in its own get/set methods makes code easier to maintain. But you don't have to write all the accessor methods at the start, you can easily go back and add them without refactoring all your other code.
The question is, what are you trying to optimize? Developer time or code speed? If you want to optimize code speed, make sure you know where your bottlenecks are before building your code around them. Premature optimization is the root of all evil.
This is some kind of micro-optimization. Theoretically, you can later add logic on name get/set by using magic methods (__get and __set) but practically it is not needed so much. And again, practically, this performance improvement only important only if you have everything else so optimized, that even a few microseconds add the value. In this case you can use other optimization techniques like merging all the included PHP files in one, remove type hints, decrease number of function parameters, use plain functions instead of classes. But usually adding a simple caching adds the 10-100x performance boost than all these micro-optimizations.
A boilerplate answer, I'm afraid but I would suggest the following:
If you have no encapsulation problems for your class (enforcing business logic, etc.) by exposing this property to other users, it is perfectly ok to do so.
You could also use the __get and __set magic methods:
class Example
{
private $allowedProps = array('prop1', 'prop2', 'prop3');
private $data = array();
public function __set($propName, $propValue)
{
if (in_array($propName, $this->allowedProps))
{
$this->data[$propName] = $propValue;
}
else
{
// error
}
}
public function __get($propName)
{
if (array_key_exists($propName, $this->data))
{
return $this->data[$propName];
}
else
{
// error
}
}
}
At first I was surprised, I was like ... wtf. But after wrapping my brain on it a few seconds, I realized the example calls the getter function 1 million time in a loop. Of course if the variable is wrapped in a getter, we have added instructions and of course it's going to take longer.
In my opinion in most situations this is very trivial because I have yet to come accross a script that comes event close to calling getters 1 million time when running. If you do need to squeeze performance to the very last drop, it is good to know this optimisation technique.
It depends on whether $name is public or not. If it's not, you can't access/modify it directly. The trade off is exposing your class's internal data elements directly to integrators. This may be OK for some classes, but not for others.
For example, you wouldn't necessarily want others to be able to modify the price of a product directly in a Product class.
I would say this is really a matter of personal preference. If performance is truly that important, then I think you answered your own question.
However, in your first example, you can still access dog::name without the getter/setter just like you do in your second example: $rover->name = 'rover'; because $name is public.
If you specifically want to hide a class member, you would need to declare the variable private or protected and then a getter/setter would be necessary.
I'm currently needing to extend a class to add functionality to it (I do not have access to the base class to modify it), and I'm running into an isssue with it.
Basically, I need the magic getter function to return a set of private variables if they are requested, but otherwise default to the default behaviour. I need these properties to be private so as to use the magic setter function to automatically sync some data.
That said, here's some example code:
class newClass extends baseClass {
private $private1;
private $private2;
...
public function __get($name) {
if($name == 'private1') return $this->private1;
if($name == 'private2') return $this->private2;
... (and so on)
// and here, it should default back to it's default behavior (throwing
// an error on getting invalid/inaccessable property, etc.)
// I cannot just use property_exists, because there may or may not be
// private variables in the base class that should not be exposed.
}
public function __set($name,$val) {
// I use this to do some automatic syncing when the two private variables
// above are set. This needs to be triggered, hence the private variables
// in the first place.
}
}
I know, I could use getProperty/setProperty functions, but I would like this to remain as intuitive as possible, despite the argument that performing such operations is counter-intuitive. The two private properties are very much connected to each other. When one of them is set, it is logically going to affect the others.
As of right now, this is the only logical way I can think of to avoid getter/setter functions and maintain the closely bonded sync between properties. If you guys can think of anything else that may be a viable solution, feel free to suggest options :)
PHP does not have a property builtin like other languages, __get and __set are indeed what you should use here. But it's a bit more work to accomplish therefore.
Your problem seems to be property_exists foremost. It's not easily possible to determine the publicity of properties from within the class (except with introspection). But you can use get_object_vars to filter out private variables from the base class at least:
function __get($name) {
static $r; if (!isset($r)) { $r = new ReflectionClass($this); }
if (($p = $r->getProperty($name)) and $p->isPublic()) {
return $this->$name;
}
elseif (method_exists($this, "get_$name")) {
return $this->{"get_$name"}();
}
else trigger_error("inaccessible property ->$name", E_USER_NOTICE);
}
For reverting back to default behaviour the best you can do is to manually output an error message.
Don't do this, use getter/setters. They are exactly the same amount of work as what you are doing here.