What defines a valid object state? - php

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.

Related

Letting a setter set a value of a property belonging to another class

Should a setter always be setting values of its direct properties and not of properties of associated objects? For example, I have something like below where the API client takes in an XML:
Class XML {
private $value;
// Setter for $value exists here
...
}
Class Client {
private $xml; // XML
public function __construct(XML $xml)
{
$this->xml = $xml;
...
}
}
I want the $value modified after Client is instantiated because, say, I want to change or add some options to the request. Should I use the setter in XML and re-instantiate the Client when modifying requests, or have a setter in Client directly so that I don't need to re-instantiate Client?
I'm typically prefer the former, but is there a reason why the latter approach would be preferred? I can't think of any except that it's easier to make quick changes.
Generally, if a class has public methods, they are meant to be accessed. So, no harm in using them, you might think.
However, ask yourself: Why does a class have getters/setters in the first place? Accessors are usually found on classes for data objects. The main purpose of such objects is to carry data, they usually don’t do anything – unlike, for instance, a service or a controller class.
Next question: What is a constructor for? A constructor is used to set up the internal state of an object, and it will require it’s dependencies as parameters. In the spirit of loose coupling, dependencies should not be mutable from other classes.
Looking at your code, I guess that you’re writing some sort of XML-based client application and you want the Client class to depend on an instance of the XML class.
Modifying the internal state of the XML object from Client is a bad idea. Other classes depending on that instance will not know about the modification and will possibly get unexpected results.
There are several ways to solve this, depending on the actual task to perform:
1) If you need to set the value only for the context of a single method call of XML, modify the method to take $value as a parameter. But do not set it as an object member inside XML!
class XML
{
public function doSomething($value)
{
…
// do whatever you need with $value,
// but do *not* do something like $this->value = $value
}
}
2) If the interaction with $value needs to be consistent across several operations, you should extract these operations from XML into an own worker or data object class. XML should then have a factory method to create an instance of this helper class. Then either XML or Client might have methods to use the worker:
class XML
{
public function createWorker($value)
{
return new XmlWorker($value, $this);
// XmlWorker might even contain a reference to the XML instance, e.g.
return new XmlWorker($value, $this);
}
public function doSomethingWithWorker(XmlWorker $worker)
{
$value = $worker->getValue();
$worker->doWork();
}
}
class Client
{
private function doSomething()
{
$worker = $this->xml->createWorker($value);
$worker->doWork();
}
}
I would recommend to read up on Design Patterns; in this context especially about Loose Coupling & Separation of Concerns, Factory methods and Depedency Injection.

when to use static method or simple class method?

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();

Why single function accessor appears to be considered as bad habit?

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

Purpose of PHP constructors

I am working with classes and object class structure, but not at a complex level – just classes and functions, then, in one place, instantiation.
As to __construct and __destruct, please tell me very simply: what is the purpose of constructors and destructors?
I know the school level theoretical explanation, but i am expecting something like in real world, as in which situations we have to use them.
Provide also an example, please.
Regards
A constructor is a function that is executed after the object has been initialized (its memory allocated, instance properties copied etc.). Its purpose is to put the object in a valid state.
Frequently, an object, to be in an usable state, requires some data. The purpose of the constructor is to force this data to be given to the object at instantiation time and disallow any instances without such data.
Consider a simple class that encapsulates a string and has a method that returns the length of this string. One possible implementation would be:
class StringWrapper {
private $str;
public function setInnerString($str) {
$this->str = (string) $str;
}
public function getLength() {
if ($this->str === null)
throw new RuntimeException("Invalid state.");
return strlen($this->str);
}
}
In order to be in a valid state, this function requires setInnerString to be called before getLength. By using a constructor, you can force all the instances to be in a good state when getLength is called:
class StringWrapper {
private $str;
public function __construct($str) {
$this->str = (string) $str;
}
public function getLength() {
return strlen($this->str);
}
}
You could also keep the setInnerString to allow the string to be changed after instantiation.
A destructor is called when an object is about to be freed from memory. Typically, it contains cleanup code (e.g. closing of file descriptors the object is holding). They are rare in PHP because PHP cleans all the resources held by the script when the script execution ends.
Learn by example:
class Person {
public $name;
public $surname;
public function __construct($name,$surname){
$this->name=$name;
$this->surname=$surname;
}
}
Why is this helpful? Because instead of:
$person = new Person();
$person->name='Christian';
$person->surname='Sciberras';
you can use:
$person = new Person('Christian','Sciberras');
Which is less code and looks cleaner!
Note: As the replies below correctly state, constructors/destructors are used for a wide variety of things, including: de/initialization of variables (especially when the the value is variable), memory de/allocation, invariants (could be surpassed) and cleaner code.
I'd also like to note that "cleaner code" is not just "sugar" but enhances readability, maintainability etc.
The constructor is run at the time you instantiate an instance of your class. So if you have a class Person:
class Person {
public $name = 'Bob'; // this is initialization
public $age;
public function __construct($name = '') {
if (!empty($name)) {
$this->name = $name;
}
}
public function introduce() {
echo "I'm {$this->name} and I'm {$this->age} years old\n";
}
public function __destruct() {
echo "Bye for now\n";
}
}
To demonstrate:
$person = new Person;
$person->age = 20;
$person->introduce();
// I'm Bob and I'm 20 years old
// Bye for now
We can override the default value set with initialization via the constructor argument:
$person = new Person('Fred');
$person->age = 20;
$person->introduce();
// if there are no other references to $person and
// unset($person) is called, the script ends
// or exit() is called __destruct() runs
unset($person);
// I'm Fred and I'm 20 years old
// Bye for now
Hopefully that helps demonstrate where the constructor and destructor are called, what are they useful for?
__construct() can default class members with resources or more complex data structures.
__destruct() can free resources like file and database handles.
The constructor is often used for class composition or constructor injection of required dependencies.
The constructor of a class defines what happens when you instantiate an object from this class. The destructor of a class defines what happens when you destroy the object instance.
See the PHP Manual on Constructors and Destructors:
PHP 5 allows developers to declare constructor methods for classes. Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.
and
PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++. The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence.
In practise, you use the Constructor to put the object into a minimum valid state. That means you assign arguments passed to the constructor to the object properties. If your object uses some sort of data types that cannot be assigned directly as property, you create them here, e.g.
class Example
{
private $database;
private $storage;
public function __construct($database)
{
$this->database = $database;
$this->storage = new SplObjectStorage;
}
}
Note that in order to keep your objects testable, a constructor should not do any real work:
Work in the constructor such as: creating/initializing collaborators, communicating with other services, and logic to set up its own state removes seams needed for testing, forcing subclasses/mocks to inherit unwanted behavior. Too much work in the constructor prevents instantiation or altering collaborators in the test.
In the above Example, the $database is a collaborator. It has a lifecycle and purpose of it's own and may be a shared instance. You would not create this inside the constructor. On the other hand, the SplObjectStorage is an integral part of Example. It has the very same lifecycle and is not shared with other objects. Thus, it is okay to new it in the ctor.
Likewise, you use the destructor to clean up after your object. In most cases, this is unneeded because it is handled automatically by PHP. This is why you will see much more ctors than dtors in the wild.
I've found it was easiest to grasp when I thought about the new keyword before the constructor: it simply tells my variable a new object of its data type would be give to him, based on which constructor I call and what I pass into it, I can define to state of the object on arrival.
Without the new object, we would be living in the land of null, and crashes!
The Destructor is most obvious from a C++ stand point, where if you dont have a destructor method delete all the memory pointed to, it will stay used after the program exits causing leaks and lag on the clients OS untill next reboot.
I'm sure there's more than enough good information here, but another angle is always helpful from what I've noticed!
constructor is function of class which is executed automatically when object of class is created we need not to call that constructor separately we can say constructor as magic method because in php magic method begin with double underscore characters

Is it reasonable to have a fair amount of public properties in a class?

Or in more specific words, is it "ok" to not be relying on setters and getters?
I'm dealing with a class that checks the availability of rooms and sets public properties of which there are more than a dozen. Things such as:
unitNumber
roomTypes ( array )
codeCorporate
codeGroup
numberKids
numberAdults
numberRooms
currency
minRate
maxRate
soapServer
units ( array )
hotelId
And after an object is instantiated those properties are set with $this-> inside various methods. However the code that deals with the object often sets public properties directly instead of using getter/setter methods:
$object->something = 3;
foreach ($object->things as $thing ) { }
If I have the time to refactor this class..
Should I stick all of these properties in a data array that's a private property, and define __set and __get methods?
Should I make a single getter method for each of the properties?
In my opinion, it is rarely a good idea to have any public members. It increases coupling between classes, and makes refactoring very complicated (should you need it.)
Setters/Getters are the way to go, and the very small performance penalty that you pay for it is usually either optimized away, or trumped by elegance.
To answer your question about array vs. single-getter-per-var, it's a matter of taste. I tend to only keep variables of a similar type within an array, and separate the rest.
I personally have yet to find a truly good reason for a public property, though im open for suggestion :-)
Although i much prefer specified getters/setters for each property (whether that's a proxy to a generalized get($name) or not). I assume you have other code already that uses direct assignment so in that case i would say to proceed with using the magic __get/__set methods.
I think most people will recommend using setters & getters. Right now you're limited to simply setting & fetching the property, but what if you want to log when that property is accessed? Or perhaps you want to run the value by a validation function first (email, phonenumber, zip code, etc). Maybe you'll need to call another function, or set another property. I think you see where I'm heading with this. By using setters & getters, you add a valuable layer of encapsulation to your classes, and 99% of the time this is worth the extra typing you'll need to do ;) Imagine trying to do the examples above without setters & getters. It'd be a big headache to say the least.
Edit: I forgot to mention Doctrine. It's an object relation mapper (ORM) that can automatically setup setters & getters for you (amongst other things). You can check it out at http://www.doctrine-project.org/
I would take a step back and ask some more general questions:
Why am I having to expose this much information; what is using it and why?
Is this class really just a data structure without behavior, in which case should be a private class to some other class?
Does this class serve a single purpose, or is it on the path to becoming monolithic?
You may discover that you are able to create views of an instance of a class to export to a database, display in a form, etc. Check out the "Builder" and "Acyclic Visitor" patterns to start with.
Regarding accessors, I do not see a need to use them for what you are describing: retrieving class properties and internal state information, aka a struct. However, for attributes of a class I could see the benefit in certain cases, but more for retrieving attributes, not for mutations of your object's state.
If I may add my grain of salt several months later :
It is very un-OO to have public properties. Everything should be encapsulated, simply because (among other reasons) using direct attribute manipulation doesn't give you ways to easily refactor or perform (more) control checks when some external source modifies the field. For example, let's say you have a class with many fields that is used throughout a project several times, and that project contains several thousands of files; it's a project that has been running and expanded for a few years now. Let's say that the company is changing it's business model, or that a problem is found with some of the field's data type and now is required to have some validation; will you duplicate that validation in all those thousands of source code that is directly accessing the public member? In PHP, the solution may be simple, but not in most OO programming language (i.g. Java). The fact is that OO is based on encapsulation. In short, encapsulation doesn't only produce clean code, but also highly maintainable (not to say cost-effective and cohesive) code.
Your suggestion of having a private member (array) being manipulated by __get / __set is good. This way, if you need some extra validation along the road, simply create your setter and/or your getter and it will be the end of it. Some may argue with that being counter productive as the code completion cannot kick-in on __get / __set. IMHO, relying on code completion is simply lazy coding. But then again, having every member have it's own getter and/or setter allows you to write a more comprehensive API documentation. Personally, I usually use that technique for internal or very general purpose classes. If all your fields do not require any validation, or there are as you said several dozen of them, then using magic methods would be acceptable, in my opinion.
The bottom line is to avoid direct member access on class instances, period. How you decide to achieve this is strictly up to you. Just make sure that the API is well documented the more abstract you make it.
On a final note, in PHP, if you already have classes that are being used that are not encapsulating their fields, for example something like
class SomeObject {
public $foo;
public $bar;
public $baz;
//...
}
you can simply fix this class without having to refactor anything with something like :
class SomeObject {
private $_foo; // having underscore as prefix helps to know what's private/protected
private $_bar; // inside the code.
private $_baz;
public function __get($name) {
$methodName = 'get'.ucfirst($name);
if (method_exists($this, $methodName)) {
return $this->{$methodName}();
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function __set($name, $value) {
$methodName = 'set'.ucfirst($name);
if (method_exists($this, $methodName)) {
$this->{$methodName}($value);
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function getFoo() { return $this->_foo; }
public function setFoo($value) { $this->_foo = $value; }
public function getBar() { return $this->_bar; }
public function setBar($value) { $this->_bar = $value; }
public function getBaz() { return $this->_baz; }
public function setBaz($value) { $this->_baz = $value; }
}
And then
$obj = new SomeObject();
$obj->foo = 'Hello world'; // legacy code support
$obj->setFoo('Hello world'); // same thing, but preferred
And you satisfy both the OO paradigm and having direct access to attributes of an instance. You could also have __call() check for prefix 'get' or 'set' and call __get() and __set() accordingly, but I would not go that far, though this would truly enable general purpose classes to access it's private members via ->member and ->getMember()/->setMember()

Categories