Refactoring a Massive View Controller

Now that Apple has announced a long-delayed revamp of refactoring in Xcode 9, it’s a good time to talk about my proudest refactoring moment over the last year:

I successfully broke apart a massive view controller in shipping code.

How? When you refactor a massive view controller, you know what you want your code to look like when you’re done. The places you’ll put all the diverse logic that’s currently twisted and squashed into one place.

Where you stumble over is how to get it there while you keep it all working.

When I looked at my massive view controller, I saw about four different areas of responsibility, four different related sets of methods and instance variables. But they weren’t cleanly divided: if I tried to take out any one of those areas, I’d be dragging in bits of the other areas along with it.

So I did.

I made a new class, let’s say for Login functionality, and pulled out all the methods and related ivars.

But since the existing spaghetti code that was left in the view controller wanted access to some of those methods and ivars, I couldn’t make a well-designed Login class at this stage. Instead, I left plenty of methods public that should be private, so they could be called by the old view controller. I left plenty of read/write properties public, so they could be called by the old view controller. I think I wound up exposing 12 of properties in all.

It was a total mess.

But it still worked exactly like it used to, no regressions, because it was exactly the same code — just moved.

Then, instead of trying to fix up the Login class, I moved on to the next. Maybe the next one was Network Connectivity. Maybe the one after that was Model Loading. Whatever they were, I pulled everything related to them out into their own classes, doing nothing except cutting and pasting the code from one place to another.

And as I went about it, a funny thing happened.

Even though I wasn’t trying to finalize the design or the APIs yet, for each new area I pulled out, I found I could refine the previously-extracted areas. Exposed properties that before were accessed seemingly at random, I could now see were only used by one of the specific areas I’d pulled out, and only at specific times. I could start to move properties around between the extracted classes, cut and paste them where they should go. I could move closer to the encapsulation I wanted.

All without breaking anything, because I was taking such tiny, straightforward, safe steps.

That meant, by the time everything was extracted, I was actually much closer to a final design than I had any right to be, given initial conditions.

At that point, I could finish the redesign through more conventional means.

One comment

  1. Pingback: Michael Tsai - Blog - Refactoring a Massive View Controller