If I have a database table containing a flag that can have multiple states, should I do this
if ($Object->isStateOne()) {
// do something
}
else if ($Object->isStateTwo()) {
// do something else
}
else if ($Object->isStateThree()) {
// do yet something else
}
or this
switch ($Object->getSomeFlag()) {
case ObjectMapper::STATE_ONE:
// do something
break;
case ObjectMapper::STATE_TWO:
// do something else
break;
case ObjectMapper::STATE_THREE:
// do yet something else
break;
}
?
Whichever makes sense, of course.
The switch looks much cleaner. But, what is this 'state' you are checking? If you're translating a string, use an array, for example.
The if has different behavior from switch. The method calls MAY have side effects. The if is better if multiple states may be active on the object at once, though.
From an OO perspective, both are discouraged. If you have different state, you may want to create a virtual methods, and override it in inherited class. Then based on polymorphism, you can avoid the if, and switch statement.
The second option just seems to be the better solution. IMHO, the unsightly duplication of the comparison code that would accompany the methods of the first solution would be the show-stopper for me, for example:
public function isStateOne() {
if(strcmp(ObjectMapper::STATE_ONE, '1') == 0) {
return true;
}
}
public function isStateTwo() {
if(strcmp(ObjectMapper::STATE_TWO, '2') == 0) {
return true;
}
}
public function isStateThree() {
if(strcmp(ObjectMapper::STATE_THREE, '3') == 0) {
return true;
}
}
Of course, others might disagree. I just don't like having classes cluttered up with 'almost the same' methods.
Related
please provide some example or pattern name to avoid a lot of if else constructions. Maybe some design pattern exists for more clean and readable code?
public function process(CreditNotificationInterface $obj)
{
$this->creditNotification = $obj;
if ($obj->isAccepted()) {
return $this->accept();
} else {
if ($obj->isDeclined()) {
return $this->decline();
} else {
if ($obj->isError()) {
return $this->error();
} else {
if ($obj->isAbandoned()) {
return $this->abandoned();
}
}
}
}
return false;
}
If you really want to use design pattern strategy pattern looks to me like best solver for lot of if/else's. http://www.phptherightway.com/pages/Design-Patterns.html
The switch statement was conceived to solve exactly this problem. It allows you to check values serially in an attempt to reduce nested ifs and condense serial if-elses. Take a look here for examples on how to apply the switch statement in PHP. Then apply it to your problem.
https://www.w3schools.com/php/php_switch.asp
This is more or less a readability, maintainability and/or best practice type question.
I wanted to get the SO opinion on something. Is it bad practice to return from multiple points in a function? For example.
<?php
// $a is some object
$somereturnvariable = somefunction($a);
if ($somereturnvariable !== FALSE) {
// do something here like write to a file or something
}
function somefunction($a) {
if (isset($a->value)) {
if ($a->value > 2) {
return $a->value;
} else {
return FALSE;
} else {
// returning false because $a->value isn't set
return FALSE;
}
}
?>
or should it be something like:
<?php
// $a is some object
$somereturnvariable = somefunction($a);
if ($somereturnvariable !== false) {
// do something here like write to a file or something
}
function somefunction($a) {
if (isset($a->value)) {
if ($a->value > 2) {
return $a->value;
}
}
return FALSE
}
?>
As a matter of practice, I always try to return from ONE point in any function, which is usually the final point. I store it in a variable say $retVal and return it in the end of the function.It makes the code look more sane to me.
Having said that, there are circumstances where say, in your function as the first line you check if a var is null and if yes you are returning. In this case, there is no point in holdin on to that variable, then adding additional checks to skip all the function code to return that in the end.
So...in conclusion, both ways works. It always depends on what the situation is and what you are more comfortable with.
I have checked a few other questions but they don't really give me the answer I expect..
My code is a like this..
private function handle()
{
if()
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition))
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
code
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
}
In my opinion it is readable but messy, sadly I haven't found really a way of making it look 'pretty'. Any ideas?
EDIT: Each return is different.
EDIT2: Gave an answer of my own, thanks everybody!
Conditions can be merged by a && operator..It works form left to right, which means, as soon as the any one starting from left fails, it stops evaluating the condition..
if($a) {
if($b) {
}
}
can be replaced by
if($a && $b) {
}
Use a variable check, or combine the conditions into fewer IF statements.
Variable check like so:
$execute = TRUE;
// Opposite of what you want, e.g. if you want $a only to be TRUE, do $a !== TRUE
if (condition) {
$execute = FALSE;
}
...
// If all the conditions were met, then everything is OK
if($execute === TRUE) {
// code
}else {
// return
}
Edit:
Variable check can be preferably to combining IF statements if you want more control on what returns, e.g. something specific happens if a certain condition fails, which combining conditions can not always allow for.
Like already posted use
if(condition1&&condition2){}
or if this will not work, you can also use function which stops as soon as a condition is true
function some(){
if(!conditon 1){return 0;}
if(condition 2) {return 1;}
}
this provides more power as second if works only if first doesn't satisfy.
You must choose based on your requirements. Sometimes though nested loops are unavoidable.
I thought it out and have found a nice way of doing it, basically I'll make a method for each basic condition, and I'll call them in an if statement with the bitwise AND operator (&), which don't short-circuit.
/**
* nonsql_condition - It means it doesn't check with the database
*
* sql_condition - It means it does check with the database.
*/
if(!$this->nonsql_condition() & !$this->nonsql_condition() & !$this->nonsql_condition() & !$this->nonsql_condition())
{
if(!$this->sql_condition())
{
return error;
}
if(!$this->sql_condition())
{
return error;
}
code;
}
This allows me to use fewer lines of code in my method, plus also not doing unnecessary queries to my database.
In PHP I need to pass some arguments to a function by reference.
I don't want to write 2 different methods for similar behaviour.
So i need to select behaviour by argument.
But I can't pass null by reference.
So I created a dummy array.
So i run it either by
$temp[0]=-1;
$this->doSomething($bigIds, $temp);
or
$temp[0]=-1;
$this->doSomething($temp, $smallIds);
public function doSomething(&$bigIds, &$smallIds) {
if ($bigIds[0] != -1) {
// make some thing
}
if ($smallIds[0] != -1) {
// make some thing
}
}
Is there a better/ elegant way to do this?
I would suggest an enum but this is PHP. So this should do it for you:
class YourClass
{
const DoSomethingSmall = 0;
const DoSomethingBig = 1;
public function doSomething(&$ids, $actionType) {
// can also use a switch here
if($actionType == self::DoSomethingSmall) {
// do small
}
else if($actionType == self::DoSomethingBig) {
// do big
}
}
}
Then you can do:
$this->doSomething($bigIds, self::DoSomethingBig);
$this->doSomething($smallIds, self::DoSomethingSmall);
From outside the class you can use YourClass::DoSomethingBig and YourClass::DoSomethingSmall
There could be loads of things you might rather do, for instance what #ad7six says in a comment, and you could also just give it some sort of setting and just one array..
public function doSomething(&$bIds, $mode) {
switch($mode){
case 1: do smallthing;break;
case 2: do bigthing;break;
case 3: do both;break;
default: do nothing;break;
}
It all depends on what you need really
I'm basically creating a display-module for an ad-system I've created.
I'm trying to avoid the following construction, with repeated if-statements.
My gut feeling tells me there's a smarter way to do this, maybe with polymorphism?
<?php
class Ad {
public $adState = 'active';
}
class AdWriter {
public function displayAd(Ad $ad, $viewmode = 'visitor') {
if ($viewmode =='visitor') {
if ($adState == 'active') {}
else if ($adState == 'paused') {}
else if ($adState == 'inactive') {}
}
else if ($viewmode = 'owner') {
if ($adState == 'active') {}
else if ($adState == 'paused') {}
else if ($adState == 'inactive') {}
}
else if ($viewmode == 'administrator') {
if ($adState == 'active') {}
else if ($adState == 'paused') {}
else if ($adState == 'inactive') {}
}
}
}
?>
Apply the Refactoring Replace Conditional with Polymorphism and have a look at the State Pattern.
You could create an Factory (Pattern), using an switch on viewmode and create an specific Ad implementing an interface having an simple function 'display' for example.
Pseudo example:
class AdFactory {
public static function getAd($sType) {
switch($sType) {
case "AdOne":
return new AdOne();
case "AdTwo":
return new AdTwo();
}
}
throw new Exception("Unknown ad!");
}
class AdOne implement AdInterface {
public function display() {
// All that AdOne does when displaying.
}
}
interface AdInterface {
public function display() { }
}
$oAd1 = AdFactory::getAd('typeOne');
$oAd1->display();
$oAd2 = AdFactory::getAd('typeTwo');
$oAd2->display();
Instead of passing $viewmode, pass an object that would encapsulate the logic for this viewmore and call its method that would do the work. This way you'll avoid the need for if-statements.
I'm sneaking onto StackOverflow at work, so don't have time to write a detailed reply of all your possibilities.
But to 'tidy up' those ifs, you can do this:
switch $viewmode {
case 'visitor':
your_code_here;
break;
case 'owner':
your_code_here;
break;
default:
will_run_if_nothing_above_matches;
break;
}
switch($viewmode){
case "visitor":
switch($adstate){
case "active":
//statement
break;
case "paused":
break;
case "inactive":
break;
}
break;
case "owner":
break;
case "administrator":
break;
}
In 8 chapter of this book you can find very detailed answer to your question.
In short: use Composition or Factories. (see answer of Wesley van Opdorp).
Also, avoid using string arguments as enumerable:
$viewmode = 'visitor'
with this argument, you will have to keep in memory all possible values of this argument. Or look into code of function to remember them. And these values are strings - good place for typos. Also, it will be very difficult to change values in feature, because all calls of this method will contain hardcoded strings.
Use class-constants:
class AdWriter {
const view_mode_visitor = 1;
...
Also, $adState - wrong code, should be $ad->state. But using public fields it's bad practice too :)