Replacing legacy code

In this article i will try to guide you through the process we're following for modifying or replacing a legacy codebase. Please note, that's a guide only and not as a solution for all circumstances.

Isolate the work

When starting a refactor it's a good to ensure the work is done in a separate branch. We only commit changes related to the refactoring and don’t mix in any other changes, otherwise we risk breaking or conflicting with changes made by other teammates when our branch is merged.

Provide good test coverage

Refactoring is when you’ve made modifications to your code without changing its external behavior, and the only way to be sure you haven’t changed its external behavior is using tests. In other words before making any changes, we create or add additional tests that verify the existing behaviour.

Deprecate, the existing legacy code

We will start by deprecating the existing implementation. In Swift we can make use of @available attributes to indicate that the legacy type or methods should not be used. Eg:

extension CustomClass {
    // ...
    
    @available(*, deprecated, renamed: "newMethod()")
    public func oldMethod() -> Void {

    }
    
    // ...
}

When replacing a legacy Objective-C implementation we use the DEPRECATED_ATTRIBUTE and DEPRECATED_MSG_ATTRIBUTE macros defined in AvailabilityMacros.h.

Refactor by abstracting

After deprecating the existing code we will introduce an abstraction such as a protocol factory or strategy around the legacy code so that it can be dropped in later without changing so many classes.

The advantage of abstracting our logic is it helps us keep the existing legacy code as we incrementally create a new implementation and avoid situations where the application is broken or does not compile.

Once the new implementation is complete tested and proven to work as expected we can make the new implementation the default.

Communicate with the team

As the new code comes into the project’s main branch, we will let other team members know about it so they can start using it. As our ultimate objective is to completely remove the legacy code from the codebase. We can only do that if everyone stops using it and knows how to use the new implementation correctly.

To view or add a comment, sign in

More articles by AbdelAli J.

  • Which property wrapper for what purpose?

    In SwiftUI property wrappers are often overused even though they are powerful tools. A key principle is to use regular…

  • Leave your ego behind

    Ego is our sense of self-esteem that helps shape our identity and life goals. However an unchecked ego can lead to…

  • How I Interview Developers: A Simple Approach

    When I interview a developer I focus on three important questions: Are they smart? Can they get things done? Can We…

    1 Comment
  • The Power of Naming Conventions

    When SwiftUI 2 was released our team eagerly adopted it for our project. We jumped right in and enjoyed the excitement…

  • Understanding SwiftUI’s Observation Framework

    In SwiftUI observation tools like @Published and ObservableObject weren’t perfect. They often made us either watch too…

  • Swift Enums tips and tricks

    Swift enums are perhaps one of the most interesting features of the language. From defining a finite list of cases, to…

    1 Comment
  • Build, Test, & Deploy an iOS App with Github Actions (Part1)

    In his article, you'll learn how to automate the process of deploying your builds to testers using TestFlight. The Goal…

  • Why tests?

    Adding tests to your app provides a way to ensure that our app does what we expect of it. And not only do tests check…

  • Encapsulate new SwiftUI APIs

    Apple’s SwiftUI framework is progressing at a rapid pace and as we support older versions of the operating system the…

  • How to handle errors in Swift

    Good error handling is one of those factors that distinguishes good applications from bad ones, yet we often tend to…

Others also viewed

Explore content categories