We implement UI in iOS: we improve, accelerate, scale
- Transfer
Hello! My name is Azat Zulkarnyaev, I am developing iOS-applications at Badoo. When creating mobile applications, most of the time is spent on developing the UI, and optimizing this process is always a hot topic among developers. My colleague Alexis Santos wrote an article about what problems we encountered and how we moved towards their resolution when working on this task. I decided to share the translation with you. I also recommend watching a recording of a recent report by Igor Savelyev at Mobius 2018.
A few months ago, I came across a very interesting documentary series from Netflix - “Abstraction: The Art of Design”. It details the work of designers from various fields: architecture, graphic design, fashion, etc. It is easy to notice a certain similarity of their work with the activities of iOS developers involved in the implementation of user interfaces. In particular, while working on a large project, designers try to break it down into many small tasks on the principle of “divide and conquer” and get the opportunity to assemble all the elements together at a later stage.
This separation makes it possible to concentrate on a particular problem, without taking into account the interconnection of the components. Nevertheless, you can’t completely forget about the big picture - otherwise, when the assembly time comes, difficulties may arise.
On the other hand, during the viewing process, I noticed that the final design of many products - shoes, posters or buildings - does not undergo any changes over time. Nike, sending new sneakers to store shelves, will no longer update their appearance. In some cases, the product still looks great in 20 years. Unfortunately or fortunately, this principle does not apply to the design of mobile applications - developers must be prepared for frequent changes in the appearance of their products.
Nike Air Max 97, Empire State Building (New York)
Many iOS developers, working on large and complex applications, spend a lot of time creating interfaces, defining object relationships and honing small details. For effective work, it is necessary to keep in mind what the application as a whole should look like, and it is equally important to think about its division into separate components, which are subsequently reused when developing application elements.
Our team releases new releases weekly, and each of them contains new features, improvements, and other changes that affect the user interface. We always strive to work as quickly and efficiently as possible, but a year ago, during the development of the UI, several problems were discovered.
Issue
In short, the process of our UI development was not clearly structured.
In practice, this meant that the launch of any new function could lead to the most unpredictable consequences. For instance:
- There were no clear rules for interacting with designers: colleagues were not always aware of our work, and this led to the fact that they created new components, in fact, similar to existing ones, but looking different;
- we did not have a universal model for implementing new UI components: each developer implemented the components in his own way, which complicated the support of the project;
- code duplication also did not make the codebase better.
Consequently:
- to make changes to one UI element, it was necessary to change the code in many places of the project;
- increased risk of breaking parts of the application in cases where the updates did not concern them and their work was not tested.
Of course, all these problems could not disappear by magic. To change the order of things, it was necessary to come to an agreement between the various teams and to convince all participants in the process that changes are necessary.
Incidentally, the principle of "divide and conquer." We started small, identified problems one by one, after which we came to a global solution step by step. Below I will tell you how we did it.
UI frameworks
We approached the solution to the problem with all seriousness and started with the basics. First of all, it was necessary to get rid of code duplication. To do this, we unified the components used, putting them together.
We decided to create a couple of frameworks called BadooUIKit. According to our idea, they should contain all the necessary UI components (like Apple’s UIKit). Each of the framework classes corresponds to the UI element of an application (our company is developing other applications, but in this UIKit we have added only the components used in Badoo).
Each application has its own fonts, colors, margins and other attributes, and therefore it is very useful to have a stylesheet that relates to a particular application.
But what if one or another UI component can be used in different applications?
For this case, we created another framework - Platform_UIKit. It contains all the components suitable for other applications.
Did you just transfer all the UIs to the new framework at once?
No, this is very problematic. Instead, we created each new UI element inside the framework, and existing components were transferred only if we touched them as part of our work on our tasks. Sometimes a component was difficult to migrate due to too many dependencies - then we worked on it separately. First of all, we transferred basic elements like fonts, colors, and buttons. Then, having built the foundation, we transferred the entire interface of our chat to the framework. To make it easier, we did it after the creation of the infrastructure.
Offtopic: if you are interested in the process of creating components, catch a cool article by my colleague Valery Chevtaev myltik .
One of the main requirements for frameworks is the lack of dependence on other frameworks and classes that are not related to the UI. In particular, we never import models from the main application, network-related classes, analytics, etc. Thanks to this, we can reuse components:
We can import data from Platform_UIKit into BadooUIKit, but not vice versa: Platform_UIKit must remain independent .
Creating these frameworks did not require much work, as well as their subsequent support. Each new Badoo project is different from the previous one, and it can be difficult for us to maintain the described structure, but our solution has benefited both in the short and long term.
Pros of using UIKit:
- storing all UI components in one place makes them easier to find; accordingly, the work becomes more organized;
- freeing classes from dependencies helps reduce compilation time;
- elimination of dependencies facilitates the reuse of components and also speeds up compilation;
- updating a component in BadooUIKit, we update it everywhere; if the application uses components from BadooUIKit, the process of making changes to components throughout the application is simplified;
- isolated components are much easier to test;
- If necessary, a separate framework can be used in other applications (for example, when creating an application - a catalog of all the components of this framework).
Creating Badoo Gallery
BadooUIKit helped us solve a significant part of the problems, but we understood that there was no limit to perfection.
How to see all the UI components individually? Can I customize the search for components and see each of them in different color schemes? Can their testing be facilitated? Is it possible to create for designers a catalog of all existing and implemented UI components?
By launching BadooUIKit, we decided to create a simple separate application-directory for internal use. So there was Badoo Gallery.
Badoo Gallery is a tool that helps developers, designers and even members of the product team see all the UI components in a clear, accessible way. When creating it, we used a variety of tools that facilitate interaction with components.
Since our application was not intended for publication on the App Store, we could add any tool we thought was necessary. As the key, we identified the following functions:
- component search;
- sorting components by name;
- Add items to favorites
- switching between styles - so you can see how the component will look in a particular design;
- FLEX ;
- FPS counter.
Each component can be in different states depending on the actions of the user and the internal logic of the application. For example, UIButton has five states: 1) by default, 2) highlighted, 3) on hover, 4) on click, and 5) locked.
Interesting? Read more here .
In addition, we wanted to be able to present all the possible combinations in one place - we do this with every screen of each component. Of course, the states of our buttons may differ from the states of the UIKit Apple buttons.
Key benefits of Badoo Gallery:
- the ability to create a list of implemented UI components;
- easy search for UI components: each of us can see all possible options for the appearance of the UI component and find application for them;
- a lightweight search for existing components helps convince designers to reuse them;
- the compilation time of such a small application is very short, it helps to significantly reduce the development period;
- Favorites function helps to find the components that are currently implemented;
- the addition of external tools like FPS, FLEX and MultiBrand allows you to measure the quality of UI components and improve them;
- all components are placed in a separate framework and presented in an isolated environment - testing has become much easier.
A little bit about testing
New tools helped solve most of the problems described at the beginning of the article, but some questions remained unanswered.
Can we be sure that after making the changes, the UI will look like we intended? How to protect components and other parts of the application from the adverse effects of new parameters of subcomponents?
Find answers to these questions will help tests UI-components. There are a lot of articles on the web about the organization of UI testing on iOS. In addition, there are many different tools designed to test various aspects of the interface.
We decided to conduct snapshot testing by introducing one of the most popular open-source utilities iOSSnapshotTestCase (previously known as FBSnapshotTestCase, since it was created by Facebook).
You can learn more about testing using screenshots and about this framework using one of these links:
- https://github.com/uber/ios-snapshot-test-case/
- https://www.objc.io/issues/15-testing/snapshot-testing/
- https://ashfurrow.com/blog/snapshot-testing-on-ios/
We needed a way to test the components already in BadooUIKit to avoid regression when updating application components. We also wanted to automate the process of introducing new snapshot tests to the maximum.
Earlier, I talked about the gallery we created, which contains a list of all components and states that each component can accept. This is very convenient, since in this case tests can be run based on Badoo Gallery as a host application.
All components located in BadooUIKit are contained in a repository class that provides access to all components. This repository can both demonstrate the list of components in the gallery and open access to them using snapshot test classes. This frees us from the double work of creating objects and preparing different states for each of the components, since all this was already done when we introduced the component into the gallery.
Here are answers to the most common questions about testing with snapshots.
Where are snapshots stored?
We store them directly in the Git repository. We were afraid that this could lead to its bloating, but in reality everything turned out to be not so bad. As a rule, we test small components, and therefore screenshots weigh very little. At the moment, the folder with screenshots takes about 11 MB, which, in our opinion, is tolerable.
Are you testing all possible permissions in all possible environments?
No, the benefits of this approach are few. But there may be enough problems: the tests will become unreliable, the folder with snapshots will become more voluminous, and the test suite will be more difficult to support. We pragmatically conduct tests only for the most popular devices. In addition, our CI system is configured to use the same simulator that was used to create the snapshot.
Can snapshot tests cover the entire interface?
I think no. We at Badoo carry out various tests for different levels of the application. For example, functional (using Calabash and KIF frameworks) and integration.
conclusions
Of course, during the construction of the new platform, we learned a lot - and continue to learn. The tools and processes described above appeared about a year ago and are still developing. At this stage, we can conclude that they all benefit developers and the company as a whole.
Here are some of the lessons we learned in the course of our work:
- the transfer of all existing components is not an easy task, but by implementing the design system and prompting the team to use it, you will see how the number of components grows quickly: the transfer of components used by developers not only automatically increases the number of reused UI elements of your system, but also helps existing elements free up from dependencies; in the future, this will allow the transfer of more components;
- designers like to reuse components (convincing them to do this becomes easier when it is possible to show a fully working component that meets their requirements);
- saving time is necessary; we all know that the duration of compiling projects on Swift and Objective-C leaves much to be desired, while the Badoo Gallery application is lightweight and very fast to compile; we realized that it is much more convenient to implement UI components directly using the gallery, and then use them through the main application, where compilation is not so fast;
- By combining all the components in UIKit and launching a gallery application where you can test them, we have made the whole testing process much more efficient and easier.
Next - Cosmos
We pay a lot of attention to each of our products and want all of them to have a universal and attractive interface. In order for our users to enjoy their use as much as possible, we decided to make global changes. With the assistance of designers and the product team, we are introducing a new unified design system, called Cosmos.
Cristiano Rastelli has written some fascinating articles on how the Cosmos system came about. Do not miss!
Acknowledgments
The work on the project was carried out by more than one person - to one degree or another, the entire Badoo iOS team participated in it, including managers, developers and testers. I thank them all, because each of them was on board from the very beginning of the journey.
Thanks to our amazing designers who are always ready to make every effort to improve the design process.
Special thanks to Alexander Zimin : for the many proposed improvements, visiting the countless gliders, as well as for the support provided to me in this adventure.
I also thank Alissa Ordigliano for the excellent illustrations that made this article more accessible.