You are gonna need it, but not immediately
So the point of vertical slicing is to take something like the database and say precisely, “I do not need the whole database right now.” So let’s validate your claim: do you need the database?
Let us be clear about what a database does: it distributes changes of state across several servers, and persists those changes when the server restarts. If you want plain persistence but no distribution, you can write to a local JSON file or so. If you want distribution but no persistence, you can have nodes broadcast messages to each other e.g. with ZeroMQ.
I don’t see anything in your first user story about any number of parallel servers, and I’m not sure I see anything in your first user story about any persistence; you might be able to tolerate the default in-memory behavior of “when we roll out a new version of the software everyone gets logged out and any changes they have made get reset.”
So you don’t need a database. You might need (if you have a list mapping some smartcard tokens to some sort of internal username) some static JSON file (not clear on whether it should be committed to repo or just a config file distributed over email/Slack and copied in as the last part of initialization; if you do not mind the data being saved to the repo then it can even be saved into one of your source files, no JSON parsing/file reading needed).
Similarly, do you need a big Javascript SPA? I don’t think so—you might need a card reader or an HTML form depending on whether it’s a hardware token displaying some digits or something more interesting.
Do you need a permissions structure? No, the only permission your user story covers is “is able to log in with a username and a smartcard associated with that username” and that is a global permission.
When you slice vertically you reduce each layer to only the subset of functionality which it needs to make the user story work. You are not trying to deliver one twentieth of the database and one twentieth of the permissions structure simply because you have twenty user stories and you are trying to deliver one of them. You may often find that in the early phases several of the layers are empty.
Use delayed functionality to get better business requirements
In fact you should desire this. I would strongly recommend that you delay creating the database as long as possible, which means, until you have real users who will get grumpy both about downtime and about their changes not being persisted over server restarts. There is a really important reason for this: top-down design is typically nearsighted. You want to be able before you eliminate your freedom to mess with data structures to get a real user to mess around with the business logic of your tool and tell you something like this:
“Oh no! You are assuming every Purchase Order has a Contract but that’s not correct, we actually have Prototypes which are experiments to try and get a Contract... We register purchase orders against them to build them, but they are not part of any Contract.”
“Yeah that wasn't part of our original spec. Do you have a common term that encompasses both Prototypes and Contracts so that I can show you a list of _____ and then a column that says "type=Prototype" vs "type=Contract"? What would that list be called?”
“Oh yeah, we just call them all projects.”
And then you rewrite your internal data structure so that purchase orders belong to a project, which might have type=Prototype
or type=Contract
, unless you get enough differences between them that you need a Prototype table and a Contract table that are foreign-keyed-to by the Project.
The point is that if you don’t delay the creation of the database until you get this feedback, then under pressure you will start to get a very warty database:
“Uh, why are these Contracts having all of these null values? Did we just forget to make them NOT NULL
?”
“Maybe. Do they have a number for their prototype_id
?”
“Yeah...”
“Well see what the database calls a contract is actually what the UI calls a project, because when we started we thought that all projects were contracts, but they are not, some are prototypes. So either all of the contract columns need to be null and the prototype_id
needs to be not-null or else the prototype_id
needs to be not-null and the contract columns need to be null.”
People think best when they can interact with a system. Especially people who are giving you requirements. The point of Agile is that traditional software design is sort of like asking a committee who knows nothing about clothing to write a specification about what sort of clothes they want to wear and then we will produce those clothes exactly to that specification and then if they are unhappy with how they fit they are free to not wear them or to produce follow-up documents anticipating how they change. An Agile shop is trying to instead produce a set of successive tailored approximations that at all times fit the client exactly but do not look right. So they start with “ok, we will throw a sheet over your head” and receive the feedback “OK but I cannot see through the sheet and also it is the wrong color for what I am going for.” New sheet in a better color with a hole in it. “No, it needs sleeves and a hood.” And so forth.
You can deliberately delay getting important bits of functionality right, because you might be misunderstanding something like the “color” that requires a considerable amount of rework from scratch. This happens all the time with database structures.