This is the 3rd part of my trilogy of blogs on classes and code quality in plugins, the previous two parts are
I have written an increasing number of articles focusing on the quality and design of code, which you can find Hosk’s CRM Developer Articles
To summarise the first blog discusses the effects of creating plugins and putting the code into the plugin.
- Complex code
- Hard to read
- No code reuse
- Difficult to debug
- Writing unit tests is hard so most CRM developers don’t bother
- Creates duplicate code
The second blog post discusses the benefits of creating classes and using abstractions, it allows the developer to manage the effects of change whilst cr
The role of classes
- Removes duplicate code
- Modelling real world and abstract ideas
- Reduces complexity
- Manages the effects of change
- Information hiding
- Create reusable code
The benefits of classes
- The code is created from many simple classes and methods
- The code is easy to unit test
- Well designed classes have minimal dependencies
- Well designed classes should be able to be reused
- Classes and method can make the code easier to understand
- Good abstractions can be used in different projects
You should now be convinced creating classes is the way to go, so how do you find classes
The benefits of creating classes have been outlined above but finding classes and abstractions can be tricky. Numerous times I have created some initial classes only to find my one class could then be broken into two or three separate classes.
The design of code emerges overtime with unit tests allowing developers to change the code and test it still works. Development tools can help refactor the code but there is an overhead to changing existing code and tests.
The earlier you can successfully identify classes/abstractions the less time you can spend refactoring your code, so it’s worth improving the methods you use to find classes.
There are some common methods to help developers find classes which I will outline below.
NOUNS = Class, Verbs = Methods
CRM developers usually get a requirements document/functional spec. It’s good practise to create a use case document to see what steps the end user will go through using the functionality (This will find the different paths through the customization).
The requirements document/use case can be used to find nouns and verbs to help you creates classes and methods. Nouns give you the classes and Verbs give you the methods.
Nouns – Person/Place/Things
Verbs – Methods/Behavior/action
Using the nouns/verbs method gives you a good start identifying classes but it’s far from fool proof and will miss some classes and create duplicates.
When using this method be aware classes are not always specified as nouns, you may need to look a bit harder.
The nouns/verb method of finding classes and methods is a good start point for finding classes/methods. When using the process keep in mind you are trying to find abstractions and common functionality in the requirements, design is an iterative process which involves understanding the problem and solution, uncovering more details as you go.
It’s common in use case to use different nouns whilst referring to the same abstraction, so you will find duplicate nouns and part of the process will involve getting rid of duplicates and merging some of the nouns together.
Code Complete 2 gives a clear definition of what an abstraction is
abstraction is the ability to view a complex operation in a simplified form. A class interface provides an abstraction of the implementation that’s hidden behind the interface
A good way to think about classes as an interface, methods are the actions performed. Inside a class you have hidden variables.
Finding classes, designing the methods before you start coding helps give a developer a more holistic top down view of the design. Once a developer starts coding the perspective tends to shift more towards a bottom up approach of the functionality required.
After identifing a list of potential classes a good method to find the relationships between those classes is to do a quick Conceptual object of those classes
This helps to identify the interactions between classes, the goal of this task is to highlight any missing classes.
This will show you the behaviour of the classes and what classes will interact with other. Some of these behaviours will have been found when you looked at the adjectives in the use case.
It’s interesting to think about the responsibilities your classes are going to have, which class is responsible for certain data
Responsibilities can be
- Knowledge/state an object maintains
- Actions/methods an object will perform
- Services/functionality provided by an object
It can be useful to CRC models
CRC models shows the Colloborators and Responsiblities of a class, below is a useful video
Find Common Functionality
Classes are also in common functionality and actions used by other classes.
It can help to create class diagrams to see the classes and the interactions between classes. This can help you find missing classes.
The next stage is create the classes, code and unit tests. Once the code is working you can think about refactoring/tidying the code and thinking about apply SOLID principles
A good way of finding 2 or more classes within one class is to check the class is focused and doing one thing e.g. The Single Responsibility principle.
A quick way to check if a class is doing more than one thing is the name of the class. The class should clearly describe what it is/what it does. Badly named classes often are badly named because they are doing more than one thing.
Actions, manager, Super
Here is a list of class smells which often indicate the class is doing to much and could be split into more separate classes
- Difficult to name the class? This is usually a sign the class is doing more than one thing
- Cohesive. Are all class variables used by most methods, do some methods not use certain variables. A lack of cohesion is usually a sign a class can be broken out.
- To many methods. A high number of methods usually means high complexity, indicating the class is a candidate for refactoring to simplify the code
- Method length (in lines) – a class bigger than 200 or 300 hundred lines is to big
When checking classes you are often checking for cohesion and if the class can be broken into smaller more cohesive classes.
Cohesion when used to describe design can confuse some readers, so here is wiki’s definition of cohesion
In computer programming, cohesion refers to the degree to which the elements of a module belong together. Thus, it is a measure of how strongly related each piece of functionality expressed by the source code of a software module is.
Cohesion is the concept all the variables and methods in the class fitting together under the name and purpose of the class. A class should have a single responsibility, a single purpose. If a class has more than one purpose then it should be split up.
Here is a quick example
A bank customer must be able to make withdrawals from the ATM machine using their card. The card must be validated before the ATM will give money.
ATM machine will check the user has at least the amount of money to be withdrawn in the account.
The bank customer can make a balance enquiry.
- ATM Machine
From the awesome Bertrand Meyer. I found the article above very useful