At Procurios we design, build and maintain our own platform with more than 20 developers, pushing hundreds of commits to our central git repository every day. At this moment (2015) our codebase contains about 3 million lines of code.
A significant part of our work is tending our software garden: weeding, pruning and tidying up our code, to keep it healthy and allow new features to grow.
We read and improve our code frequently. It must be readable, debuggable, maintainable. A consistent code style helps a lot.
Our style guide consists of two parts, code style and coding habits.
We basically follow the coding style related PSR standards issued by the PHP Framework Interoperability Group:
The string concatenation operator MUST be preceded and followed by a space.
// bad
$string = 'Hello '.$name;
// good
$string = 'Hello ' . $name;
About the names of identifiers like classes, functions, methods, variables:
- A name SHOULD be descriptive, distinctive, precise and readable.
- A name SHOULD NOT be abbreviated.
- A name SHOULD NOT be pre- or postfixed with Interface, Trait or Abstract.
A long name is not a problem, since our IDE has auto completion.
Consecutive assignments or declarations SHOULD NOT be aligned. Adding one item may require you to re-align the other items, resulting in unnecessary changes in your commit.
// bad
$short = 1;
$veryLongItem = 2;
// good
$short = 1;
$veryLongItem = 2;
Every class, property and method MUST be preceded by a DocBlock comment.
Class DocBlocks:
- It MUST contain an @author tag.
- It MAY contain documentation about the class.
Property DocBlocks:
- It MUST contain a @var tag indicating the type of the property.
- It MAY contain documentation about the property.
Method DocBlocks:
- It MUST contain @param tags for every parameter of the method.
- It MUST contain a @return tag if the method returns something.
- It SHOULD contain a @throws tag if the method throws an Exception.
- It MAY contain documentation about the method.
Example:
/**
* @author John Doe
*/
class Foo
{
/**
* @var array
*/
private $foo = [];
/**
* @param array $foo
* @return int
*/
private function setFooAndReturnNumberOfItems(array $foo)
{
$this->foo = $foo;
return count($this->foo);
}
}
What makes good code?
There isn't one answer, nor one authoritative list of criteria. It depends on the language, the requirements, the purpose of the code, and a bit on personal taste.
Many great books have been written about good code and being a good coder. This is our list of recommended reads:
- Robert C. Martin - Clean Code
- Robert C. Martin - The Clean Coder
- Martin Fowler - Patterns of Enterprise Application Architecture
- Martin Fowler - Refactoring: Improving the Design of Existing Code
- Steve McConnell - Code Complete 2
- Eric Evans - Domain-Driven Design
We have gathered some of the rules of thumb that help us write better code.
PHP is a dynamically typed language. Careless type juggling can lead to unpredictable code behaviour and hard-to-find bugs.
Be as strict as possible:
- Use type hints
- Use strict comparisons (=== and !==)
- Use value objects that check their arguments
- Use constants for values that are used more than once
If your editor can complete your code, you'll likely make less mistakes. And your editor can refactor your code later on.
- Use constants instead of string values
- Use value objects instead of associative arrays
- Use exceptions instead of return types
You write code only once, but it is read (and changed) many times. Write your code so that other developers can easily understand it.
Quoting Martin Fowler:
Any fool can write code that a computer can understand.
Good programmers write code that humans can understand.
- Prefer simple solutions over complex solutions. No over-engineering. No premature optimization. No premature abstraction.
- Be consistent in approach, naming and structure with the rest of the codebase. Do not reinvent the wheel.
- Write documentation explaining why the code exists, not what it does. Don't state the obvious.
- Use object calisthenics.
Not only on the scale of a method should your code be readable. Let the methods of a class tell the story of the class.
Bad code is hard to change, unstable, fragile and non-reusable. A small change can have unexpected and undetected effects anywhere.
Design your code to minimize the ripple effect of a change.
The SOLID principles help to achieve this on the level of classes; The lesser known RCC ASS principles do the same for packages, components or even entire systems.
Do not assume that:
- input will be sane
- all users are benevolent
- other developers don't make mistakes
- external services are always available and don't change
Don't ignore errors, edge cases or faulty input. If something is really wrong, stop immediately with a descriptive and distinctive error.
Use example.com, example.org and example.net for all example URLs and email addresses, per RFC 2606.
Use english names like John Doe, Alice or Bob. Never use customer names.
For sample or temporary code, always use meta syntactic variables like $foo
, $bar
, $baz
and $quux
.