I hate methods/functions returning multiple types


Basically the title.





i always see these functions like





function f1 ( $a1, $a2, $a3 ) {

if ( $a1 ) {
return false;
}

if ( $a2 ) {
return 'some string';
}

return array('some data');


}




When the code returns multiple types from a single function it automatically becomes code smell.





Because whenever i want to use this function f1, i would need check the type it returned.






$result = f1( $a1, $a2, $a3 );


if ( is_array($result ) ) {
// do thing 1
}
elseif ( is_string($result) ) {
// do thing 2
}
else {
// do thing 3
}




just to use this function i would need 6 lines of code. 6 lines of code everywhere where i need to use the function. As a developer i would hate to use this function anywhere, because everywhere i would need to handle 3 flows.





But i get your intention, what happens when the value doesn't match function expectation in run time. You can avoid this by either






  • Throwing exceptions




  • Creating objects to represent invalid states





Throwing exceptions





Throwing exceptions is usually helpful, because i could handle all the exceptions which arise in the block of code with the single try catch block.





function f1($a1, $a2, $a3 ) {
if ( ! $a1 || !$a2 ) {
throw new Exception('something terrible happened');
}
return array('some data');
}




Creating objects to represent invalid states





lets say you have a function which returns subscription by id and the interface for subscription looks like this.





interface Subscription {

function get_id();


}




and the function looks like this.





function get_subscription_by_id ( $id ) {
if ( ! $id ) {
throw new Exception("subscription id is not valid");
}

return Subscription_Factory::get($id);
}




I could create a object which represent invalid subscription and return it instead of throwing exception






class Invalid_Subscription implements Subscription {

function get_id() {
// do nothing.
}

}




now one might ask how to handle this state, i prefer to handle it inside a factory.





Lets say i get a subscription and i call an api. in that that logic would be inside the factory method





class Request_Factory {

// request class has execute() method which sends the request.

static function get($subscription) {

if ( ! $subscription instance of Valid_Subscription ) {
return Invalid_Request();
}

return Valid_Request();


}

}




now lets see how the usage would look like.





Request_Factory::get( Subscription_Factory::get(2) )->execute();




we have eliminated all the ifs, they are delegated to factories.





Let me know your thoughts on the comments.


Share:

0 comments:

Post a Comment