Let me tell you a story
A company I was hired for as a Senior Developer was in what most would consider a crisis or at a crossroad. In the past, developers had near-zero communication with each other so that the products they were building were created in totally separate ways - with no expert guidance, code review, etc.
They had also spent about two-years allowing a "rockstar" developer re-engineer most of their products. Long story short, he was fired because he didn't want to communicate and share with other developers when the company decided it needed to foster a "team" mentality rather than have one developer drive all development. Come to find out what was re-engineered was actually a million times more complicated and tightly coupled than before!
All this to frame what the situation was when I started. Nobody knew how the system really worked. There were no standards of development. There was no guiding organization or architecture when adding new features (e.g. free-for-all).
Deployments involved some FTP'ing and multi-step process that could take up to 30 minutes - not to mention what happened when things were not "built" in the correct order. And the list continues...
One of the issues I tackled immediately was the idea of "where do I put my code?"
What existed (i.e. what was re-engineered) was just too complicated. Adding parts to an existing feature took days, and sometimes weeks! 99% of that time was just figuring out where to put your code!
I will show you what I did to improve this situation - and brought what would have taken weeks to do down to days/hours.
How the typical app gets structured. And why that can be a problem.
Every company I've worked for that had an existing system in place organized their system/code by infrastructure. For example - most of these systems had a data access layer, a business layer (which was usually just a shell that deferred logic to the data access layer) and an application layer.
The application layer was the web app, which then called into the business layer and then finally into the data access layer. This is probably how most enterprise systems are organized.
Why is this bad? A few reasons:
Parts of the system (features) that need to be different due to the benefits of using other technologies or paradigms are usually dismissed as they don't "match" the governing architecture.
Finding specific features of a system are difficult because they are dispersed into multiple areas of the code.
Therefore, fixing or adding to existing features takes more time.
It causes a disjunction between how developers understand and speak about the product and how everyone else in the company does.
The entire solution or codebase is "glued" together in a fundamental way.
Imagine you are a new developer for such a company. Think of the folder/structure of such an app (you might have one already opened on your other monitor right now). Just by looking at it from a high-level view - can you tell me what this app does?
- What business problems does it solve?
- What problems does your company care about?
- What are the capabilities of the system?
You can't. At least, not easily. The code is organized by infrastructural concerns - not business oriented concerns.
A better way to organize and maintain code
How do we fix this? It's a very simple idea. It's just so different from what the industry has become automatic at doing. Organize your code by the products and features that your company actually makes!
For example, an e-commerce app might have features like (off the top of my head) "search", "browse", "cart", "payment", etc.
Imagine I asked you (a developer who's new to the team and product) to add a new feature: Allow users to pay using Bitcoin.
Could you figure out where you should start?
Yes, that's a rhetorical question. (It should go into "payment" π)
What your app actually does vs. how it does it
The main point of this entire article is that you should focus on what your system can do and not how the system does it. Take for example a typical MVC structure:
Can you tell me what this app can do? What business problems does it solve? Where would you start to try and debug a certain feature?
Now, look at this:
What about now?
As a side note, if you are using an MVC framework (for example), then you can make each of these features into it's own "mini" app:
Now your solution is primarily focused on the business domain you are trying to solve - and it just happens to be an MVC app.
Other Benefits
This leads to other benefits, such as:
Individual features can diverge in their implementation details if the need for different technologies is justified. Since they aren't locked into a structure that already determines the infrastructural organization, specific features can evolve as needed.
The complexity of an individual feature is isolated and doesn't bleed into other "layers" or parts of the code.
Finding code for specific features or parts of a feature is super quick.
It forces developers to think about and focus on the business and product instead of how to shoehorn the goals of the business into a predefined and non-related structure.
The system as a whole is not as "glued" together as the typical paradigm would be.
To highlight the last point, many readers will note that this gives the flexibility of later hoisting these features into what most of us call "Micro-services".
If 70% of the site's traffic and overall load is targeted at the "search" feature (due to all the database queries needed or whatever) - we can "lift" this feature out of the codebase as it's own separate project (or module, package, etc.) and scale it by running multiple instances of this feature at run-time (using containers, let's say).
The remaining features, which are now 30% of the overall load, can potentially just be put on a cheaper server that still performs well enough.
Next steps
I would encourage you to try this strategy on your next project. Let me know how things work out by tweeting @jamesmh_dev!
If you are looking for more details and thoughts around these ideas I would suggest the following resources as starters:
Vertical Slice Architecture
Solid Architecture: Slices Not Layers (Video)
Clean Architecture
P.S. This was originally featured on builtwithdot.net's blog
Navigating Your Software Development Career
An e-mail newsletter where I'll answer subscriber questions and offer advice around topics like:
β What are the general stages of a software developer?
β How do I know which stage I'm at? How do I get to the next stage?
β What is a tech leader and how do I become one?
Sound interesting? Join the community!
Top comments (23)
100% agree with this. I've been using feature folders (and MediatR) to build everything as vertical slices for a few years now and couldn't go back!
I really wish Microsoft and Co would change their new project templates to help developers fall into the pit of success.
Thanks for feedback Jon!
I'm on board with you. I know Angular tries somewhat to do this... Would be nice to have the backend frameworks try? lol
Absolutely agree! Group by feature not layer (or technology)! This is perhaps the biggest and most impactful lesson I've learned in my programming career.
I think one of the reasons more teams don't adopt this is partly because it can be challenging to do without higher level tools that help you visualize your modules and their dependencies. It's a lot easier to throw things together by their file extension than by their conceptual cohesiveness, especially if you have no way to visualize and reason about cohesiveness. I don't think I would be able to do it at scale without Structure101 or similar tool.
I think the biggest problem is that devs are disconnected from the business. Devs are too focused on the technical problems they are solving instead of focusing on the business problems they are solving.
If that was the focus, then organizing your code around the business's products or features just naturally flows out of that.
I think the hard part is that it's such a (poor) standard in the industry to just build all these layers (which are horizontal instead of verticle).
I agree - these types of higher level concepts or "tools" (whatever you want to call it) have been the #1 thing that has made me stand out and get to where I am in my career.
I also don't feel like I'm running around in the dark as much!
These ideas make so much sense but I also feel a bit of sadness because I know my old ways and ideas have to die :)
Do you think new strategies like this are only just now becoming available because of Moore's law?
Hahaha!
If I did have to guess, I think this one, in particular, has to do with the tendency for software developers to get too engrossed in the technologies / technical specifics of what they are doing rather than trying to understand how the business works.
Most devs after-all, I suspect, really have no interest in the business itself, but just want to "build stuff".
That is such a fresh way of thinking about it. I think you've just reshaped my head. What a useful way of thinking about the next codebase I'm looking at.
Awesome! Def. let me know how things go when you get a chance to do this kinda stuff π
This point cannot be understated. when working with horizontal layer, poor design choices affect the entire codebase, and it's difficult to fix (or even understand) the problem. But if a feature slice chooses a poor implementation, well just cut your losses and don't do it again on the next feature. The rest of your app is safely isolated from the design patterns in other features, and you have the freedom to try new things with little risk overall.
Def. agree - having done this on anonymous the team mentioned in the article it's such a breathe of fresh air that new features can introduce new concepts or not use concepts that have been found to be non-beneficial.
So for teams who want to experiment with different ways to structure code etc. it's a fantastic way to do that.
In my case, I'm slowly introducing new concepts like CQRS, Domain Driven Design, etc. to the team - inch-by-inch as new features are built. Works great!
Wow! I've actually implemented a similar structure to a few of my side-projects and definitely it made it easier for me to decide where to new features or find where certain code was. I had no idea it was actually that helpful π Totally agree with this!
This actually feels really similar to the types of design shifts made by React.
First, with JSX, code was split by feature rather than language. (Instead of dividing code into content, styles, and functionality, it's divided by feature -- by component.)
A similar type of shift has been made by the introduction of hooks. Instead of dividing a component's code by lifecycle methods, it is divided by the functionality it supports.
Both changes were controversial at first, but have grown to seem like an obvious best solution over time (more of that yet to come for hooks, I'm sure). Hopefully in the coming years we can learn to better identify and correct backwards (perpendicular?) code separation...
That Coravel Pro piece of kit looks great! We have a similar in-house tool that allows us to do that stuff but in PHP, and it really helps :D
Nice! It's good to get some feedback around that.
Are there any specific abilities of the product you have that you find the most important/helpful?
Most usefull thing is probably the scheduler. Allowing people to simple click 'add scheduled task', and letting them enter command name, options and a schedule.
Also the fact that when scheduled jobs fail, you can see the exact console output of that command when it ran
Cool - ya that's a very helpful utility, instead of relying on manually setting up a cron entry for one schedule etc.- or even code based scheduling which does require a re-deploy for compiled languages.
at work we have different directories for "app/modules/" (e.g.: shop/cart, bill/, ...) and something that we call "framework/modules/*" (e.g.: system/authentication, ...)
I highly recommend this kind of slicing! Thats what i always do before i get into code, figuring out what my app will do rather than how it is done. Everything else are details. Very good advice! ππ
Some comments may only be visible to logged-in visitors. Sign in to view all comments.