Any fool can write code that a computer can understand. Good programmers write code that humans can understand. Martin Fowler
Complex code is hard to understand code because classes and methods do so many different things it’s impossible to understand how it works without stepping through the code to understand exactly what is going on. – Hosk
When writing code you need to keep in mind – Will I be able to understand this code 6 months later when I have forgotten the business logic – Hosk
This started out as a small blog post, which seems to have kept growing and growing, so be prepared for a long read. I have a few CRM developer articles which you can find in the section Hosk’s CRM Developer Articles. It has an article on code readability and why experience is important in CRM development which I recommend you to read.
Before reading the article below I would like you to remember coding is an art, which is one of the reasons it takes a time to learn. Seeing coding as an art helps to explain why there is no right or wrong way to write code and good code/bad code is open to interpretation. So the thoughts below are my thoughts on coding and the processes and standards I use, yours might be different but I would love to hear them so please leave a comment.
Most developers have been in the situation where you get assigned to a new project and one your first tasks is to resolve a bug. project.
The first step usually when bug fixing is recreating the bug, so I will assume you have done that so now it’s time to look at the code to try to fix the bug.
- scan the code
- getting a rough idea of the structure of the code
- work out the flow
- understand the data sources
- Work out what parts of the code are changing the data.
The code is so complex and confusing the most efficient way to understand it is to debug the code, stepping through it line by line, hoping to get some understanding what’s happening and trying to find the elusive cause of the bug.
The code is one big pile of spaghetti code which you are afraid to change, if you are good (and have time) you will do some code refactoring but most likely you will cautiously poke a change towards the code with a long stick, cross fingers it fixes it before slowly backing away hoping to never see the code again.
Why complex code created
Junior developers create complex code for simple problemsSenior developers create simple code for complex problemsA rushed developer creates code to refactor later
Common reasons for complex code
- Written by a junior developer who is learning
- Quick bug fixes
- Time constraints
- Refactor Later
- No Peer Reviews
When developers rush they create code and more code but they do not create better quality code. Rushed code creates what is called technical debt, which will give you problems later (e.g. when you have to debug or enhance the code). A note for project managers, pushing developers to extremely tight schedules creates more code
Quick Bug Fixes
When developers add quick bug fixes or bug fixes in general it’s easy to wedge in some code and increase the complexity by veering away from creating simple code.
Developers know they should write better code/simpler code but they write some code which works and fixes the bug/provides the functionality needed and they promise to “Refactor later”. You already know how this story ends, the developer is too busy, something urgent pops up and the code is never refactored.
No Peer Reviews
The most effective way to reduce the amount of complex code or bad code is to have a senior developer check the code with a peer review (could also be known as a code review). The developer won’t let their standards drop and will produce better code when they know it is going to be inspected by another developer.
Peer reviews will also find some bugs in the code and are a great way to guide junior developers into converting complex code into simple code with pointers from the senior developer.
The smells of complex code
- Large methods – Monster methods
- confusingly named classes, methods and variables
- methods which do lots of things
- not consistent
- tight coupling
- dependent code
- poorly structured code
Large Monster methods
I’m sure all developers have come across a project where there is one monster method that runs for lines and lines and lines. They are often full of bug fixes and usually one developers knows the method (the poor soul has had to debug it many times) and often all the bugs flow their way.
People are scared of the monster methods and rightly so because no one can understand it and no one wants to change it.
Plugins are a common breeding ground for monster methods. I have seen numerous plugins where all the code is directly inside one big method in a plugin.
Developers should not be afraid of changing code
Badly named classes, methods and variables
Methods doing more than one thing
Complex code/poor code will be inconsistent, this can usually occur when a developer has copied the code from various different sources or you have a number of developers working on a project where there is no standards being applied.
The difficulty inconsistently structured code brings is it makes the code hard to understand because there is no common structure, the code has a different flow.
Code and customizations are difficult to understand and not being consistent makes the job even harder.
Tightly coupled/dependant code
Tightly coupled code is code which can’t be reused because it is dependent on other code in the project. The cause is often because the methods are doing more than one thing and are really a number of methods (if they were refactored) squashed into one.
Dependant code often can’t be reused even within the same project.
Poorly structured code
Code should be structured and organised in a logical manner. A simple form of structuring is splitting the business logic and queries into separate methods.
Code structuring makes the code easier to understand and splits into smaller logical areas, this will help in code reuse and bug fixing (because you are isolating the bug)
CRM Customization smells
The CRM GUI for workflows can make it difficult to work with workflows but when you have a giant workflow it can be almost impossible. There is a limit of four nested if statements in CRM (it’s true for CRM 2011, I’m dangerously assuming it’s still the case in CRM2013/CRM2015 but I could be wrong) and when you have a workflow which is hitting this limit, it’s a sign the workflow is too complex
Read more about four nested if statement limitation
Big workflows are very difficult to maintain and making changes can be very challenging, if you have workflows which are very big you should consider breaking these down into child workflows.
Lots of different customizations overlapping
CRM customizations allow you to provide functionality in lots of different ways.
- Custom Plugins
- Business rules
- WCF webservices
- Console apps
Some customizations are better suited to certain problems and best practices/experience will guide you as to which customization you should use.
You can get similar problems when workflows and plugins are used in conjunction with workflows running after the plugin (because plugin is synchronous and workflow is asynchronous) and the workflow overwrites the plugin set value.
I’m not saying using plugins and workflow is wrong and should never be used but care should be taken when they overlap it can create a solution which is difficult to understand and debugging can be puzzling.
When deciding what customizations to use, some consideration of what customizations already exist should be taken into account. The simpler the solution the easier it will be to maintain and extend the solution later. When I mention solutions I am referring to all the customizations as a whole.
What happens later if a bug is found in one of these duplicated methods, usually it gets fixed on one form. Then you have duplicated code, some of which is fixed and some which isn’t.
All the code in the plugin
My personal view is you should have no code in a plugin, it should all be moved out to separate classes.
The first reason is you have created a big monster method, which is hard to understand, debug and enhance.
Testing code in a plugin is difficult because you need to mock all the plugin code, if you remove the code from the plugin, you can test the code by just passing in a OrganisationService (e.g. a connection to CRM).
You cannot reuse any code inside a plugin
Complex code means people cannot reuse the code, so they often end up copying parts of tightly coupled code from one area in CRM to another. This can often lead to messy/poor code but can also allow bugs to slip in with code which isn’t relevant or needed.
The problems with complex code and customizations
The code is hard to read
When writing code you need to keep in mind -Will I be able to understand this code 6 months later when I have forgotten the business logic.
Complex code is hard to understand often because it’s not structured and modularized. Understanding code which is logically structured into separate classes and small focused methods is easy because the code does what you expect.
Complex code has large methods which do many things, the classes and method names are confusing because it’s difficult to apply a name to a class/method which does many different actions.
Well structured code is like a tidy room, with everything tidied away into draws, bookshelves and wardrobes. Easy to understand and use. Things are easy to find. If you add a new item to the tidy room, you can place it with the other similar items
Complex code is like a messy student room, everything is on the floor. It’s hard to understand the where everything is or should be. Objects are to find because you are not sure where to look. If you add a new object to the messy room, where do you put it and will mess up the organisation of the room.
Slightly improved code is where the messy student buys a big wardrobe and a chest of drawers and chucks groups of things. You know you need to look in the chest of drawers but if the socks are not in their own drawer it’s going to take you time to find them among the other clothes.
The code is hard to debug
Complex code is hard to debug because it’s because it isn’t structured logically (because it’s in big methods) and the code isn’t easy to understand. Often the only way to understand what the code is doing is slowly stepping through it.
The code is hard to enhance
Complex code creates complex bugs
Complex code is tightly coupled and big methods are very difficult to reuse. It means developers have to write more code, which means more testing.
More code will increase the chance of more bugs.
A lack of reuse in code will result in developers copying parts of code which can result in copy and paste bugs.
Duplicate code will result in bugs where some of the duplicated code is bug fixed and other parts get forgotten about.
Encourages more of the same
Junior developers and developers in general will copy working code. The good developers will refactor the code, the poor developer will just leave it as it is.
Copying complex code will create more complex code.
If developers see other people creating complex/bad code then they will too. It’s letting standards drop and everyone will pay for it later down the line when bug fixing takes twice as long
Junior developers will copy it
Developers should set high standards and great code for Junior developers to learn from.
If everyone is creating simple well-structured code, the junior developers will follow their lead.
Creating complex code/quick code really causes problems for a project later. Finding and fixing bugs takes a lot longer because the code is harder to understand and fixing the bug is difficult because the code is in large methods and not well structured.
The difficulty in fixing large methods is they do many things and you have to make sure the method still does all those actions and changes.
If you compare this to fixing a small focused method, you only need to make sure it still does the one action.
Complex code creates problems for the project later on where it will become harder to maintain the code whilst fixing bugs and enhancing. Complex code will mean people take longer to get up to speed on a project, whilst they learn how this individual project is setup and works.
I’m sure lots of developers have worked on legacy projects with complex code and it’s not an enjoyable experience, so make sure you are not creating projects like that.