Refactoring remains a much-misunderstood discipline. Even when folks do have unit tests to back their changes, how long does the code stay broken? Let’s return to the idea that refactoring happens in very small steps.
No, even smaller than that.
When you refactor, do you have unit tests covering you? …If not, why not? …If so, how do you know?
To me, it seems that the state of refactoring has gotten worse across the industry. Both managers and programmers and managers say the word “refactoring” more than ever. But they almost always mean, “I’m going to change a bunch of stuff. Then at the end, we need to make sure I didn’t break anything.”
But that’s not refactoring. That’s rewriting.
Does your code have comments? Sometimes they’re helpful. But most of the time…
Disclosure: The book links below are affiliate links. If you buy anything, I earn a commission, at no extra cost to you.
As Jeff Atwood explains, code tells you how, comments tell you why. A well-placed code comment is a level above the code itself, explaining why something is written the way it is. But! We can express most comments as code, using well-named identifiers. The Refactoring book calls this Introduce Explaining Variable. Martin Fowler has since renamed that refactoring to Extract Variable to help folks find it in their IDEs.
It’s time for a quick exercise in code smells!
How many code smells do you see below?
The “Single Responsibility Principle” (SRP) sounds so noble. But I’m afraid it’s misunderstood and misapplied. Ask your teammates: “What is the Single Responsibility Principle?” Go ahead, ask them. Then ask if the SRP is a good thing or a bad thing. I’d bet many of them will say something like this: “In principle, it’s a good idea. But in practice, it’s overkill.”
On Twitter, Chris Eidhof pointed to an example of taking the Single Responsibility Principle too far. Specifically, Chris was unhappy with the argument that Singletons violate the SRP because, besides their main responsibility, they also manage their own life cycle:
This argument against singletons made me cringe (specifically, the SRP point): https://t.co/C9wVVnqHFs
— Chris Eidhof (@chriseidhof) June 29, 2017
This led to a lively discussion. Many reacted against “over-architecture.” No doubt they experienced fragmented code that grew from over-zealous attempts at SRP.
I think that SRP isn’t just over-applied. It’s fundamentally misunderstood, even misquoted. The repeated misquotes perpetuate that misunderstanding.
Let’s see if we can clear things up, and point to a better way.
Refactoring. It’s a word I hear quite a bit. Usually, in the context of conversations with management, it means, “Rewriting that thing. Hopefully without introducing bugs.” Often, among developers, it means, “One of the options in the Refactoring menu in my IDE.”
Code that’s easier to understand, maintain, and extend — that’s the promise of Object-Oriented Programming. But the reality for many iOS developers is that our objects are bloated. They know too much, and do too much. …What if our code has hidden objects, waiting to be found?
Each hidden object could provide a new abstraction, a new tool. They could make the code more manageable. Is there a way to discover these hidden objects? Domain-Driven Design (DDD) provides a way.
How can we unit test JSON parsing, handling every possible error? Can we generate immutable models? And for Swift, how can we keep our Response Models free of optionals?
Of course, there are many JSON parsing libraries out there. Plug one in, define all fields as non-optional, and you’re good to go! …Until your app crashes, because something was different in the actual JSON data.
Unlikely? “The backend team would never do that to us”? I’ve had a released app crash because the backend folks changed one field from a string to an integer. I’ve seen app development and QA forced to pause because a commit assumed all fields were non-optional. (It crashed on the missing field, because Swift.)
So let’s look at a pattern that will help us
Even if you never plan to do your own parsing, we’ll learn things along the way about design and testing.
When you’re new to Test-Driven Development, there’s a strong tendency to continue writing code the way you used to. Then you step back and ask, “But how can you unit test this? TDD is so impractical!”
Almost always, my answer is: “Then don’t write it like that.”
Apple recently published a blog post, Working with JSON in Swift. I was looking for tips on Swift JSON parsing, and found the beginning of the article quite helpful. But it took a bad turn at the end…
You face a problem with your code. Maybe something is bugging you about the design approach. Or maybe you’re just plain stuck. What can you do to break through a mental block?
During one job interview, I remember asking how the candidate approached problem solving. That candidate’s answer has stuck with me over the years: