Building URLRequests with ease

Thanks to undraw.co for inspiration

In this article, I will show you an easy way to simplify one of the longest and most boring tasks that the developer must perform during the development of an application.

Nowadays, most applications require some type of network. In iOS it means that we have to fight with the URLRequest class at some point. This is not always easy and can lead to a wide range of errors and problems if we are not careful.

First, to better understand the examples, we need to know these definitions:

https://gist.github.com/Juanpe/8c902c8c0c5f342767a67ee62308d5e2

Imagine that we have an APIClient that executes network requests. And this class has a method that builds the URLRequests. Our code could be something like this:

https://gist.github.com/Juanpe/58439c60e7d63d605ad06427a6fa0caf

As you can see, this method is very long and also has more than one responsibility. Therefore, we are adding complexity to our tests and we are not complying with the SRP principle.

It’s time to Builder

It’s a perfect scenario using Builder pattern:

Builder is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.

Although I think it is clear, basically this pattern helps us to build complex objects in an easier way.

The pattern organizes object construction into a set of steps. To create an object, you execute a series of these steps on a builder object. The important part is that you don’t need to call all of the steps. You can call only those steps that are necessary for producing a particular configuration of an object.

Now, we know the definition of the pattern, so we are going to create our URLRequestBuilder:

https://gist.github.com/Juanpe/e8b3cd2c5a17a14d68ccc01d79aa553b
On top of each method has a keyword discardableResult to avoid warning of unused result.

This class has all the properties we need to create a URLRequest, some of them are optional and others are mandatory. Then we define steps, each set method would be like a step that we need to create our object.

Finally, we have a compilation method, which collects all the information and generates the final object.

Thanks to Swift, we can use method chaining, so the method would look like this:

https://gist.github.com/Juanpe/6707fc371d0a496910d1a9bd008c29e4

The result is a method more readable, with only 5 lines of code and with only one responsibility. So, we have isolated from our APIClient, the creation of the request.

Bonus

Many times, before sending the request, we must do one or more of an adaptation to meet the requirements of the API. For example, if we use OAuth2 to authenticate requests.

Using Alamofire’s approach, we could create a RequestAdapter. Its goal is to receive a request, makes changes needed and return it again.

The RequestAdapter would be:

https://gist.github.com/Juanpe/d953000cc55522c0f5f2312cd2a1d662

Using OAuth2 example, his adapter would look like this:

https://gist.github.com/Juanpe/e877f96aaaac1c7e1c122dd6e96ca80c

To include this new element in our builder, we only need to add a new property with all the necessary adapters and add the logic within the compilation method:

https://gist.github.com/Juanpe/721a2198bed905becd0cc859628895e4

Conclusion

Maybe seeing all the code that we have added to the project, we think that we have increased the complexity, but it is not true. In the initial example, our APIClient, had the responsibility to create the requests, and that is not correct, because the only thing that should do is send them. So we would be breaking the SRP principle.

In addition, now our code is more scalable, more readable and more testable. In a real project, the specifications of the API change constantly, so we would have to modify the creation of the requests. With our code, we would only have to modify our builder, without having to modify any other element of our structure.

Finally, we have seen how the Builder pattern works. And I could tell you that it is very likely that you end up using it in other parts of your application. For example, it is very usual to use it within registers with more than one step.


I hope this article helps you to learn a little more about Builder pattern and how he can help us constructing URLRequests in an easier way.

Thanks for reading this article. Share it if it was useful for you or if you think could be useful for someone. Feel free to comment below if you have any doubts or any suggestion of improvement.