You are on page 1of 6

Do’s and Don’ts of C Program

Use one exit point in a function. Except for


exceptions.
This eases debugging, and makes your code more readable. Since the flow of the function will
always end in one point (and not break flow somewhere in the middle) it is easier to understand
what it does. Use a standardized value name to store the return value for the function, like 'ret',
which you will not use in any other circumstance. Always initialize this value at the top of the
function with a default value, even if the default value will never be used, so it is visible that your
function will be busy determining what that value should be.

PHP:

1 function doSomething($param1, $param2) {


2 $ret = null;
3 if($param1 == doSomethingElse($param2)) {
4 $ret = $param1;
5 } else {
6 $ret = $param2;
7 }
8 return $ret;
9}

If you have a function or method that might enter an unknown state, or unexpected state throw
exceptions, that's what they're for. Check your input and be aware that even if your function is
called only internally, you never know what people will get to work with the code and you
therefore never know what they might think is appropriate to feed it.

Don't:
PHP:
1 function checkStuff($foo) {
2 switch($foo) {
3 case 'a': return 1;
4 case 'b': return 5;
5 }
6}

Do:
PHP:

1 function checkStuff($foo) {
2 $ret = null;
3 switch($foo) {
4 case 'a':
5 $ret = 1;
6 break;
7 case 'b':
8 $ret =2;
9 break;
1 default:
0 throw new InvalidArgumentException('Expected a or b for $foo');
1 }
1 return $ret;
1}
2
1
3
1
4

The exceptions I use most are InvalidArgumentException (for arguments I didn't expect),
UnexpectedValueException (for return values of other functions I didn't expect) and
LogicException (for a combination of circumstances that don't make sense). Whenever possible
and suitable, I extend these to provide more information about the context of the exception.

Use 0, null and false consistently


If you use 0, you mean a countable or arithmetic result 0, which is a numeric representation of
"nothing".
If you use false, you mean a boolean state of the variable or property, which means that the
only other state the property or variable can be in, is true. Unfortunately, some of php's standard
library functions don't follow this (e.g. strpos()), but don't let that be a guideline ...
If you use null, you mean either an unknown state of the variable, or the variable has not been
initialized (yet), or the state of the variable is to be considered invalid. To check if a variable is
null, use "is_null()", since an initialized state of the variable can be a value that evaluates to
false in a boolean expression. This leads to the following paradigm: is_null() checks if a variable
has a sensible value (yet).
PHP:

1 function getCount() {
2 if(is_null($this->_count)) {
3 $this->_count = count($this->_property);
4 }
5 return $this->_count;
6}
Design by contract, design for extension
Try to extract interfaces for all your classes. Even if you don't explicitly use these interfaces, e.g.
in type hints, next to being a good exercise it still serves the purpose of showing what parts of a
class are specific to the classes (own) implementation and what parts aren't. In other words: it
shows the reader what functionality of a class is actually there because it follows a contract
defined by an interface, and what code is merely aiding the implementation; hence showing how
the same interface could be used for other implementations.

Designing for extension means that you show what parts are actually meant to be extended.
This does not mean that you should declare everything protected or public. It means that you
should think hard about what entry points a derived class should use, and where it is supposed
to hook into base functionality. Think about what method should be final and what properties
could possibly be private, so you're not ambiguous about where you'd want a derived class to
hook in:

Don't:
PHP:

1 // We have 3 extension points


2 class Foo {
3 // #1 (could be set by a derived constructor)
4 protected $_thingy = null;
5
6 // #2 (could be overridden by a derived class)
7 function getThingy() {
8 if(is_null($this->_thingy)) {
9 $this->_thingy = $this->_loadThingy();
1 }
0 return $this->_thingy;
1 }
1
1 // #3 (could be overriden by a derived class)
2 protected function _loadThingy() {
1 return "some value that relies on some heavy resources";
3 }
1}
4
1
5
1
6
1
7
1
8

Do:
PHP:

1 // now we have only one. It is obvious the we


2 // want _loadThingy to be the extension point
3 class Foo {
4 private $_thingy = null;
5
6 final function getThingy () {
7 if(is_null($this->_thingy)) {
8 $this->_thingy = $this->_loadThingy();
9 }
1 return $this->_thingy;
0 }
1
1 protected function _loadThingy() {
1 return "some value that relies on some heavy resources";
2 }
1}
3
1
4
1
5
1
6

It goes without saying that if you don't intend your class to be extended at all, you should
declare it final too. 

Last but not least: always define a base constructor, even if it does nothing. This way, a derived
class has no reason not to call the base constructor (which imho a derived class always should),
so you won't break compatibility if you add initialization code to the base constructor later.

Make your symbols explain themselves


I have the following few rules of thumb I use for naming methods and variables which I (try to)
use consistently throughout my code.
Be consistent in your naming throughout your application. Don't use a "name" field in one table,
and a "title" in another with exactly the same semantics. Avoid mixing your native tongue with
English unless there is absolutely no way around it.
"Long" names are in the eye of the beholder. Get a bigger screen, get rid of that hopelessly
outdated 80-character wordwrap in your IDE and consider that every time you or your colleague
needs to wonder what something means, it is a precious human CPU cycle lost.
A method that starts with get never changes the object state, except for lazy-load, in which case
the changed object property is accessed only by that method. It always returns the property that
the method name is implying: getTitle() returns a title.
A method that starts with load does some heavy loading, and it never caches the value. The
caching is done by the get() method (or the service which it is calling, for that matter), which
lazy-loads the property. In other words, a loader method is typically private, since the getter that
stands right next to it is the only one to call it.
A method that starts with init does local initialization, and does not call any external services or
heavy-duty work. It is a piece of initialiation that is either there for lazy-load reasons, or because
it is a Template Method for hooking into another method (typically a parent's constructor).
Variables and methods that have boolean values or return values always start with "is" or "has".
This way the names explain what the value stand for, and that they represent a true boolean
value: either yes or no and nothing in between.
Use your own exception implementation, with which you provide additional context information
on why and how the exception occurred. Since you use your own definitions, you can easily
catch and handle the exceptions at a higher level.

Only comment on code that needs clarification


Following #2, it does not make sense to comment on stuff that the code itself already explains. If
you have code with clear symbol names, commenting is simply redundant most of the times. On
the other hand, if you feel a piece of code needs more explanation, check to see if it could be
solved with better naming of your symbols. In many cases, the code could easily transformed in
a more readable equivalent, just by renaming some variables.

Don't:
PHP:

1 // Check if $c is the last one


2 if ($c == $l) {
3 // print the table footer
4 echo $tfoot;
5}

Do:
PHP:
1 if($current == $last) {
2 echo $htmlTableFooter;
3}

And most of all, don't repeat your code in your comments, as I saw some time back:

PHP:

1 // get page
2 $page = getPage();
3
4 // assign page to template
5 $smarty->assign('page', $page);

You might also like