Interview with Angry Nerds - Project description helpers are a game changer for modular apps
In this blog post we interview Marcel from Angry Nerds, a custom software development company based in Wrocław, Poland. Marcel talks about a wide range of topics which includes their workflows, preferred code patterns and architecture, and their testing strategy.
Interviewee: Angry Nerds
In this post of our Apps at Scale series where we interview teams building apps at a large scale, we interview Marcel, iOS developer at Angry Nerds, a custom software development company based in Wrocław, Poland. Angry Nerds builds mobile apps for all kinds of industries, including education, entertainment, healthcare, transportation and more.
Currently, the Angry Nerds iOS team consists of 7 developers, mostly mid- and senior-level. The number of team members engaged in a particular project usually depends on the client’s requirements and the project’s scope. Commonly, there’s at least one iOS developer working in every mobile project. As for organizing the work, we run projects according to agile principles and best practices. We usually work in 1- or 2-week sprints that allow us to be flexible towards changing requirements. CI/CD, GitFlow and regular code reviews are fundamental processes we apply to every project.
The collaboration with designers is practically seamless, as we have an in-house design team. We’re in constant communication and solve any issues almost instantly. Designers often consult their work with us, and the other way round, to assure consistency and make the teamwork more efficient. We also build close relationships with other stakeholders, including the clients. With daily communication and regular demos, we want to make the workflow and knowledge transfer as smooth as possible.
First of all, our projects are open for the whole iOS team and code reviews across the projects are highly encouraged. The yml
template definitions of our CI system pipelines are shared across projects. We have also CD definitions to reflect all changes made on the development branch that need to be tested by our QA team. As for pull requests, the template requirements are filled out by the developer who creates the particular PR. And of course, in all our projects we follow Xcode’s Clean Swift templates.
We are still in the process of finding the most effective way to create and manage our projects with consistency. We’ve tried using XcodeGen which has its definitions written in yml
. It worked quite well but it didn’t feel native enough for us. After discovering Tuist and trying it on a sample project, we really appreciate the fact that the project definitions are written in an already known language, used by most iOS developers – Swift. We haven’t finished working on the process yet, but we are definitely getting closer to it everyday.
We try to discover and extract common APIs / code parts into one accessible place for our iOS team to reuse (and possibly improve in time). For example, we did it with Networking Layer code or most common Foundation extensions.
We do have modules that you could call our “core” modules, for example: the Design System module which encompases the app’s fonts, font styles and colors, the CommonUI
module which contains all common views, assets etc. that other “feature” modules use, and the Networking
module which includes the core of networking layer that other modules use. Other modules are created organically and based on particular features/requirements.
Most of our projects are now written using Clean Swift architecture which is based on Uncle Bob’s Clean Code paradigm of code separation. We also have some projects written using RxSwift + MVVM.
We did some projects using reactive programming in the past, however right now, as our recent projects are utilizing the Clean Swift architecture, we tend not to use reactive paradigms in those. Code separation and unidirectional communication between the entities in Clean Swift’s modules are sufficient and the usage of reactive paradigms would not be as beneficial. Still, we are not against those paradigms. Lately, we’ve been looking into Swift Composable architecture - its usage of reactive paradigms is actually very promising. We would like to try it out in some of our future projects.
In most cases, we use Swift Package Manager. As a fallback, we practice manual addition to a project, if a particular dependency does not support SPM.
The key ones are: RSwift for resources management, Needle for Dependency Injection and Alamofire for Networking purposes.
We think that dependencies that solve the core problems of the app (like Networking layer, AutoLayout definitions, Resource management or Dependency Injection) are fine to incorporate into a project as they are mostly well written, tested and maintained. We tend not to add external dependencies that solve app-specific problems, are not up-to-date or are no longer maintained by their creators (or the open source community).
In most projects, we try to cover core business logic with unit tests. We also add some UI smoke tests. Our goal is to cover as much as possible in Interactor and Presenter layers with unit tests. In some current projects we also use Swift Vapor server to mock network traffic.
We follow a general principle that the number of unit tests should outweigh the number of integration tests.
We think that confidence comes from somewhere in-between unit and integration tests, as integration tests depend on unit tests, but they are worthless without quality unit tests.
The essential ones are:
As we’re constantly working on improving the way we build and manage our projects, we see Tuist as a great tool to support our efforts. To be more precise, we appreciate these particular things about Tuist and they were direct reasons why we decided to adopt the tool to our workflow:
Setup.swift
definitions and tuist up
command)Tuist up command - we really like the fact that we can provide the project’s dependencies to other developers beforehand, so they don’t need to waste time on the tools setup and just do it all by executing one command. We also appreciate Tuist graph command - because we can quickly show other developers the high level view of communication between all app’s modules.
Yes, we do! It’s a game changer for us while developing a project with separate modules. We have one common project definition with base settings and schemes which we use in a new module creation. It all comes down to new Project.swift
file, e.g:
let project = Project.framework(name: "NewModule",
targets: [.framework],
packages: [
.package(url: "https://github.com/airbnb/lottie-ios.git", from: "3.1.6")
],
externalDependencies: [.package(product: "Lottie")],
internalDependencies: [
"Core",
"CommonUI",
"DesignSystem",
"Networking",
"Map",
"Rating",
"Settings"
],
resources: [
.glob(pattern: "**/*.swift"),
.glob(pattern: "Resources/**")
])
And we have a new module ready for implementation!
To be honest, Tuist adds new features much faster than we are able to adopt them, so anytime we come up with an idea – it’s there 😅 Still waiting for that run command though 🤞
AppClips look very promising. Also ARKit advancements are something we are looking forward to, as we have a project coming up in the pipeline, which will make extensive use of it.
Our recent favorite is Cats and Dogs: The Weather App, a gamified weather app we created with a UK-based creative agency. The key purpose of the app is that apart from receiving a reliable weather forecast, you get to take care of a virtual pet and earn bonuses for dressing it according to the weather. The client provided all the designs, including over 10K (!) animations which are the very heart of the project. They were also one of the biggest challenges in development, as it required weeks of detailed work to integrate the animations and sounds with the app’s features. We’re really proud of how it turned out! The app has been created with MVVM + Coordinators architecture and RxSwift library, and for the animations we used Lottie. We’ve also been a long-term partner to an international optoelectronics company, working with them on a complex mobile app for hunters, with such features as ballistics calculator, GPS assistance and more. There are also many exciting projects we worked on that we can’t mention because of the NDA agreements with our clients.
It was quite impressive that a team of over 70 people switched to remote work basically overnight – and it went so smoothly. We are seriously blessed that our work can be done virtually from any place in the world with good internet connection. I think we should acknowledge it a little more. As much as we’re used to remote work right now, we look forward to meeting once again in the office with the rest of the Angry Nerds team!