We need to move people from time to time between products. It can be tough when you move from SSIS/ Sql/ SAP stuff to job-based Excel automation. How can we make a hard task easy?
The very first things that developer see are the assemblies and the folder structures. Let me first put some bad examples for assembly structure and then discuss folder structures:
Why is that bad?
Let’s do the same thing for assemblies and for the folder structure. Let’s say you step into the code and this is first time you open this solution. Let’s assume you have to implement a new feature. This feature includes various changes. You need to add a field in the persistence that should be reflected by the UI. So mainly you need to go the complete distance from bottom up. What are your questions?
- How are the assemblies structured, meaning: Where do I find what?
- What is the main architecture? Read this as: What do I have to accomplish to keep available strategies?
- How do I make sure that I understood everything/ that I don’t miss any pieces?
There are several confusing parts above, but naming is hard. Let’s start with my questions for the assemblies above:
- First thing that come to my mind is: Why is there a „controls“ and a „UI“ assembly?
- What is a „maintainer“?
- There is an assembly just for tools?
- What does the „Libraries“ assembly contain?
- An assembly for languages?
- And for icons? Plus another one for images?
- There is one assembly for data and one for models.
- There is an assembly called persistence.
- The first assembly is called like the project. What is the content?
You may have to be good in ignoring the pieces you are not interested in as a developer. I do like to get the big picture instead. I don’t need to understand every single line of code, but I need to have the overall understanding. I really hate recognizing I had to change my overall architecture or implementation right in the middle of doing so.
What does that structure means?
I have pretty much no idea where to start.
I need to click through all assemblies and have a look what is in there to understand where to start. That costs time and wasting time sucks. Let’s have a look.
Just opened some of them. Now I feel like…
What does that tell me? To make it short, I don’t know.
Not understanding the file structure is as bad as not understanding the assembly structure.
Let’s have another (more constructive) sample:
Why is that bad, does look clean, doesn’t it? Because it doesn’t add any value. Let’s ask some questions to understand why it doesn’t:
- How is the code structured?
- What is the main architecture?
- How do I find a certain (feature) implementation?
- How do I know if I do see all the pieces of a certain feature?
- How do I get the big picture?
- Under which coding principles is this program implemented?
Our coding principles are based on SOLID/ clean code. This does mean we use dependency injection, and create a lot of small classes that have to interact with each other. This puts some more pressure on the necessity to structure them.
Let’s have a look onto a more constructive and sensible assembly structure:
What are the differences?
The overall information just by cutting the assemblies in a sensible way does add value. This certainly is also true for folder structure. Let’s getting closer.
- Contracts: You can expect every piece of information that is used to communicate or to persist to be available there.
- Core: You can expect common functionalities there. You could also name it „Common“, but this is maybe a container for everything. That’s a more philoshopical question how to name it but something like this should be in place. Every project has an area were functionality has to be shared.
- Caching: You can expect some kind of persistence
- Database.Polling: This clearly stated that it will get information from a database periodically.
- Invalidator: This doesn’t tell anything.
- Loader.Controller, Loader.Worker, Loader.Worker.ConsoleApp: Looks like these three assemblies are a group and belong together. Expecting the names to be sensible, the controller will take action and the workers will execute the actions
- Reader: This can read, but what?
- RequestSimulator: Something that can simulate requests, ok.
To summarize in the first run: There will always be questions when you don’t have any idea what this product/ project does. So before you start watching the code, normally you’ve got a picture what it is and what it is good for. In terms of this project, it is a cloud solution being that maintains a Redis cache in the cloud. There components available for keeping the cache consistent and a component that enables people from the outside to read out the cache. Having this information in place, I guess you got a picture.
Name your assemblies as straight as possible. Have a big picture in place – a simple architecture diagram may does it. Even if you cannot answer all questions, there is no need to raise questions unexpectedly.
Now getting to the folder structures:
The folder structures are moreless identical.
- Services: contains all functionalities offered in this assembly
- Extensions: contains all extensions for that assembly. You can expect all extensions to be in place like this. Meaning you can assume where all other extensions are when you referenced any other lib.
- Interfaces – contains programmatical contracts
- Messages – contains communication contracts
- Models – contain all data model information. You could also name this ponos, data, whatever is appropriate. But it should be identical.
Use the same names for the same entities in all your products/ projects/ assemblies. Stepping from one to another will be pretty easy in terms of first orientation
It is a pleasure going from one product/ project to the other and being able to navigate through the code exactly knowing where to expect what. You are way faster.
We need to be conservative, maybe even bourgeois as a developer. Because we need to be fast.