How to balance a shiny refactor with shipping features

Note: This post is about Swift in particular, but a lot of this applies to general software development.

Functional Programming is fun and all the cool kids are doing it. MVVM has made my code clearer and more testable. Several libraries I’ve written make my code more flexible, while others allow me to skip to the fun stuff.

There’s a lot of really neat stuff happening in Swift these days. I’ve been super excited about the great content coming out of PointFree, and cool new libraries are coming out weekly at least. Swift gives us so many powerful features and shiny new toys to play with, it’s easy to get carried away.

However, while it’s very tempting to, as soon as you discover a cool new way to do things, refactor all your codebases to make use of [shiny new architecture/library/paradigm], it often adds unnecessary dev cycles to your work (I find it similar to the “let’s start from scratch” phenomenon). We all want to build something beautiful – but the truth is, what we had was probably already pretty good… which is why I try to remain pragmatic about my codebases. Here are some rule I use to keep shipping while still loving my older codebases.

Ask yourself: will this improve the codebase (in a non-aesthetic way)?

Sure, the new thing is pretty. But will it make something you plan to do easier? Or do you just want to do it because it’s pleasing? Does it enable you to do more in the future? Or just reduce line count on what you’ve already written?

This is the heart of pragmatism here: unless it helps future-you, it’s probably not worth giving present-you more work rewriting stuff that past-you already completed. Moreover, you need to consider how much work doing a refactor will take, and compare that to how much work it’ll save you in the future compared to sticking with what you’ve got. If it doesn’t balance out, it may not be worth the investment on this codebase, which is why I try to:

Always have new projects

This one I always keep in my back pocket, and keeps me from overhauling a project that doesn’t need it just because I want to play with something new and fascinating. New projects are a great chance to try out new things; they allow you to play, but productively.

Whenever I want to start a new project (which is h*ckin often) I try one of the new toy libraries out there.

But what if you need to do it in an existing project?

Stick to SOLID

SOLID is a classic for a reason. When incorporating something into a pre-existing project, try to limit the interface between them. That makes it easy to tear out and replace it with the next new thing you want to try out.

That said…

Prefer protocols to classes; prefer functions to protocols. The first part of the statement should seem pretty familiar to Swift devs who are already sticking to SOLID. The second might be a little less familiar, but I’ve written a short article with an example of why preferring functions makes your code simpler, more modular, and easier to understand.

Love the lazy refactor

Wanna use something new and neat in your codebase but don’t want to spend a lot of time rewriting the old way of doing it? Use the Lazy Refactor! It’s simple: if you, in the course of doing something you’d do anyway, stumble across the old way of doing things, then refactor just that one place.

There is danger here: if you never complete a lazy refactor, your codebase can get littered with obsolete code and bloated with barely used libraries.

So what do you think? What strategies do you use to stay on top of changes in the Swift ecosystem without giving yourself way more work than you need to?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s