For years now I have been writing (on and off) at an office-management app. I need to rewrite it, because the code has become unmaintainable, so I will choose a PHP-framework and rewrite the business logic into classes.
Now I am stuck with this fundamentamental question: do I still need to return the result and if yes, how do I capture that result? Some pseudocode to make my question clear:
function a( $1, $2, $3 ) {
doThis( if ... return TRUE; if ... return FALSE; );
if ( doThis() != TRUE ) { return; }
doThat();
}
vs
class example {
private $1;
private $2;
private $3;
public function go() { $this->doThis(); $this->doThat(); }
private function doThis(){}
private function doThat(){}
}
$a = new example;
$a->go();
How can I stop the execution of the go()-method if the doThis()-method does not perform as expected? I presume I should not go about returning booleans and checking inside every method if a certain property is set to false? Or do I simply throw an Exception if something went wrong and don't do anything if everything is ok?
This is pretty basic, I know...
Thx!
Exceptions are for exceptional behaviour, so don't throw exceptions just because your code isn't in a preferred state. When it comes to writing OOP, some people still manage to write procedural while using a object oriented framework, obviously you'd want to avoid that, a simple rule of thumb is to not write God-objects.
Now what I'm guessing that you want to do is to call two functions that should be called in a specific order, and there are several ways to do this, and it actually boils down to, what kind of class you have. Lets say you have an object of the type Person then you might want to call different methods on that person from somewhere else:
$john = new Person();
$john->tryToWakeUp();
if($john->isAwake) {
$john->brushTeeth();
} else {
echo "John is still sleeping!";
}
On the other hand you might have an object of the type Engine which might want to do several stuff internally for certain actions, like start:
class Engine {
public function start() {
$this->checkFuel();
if($this->hasFuel()) {
try {
$this->initializeSomethingThatHasToDoWithEngineStartUp();
} catch (EngineException $ee) {
$this->engineState = BAD_ENGINE;
Logger::log("Engine did not start");
}
}
}
}
I'd recommend you to read up on object oriented design and play around with it before you try to convert all of your business rules, because It's likely that half way through you'll realize that you've designed everything wrong. Object Oriented Design is not easy, but it does make sense EDIT:( It should make sense ).
Related
Within the class, I created a set method if what that is called that accepts data.
<?php
public function set_name($name)
{
$this->name = ucwords(trim($name));
// return $this->name;
}
?>
My question is, do I have to return the result of the function or not necessary. If not why? I know in the display() method you have to return like so: return $this->name;. I'm really confused.
You don't have to return anything.
However, it's good practice to return something on certain functions to perform tests on it, even if it's just true or false, to clarify that the function performed correctly.
Given your code, generally, I personally don't set a return on setters. So it's fine not to return anything.
For example, you may want to test that your name only contains letters and return false if it doesn't
<?php
public function set_name($name) {
if(preg_match("/[A-Za-z]+/", $name) {
$this->name = ucwords(trim($name));
return true;
} else {
return false;
}
}
?>
Then you'd call it by:
<?php
if(!set_name($name)) {
echo "There was an error";
}
?>
However, this doesn't comply with mvc framework.
In Object Oriented programming language return the value is the best. Otherwise it will be childish and hard to maintain bugs when your sites grow bigger and it tend to errors prone.
You don't HAVE TO return the result in a setter function, the best use is to make some getter functions to get the datas.
Otherwise my point of view with setter is to return $this. With this little trick you can chain up setter functions.
For exemple :
class C
{
private $arg;
private $arg2;
function setArg($NewArg)
{
// your tests or so
$this->arg = $NewArg;
return $this;
}
function setArg2($NewArg)
{
// your tests or so
$this->arg2 = $NewArg;
return $this;
}
function getArg()
{
return $this->arg;
}
function getArg2()
{
return $this->arg2;
}
}
And you can use it that way :
$Item = new C();
$Item->setArg('hello')
->setArg2('hi');
$Item->getArg(); // return 'hello'
$Item->getArg2(); // return 'hi'
It's more semantic in this case. Do I expect a function called set_name to give me the name? No, not really, that sounds silly. In this case, I wouldn't return anything.
Because a function should only do one thing, you should always be able to reduce the choice to a binary "yes, I'd expect it to return something" or "no, that doesn't make any sense" decision.
Generally speaking your methods should do what somebody would expect them to do just by looking at their names (some people will hate me for saying this).
It's always a good idea to put yourself in the position of a programmer who has to work with your code. If had to use a method called: set_name() he would never expect it to return something.
Your methods always should do what one would expect them to do and complain to the outer environment through exceptions. Not more, not less.
If you put this into practice: Congratulations. You have just built yourself a great and reliable alarm bell for methods that are doing too much (seperation of concerns) and you're a step closer to clean software design.
Of course that's not something you would force come hell or high water (nothing is), but that's something you need to decide by yourself. If you cannot do that for whatever reasons (for example method chaining, which has been mentioned several times) , you could provide a good documentation of your class(es) and make clear what the methods actually do.
I was reading about Object Calisthenics and one of the rules was wrapping primitive types and strings:
class UIComponent {
public function repaint($animate = true)
{
//
}
}
$component->animate(false);
becomes:
class UIComponent {
public function repaint(Animate $animate)
{
//
}
}
class Animate {
private $animate;
public function __construct($animate = true)
{
$this->animate = $animate;
}
}
$component->animate(new Animate(false));
What advantages do I gain with this technique? In my opinion, I think it just complicated things and added more lines of code.
In this case, it is true, that it is a little bit oversized, but there are other examples, where it can make sense
class Identifier {
protected $id;
public function __construct ($id) {
if (!preg_match('~^{a-z0-9]$~i', $id)) throw new Exception("Invalid id '$id'");
$this->id = $id;
}
public function getId () { return $this->getId(); }
}
So this one is immutable and it ensures a specific format. When you type-hint against this class within another class, you don't need to test, whether or not the identifier is valid
class MyClass {
protected $id;
public function __construct (Identifier $id) { $this->id = $id; }
}
This is just a simple example and in fact it is not that common in php.
[..] and added more lines of code.
I don't think "more lines of code" is bad by itself. If it needs more lines (or even classes), to write readable and clean code, it is much much better, than compact, but unreadable stuff.
Imagine a new developer (or yourself maybe a year after you last touched the project) reading the code in the first example:
$component->repaint(false);
Without jumping to the definition of repaint() or otherwise reading your documentation for the method, you have absolutely no way of knowing what that false means in terms of how the method behaves. I mean, it literally reads "repaint false", so... repaint but... don't actually repaint? The intent is not clear, and that is a bad thing.
This extremely simple example serves to demonstrate how code readability can be greatly improved by wrapping primitives. The benefits are even greater when you want to start adding just a little bit of behavior like baking in simple validation and comparing itself against another instance.
You should have no concern at all in regards to the performance impact of new'ing up such a tiny little object. As for "more lines of code" why is that bad? SRP almost always results in "more code" but it is clean, readable and maintainable code.
This is actually an interesting question, and there's an easy (but ugly) fix to it (see below).
So I'm asking if there's a better way to do it.
What I'd like to do is making an object constructor return something else rather than a new instance.
Here's an example of what I'm trying to achieve:
$GLOBALS['object_cache']=array();
class Test {
public function __construct($id=0){
if(isset( $GLOBALS['object_cache'][$id] ))
return $GLOBALS['object_cache'][$id];
$GLOBALS['object_cache'][$id]=$this;
}
}
$t0=new Test(0);
$t1=new Test(1);
$t01=new Test(0);
// modifying $t01 would presumably also modify $t0
The easy (but ugly?) fix:
$GLOBALS['object_cache']=array();
class Test {
public static function create($id=0){
if(isset( $GLOBALS['object_cache'][$id] ))
return $GLOBALS['object_cache'][$id];
$new=new Test();
$GLOBALS['object_cache'][$id]=$new;
return $new;
}
}
$t0=Test::create(0);
$t1=Test::create(1);
$t01=Test::create(0);
// modifying $t01 would presumably also modify $t0
What do you guys think? Example 1 doesn't work, by the way; it returns a new instance regardless of the return statement.
So am I missing something, or is the better way the second one?
PS: No need stating the obvious about patterns (factory/singleton)...
Omg. Constructor cannot return anything.
It is called factory method pattern http://en.wikipedia.org/wiki/Factory_method_pattern and it is a common practice to instantiate objects.
ps: Store the instances in static class variable and second solution will not be so weird like now.
You could also use a procedural version:
class Test {
function __construct($i) {}
}
function Test($i) {
static $cache;
if (isset($cache[$i])) {
return $cache[$i];
}
else {
return $cache[$i] = new Test($i);
}
}
It's slightly nicer on the eyes, and allows for e.g. instant fluent Test(1)->do()->else() calls.
Basically what you're trying to do is implementing a Singleton pattern combined with a Factory method pattern. Anyone should be able to tell how it works if you document it in your technical documentation (and in your comments), so the first way can be used.
The second solution actually seems less obvious to me.
I was reading about how to detect the encoding of a file in PHP, and on some blog or somewhere, it was suggested to do this:
if (function_exists('mb_detect_encoding')) {
function is_utf8($str) {
// do stuff using the mb* libraries
}
} else {
function is_utf8($str) {
// do stuff manually
}
}
To me this feels very messy, and could be replaced with this:
function is_utf8($str) {
if (...) {
// mb stuff here
} else {
// manual stuff here
}
}
However, I can also see that it also has some benefits. Depending how complicated the if statement is, and how often the function is called, this might be much more efficient. My question is this: At what point would you consider splitting a function into two like in the first example? Are there any other pros/cons that I've missed?
Edit: Please don't get hung up on the example here, the question is about this practice in general.
My gut reaction is to go with a single declaration of the is_utf8 function. The PHP engine is mighty good at optimization and the overhead of multiple calls to function_exists() should be negligible.
A good practice, maybe not in that case, but in general might involve the use of OOP (objects) with factory methods.
class my_utf8
{
// A static method that determine what object to create
public static function factory() {
if (function_exists('mb_detect_encoding')) {
return new my_utf8_with_mb;
} else {
return new my_utf8_without_mb;
}
}
}
class my_utf8_with_mb extends my_utf8 {
public function is_utf8($str) {
// do stuff using the mb* libraries
}
}
class my_utf8_without_mb extends my_utf8 {
public function is_utf8($str) {
// do stuff without the mb* libraries
}
}
And in your application :
global $myUtfInstance;
// Call once
$myUtfInstance = my_utf8::factory();
// later and forever...
$myUtfInstance->is_utf8($str);
You could also involve a singleton pattern depending on what you do. It does not skip the IF but eliminate the need of a global variable.
class my_utf8
{
private static $instance;
public static function factory() {
if (function_exists('mb_detect_encoding')) {
return new my_utf8_with_mb;
} else {
return new my_utf8_without_mb;
}
}
public static function getInstance()
{
if (!self::$instance) {
self::$instance = self::factory();
}
return self::$instance;
}
}
And in your code :
my_utf8::getInstance()->is_utf8($str);
Stylistically, I'm inclined to push for the second. If performance is an issue though, you'd do well to consider using the first.
if (function_exists("sin")) {
function baz($farfs) {
print "I am the first baz";
}
} else {
function baz($farfs) {
print "I am the second baz";
}
}
function blarg($fgar) {
if (function_exists("sin")) {
print "I am the first blarg";
} else {
print "I am the second blarg";
}
}
for ($i=0;$i
I ran this on my workstation here, and found that the aggregate time of calls to baz took anywhere from 50-75% of the aggregate calls to blarg, depending on whether the function being tested actually exists.
Here are the actual numbers:
function_exists("foobar")
blarg: 36.64 ms
baz: 14.71 ms
function_exists("sin")
blarg: 35.24 ms
baz: 23.59 ms
The only difference between these two functions is the conditional and the two extra characters in the output. Interestingly enough, the 10001 calls to function_exists only take 0.18 and 0.11 ms respectively on the two tests. I'm wondering if there is some function call overhead not being accounted for in either profile.
As for style though, I really dislike the first. Defining a function by name in two different places seems like a shady thing to do, especially when relying on the oddness in PHP that makes function definitions not performed in global scope affect global scope anyway. On the other hand, my biases just might be showing, and the rest of the PHP community might not have a problem with relying on the PHP interpreter as a sort of preprocessor in this instance.
shrug Such are the matters of style.
By default, go always with the most readable solution. If that particular piece of code turns out to be a significant drag (measured, not assumed) on your application, then you optimize it.
I'll apologize in advance for what's most likely pretty ugly PHP, but I'd do something more like:
if (function_exists('mb_detect_encoding')) {
function is_utf8_mb($str) {
// do stuff using the mb* libraries
}
}
function is_utf8_manual($str) {
// do stuff manually
}
if (function_exists('is_utf8_mb')) {
function is_utf8($str) {
is_utf8_mb($str)
}
} else {
function is_utf8($str) {
is_utf8_manual($str)
}
}
That is: an is_utf8 variant will exist in the execution environment dependent only on if it can work in that environment. Each variant is in a code block of the minimal size needed to determine if that variant should be loaded, and to perform its function. The main reason is that I think the smaller the amount of space you need to write your function, the easier it is for a reader to build an understanding of the function's behavior. Your eyes have to travel less, you have to scroll less, there are generally fewer of those trivial frustrations involved in understanding a function for the first time. The second reason is that it provides a better way of testing your code - you can more easily automate a check that the is_utf8 variant routines are producing the same result when you can access all of them at the same time.
There are two aspects at play here: performance (don't pay for what you don't need), and readability.
As many wise posters say: don't bother about performance until it's proven to be a problem.
But concerning readability, in my opinion, a function should show as little layers of responsibility as possible. Functions that do exactly one thing are easiest understood.
Your question is actually about 'how should I mix two responsibilities':
what: detect the presence of a library, and 'dispatch' to the correct code block
how to use the library vs. how to do without.
That's why I would really create two 'layers': one layer dispatching to the appropriate function, and another layer containing 'code blocks', wrapped in a function with the proper name.
And then you still have the choice whether to do the dispatching explicitly, or to use PHP's possibility to declare functions on-the-fly.
// functionality: defines how to detect utf8 encoding
//
function is_utf8_mb( $arg ) {
... // using the mb library
}
function is_utf8_bare( $arg ) {
... // hand coded
}
// dispatching layer: decide what library to use
//
// option 1: define on-the-fly
function define_utf8_function() {
if( function_exists('mb_detect_encoding') ) {
function is_utf8( $arg ) { return is_utf8_mb( $arg ); }
} else {
function is_utf8( $arg ) { return is_utf8_bare( $arg ); }
}
}
// option 2: check the dispatching on each function call
function is_utf8_runtimedispatch( $arg ) {
if( function_exists('mb_detect_encoding') )
return is_utf8_mb( $arg );
else
return is_utf8_bar( $arg );
}
Is it possible to exit gracefully out of a constructor in php? Something to the effect of
class Foo {
function __construct()
{
$active = false;
if(!$active)
{
return false;
}
}
}
I'm trying to accomplish this because I want to check to see if any of the methods in the class should run based on a configuration file. I don't want to have to check the configuration file in every method to see if the methods should be running.
That depends on what you mean by "gracefully". If you want your constructor to fail you can throw an exception, or you can use the factory pattern:
class FooFactory {
function makeFoo() {
return $someConstraint ? null : new Foo();
}
}
Maybe you can elaborate a bit on what exactly it is you want to accomplish.
Make it blow up. There is no such thing as a graceful failure in a constructor. Perhaps in the calling code, but not in the constructor. Throw an exception and handle it appropriately.
I can smell the Proxy pattern coming your way. What you are trying to achieve is not having the constructor fail gracefully but not allowing methods to be called on an object based on some $active criterion.
This might point you in the right direction. Or maybe not (=>> I don't quite like the page I linked in, but it was the best I could find for PHP). Do give Proxy a read, from other sources too perhaps. Basically, your ProxyObject will have a reference to a real object that will execute methods. Your client code will be calling methods on the ProxyObject as if it were the real thing, and the ProxyObject would decide whether it's active or not, whether to pass the message on to the real thing or to return nothing or nulls or dummy values. Sounds good?
If the constructor does so much logic, then it's not well designed.
Leave it empty, pass the configuration to it via a setter method and let it fail there.
It is not OO programming:
$o = new myObject();
if (!is_object($o)) // then what???
If your constructor fails, you should throw an exception, not return a false value. Unless you're using a language like C in which exceptions in the construction of the object means it can never be deconstructed.
The reason for this is because an exception forces the program to deal with it, and it give you the bad data. If you return a value, say -1 or whatever, the program can continue silently and ignore that until it causes a problem later down the road. Throwing an exception prevents these silent bugs from entering the code. You may know that it returns false if it failed to construct properly, but your co-worker may not and may happily try to use an object he thought was what he constructed to find out that it's really a boolean.
I think N3rd suggested a very cool solution but here is another simpler method.
class Foo {
private $active = TRUE;
function __construct() {
$this->check ( $active );
//OR
//if ($this->check ( $active )) { do something }
}
function check($var) {
if (! $var) {
$this->active = FALSE;
return FALSE;
}
return TRUE;
}
}