These principles helped me a lot writing maintainable code:
These principles are well known and easy to refer to when you do a code review. I still feel that I have to add one principle that is missing: descriptive names everywhere
After applying these 5 principles, your code will probably be quite maintainable.
Give a descriptive name on all places where possible. Avoid everything that is anonymous or has an non descriptive name. It is closely related to the SOLID Single-responsibility principle. If something has one responsibility, it is easier to give it a name. At all levels, from the highest architectural level to a single line of code.
Examples are more clear then a long story so: "show me the code"!
This code has an anonymous block
public void PayAllEmployees(IEnumerable<int> ids)
{
foreach (var id in ids)
{
// This is an anonymous block
var employee = _employeeRepository.Get(id);
var salary = _salaryRepository.Get(employee.SalaryLevel);
_bankService.Pay(employee.BankAccount, salary.Amount);
}
}
The anonymous block can get a name by moving the single responsibility 'pay employee' to a separate method:
public void PayAllEmployees(IEnumerable<int> ids)
{
foreach (var id in ids)
{
PayEmployee(id);
}
}
public void PayEmployee(id)
{
var employee = _employeeRepository.Get(id);
var salary = _salaryRepository.Get(employee.SalaryLevel);
_bankService.Pay(employee.BankAccount, salary.Amount);
}
You don't have to read the code of the bock to determine what the code is doing. Bonus: if you need to pay only one employee, you don't have to refactor the code.
The expression in this 'if' does not tell the what or why it is true or not.
if (age >= 67 && isFormerEployee && insuranceRule4Applied)
{
// Do something
}
It is more clear to the reader when the expression has a name:
var pensionMustBePaid = age >= 67 && isFormerEployee && insuranceRule4Applied;
if (pensionMustBePaid)
{
// Do something
}
Avoid primitive types and strings in signatures of public methods. See also primitive obsession and tiny types.
This method signature...
public void WritePageContentToDisk(string page, string fileLocation)
... can have much clearer types using System.Uri
and System.IO.FileInfo
:
public void WritePageContentToDisk(Uri page, FileInfo fileLocation)
The types are better validated. This will throw an exception (wrong slashes):
new Uri("http:\\siepman.nl")
The FileInfo types also has handy methods and properties like .Exists
.
The meaning of the page
parameter is also more clear. It is the address of the page, not the content.