Clash

I currently serve as Lead iOS Developer on the Clash distributed team. 

Clash is a short-form video application. However, unlike other video apps, Clash aims to bring creators closer to their fans with a variety of community building-focused tools.

The tech stack is based around SwiftUI in an MVVM architecture with coordinators used for navigation. Networking is achieved using Apollo/GraphQL and we make heavy use of In-App Purchases (subscriptions and consumables) for monetisation features. The app also makes heavy usage of web sockets for real-time chat features and AVFoundation for video generation and playback.

When not developing core features for the user experience, I spend a good deal of my time introducing architectural and tools-based improvements into the application.

During my time here, some of the team-wide improvements I have made include…

Improving Developer Happiness and Researching Meaningful Areas of Improvement

When starting at Clash, I noticed some areas of development and the product/engineering collaboration which seemed to be causing friction and a slow-down in velocity.

To solve such issues, I try to start by interviewing iOS engineers, understanding what has been holding them back and then formulate a plan to address them. After writing an RFC to explain and gather feedback on my plan, I begin work on these improvements.

Gaining insights from development and design is an approach I use as Lead iOS Engineer to improve our codebase in ways which maximize velocity and productivity in affected areas whilst increasing team member happiness.

One such area of friction was the app’s 100% usage of SwiftUI…

Although I love SwiftUI, I didn’t believe it was ready for shipping production applications at the time a previous decision to buy into it was made at Clash. Interviewing developers working daily on the application helped confirm this hypothesis. The APIs were sparse, engineers found working within it difficult, aspects such as navigation became messy and the design team were frustrated at the lack of customisation options. In particular, wrapping UIKit-focused elements such as looping video playback and native pull-to-refresh in UIViewRepresentable was often buggy. 

After receiving sign-off on the RFC and a time/resource allotment based on my estimations, I refactored the application to be a UIKit-based application with embedded SwiftUI content. This approach allowed us to continue taking advantage of SwiftUI and Combine whilst still allowing rollback to UIKit when it made sense.

The result was that the development team were able to work more quickly, task timing estimates were easier to predict, the codebase became much cleaner and developer happiness increased.

Modularization

Other points of contention I noticed whilst working on the team were the lack of code separation, long build times and broken SwiftUI previews. To improve these elements, I performed the task to modularize the Clash codebase. This began with mapping out all elements and dependencies within the codebase on paper and then separating them out into modules using Swift packages. 

Spaghetti-like code was greatly improved using modularization.

This process began with modules such as “ClashNetworking” and “ClashUI” as these were the areas of the code which would have the largest amount of cross-module dependencies.

Once this was done, feature modularization was possible. Each tab of the application is its own module. This made code cleaner due to enforced code separation and greatly-reduced build times which also brought back the possibility of using SwiftUI previews. Modularization of the UI layer also allowed me to write a suite of UI components whose colours, fonts and gradients directly mapped to the style guide used by the design team, reducing friction between the two parties. 

Communication between modules such as displaying a screen in one module which exists within another module is achieved using the coordinator pattern. 

Adopting Modern APIs and Coding Conventions

When paying off tech debt, modernising or tidying up the codebase, I prioritise tasks and improvements based upon what will also give tangible benefits to the company. One such improvement I made at Clash was refactoring networking code to use Swift’s async/await pattern. 

Moving away from traditional block-based networking code to async/await massively reduced the code involved when performing asynchronous operations, particularly when chained or conditional-based network calls were taking place. Error handling was also improved using the do/try/catch pattern and code became more readable which in turn sped up the PR review process. Threading-related UI bugs were also alleviated thanks to Swift actors.

I also reworked our GraphQL query structures to use fragments, simplifying client-side response parsing. You can read more about my process in this Medium post I wrote in retrospect

Management Responsibilities

Aside from programming-related responsibilities, I have served as interim front-end team manager during paternity leaves and assisted with many aspects of product development throughout my time at Clash.

A large project, named “Huddles”, is an example of where I facilitated communication between front and backend, strategised how to unblock those who were blocked on specific tasks and monitored and maintained project timeframes. 

This was achieved by introducing tighter communication and encouraging the documentation of meeting minutes to alleviate the issue of lost key decision making moments and reducing catch-up conversations. My inputs were a tight deadline and the introduction of some unknown technology and my outputs were a fairly seamless workflow, valuable feedback on UX and UI and a project which was delivered on time. 

Efforts In Product Ideation and Design

I am very much interested in understanding users and directing engineering, design and product focus in a way which helps solve those users’ problems whilst staying within a company’s core goals and project deadlines.

To this end, I often help design teams understand the importance of covering all UI states and building designs which are robust and, most importantly, give engineers all the information they need to implement a new feature correctly, quickly and smoothly. 

I wrote more about a tools-based approach to this challenge during my tenure at Cookpad.

Giving feedback on where our company’s time and efforts are best spent to achieve product fit and success is also an area of great interest to me. Contributing towards product development is one of my main career ambitions.