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.
0 comments:
Post a Comment