Tag Archives: Phpdoc

Best Practices – Part 1

I am in the middle of Matthew Weier O'Phinney and Lorna Jane Mitchell's talk on PHP Best Practices and after the 3 pages of notes I took in the first hour I wanted to get some things down on virtual paper before getting too far into it.  There is a lot of information that they're giving out.

Source Control

The first thing they talked about was Source Control.  Unfortunately, I was doing my writeup on MongoDB and I missed a bunch of stuff.  That said, there were two things that I had time to write down.

The first thing was "If you are not using Source Control, START!"  I have to agree.  It'd be silly if I disagreed.  The only real question is which source control to use. For that there was a list provided from Wikipedia that gave a comparison of different version control systems that looked pretty useful.

Coding Standards

The next section that they started talking about was that of Coding Standards.  There are a few ways that you can know if you don't have a coding standard.

  1. You reformat it
  2. Code you wrote 6 months ago looks different from today
  3. Modifying old code introduces syntax errors

When trying to determine whether or not you need a coding standard ask your self the following questions.

  1. Can you read your own code
  2. Can others read your code
  3. Can you read someone else’s code
  4. Can you switch between code bases easily

Coding standards assist in the maintainability and collaboratibity of your code.  What this means is that you can have more people working on your code.  Code is structured predictably.  When something is predictable it is easier to have someone new work on your code.  Coding standards decentralize who can work on code.  In other words, when you're on vacation and you don't want to be bothered by some emergency code change that needs to be done you can simply pass it off to someone else who can get working on it faster than you can get to a computer.  And really, after having several umbrella drinks on a Caribbean beach somewhere, would people really want you working on code?

One of the statements  I really appreciated was the statement; "Don’t write your own coding standards!!!  There is nothing special about your code."  When I was working in Zend's Services department I would work hard to encourage customers to embrace some kind of coding standard.  I didn't care which, but they had to chose one.  OK, well, that's not entirely correct.  I told them to use the Zend Framework coding standards because they have already born themselves out in the real world.  But the Zend Framework coding standards were no different from the PEAR coding standards (which ZF stole from) which was no different from the Horde standards (which PEAR stole from).  In other words, the problems that people were trying to solve did not change.  There were some updates made to handle some new cases, but for the most part, the coding standards have been relatively static.

Design Patterns

Design Patterns for me are a bit of a double edged sword.  On one hand they solve a very useful purpose.  They provide common solutions to common problems.  The problem is that there are so many problems that need to be solved that there are, in my mind, too many design patterns.  In other words, because there are so many potential gloves to fit the hand people sometimes worry too much about getting the exact right design pattern.

That said, Design Patterns have a great use if you don't become too overburdened by them.  Lorna did a great job about describing some of the more pertinent.  but she also said something important; "don't invent reasons to use design patterns".

Factory

  • Has methods to create and return objects
  • May return different objects
  • May use complex logic to work out the returned object

Registry

  • Can be a singleton but not a requirement
  • Register them here but access them elsewhere

Adapter

  • “Adapts” a specific interface to fit something else
  • Allows the class wrapped by the adapter to exist independently from the component

Root cause analysis – Client got a bit of knowledge!

Decorator

  • Wraps another class in order to modify its behavior
  • Target class doesn’t change
  • Decorating class often implements the same interface
  • Can be visually decorative, but not always

This one was the most interesting to me because you don't see it much in PHP applications, but the example that Lorna showed looked eerily similar to Swing layouts.  The example looked something like this.

interface LabelIterface
{
    public function render();
}

class BasicLabel implements LabelInterface
{
    public function render()
    {
        return $this->lable->render();
    }
}

class LabelNewLineDecorator extends BasicLabel
{
    public function render()
    {
        return $this->labout->render() . "n";
    }
}
class LabelStarDecorator extends BasicLabel
{
    public function render()
    {
        return '** ' . $this->labout->render();
    }
}
class LabelHyphenDecorator extends BasicLabel
{
    public function render()
    {
        return str_replace(' ', '-', $this->labout->render());
    }
}

You have some basic functionality, but it is easily extendable.  It "decorates" the original class.  Neat.

Observer

  • Watches for changes in another object
  • Responds to those changes
  • Target class is aware, notifies observers

I was thinking about this and this sounds a lot like the Zend Framework plugin and action helper functionality. 

Matthew and Lorna are getting up and running again so this is where I'll stop.  Nevertheless, I made a really good call in attending the Best Practices talk.

Zend Studio and PDT Code Completion Tips

Code Assist is one of those "must have" features in any IDE.  Some developers are so brilliant and have such good memories that they are able to know what parts of their application do what and those silly drop down boxes just get in their way.  I am not one of those developers.  I love Code Assist.  In fact, I learned Java via code completion in JBuilder 8.  It was horrible Java code, but it worked.  And eventually I learned how to write good Java… using code completion as well.

The concept of code completion is very easy to implement when you have a statically typed language.  It's not really a question of IF you will get a certain type of variable.  You WILL get it.  A dynamically typed language is a bit different.  You can have structure, but only if you decide to follow it.  I think this is a good thing.  There are many problems that don't need to have a highly structured solution.  In fact, most problems you need to solve on the web don't really need a highly structured solution.  That's one of the reasons, in my opinion, why PHP is so popular.  You can have the structure if you need it, but if you don't need it you don't need to use it.  That's also one of the reasons why I don't like rigid frameworks.

So, if you're going to give your PHP application more structure, how do you tell other developers about it?  When using Zend Studio or PDT comments are your friend.  Not just any comments, but PHPDoc.  With that you are able to both document your code and also provide hints to the IDE about what your return types are.

Let's start with a class

class User
{
    public function getParent()
    {
        if ($this->_parent) {
            return $this->_parent;
        }
        return null;
    }    
}

Now let's try some code completion on it.

Easy enough.  But what if you want to get the parent of the parent?

Parent of parent

Nothing.  And how should it?  The IDE has nothing to base the return type on and so has nothing to provide.  So how can you tell the IDE?  With PHPDoc.

class User
{
    /**
     * @return User
     */
    
    public function getParent()
    {
        if ($this->_parent) {
            return $this->_parent;
        }
        return null;
    }    
}

As you can see, we simply added @return User to our PHPDoc.  Now when we try out code completion we get

With Code Assist

Piece of cake.  But, what if we have code like this?

foreach ($users as $user) {
    $user->
}

We know that $user is an instance of User but the IDE doesn't.  However, what we can do is tell the IDE what the variable type is inline with the code.

Inline code completion

The code /* @var $user User */ provides information that the IDE can use to give you the code completion you need.  It is a simple multiline C comment with a tag @var in it.  Following the tag, the name of the variable is provided, in this case $user.  Then the variable type is provided. 

Easy.