Think about delete
TL;DR
Thinking about deleting objects and records can often lead to good modelling insights. However, most patterns, guides, prototypes etc focus on creating, updating and persisting items, and gloss over the issues presented by thinking about delete.
I recommend putting “delete” into the early use cases and/or repository-style interfaces, as it forces you to address assumptions about the lifetime of objects and what it means for their relationships.
How I came upon this
Most prototyping is about getting something to demonstrate. Most guides and tutorials focus on how / when do I create an object, persist it, update it etc, while delete is usually passed off as something that is easy…(just delete the records… and let the ORM/DB-constraints/Garbage-collector delete all of the linked objects).
This simplicity is usually because ‘delete’ is the sort of functionality that is used by an operational system to remove old or erroneous items, and is NOT the sort of thing that you need at first! (Or if you are really lucky, you are not working on a system with persistent records).
However, I often find that delete is a difficult thing to get right, especially if the system needs to have soft-delete of some sort for auditing, history or rollbacks. Additionally, I have often found myself working on new systems, and the major stakeholders are much more interested in adding the next real feature.
Most recently I found this on a project where field devices would sent in periodic reports, and these reports were also used to trigger the ‘discover a new device process’ if they had never been heard from before. In this project, delete was a particularly useful case to consider, especially in the following circumstances:
- if the device has failed, we need to delete the device so it no longer shows up in the UI….it should never contact us again (unless it is not really dead)
- if the device has been deleted, but a stale status message (i.e. from before the delete) arrives we need to ignore the message
- if the device has been deleted (for whatever reason), and a NEW status message arrives then we should consider it newly discovered
Things to consider
This is just a list of things to consider about delete, and why it should be thought about early in the design process:
- Delete often illustrates the ownership boundaries more cleanly than create. I.e. when you delete an object in the middle of some graph, you can reason about “should it be possible?” / “what else should get removed” / “are the other objects that don’t need to be deleted still in a reasonable state”??
- Deleting objects is a good way to uncover inconsistencies and/or errors in modelling, as it often breaks logical assumptions thought to be impossible or protected some other way
- The implementation of a repository often focusses on the creation of objects, and the maintenance of the aggregate boundary. A great way to test it is to put “delete” up-front in the design effort (OR to identify that you do not to allow mutation via the repository at all).
- Thinking about delete early also helps think about DB constraints…. Doing validation in the DB is great when you get it right and super painful when you get it wrong. It is often good to think that the database and the stuff it contains will long outlive your application code. I used to do spend a lot of time worrying about the relationship constraints etc in the DB design. These days I generally keep it to a minimum, and focus on “it is a logical truth, well then it warrants a DB constraint”…if it is “business rule….even if it will NEVER ever change (like ‘people never change their sex, that is impossible’)….I try not to make it a DB constraint…because, you never know….if your code survives to the next decade, who knows what the world will be like.
- Delete is usually thought of as something that is “easy”, but the truth is very different. In most business systems soft-delete is the prevailing technique, usually because audit and/or history are required features. This immediately hints at complex, temporally sensitive behaviour.