Commenting in Magento: PHPDoc + Requirements

This post assumes you have a fairly good understanding of Magento’s structure

Recently here at our Demac Factory, we’ve launched several Commerce websites in fairly quick succession. As a result of quick turnarounds, and short deadlines, our teams here saw large amount of code being deployed in relatively short sessions. With all hands on deck, code tends to get thrown around, removed, deleted, changed and moved around for various reasons and without proper documentation, things get a little chaotic. Luckily, we have versioning tools and commit standards that help us walk through the lifelines of our code bases but what really helps prevent confusing problems is proper documentation.

Proper documentation particularly helps when I’m picking up a ticket that’s been backlogged, or a bug that’s happening in a piece of code someone else wrote months ago. Imagine receiving a task to refactor code with absolutely no direction, or comments. It’d be a little like reading this:

<?php

function thisDoesSomething($a, $b) {
    var $_a = findThisDeclaration($a);
    var $_b = findThis($b);
    return something($_a, $_b);
}

That’s an extreme case of course.
One of the most frustrating things in doing maintenance on code is not remembering what that code was used for to begin with.

Magento Commenting

Interesting enough, if you run a search online for complaints about Magento, one of the leading reasons is “Not enough documentation”.
Isn’t far from the truth, but following their comments is surprisingly helpful for those who are willing to tread through app/code/core.

What you’ll notice though in Magento’s core code is, it follows PHPDoc’s commenting standards (allowing PHPDoc documentator to properly generate documentation for your files!), that allows a developer to quickly learn some vital information about the file they’re currently reading. First, let’s look at PHPDoc basic standards. (For more information, visit PHPDoc’s documentation section)

PHPDoc basics

A standard PHPDoc comment block starts with /** and each corresponding line starts with an *. The comment block ends with */.
For example:

<?php
/** This is a standard PHPDoc comment block
 * It can span multiple lines
 */

At the top of every file, the first comment block generally describes the file’s usage, author and any other licensing information that follows. If there is only one commenting block at the top and a class is defined after, the commenting block belongs to the class. Therefore, to avoid having that misconception, always comment both the file and your classes also. (As you should anyways!)

<?php
/** I'm supposed to describe the file.
  */

/** I describe the class.
  * If I don't exist, then the block above me
  * ends up describing the class instead.
  */
class Demac_Module_Model_Example {
}

For classes that have public objects that are accessible by the magic method, the method should be defined with the @method tag at the top of the class.
This way, other developers will know how the method is called and what it returns at first glance to the class.
For example, if you see a function to your module in this code:

<?php
   $instance = Mage::getModel('demac_module/example')->getSomeObject();

and you run a search for it in your class above, you might not find a declaration of it.
While it might not seem devastating at first glance, imagine your class extends on top of several parent classes.
If a developer isn’t aware of whether getSomeObject() is a magic method or not, they might search into all parent classes to try and find the definition.
To save other developers some time (so they can avoid the wild goose chase), add the following to the comment block of your class:

<?php
/**
  * @method return_type getSomeObject()
  */

For example, if getSomeObject() returns an instance of Mage_Catalog_Model_Product, then your tag will be:

/**
 * @method Mage_Catalog_Model_Product getSomeObject()
 */

Related: Mini Tutorial: Understanding Magento Blocks – The Basics

Functions

For functions and methods, a comment block follows the following format:

<?php
/** 
 * Summary of your function
 *
 * Long description of your method if needed. (optional)
 *
 * @param type of $bar, description if necessary
 * @return type of variable, description if necessary
 */
function foo($bar) {
}

Use discretion when writing the short summaries and long descriptions.
Try to avoid using vague descriptions such as “This function adds product to cart”.
As a rule of thumb, try to describe in pseudo code logic what the function is supposed to do.

Note: If you notice your description is very long with extremely complicated logic,
you might need to refactor your code into smaller functions 🙂

Templates

Templates in Magento should have little to no logic except for if statements that might govern how the page looks.
Aside from including those comments, make a habit of including the block name that the template is associated to.

E.g. If you have a block called:

<?php
class YourPackage_YourModule_Block_FeaturedProduct extends Mage_Catalog_Block_Product {
}

and it uses the template:

/app/design/frontend/yourpackage/yourtheme/yourmodule/featuredproduct.phtml

Then in your comment block for featuredproduct.phtml, it should include the following tag:

/**
  * @see YourPackage_YourModule_Block_FeaturedProduct
  */

Whoever looks at your template file will now be able to map any $this->function calls to the proper block file.

From PHPDoc:
The @see tag indicates a reference from the associated Structural Elements to a website or other Structural Elements.

For a list of tags that are used in PHPDoc, refer to the following link:
http://www.phpdoc.org/docs/latest/references/phpdoc/tags/index.html

Closing Remarks

When writing descriptions for your classes and functions, try to be descriptive. For example:

<?php
//Gets the video of the product
$_video = $_product->getVideo();

This doesn’t tell us anything.
Try to summarize what the variable is for, and at the minimum describe what the variable should hold.

<?php
//Gets the (string) video URL of the current product
$_video = $_product->getVideo(); 

With the proper commenting format, it won’t be nearly as big of a nightmare to try and pick up old code that’s been lying around from several months back.
Good luck coding!

Related: The Challenges with Magento As a New Developer