Flexible PHP Interfaces

While working on converting old and flaky code to our current framework, making it more object orientated, with less duplication and easier to understand and use I thought I'd cover a few things which to me make classes, methods and interfaces "Programmer Friendly".

1. Doc Comments

You might be in a hurry, but documentation comments can speed up development to an order of magnitude. With most advanced PHP editors such as PDT supporting JavaDoc style comments and subsequently type hinting from them for auto-completion, taking a few extra seconds to add these annotations is well worth it.

interface BelongsToCompany {
  /**
   * @return Company
   */
  public function company();
}

2. Flexible Parameters

Always require the minimum amount of data from the programmer to run the function. For example if you only require the `Company` primary key to run some queries, the only require the primary key as a parameter.

However it can be useful to convert known input types into what you want, allowing the programmer to pass a Company object or a User object (which belongs to a Company) as the parameters and to get the company ID from that.

class Something {
  /**
   * @param integer|Company $company_id
   */
  public function staffCount( $company_id )
  {
    if( $company_id instanceof BelongsToCompany ) {
      $company_id = $company_id->company();
    }

    if( $company instanceof Company ) {
      $company_id = $company_id->id;
    }
  }
}

3. Use method Entry contracts

Wherever you implement an interface method, and generally any method, add input contracts using asserts() for more robust code and faster less obscure error feedback to other programmers. A fine balance is needed between allowing flexible parameters usually setup above the entry contract, and ensuring that the main body of code only runs with the correct types of parameters.

I'm including this under the topic of flexibility because these provide safeguards to let the programmer know when then underlying function cannot handle or automatically convert the parameters.

Some situations would be:

  • $parameter is a number
  • $parameter is an instance of SomeClass or SomeInterface
  • If $param1 is passed, ensure $param2 is there too
  • Ensure $parameter is not empty

However, avoid using `is_int` or `is_bool`, or other underlying functions which query the underlying ZVAL structure in entry contracts; instead use the `ctype_*` functions or type-casts first, then check that the values are within expected ranges.

/**
 * @param integer $p1
 * @param boolean $p2
 * @param string $p3
 */
function testContract( $p1, $p2, $p3 ) {
  $p1 = (int)$p1;
  assert( $p1 > 0 );

  // Boolean is implicitly within range
  $p2 = (boolean)$p2;

  assert( !empty($p3) );
  assert( strlen($p3) < 100 );
}

4. Be Stateful and Refactor

One of my major gripes are groups of 'stateless' static methods which all accept a common parameter. These should be flagged early on for re-factoring as they make your classes brittle and inhibit changes in future. Common places where these pop up are when procedural code has been hastily converted into classes.

class Company {
  public static function getUsers( $company_id ) {}
  public static function getPeople( $company_id ) {}
  public static function getCustomers( $company_id ) {}
}

One of the problem factors here is that the programmer is required to carry the objects state around wherever it's being used and implicitly pass it when calling the methods. A particularly bad example would be:

$users = Company::getUsers( $this->company->id );

2 Responses to Flexible PHP Interfaces

  1. 138 Developercast.com 2008-06-11 14:46:42

    In an effort to breathe as much life into an old bit of software he was having to update, Harry Roberts worked up a list of things that he sees can make things a bit more “programmer friendly” when it comes to using classes...

  2. 143 Glîndûwath 2008-06-16 04:43:55

    Is there a mistake in the second example (Flexible Parameters)? I think $company should be $company_id ...

Leave a Reply



About

Harry is a professional developer and sysadmin from London, UK.

He's an atheist, employed at PixelMags LLC, a socialist and has a pragmatic outlook on life, love and religion.

Bookmarks

I'm constantly finding interesting stuff, here are some of the things I've bookmarked recently:

HarryR on Faves.com