WET models: deploy faster without premature abstraction
3 minutes

In actuarial model development, repeating yourself might be the smartest move. Here’s why delaying abstraction leads to faster, more flexible models.
Building actuarial models in a modern software ecosystem can be disorienting, especially for actuaries transitioning from spreadsheets and rigid legacy systems. As actuaries, we’ve skirted along the edges of software engineering for decades and yet many of the best practices from our adjacent industry are still alien to a lot of us. One principle that deserves a closer look is that of generalisation and abstraction. The classic WET (write everything twice) vs DRY (don’t repeat yourself) debate.
In general, never writing the same thing more than once (as per DRY principles) is a bit of an extreme. In the same way that literally writing everything twice (WET) is the other end of the spectrum. This post explores how code shared between actuarial models need not be generalised at the outset. Allowing for some duplication early on isn't a mistake in actuarial modelling, in fact, it is often the right approach. Done well, it prevents over-abstraction and avoids planning paralysis. What’s more, it could be argued that this approach aligns with professional model development standards that actuaries are already familiar with.
An alternative approach
There’s a common urge to "solve insurance" by building the most generalised model structure imaginable. You hear it in phrases like "let's build it properly this time" or "what if we want to add X later?" Images of a crazed inventor envisioning his masterpiece come to mind. The intention is good, but the path to get there is long, expensive and risky, and we can end up doing more damage if we bite off more than we can chew.
Software engineers have a name for this: premature abstraction. It’s when you generalise before understanding what really needs to be reused. Things like this are akin to “boiling the ocean”. An alternative approach is to ignore those urges and commit to generalising later. Especially for actuarial models, it’s far better to allow differences between models and allow for some duplicate code, in the beginning. Then, only when the models are built and released should we look for abstractions.
This is not the same as abstracting within the model. There are plenty of cases where generalised functions and classes can be used to good effect within the same codebase, but again here we should build first and generalise later.
Repeating yourself isn’t wasteful (mostly)
There are benefits to creating model components more than once:
It allows your team to deeply learn the nitty gritty of the calculations themselves. No one can truly say they’ve got their head around something until they’ve got hands on with it. It’s the same with calculations and code, if you’ve implemented it, you’ve fully understood it and can then have meaningful conversations with others about generalising and exchanging ideas.
It supports independent validation. Two implementations of the same logic are more likely to expose methodology flaws. Model validation is familiar ground for most actuaries, with challenger models and re-implementations lending credibility to reporting outputs.
It avoids the trap of building a "perfect" model that still wouldn’t reflect all of the real-world use cases. By getting something out sooner that can be used in anger, you’re solving a problem that matters to the business. That perfect model may never get released.
In education spheres, there’s an adage around saying everything 3 times. Say what you’re going to say > say the thing > then say what you’ve just said. We don’t need 3 analysts to build the same model, but components of each model can be allowed to be duplicated, especially if it allows for the benefits above as well as faster delivery.
Inconsistencies in models
Something else to bear in mind is how not all models are the same, even when you think they should have the exact same methodology, you’d be surprised how many subtle differences in the pricing and underwriting process there are. I have seen developers find this out too late and then have to invest time in rebuilding or adapting a generalised solution, all because ABC use case wasn’t known. Now you have to write more code, making it harder to maintain and more unreadable, just to get out of previously over-engineered logic. Not only does this mean more time to deliver, but we have to throw away large parts of our abstracted solution.
The Moving Target of "Done"
One of the most difficult aspects of model building is that "done" is rarely static. Whether you're new to actuarial development or an experienced model developer, you'll have been in a meeting where someone requests something new halfway through a build: "it'd be good to have the experience rater here", and suddenly the requirements have shifted.
This is where a flexible model helps. If you’ve abstracted too soon, adding that new feature risks breaking your model or invalidating your test cases. If you've kept things simple and explicit and don’t need to worry about unpicking over-generalised functions, it’s much easier to change one thing as opposed to re-thinking the whole cross-model solution.
Similarities With the Actuarial Control Cycle
Actuaries are already familiar with concepts like ongoing monitoring, feedback loops, and model maintenance; after all it forms a core part of the Actuarial Control Cycle. Quite appropriately, these ideas map neatly to Agile principles in software design:
Build small, ship early
Validate continuously
Adapt based on feedback
Agile is about making small bets and changing course when needed. It’s the antidote to Waterfall-style planning that assumes we know everything at the start. I’ve seen first hand when people realise requirements halfway through a build. If we generalise too early, we get have to swim back up the waterfall as there’s no room for maneuverer and ongoing maintenance and monitoring becomes a lot harder.
What should I do?
Perfectionism is tempting, but it’s often misguided.
The goal isn’t the most elegant model, it’s the most reliable one that’s been delivered on time. It’s a model that’s understandable by peers, and adaptable to change.
WET thinking may feel clunky, but the ideas behind it are often the fastest path to something solid. As the actuarial profession evolves alongside modern software practices, adopting a "generalise later" mindset might be the most impactful shift we can make.
You can’t eliminate change, and you probably can't eliminate scope creep. But you can delay abstraction. Build for what you need now. Generalise later.
Do you agree or have you taken a different approach? Join the hyperexponential Developer Community to share your perspective, learn from others, and help shape the future of actuarial model development.