This website uses cookies to better the user experience of its visitors. Where applicable, this website uses a cookie control system, allowing users to allow or disallow the use of cookies on their computer/device on their first visit to the website. This complies with recent legislative requirements for websites to obtain explicit consent from users before leaving behind or reading files such as cookies on a user’s computer/device. To learn more click Cookie Policy.

Privacy preference center

Cookies are small files saved to a user’s computer/device hard drive that track, save, and store information about the user’s interactions and website use. They allow a website, through its server, to provide users with a tailored experience within the site. Users are advised to take necessary steps within their web browser security settings to block all cookies from this website and its external serving vendors if they wish to deny the use and saving of cookies from this website to their computer’s/device’s hard drive. To learn more click Cookie Policy.

Manage consent preferences

These cookies are necessary for the website to function and cannot be switched off in our systems. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms. You can set your browser to block or alert you about these cookies, but some parts of the site will not then work. These cookies do not store any personally identifiable information.
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us to know which pages are the most and least popular and see how visitors move around the site. If you do not allow these cookies we will not know when you have visited our site, and will not be able to monitor its performance.
Cookies list
Name _rg_session
Provider rubygarage.org
Retention period 2 days
Type First party
Category Necessary
Description The website session cookie is set by the server to maintain the user's session state across different pages of the website. This cookie is essential for functionalities such as login persistence, ensuring a seamless and consistent user experience. The session cookie does not store personal data and is typically deleted when the browser is closed, enhancing privacy and security.
Name m
Provider m.stripe.com
Retention period 1 year 1 month
Type Third party
Category Necessary
Description The m cookie is set by Stripe and is used to help assess the risk associated with attempted transactions on the website. This cookie plays a critical role in fraud detection by identifying and analyzing patterns of behavior to distinguish between legitimate users and potentially fraudulent activity. It enhances the security of online transactions, ensuring that only authorized payments are processed while minimizing the risk of fraud.
Name __cf_bm
Provider .pipedrive.com
Retention period 1 hour
Type Third party
Category Necessary
Description The __cf_bm cookie is set by Cloudflare to support Cloudflare Bot Management. This cookie helps to identify and filter requests from bots, enhancing the security and performance of the website. By distinguishing between legitimate users and automated traffic, it ensures that the site remains protected from malicious bots and potential attacks. This functionality is crucial for maintaining the integrity and reliability of the site's operations.
Name _GRECAPTCHA
Provider .recaptcha.net
Retention period 6 months
Type Third party
Category Necessary
Description The _GRECAPTCHA cookie is set by Google reCAPTCHA to ensure that interactions with the website are from legitimate human users and not automated bots. This cookie helps protect forms, login pages, and other interactive elements from spam and abuse by analyzing user behavior. It is essential for the proper functioning of reCAPTCHA, providing a critical layer of security to maintain the integrity and reliability of the site's interactive features.
Name __cf_bm
Provider .calendly.com
Retention period 30 minutes
Type Third party
Category Necessary
Description The __cf_bm cookie is set by Cloudflare to distinguish between humans and bots. This cookie is beneficial for the website as it helps in making valid reports on the use of the website. By identifying and managing automated traffic, it ensures that analytics and performance metrics accurately reflect human user interactions, thereby enhancing site security and performance.
Name __cfruid
Provider .calendly.com
Retention period During session
Type Third party
Category Necessary
Description The __cfruid cookie is associated with websites using Cloudflare services. This cookie is used to identify trusted web traffic and enhance security. It helps Cloudflare manage and filter legitimate traffic from potentially harmful requests, thereby protecting the website from malicious activities such as DDoS attacks and ensuring reliable performance for genuine users.
Name OptanonConsent
Provider .calendly.com
Retention period 1 year
Type Third party
Category Necessary
Description The OptanonConsent cookie determines whether the visitor has accepted the cookie consent box, ensuring that the consent box will not be presented again upon re-entry to the site. This cookie helps maintain the user's consent preferences and compliance with privacy regulations by storing information about the categories of cookies the user has consented to and preventing unnecessary repetition of consent requests.
Name OptanonAlertBoxClosed
Provider .calendly.com
Retention period 1 year
Type Third party
Category Necessary
Description The OptanonAlertBoxClosed cookie is set after visitors have seen a cookie information notice and, in some cases, only when they actively close the notice. It ensures that the cookie consent message is not shown again to the user, enhancing the user experience by preventing repetitive notifications. This cookie helps manage user preferences and ensures compliance with privacy regulations by recording when the notice has been acknowledged.
Name referrer_user_id
Provider .calendly.com
Retention period 14 days
Type Third party
Category Necessary
Description The referrer_user_id cookie is set by Calendly to support the booking functionality on the website. This cookie helps track the source of referrals to the booking page, enabling Calendly to attribute bookings accurately and enhance the user experience by streamlining the scheduling process. It assists in managing user sessions and preferences during the booking workflow, ensuring efficient and reliable operation.
Name _calendly_session
Provider .calendly.com
Retention period 21 days
Type Third party
Category Necessary
Description The _calendly_session cookie is set by Calendly, a meeting scheduling tool, to enable the meeting scheduler to function within the website. This cookie facilitates the scheduling process by maintaining session information, allowing visitors to book meetings and add events to their calendars seamlessly. It ensures that the scheduling workflow operates smoothly, providing a consistent and reliable user experience.
Name _gat_UA-*
Provider rubygarage.org
Retention period 1 minute
Type First party
Category Analytics
Description The _gat_UA-* cookie is a pattern type cookie set by Google Analytics, where the pattern element in the name contains the unique identity number of the Google Analytics account or website it relates to. This cookie is a variation of the _gat cookie and is used to throttle the request rate, limiting the amount of data collected by Google Analytics on high traffic websites. It helps manage the volume of data recorded, ensuring efficient performance and accurate analytics reporting.
Name _ga
Provider rubygarage.org
Retention period 1 year 1 month 4 days
Type First party
Category Analytics
Description The _ga cookie is set by Google Analytics to calculate visitor, session, and campaign data for the site's analytics reports. It helps track how users interact with the website, providing insights into site usage and performance.
Name _ga_*
Provider rubygarage.org
Retention period 1 year 1 month 4 days
Type First party
Category Analytics
Description The _ga_* cookie is set by Google Analytics to store and count page views on the website. This cookie helps track the number of visits and interactions with the website, providing valuable data for performance and user behavior analysis. It belongs to the analytics category and plays a crucial role in generating detailed usage reports for site optimization.
Name _gid
Provider rubygarage.org
Retention period 1 day
Type First party
Category Analytics
Description The _gid cookie is set by Google Analytics to store information about how visitors use a website and to create an analytics report on the website's performance. This cookie collects data on visitor behavior, including pages visited, duration of the visit, and interactions with the website, helping site owners understand and improve user experience. It is part of the analytics category and typically expires after 24 hours.
Name _dc_gtm_UA-*
Provider rubygarage.org
Retention period 1 minute
Type First party
Category Analytics
Description The _dc_gtm_UA-* cookie is set by Google Analytics to help load the Google Analytics script tag via Google Tag Manager. This cookie facilitates the efficient loading of analytics tools, ensuring that data on user behavior and website performance is accurately collected and reported. It is categorized under analytics and assists in the seamless integration and functioning of Google Analytics on the website.

Clean Swift Architecture: Is It Really Good for Your App?

  • 203685 views
  • 9 min
  • Aug 13, 2018
Daryna P.

Daryna P.

Copywriter

Evgeniy A.

Evgeniy A.

IOS Developer

Share

Nowadays, users expect their mobile devices to be even more powerful than desktops. They want their phones to do everything from waking them up in the morning to recognizing their faces via facial recognition technologies.

These rapidly growing expectations have triggered a generation of complex apps with large codebases that integrate multiple components. Mobile apps of this complexity have placed in doubt the existing architectural patterns including Model–View–Controller (MVC).

What’s wrong with MVC?

Developers often refer to MVC as Massive View Controller. There’s a reason for it. In MVC, the controller is thought to update the data in the View and capture events generated by the user. But in reality, the controller

  • updates data in the View;
  • captures events generated by the user;
  • is a delegate of diverse services;
  • processes input data;
  • is responsible for navigation between screens;
  • manages data flow between screens.

Model–View–Controller leads to large classes and contravenes SOLID principles: each component has lots of responsibilities. Big apps built on MVC are also hard to debug and modify.

Another huge downfall of MVC is that it hardly works with unit tests. Since the View is bound up with the Controller, you’ll probably test only the Model. To test the View, you have to play around with replacing the View with mock objects and imitating the lifetime of the View. You should also write code for the View Controller so that the business logic is separated from the View Layout code as much as possible.

You also need to remember that MVC is a UI-related pattern. If you’re building a complex application, you should take everything not related to the UI out of MVC triplets and move it to any other classes, subsystems, or layers.

To solve these problems in iOS apps, we’ll consider the Clean Architecture approach.

Have you heard about Clean Architecture?

Introduced by Uncle Bob, Robert Cecil Martin, in 2012, Clean Architecture is a set of recommendations on how to build an app. Clean Architecture encompasses the ideas of several other architectural approaches and says that an app’s architecture must be:

  • Independent from frameworks ‒The architecture should not rely on any library so that you can use frameworks as tools rather than having your system be driven by their limitations.
  • Testable ‒ Business logic should be tested without any external elements like interfaces, databases, or servers.
  • Independent from the interface ‒ The interface should be easy to change without changing the rest of the system. For example, the web interface should be able to be replaced with the console interface without having to change the business logic.
  • Independent from the database ‒ Business logic shouldn’t be tied to а specific databases.
The Clean Architecture Model
The illustration of the original Clean Architecture model proposed by Uncle Bob.

In this scheme, we can see the following layers:

  • Entities ‒ This layer contains business logic common to all applications. In the case of a separate application, this layers refers to the most basic business objects.
  • Use Cases ‒ application logic that controls the flow of data from the previous layer.
  • Interface Adapters ‒ This layer contains adapters between Use Cases and the outside world. It converts data into a format suitable for external layers, such as the web or databases. It also transforms external data into a format suitable for internal layers.
  • Frameworks and Drivers ‒ This external layer contains the UI, frameworks, tools, databases, and so on.

All layers are bound by the dependency rule. The dependency rule tells us that inner layers should not depend on outer layers. That is, our business logic and application logic should not be pegged to the Presenter, UI, databases, or other elements. Nothing from an external layer can be mentioned by the code of an internal layer.

This rule allows us to build easy-to-maintain systems as changes in the external layers won’t affect the internal layers.

For iOS development, the original concept of Clean Architecture was a bit modified. Let’s look under the hood at Clean Swift.

What do you need to know about Clean Swift?

Clean Swift is implemented in the VIP and VIPER models positions themselves as a replacement for the MVC pattern. In our article, we’ll talk about the VIP model (View‒Interactor‒ Presenter), as it’s one of our favorite patterns. This model has the following look:

The Clean Swift Model
The complete Clean VIP cycle

The standard VIP model consists of a View Controller, Models, a Router, a Worker, an Interactor, a Presenter, and a Configurator.

View Controller

The View Controller starts and ends the VIP cycle. It’s partly isolated. The View Controller sends data to the Interactor, though it doesn’t get responses from the Interactor. This class has a one-sided interaction with the Presenter as well. The View Controller gets responses from the Presenter but can’t transfer anything to it.

Models

The Models class is related to each component in the VIP model. Models is a class containing such structures as Request, Response, and ViewModel:

  • Request – A request model contains parameters sent to the API request, which are user inputs such as text entered in text fields and values chosen in pickers.
  • Response – This type of model receives the response from the API and stores the appropriate data.
  • ViewModel – This model encapsulates responses sent to the Presenter in primitive data types such as String and Int.

We’ll consider the different VIP components using the example of an iOS app that generates random cocktail recipes.

Router

The Router deals with transitions by passing data between view controllers. If you use Segue, you can simplify the initialization of the transitions by calling the Router methods from Prepare for Segue. The Router knows how to transfer data and does this without the extra cycle code from the Interactor/Presenter. Data is transferred using the data store protocols of each module implemented in the Interactor.

The Router also performs setup of the next View Controller and takes care of wiring and delegation setup.

Worker

The Worker handles all the API and Core Data requests and responses and prepares data for the Interactor. It also sends success and error responses to the Interactor.

The Worker frees the Interactor from certain tasks. For instance, you can put the logic of database interaction in the Worker. This is especially useful when the same queries to the database can be used in different modules.

Interactor

The Interactor is an intermediary between the Worker and Presenter. First, it communicates with the ViewController, which passes all the query parameters required for the Worker. Before sending data to the Worker, the Interactor checks this data. If everything is good, the Worker returns the response and the Interactor sends a response to the Presenter.

Presenter

The Presenter is responsible for presentation logic. It decides how data will be presented to the user. The Presenter organizes the response sent by the Interactor into view models suitable for display. Next, the Presenter passes those view models back to the View Controller to display to the user.

Configurator

The Configurator is a class that initializes all the Clean Swift components. Yet this class is optional. You can configure scenes by creating a private function in ViewController.

Now that you know the main components of Clean Architecture, it’s time to consider the main benefits and drawbacks of this approach. We’ll talk about the goodies first.

Advantages of Clean Swift

#1 Ready-made templates

Clean Swift has ready-made templates that streamline module creation and save developers’ time. These templates automatically generate files for either one or all components of the VIP model with all bindings between them.

#2 Unidirectional flow of data

Clean Swift realizes a unidirectional flow of data processing and decision making, meaning that there’s always only one cycle: View–Interactor–Presenter–View. Since most of the time you have to change fewer entities, Clean Swift simplifies refactoring. Given that, the Clean approach is best for refactoring projects in which the logic is often changed or complemented.

#3 Testability

In Clean Swift, you can easily replace the module with which your interaction takes place with a mock object. You can do this by determining the functionality of each module via a protocol. Additionally, the business logic gets put into a single place instead of being scattered around.

If we simultaneously create business logic and related tests (Interactor, Interactor tests), this makes it possible to do est-driven development (TDD). Since the output and input of each logic case are defined by the protocol, you can simply write a test that determines its behavior and then implement the method logic directly.

#4 Reusability

You can put most common tasks, such as getting users, into the Worker and then reuse the same workers in different scenes. This way if the processing logic is modified or you need to make additional changes, you can amend the logic in one place but these changes will be available for all scenes.

#5 Collaboration

Clean Swift divides logical units into small pieces. Each developer has their own task. When several developers work on one project and make some changes in the code, these changes have minimal impact on each other. This approach helps to eliminate conflicts inside the team and avoid development delays.

Despite all the advantages mentioned above, Clean Swift still has some downfalls you need to be aware of.

Disadvantages of Clean Swift

#1 Barriers to entry

Even though good documentation for Clean Swift exists, switching from MVC to VIP can take lots of time. You’ll face way more classes that you need to bind somehow. Thus, some developers encounter difficulties in understanding this pattern and use old architectural patterns like MVC that fit a small number of apps.

#2 Over engineering

Initially, Clean Architecture was designed for big server-side applications. This approach requires you to create many entities even for a small feature. Thus, you may end up with too many files. Clean Swift doesn’t fit mobile client-side applications of medium complexity with no intent of further development.

Should you use Clean Swift?

Clean Architecture is gaining traction among iOS developers. Clean Swift is a smart and effective solution for

  • long-term projects;
  • projects with a generous amount of logic;
  • projects for both macOS and iOS platforms;
  • projects you want to reuse in the future.

This approach, though, isn’t suited for small projects. So you need to thoroughly evaluate your project and only then decide on the architectural pattern.

If you want to get more news devoted to iOS development, subscribe to our blog.

CONTENTS

Authors:

Daryna P.

Daryna P.

Copywriter

Evgeniy A.

Evgeniy A.

IOS Developer

Rate this article!

Nay
So-so
Not bad
Good
Wow
8 rating, average 4.88 out of 5

Share article with

Comments (0)

There are no comments yet

Leave a comment

Subscribe via email and know it all first!