fir3net

Sponsored by

PPS Logo Red 200mm

How to Write Clean Code

Contents[Hide]

Introduction

Even bad code can function. But if code isn't clean, it can bring a development organization to its knees. Every year, countless hours and significant resources are lost because of poorly written code[1].
Within this article we will take the key concepts, and points around writing Clean Code - referenced from the amazing book, The Clean Coder: A Code of Conduct for Professional Programmers by Robert Cecil Martin (aka Uncle Bob).

 

Names

How should we name our objects, functions, variables and methods?

  1. Names should be well thought out.
  2. They should communicate your intent. If you require a comment to describe your name, you have chosen a bad name.
  3. Use pronounceable names. People will need to talk about your code, make it easy for them.
  4. Code should read like well written English, writing a line code so it reads like a sentence. The names you choose should lend itself to this, i.e
    1. Classes are named with a Noun. i.e.
      class Logs(object):
      ....
    2. Variables are named with a Noun. i.e

      user_account_id = 124816
    3. Method/Functions are named with a Verb. i.e.

      def get_user_account_id():
      ....
    4. Predicates should return a Boolean. i.e

      def is_valid():
      if x == 2:
      return True
  5. Ensure you stick to the rule of naming inside of the realms of your scope.
    1. variables names should be named extremely short if there scope is extremely small.
    2. variables names should be long if they are in a big long scope, such as a global variable.
    3. function names should be short if they have a long scope
    4. function names should be long if they have a short scope
    5. classes names should be short, as in the realms of Python they can be considered public.

You mentioned nouns and verbs - can you explain what they are?

  • Noun: a word that refers to a person, place, thing, event, substance or quality e.g.'nurse', 'cat', 'party', 'oil' and 'poverty'.
  • Verb: a word or phrase that describes an action, condition or experience e.g. 'run', 'look' and 'feel'.

Functions

How should I construct my functions and how should they operate?

General

As a general rule of thumb, functions should,

  • be small, very small
  • do just ONE thing

How do you ensure your function is only doing ONE thing ONLY? Ensure you can extract no further functions from the original function. Once you can extract no more, you can be sure the function is doing one thing, and one thing ONLY.

Arguments

  1. You should not pass Boolean or None types into your function
  2. No more then 3 arguments should be passed into your function

Errors

  1. It is better to raise an exception then return an error code
  2. Custom exceptions are better then returning error codes
  3. Custom exceptions should be scoped to the class

Command Query Structure (CQS)

This is one of my favorite disciplines within functions, as this is a great way to create clean functions that only do ONE thing,

  1. Functions that change state should not return values, but can throw an exception
  2. Functions that return values should not change state

Function Knowledge

  1. It is bad for a single function to know the entire structure of the system
  2. Each function should only have limited knowledge of the system

TDD

If you want your code to be clean, then TDD SHOULD be adopted. Lets look at why, the laws of TDD and the TDD process,

Benefits

The benefits to TDD are[2],

  • promotes the creation of more efficient code
  • improves code quality
  • ensures the minimum amount of code is used
  • prevents code regression

Laws

There are  3 laws to TDD,

  1. Write no production code until you have create a failing unit test
  2. Write only enough of a test to demonstrate a failure
  3. Write only enough production code to pass the test

Process

The process for TDD is,

  • RED - Create a test and ensure it fails
  • GREEN - Write production code to ensure the test passes
  • REFACTOR - Refactor your code and ensure tests still pass

Architecture

Good architectures are NOT composed of tools and frameworks. Good architectures allow you to defer the decisions about tools and frameworks, such as UIs and databases.
But how is this achieved? This is achieved by building an architecture that decouples you from them - by building your application, not on your software environment, but based on your use-case. Decoupling your applications allows for changes to be made, fair easier that it being a single monolithic application. Also decoupling allows for clear business decisions to be made to each part of your application i.e time/money spent on the UI, API and usecase, i.e core application.

What is a Use Case?

A use case is a list of actions or event steps to achieve a goal. It is important to note within our use-case no mention is made to databases or UIs. Below is an example,

-- Create Order --

- Data
Customer-id
Customer-contact-id
Payment-information
Shipment-mechanism

- Primary Course
Order clerk issues Create Order command with above data
System Validates all data
System creates order and determines order-id
System delivers order-id to clerk

- Exception Course
Validation Error - System delivers error message to clerk

Partitioning

As more use cases are defined partitioning it is required to allow clear separation within your system, this design is also know as EBI (Entity, Boundary, and Interactor).

  • Business Object (Entities) - Entities are application independent business rules. The methods within the object should NOT be specific to any of the systems. An example would be a Product Object.
  • Controller (Interactors) - Use cases are application specific. Use-cases are implemented by interactor objects ; It is the goal of the interactor to know how to call the entities to reach the goal of the use case. An example for our example use case would be CreateOrder.
  • User interfaces (Boundaries) - A boundary is the interface that translates information from the outside into the format the application uses, as well as translating it back when the information is going out.

Below shows how this actually looks,

cleancode

References

[1] https://www.fir3net.com/Programming/Python/python-unit-testing.html
[2] Clean Code - Robert Cecil Martin

Tags: Python, Design

About the Author

RDonato

R Donato

Ricky Donato is the Founder and Chief Editor of Fir3net.com. He currently works as a Principal Network Security Engineer and has a keen interest in automation and the cloud.

You can find Ricky on Twitter @f3lix001