Request Model: How to Architect Web Service Apps

January 5, 2016

Objects are like horses. The less they know about their chaotic surroundings, the easier it is to control them.

We don’t want our objects to be spooked when there’s a lot going on. So let’s build ignorance into our systems.

But how? We typically write mobile apps with these things at the center:

  • Communication with web services
  • User interface
  • Object persistence

These frameworks bore into our apps like warts with deep roots. Web-centric, UI-centric, and persistence-centric knowledge spreads through our apps, making our code tightly coupled. And then we wonder why it’s hard to write unit tests!

Is there an alternative?

Uncle Bob Martin’s Clean Architecture offers a different way. Instead of being at the core, things like web communication and even the UI can become plug-ins. They live at the edges of the app. Use cases and business logic become the center of the app.

[This post is part of the series TDD Sample App: The Complete Collection …So Far]

First, a naive client

Let’s explore just one facet: communication with web services. And let’s only look at sending the requests; we won’t worry about handling responses for now. A naive approach for the Marvel Browser sample app looks like this:

Web request: naive version

The Marvel Comics API is out in the cloud. The Marvel Service class handles all communication with it.

The app calls Marvel Service, so there’s an arrow there. But why did I draw another arrow, from Marvel Service back to the rest of the app? Because in my experience, it’s typical for web service classes to know about the app’s model classes.

For example, we might represent Marvel comic characters with a Character class. If the Marvel Service knows about Characters, that’s a dependency. Thus, the arrow going from Marvel Service back to the rest of the app.

Can we get rid of that arrow?

Request Model: a big step forward

Let’s not pass Characters, or any model object at the core of our app, to the Service. Let’s not have the Service poke around in the Character to extract any data it needs to make a request. Instead, the caller should give the Service what it needs, and no more. We can do this with a Request Model:

Web request: Request Model

A Request Model encapsulates everything needed for a particular request. The caller creates it, and passes it to the Service. By making it a Value Object, the Request Model contains no references to the app’s model objects.

The Service is now ignorant. It knows what it’s told, and that’s all.

DIP towards Clean Architecture

That’s a big step, but we’re not done. The “rest of the app” still has a dependency on the Marvel Service. This makes it hard to change anything about the way we fetch the data. In particular, it complicates unit testing. If only there were a way to reverse that arrow’s direction, but keep the Service ignorant about most of the app.

Well, there’s this thing called the Dependency Inversion Principle — the D of SOLID.

The classic way to invert a dependency is to extract a protocol. (If you’re an Android developer, when you see “protocol,” think “interface.”) We’ll call it the Marvel Gateway. In the following diagram, it’s marked with <P> to show that it’s a protocol:

Web request: Clean Architecture

The Marvel Service will (eventually) implement the Marvel Gateway protocol. The protocol acts as a contract. Thanks to Dependency Inversion, the rest of the app can now be ignorant. It knows about the contract, but not about any class that satisfies that contract.

We just derived our way to the heart of Clean Architecture! Anything that implements the protocol can be plugged in. The Marvel Gateway serves as a Boundary. Everything to the left of the dotted lines can be sliced off and replaced without affecting the core of our app. This makes it easy to replace the Marvel Service with whatever we want to use for unit tests.

Totally worth it

Separating things in this way may look like more work. But ignorance is bliss! Loose coupling brings huge benefits at a low cost.

Next time, I’ll show you how AppCode can help us quickly create a Value Object to serve as our Request Model.

Have you felt the pain of objects that know too much? How has tight coupling slowed you down? Click here to leave a comment.

[This post is part of the series TDD Sample App: The Complete Collection …So Far]

Jon Reid

Posts Twitter Facebook Google+

I've been practicing Test Driven Development (TDD) since 2001. Learn more on my About page.

3 responses to Request Model: How to Architect Web Service Apps

  1. Raphael Oliveira January 5, 2016 at 2:21 pm

    Hi Jon, thank you for the post! I’ve been using VIPER (https://www.objc.io/issues/13-architecture/viper/) for a while now which splits the Massive View Controller into 5 components that communicate with each other through interfaces applying the same Dependency Inversion Principle. It really makes unit test easing although in my opinion it increases complexity and can be cumbersome for very simple use cases. What architectural approach do you usually use?

    • Hi Raphael,
      Do you use vipergen tool for generating the classes for the uses cases? If you haven’t, give a try:

      https://github.com/teambox/viper-module-generator

    • Raphael,
      I’m actually VIPER ignorant! (Embarrassing, I need to catch up on my objc.io reading.) Initially motivated by Massive View Controller, I’m finding that Clean Architecture helps with many things other than view controllers (such as web service requests).

      I like the idea of managing Routing as a separate responsibility. Thanks for the VIPER tip.