Design and architect and write your software solution so that its different pieces can be independent in the following ways:
- Develop Independently
- Build Independently
- Install Independently
- Test Independently
- Refactor/Replaced Independently
Don’t just separate the concerns in one way and call it good. Separate your concerns all the ways listed above.
What will this do for your project?
- It will make it so it can be easily unit tested.
- It will make it so it can be easily built.
- It will make it so it can be easily installed.
- It will make it so it can be easily changed: Patched, Refactored, or Replaced.
Wow, all that sounds great, why doesn’t everyone do this?
Because the one area that is harder is the initial development. You have to design a lot more. You have to code different. It can be hard.
However, it is the easiest way overall, just not the easiest way at the start developing.
How do I separate my code into pieces?
There is a though among many that a software tool should do one thing only, but it should do it really well. When you think of your entire project, that should be kept in mind.
The smallest item in a project is the likely the “object”.
The term object is very abstract. It is like the work “thing” in that it can be anything.
So look at it from a high level view. Imagine your software has four pieces.
Ok, how do these pieces interact? Can you build each piece without having to link to another piece? You should be able to do this.
However, you have to link to something in someway in order to use its code so what do you link to?
Ok, so you double the size of your pieces by having a piece and an interface for it. These could be eight separate dlls.
If Piece1 needs Peice2, it should link to IPiece2 and not to Piece2. This allows for Piece2 to be:
- Any version of Piece2 that implements the interface.
- Refactored without breaking the Piece1 build.
- Replaced by a completely different implementation
- Mocked for testing (really the same as three but used for Unit tests)
Real life example
In real life, applications are database driven. So what if your Piece2 is a database tool and Peice1, Piece3, and Piece4 all need to access the database using Piece2.
If you link directly to Piece2, you have a problem where you must have a real database in order to test your code in Piece1, Piece3, and Piece4.
This is a huge testing burden. This prevents your tests from running as Unit Tests and instead they must be run as Functional Tests.
However, by designing properly using interfaces, you can get back to Unit Tests for Piece1, Piece3, and Piece4 by mocking Piece2.
You use IPiece2 to create a new block called Mock2, which is just a Mock of Piece2, which can be run during a Unit Test. Now all the other blocks are testable.
Lets look at our Independent Architecture rules and see if this design works.
- Yes – It will make it so it can be easily unit tested.
- Yes – It will make it so it can be easily built.
- Yes – It will make it so it can be easily installed.
- Yes – It will make it so it can be easily changed: Patched, Refactored, or Replaced.
If you have a large application, this is one design pattern you should look at.