Suppose you are asked to build a web application with Persons, Organizations, Projects, Tasks, Subtasks, Budgets, Travel Requirements, etc. Each slice of the system has these requirements:
- Database persistence
- Business logic
There are two approaches to building the system:
- Slice horizontally: do all the HTML, then do all the Navigation, then do all the Database persistence, etc.
- Slice vertically: make a system that manages Persons, then Organizations, Projects, etc.
I believe it's better to slice a system vertically. -- SteveHowell
No, it is not, is it?
Sure it is - it allows for incremental releases. -- TomRossen
Vertical slicing should work very well if your goal is to have six independent systems... one system that manages persons, another system that manages organizations, yet another than manages projects, etc. But if your goal is a coherent system with some interdependence and FeatureInteraction, then the equation becomes a lot muddier. Consider creating transactions involving persons, projects, budgeting, and travel on one HTML page, then validating and persisting the event, plus developing the HTML to even initiate such a transaction.
It helps to start with appropriate SystemsSoftware
and programming languages because there are invariably some CrossCuttingConcern
s that are domain independent. For example, supporting concurrent operations so that more than one person can work on the above application at one time hasn't been explicitly stated as a requirement above, but it is likely to be desired. So is support for easy mirroring and backups of the data (ideally without shutting down operations), and perhaps the ability to access the data from outside the application you are building (which means not locking it up in an opaque persistence format).
In a layered system as above, people often start running into problems when attempting to figure out such things as where
to put the validation
and the business logic
. It would be nice, after all, for users to receive immediate feedback when preparing a transaction that indicates such things as: missing or invalid fields (which may vary based on other fields of the transaction), predicted results of the transaction, real-time indicators of conflict due to concurrent usage, etc. These sorts of concerns will cut cross the vertical layers (HTML, Navigation, Validation, Persistence, Business Logic) and can make OnceAndOnlyOnce
difficult to achieve. It isn't uncommon to see validation and business logic written two or three times... once for dynamic HTML, once in the persistence rules for cascading deletes and consistency checks, once in a transaction validation program server-side, etc.
for validation and predictions, along with the server and server-side validation. But, at the moment, such SystemsSoftware
is beyond StateOfTheArt
"... such SystemsSoftware is beyond StateOfTheArt.
Yes and no. Software with (at least) that intent has been around since the 80s, and probably before, in the form of business-oriented 4GLs such as Cognos Powerhouse, Dataflex, Uniface, and many others. These are very successful when the requirements fall into a well-defined, relatively straightforward, and fairly unchallenging set of user interactions, business rules, CRUD screens and reports. They tend to fall down dramatically when the requirements deviate from these -- sometimes more effort is required to develop a complete application than if a common 3GL (e.g., C#, Java, or whatever) had been chosen from the outset.
You don't really know what your requirements are for all these layers up front. If you had perfect requirements capturing, it wouldn't matter what order you wrote things in. But you don't have perfect requirements capturing, so it does matter. It's best to get a straight-through working system sooner rather than later, and then fill it out. This introduces understanding of the implications of end-to-end functionality as early as possible, maximising the information you have.
'Do both. Slice along as many axes as possible.' --RichardHenderson
What is the benefit of slicing along many axes? It seems that the benefit of vertical slicing is that you get a working (though incomplete) system as quickly as possible. The benefit of slicing horizontally is that you get a complete implementation of a layer as quickly as possible (which seems to be a dubious benefit to me, but I'm sure some would like it). If you slice both ways, and along other axes, what does that mean?
Don't forget, it all depends on your spatial orientation. I've argued for a long time that it is important to build systems in HorizontalStripes
, by which I have always meant incremental releases of small bits of end-to-end functionality. Is there any absolute argument for which 90 degree tilt is more easily understood? -- BillBarnett
Vertical vs. horizontal orientation is arbitrary, but typically the "layers" or "tiers" of an architecture are drawn as a vertical stack, so a complete path through all the layers is vertical. Note that this not only a computer-science convention--a "vertically-integrated" industrial organization is one where all the stages in the production, shipping, and sales of a single product line are integrated, whereas "horizontally-integrated" means that different product lines are functionally integrated.
Do one vertical "slice", get it working, then refactor it into horizontal layers that can be applied and reused for the remaining vertical slices? -- MikeSmith
Ah yes, I call that the diamond and the lightning bolt. -JH
One question: In a small team, everybody probably has to work on everything, so this matters a bit less. In a large team, specialization is likely to occur--you'll have database guys, HTML guys, Java programmers for the business logic, perhaps even a separate QA organization to do system testing (this doesn't eliminate UnitTest
s, so please no gripes there). In such an organization, a horizontal segmentation makes more sense, at least when it comes to work partitioning. (Of course, you could get the best of both worlds if it can be arranged such that all team members work on the same feature at once...)
Rather than vertical/horizontal (which is ambiguous), I prefer 'end-to-end'. You need at least one end-to-end use case - from GUI to database - otherwise you can't really
be confident that the infrastructure will work at all. After that, build it any way you like and have the test cases act as stubs standing in place of the unbuilt bits.
Often a system is not useful until multiple things are interconnected. If you want an incremental approach, then rank the features by need (and perhaps cost) and work the list from top to bottom. Ideally one could use a RAD approach to get basic CrudScreen
features for editing and searching of each entity and then fine-tune it over time. However, few RAD tools offer both speed and easy fine-tuning.
Any "slicing" is going to be somewhat arbitrary and no slicing dimension is clearly superior
over the others. We each have our favorite slicing, but I won't claim my favorite is objectively better. Further, the ideal slicing depends on the issue we are involved with. Ideally the grouping aspect we see or use is query-able so that we can see it any way we please for a particular issue or assignment. See SeparationAndGroupingAreArchaicConcepts
. But existing file-oriented code systems generally force us to pick one aspect over another. --top
Depends what methodology your working with. If you're working in an environment which puts a high reliance on fixing scope and working to more detailed functional specs then you will be successful with whatever method you choose; except for the fact you'll have a high price to pay in the analysis and design lead time. Modern software development environments are not like this and with vertical slicing you get a number of advantages that suit the Agile environment:
1. The meaning of requirements will not suffer Chinese whispers as they move between different teams dealing with different horizontal slices
2. You can easilly and incrementally build up acceptance tests that are meaningful to users
3. You build up a teams understanding of how a process will work beggining to end
4. You can deliver incrementally (as long as you have enough vertical slices to be useful to someone)
Important to note. Alot of the examples used here illustrate the points by demonstrating slicing through the different tiers of one application (HTML, validation, Database etc). This does not demonstrate the biggest gains. The real big gains come when your trying to integrate / interface completely different applications, e.g. getting a Sales system to talk to a Finance system. If you can get the resources that have knowledge of both those systems co-located and working in the same team you are way more likely to get the job done quickly. -Dan G
Most "hard" groupings of tools and code are merely UsefulLie
s. Most non-trivial systems have a lot of cross-cutting concerns such that hard-isolating each concern into a nice package with a small interface is probably unrealistic. But as humans we need some
kind of grouping in order to identify, find, communicate, and organize the whole thing. Finding the best way to partition is often a matter of weighing complex and myriad trade-offs, including existing tools and staff skills. No one decision will optimize every need or access pattern. This is just life (LifeIsaBigMessyGraph
). In the future, I hope some kind of multi-dimensional (multi-factor) meta-base of parts can be created to manage and find stuff, and present ad-hoc groupings to us such that we don't have to accept a hard-wired choice up-front (SeparationAndGroupingAreArchaicConcepts
See also: WebScriptFileStructure