0% found this document useful (0 votes)
7 views

MVVM-C Architecture with Dependency Injection + Testing _ by Steven Curtis _ Medium

The article discusses the MVVM-C architecture combined with Dependency Injection and testing in Swift, providing a beginner-friendly example. It emphasizes the importance of separating concerns and improving testability compared to MVC, while introducing the Factory Pattern for managing dependencies. The implementation details include coordinators, view models, and testing strategies, aimed at helping developers adopt this architecture effectively.

Uploaded by

Chung Duc
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

MVVM-C Architecture with Dependency Injection + Testing _ by Steven Curtis _ Medium

The article discusses the MVVM-C architecture combined with Dependency Injection and testing in Swift, providing a beginner-friendly example. It emphasizes the importance of separating concerns and improving testability compared to MVC, while introducing the Factory Pattern for managing dependencies. The implementation details include coordinators, view models, and testing strategies, aimed at helping developers adopt this architecture effectively.

Uploaded by

Chung Duc
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 2

Search Medium Write Sign up Sign In

You have 1 free member-only story left this month. Sign up for Medium and get an extra one.

Member-only story

MVVM-C Architecture with


Dependency Injection + Testing
A complete example

Steven Curtis · Follow


6 min read · Jul 15, 2020

273 2

Photo by Jonathan Riley on Unsplash

I’ve been using MVVM-C for quite some time. I’m sure you (probably, I don’t
know you) agree that by abstracting the navigation away from the main
MVVM architecture code gives you the opportunity for testing. Great!

What if you have multiple dependencies? How are these going to be injected
into your…wait.. where…what?

Making this clear is the goal of this article.

Difficulty: Beginner | Easy | Normal | Challenging

This article has been developed using Xcode 11.4.1, and Swift 5.2.2

Prerequisites:
You will be expected to be aware how to make a Single View
Application in Swift.

Some experience of architecture patterns are required, whether MVC


or MVVM.

The principles of Dependency Injection are explained in this article,


but some in-depth explanation always helps!

You’ll need to be comfortable with protocols

Terminology:
Factory Pattern: A design pattern where an object is created without
exposing the creation logic to the client. The factory pattern lets a class defer
instantiation to subclasses.

The Problem
MVVM-C helps with separation of concerns, and allows testing and
implementation to be…much better than MVC. Now, nothing is perfect, but
it is perfectly possible to have a variety of dependencies which can lead to
large and unwieldy initializers.

One possible solution to this is use of the Factory Pattern, and the use of
Dependency Injection to test the relevant classes. This particular article is
written with the views programmatically defined, avoiding Storyboards in
the entire project, and neatly overriding loadview().

With that understood, let’s get to it!

The Example
The idea of this article is to have a basic skeleton for the MVVM-C
architecture. There are few around, particularly coded in Swift and even
fewer making an attempt at testing.

You’re probably working in a shop where they demand 80% test coverage —
and this article and the accompanying repo isn’t quite there (this example
isn’t promised to be production ready), however it is a very good start for a
developer to build on.

The coordinator has the following responsibilities:

Initialize the network service

Perform network calls

Initialize the ViewModel with the fetched data (or instruct the
ViewModel to handle a failed network call)

The Implementation
One of the best ways to explore the implementation is do download the files
to your machine and take a look. Give me a nice star when you’re there (if
you can).

I’ve created everything programmatically avoiding storyboards

The coordinator
This is at the heart of the matter, because the coordinator controls the flow
of the App. If a UIViewController wishes to move to another UIViewController

it must do so through the coordinator.

The main Coordinator is called ProjectCoordinator that conforms to a


RootCoordinator protocol and AbstractCoordinator protocol. By using
protocols rather than base classes you do end up with a rather more Swifty
solution — something recommended for Swift developers.

The coordinator protocols

Click for Gist

Click for Gist

Which are then put to use in out ProjectCoordinator class.

The ProjectCoordinator concrete class

The ProjectCoordinator has knowledge of just the factory class, which it uses
to create the InitialViewController instance which is then pushed on the
UINavigationController stack. The reference to navigationController is weak
to prevent a retain cycle as the UIViewController instance has a reference to
the ProjectCoordinator .

The moveToDetail() function demonstrates how moving between


UIViewController instances could work, and in fact if we wanted to pass
parameters or values from one UIViewController to another (although
questions should be raised about why you’re not doing this through the
model) it could be done here.

The Factory
The Dependency Factory class lets us inject services. This example has a
‘fake HTTPManager based upon my basic http manager class at it’s heart,
although I’m sure you have your own solution for making network calls
(don’t feel like I’m bullying you into this).

The Factory protocols

For better testing this conforms to my Factory protocol that enforces


conforming classes to have a network manager and the minimum functions
in order to create the UIView instances and UIViewController instances.

Click for Gist

The dependency factory concrete class

The dependency factory creates these artifacts that will be used to create the
objects that our App requires.

Click for Gist

The ViewModel classes


The view models know about the coordinator (but not about the factory).
With this design, the view model can hit the coordinator for navigation, and
make the transitions happen. Equally the view model has the dependency —
the network manager.

The view model creates the model from here when the network model
returns data from the Endpoint API.

Click for Gist

The ViewController classes

The UIViewController classes are responsible for the UIView classes, and
since in this implementation they have no dependencies these are created
within the UIViewController .

The initializer

sometimes choose to let the UIViewController control navigation, and this


means that my UIViewController classes have visibility of the Coordinator

class.

Equally, the view controller has viability of the view model class, and it is the
viewmodel classes that are used for network calls in this implementation.

Initialization from the storyboard is not currently supported.

Click for Gist

The View classes


The views are rather dumb here, don’t have any dependencies and just set up
their subviews. For the sake of completion, the InitialView is shown here.

Click for Gist

The Model classes


The example doesn’t have a particularly inspiring model. At all. I’ve created a
model with just a single dataString.

You might well use this to store something like user details (obtained by an
API), or whatever. The choice is yours.

Unfortunately there isn’t much to learn from this class, but for completion’s
sake here is the code:

Click for gist

Testing
This article is not about testing specifically, but does contain tests and mocks
partly because there is so little out there in existing articles.

To keep this article readable (or at least approaching readable) I’ve kept the
implementation details of these tests to the repo. To access the code hop
over to the repo and press download. You can then read through the files,
but below is the explanation of the same.

Unit testing
ViewModels

These would require mocked RootCoordinator and HTTPManagerProtocol . No


problem, as FactoryMock and CoordinatorMock show we can create .

UIViews

The views should not usually be unit tested. What are you going to check?
The positions of the view in a container that doesn’t exist?

For completeness, if you wanted to do this the code is included in


InitialViewTests .

The coordinator

We can mark a test function with throws, and any exception would cause the
test to fail. This can be used in conjunction with a guard statement a mock
for UINavigationController to ensure the correct View Controller is pushed
onto the UINavigationController (well, a mock of UINavigationController )
stack.

The Factory

It doesn’t make any sense to test the dependency factory, as it is this class
that is replaced for the tests. FactoryTests is simply empty.

Conclusion
I hope this article has helped you out, going through the relevant classes that
enable you to create a MVVM-C implementation.

If you’ve been using MVC I appreciate this might seem like a change and,
yes, well it is.

However having different methods of producing your App will only help in
the long run, and I hope that this article has really helped you out.

Thanks for reading!

If you’ve any questions, comments or suggestions please hit me up on


Twitter

Swift Programming Software Development

273 2

Written by Steven Curtis Follow

26K Followers

stevecurtis.me

More from Steven Curtis

Steven Curtis Steven Curtis

Top iOS and Swift Developer WWDC 2023: What’s New In Swift
Interview Questions for 2023 It’s getting great!
iOS Job Hunters Get Ready

· 10 min read · May 19 · 5 min read · Jun 7

132 235 1

Steven Curtis Steven Curtis

Security in iOS Apps WWDC 2023: My Fears As An iOS


It’s incredibly important in FinTech! Developer
Time flies when you’re coding! At least that is
true in my experience, and it seems like…
yesterday that WWDC 2022 took the stage
· 4 min read · Apr 30 and· gave…
3 min read · Jun 2

121 95 2

See all from Steven Curtis

Recommended from Medium

Steven Curtis Brahim Siempay

Understanding Swift’s Opaque Dependency injection in iOS like a


Types Pro
Useful for SwiftUI How to do Dependency injection in a
smoother way?

· 4 min read · Sep 21, 2022 · 5 min read · Jan 3

126 1 149 6

Lists

Stories to Help You Grow as a Leadership


Software Developer 30 stories · 59 saves
19 stories · 126 saves

Good Product Thinking Stories to Help You Level-Up


11 stories · 130 saves at Work
19 stories · 102 saves

Steven Curtis Brahim Siempay in iOS Senior Tips

Swift Learning Roadmap 2023— iOS Project Structure Like a Pro


The Ultimate Guide Improved code organization, separation of
Get that first job! concerns, reusability, testing

· 6 min read · Dec 29, 2022 · 4 min read · Dec 31, 2022

176 2 136

The Coding Diaries in The Coding Diaries Eniela P. Vela in CodeX

Why Experienced Programmers iOS Memory Management


Fail Coding Interviews In iOS, memory management is the process
A friend of mine recently joined a FAANG of allocating, using, and deallocating memor…
company as an engineering manager, and… in a way that minimizes the risk of your app
found themselves in the position of recruiting using…
for…· 5 min read · Nov 2, 2022 · 10 min read · Dec 29, 2022

3.9K 84 226 2
See more recommendations

Help Status Writers Blog Careers Privacy Terms About Text to speech Teams

You might also like