The Facade Design Pattern In Swift

July 5th, 2022

⏱ Reading Time: 10 mins

The purpose of design patterns is to outline solutions to various common software design problems. Becoming popular by the Gang of Four, design patterns provide a theoretical approach on how to solve common challenges that software engineers meet on a daily basis. They do not constitute specific code implementations, therefore they can be adopted and implemented appropriately in many programming languages. Design patterns are separated in three general categories; creational, structural and behavioral. In this post I’m presenting facade, a structural design pattern.

The facade (spelled façade) design pattern is a pretty common pattern that’s usually easy to adopt. Having taken its name from the front side in architecture and buildings that hide their internals, chances are that you have already put it in motion, even without realizing it.

What the facade pattern suggests could be summarized in plain words to this:

When there is a combination of APIs necessary to use but doing so tends to be a difficult or complicated task, then implement simpler intermediate APIs if possible that are more straightforward and easier for your code to work with, and hide all complexities behind these new APIs.

Note: Even though the facade design pattern is mostly common in Object-Oriented Programming and refers to classes, in this text I make the context more general and referring to APIs instead, including under this term classes, structs, enums, protocols, functions, and everything else we meet in Swift; not just classes. Swift is not a strict OOP language, and facade can be adopted respectively.

For example, you might have a number of classes or structs that should be combined together in order to do some job from start to finish. That code might originate from the same codebase, or it’s provided from other frameworks or libraries, such as multiple Swift packages. Repeating a complicated series of steps multiple times in various sites within a project can become a daunting and counter-productive process.

Stating the obvious at first, following complicated procedures is not something we remember out of memory most of the times. It’s therefore natural to need to be advised by previous code or documentation about how to use the system of classes, structs, other types, or APIs we want to put in motion each time. And unavoidably, that is something that borns great friction to the overall workflow.

But on top of that there’s one more factor that’s potential to generate problems later down the road. That is the tight coupling that takes place between our code (let’s call it the client code), and the other APIs we are calling (let’s call it third party code, which is either ours, taken from elsewhere, or it’s included in the system SDKs). The code is dependent on those APIs, which is perfectly fine; until something changes to the third party code, leading to bugs and broken code in our projects and apps.

Suppose that just one method in a third party API becomes deprecated by its developer, and it’s replaced by another one, most probably with different requirements (different arguments to provide it with, different return values, and so on). If there are many occurrences of that method in the client code, then we have to make a bunch of changes and ensure once again that everything is solid and not breaking after having finished with all the updates. That sounds awful already! And it’s being magnified if we encounter more than one changes to the original third party code.

So, not only it’s sometimes complicated by their nature to combine a mix of other APIs in order to perform a task, it’s also risky for our project itself in case something gets changed in the future.

Now think of the opposite scenario. What if we had a simpler API to use, for instance one method instead of five, and that one method hides all the complexity from the client code, making use at the same time of the other five internally?

Well, this is the entire idea of the facade design pattern. By introducing an intermediate API right between the client and the third party code, often called an interface, we end up managing and dealing with much simpler code. An interface that’s easier to interact with, to reuse in multiple places within a codebase, to maintain, and to hide all complicated steps behind it.

In addition, depending always on how the code is structured, and the occurrences of the third party APIs in other spots within the codebase, we could also possibly remove the tight coupling between those and our client code with a facade implementation. The third party code will be appearing in one place only instead of many; the new intermediate interface. The client code will be communicating with that interface calling the custom, simpler, intermediate APIs, and it won’t be depending directly on the third party code, or being vulnerable due to changes on it. Of course, that’s a positive side effect that could possibly happen, and not the purpose of the facade pattern.

Having said all that in a theoretical level, it’s time to get a bit practical. Before that though, note that there are not any rules or guidelines about how to implement the facade pattern. Just keep in mind that you should be after making a simpler API to use that encloses all the complicated tasks in it, and that’s the only interface that your code (client code) should be interacting with. If you achieve that, then you have managed to apply the facade design pattern.

A hypothetical scenario

To demonstrate the concept of the facade design pattern programmatically, let’s suppose that we’ve been making an app that manages information about movies, and that there are two assistive libraries that we’ve been using in our project. The first one is responsible for converting to and from JSON and Property List data objects. Let’s use as example the following pretty simple implementation:

The Converter type shown here is a generic one, with the T placeholder being any type that conforms to Codable; Encodable and Codable protocols.

The first two methods are encoding and decoding to and from JSON objects respectively, while the last two do the same for Property List (plist) objects.

The second hypothetical assistive type to our example here is another class, with the sole purpose to store data persistently on disk, as well as reading back from it. Let’s call it Storage, part of it could be the following:

The first method stores the data it accepts as argument to the documents directory. It’s also using the specified file name, and it determines the file extension (“json” or “plist”) based on the last parameter value.

The other method loads the data from the file whose name is provided as the first argument, while it uses the value of the second flag to decide about the file extension.

Both the Converter and Storage types are quite simple on purpose. Let’s move on and make use of them, and after that, let’s see how a facade implementation could make things easier, including occurrences of these types.

Using the two types

In order to put the above two types in motion, we need another custom type that will be adopting the Codable protocol. The next one covers our needs in the scope of this text, as it’s a struct capable of storing data about a movie, and it conforms to Codable:

Let’s define now a MovieInfo object (using data taken from the International Movie Database):

The goal in this hypothetical project is to convert the movieInfo instance into a JSON or Plist object, and then store it to the disk. Obviously, we are going to need both of the two custom types we defined previously in order to make this happen.

So, let’s initialize both a Converter and a Storage object like so:

It’s necessary after that to perform two distinct actions so we get closer to our goal; the first is to convert, the second to store. All that will take place in a do-catch statement, as all methods implemented in our custom types can throw errors:

At first we are attempting to convert the movieInfo object into a JSON object using the convertToJSON(_:) method of the Converter class. If that’s successful, then we call the store(data:withFileName:asJSONFile:) method of the Storage class so the produced object in the previous step to be written permanently on disk.

In a similar manner we can convert the movieInfo instance into a Plist object, and then write it to disk as well:

Using the previously defined APIs, we can also load and decode a previously stored movie info like so:

Notice that in all cases we need to use both the converter and storage instances side by side, and even though this is just a simple demonstration, in a real project this could happen many times in multiple places, and of course, with more APIs to get involved in the process.

But besides that, you will notice that right now our client code is quite dependent on the Converter and Storage types. With the slightest change on any of them, the client code will need to be updated everywhere these two are used. What if, for instance, the load(fromFile:isJSONFile:) method would be renamed to load(file:isJSON:) in a future version of the class?

Putting all that aside for a moment, what our client code really wants is to convert and store or load fast. An API that would be able to carry out a request like “convert this to JSON and save it as ‘godfather’” as a single command would be the most appropriate thing to have.

Right now two steps are required; first to convert, and then to store. Or to load from a file first, and then to convert to a MovieInfo object. And that’s definitely more complicated than the ideal scenario that was just described right above. In real projects, the distinct steps would be probably more than two, while additional things to take care of, such as error handling, should also be taken care of along the way.

All the above indicate a great case to apply the facade design pattern on. By doing so, we will introduce a simpler API for the client code to use.

Implementing the facade

Let’s start with the definition of a new type:

In real projects, I would recommend to use a better name than the one I’m showing here, but anyway, that’s just for demonstration. Notice that as before, this is also a generic class aiming to be working with Codable types only.

Let’s continue by implementing an inner custom type; an enumeration that will be containing as cases the two formats we are interested in, json and plist:

Now, let’s declare two stored properties; the first will be a Converter instance, the other a Storage instance:

After having made these initial steps, we are ready to implement two new methods. The first one will be converting and storing a Codable object to a file, while the second will be doing the exact opposite work. These two methods will be the new APIs that our client code will be dealing with from now on.

So, let’s go with the first one:

What happens here is quite straightforward; the given object is converted either to a JSON or a Property List object depending on the type parameter value, and then the result of the conversion is stored on the disk using the provided file name.

The second method follows the opposite path as said already:

The new facade class is now ready, and the next step is to use this instead of the Converter and Storage in the client code. This class provides a new interface that our code will be dealing with, encapsulating the functionalities of the other two types in it.

Using the facade class

Back to the client code, the first step to do from now on whenever it’s necessary to convert and store (or to load and convert) is to create an instance of the above type:

By calling now a single method only, we can achieve the same results as above, but this time using a simpler API comparing to the initial implementation. For instance, let’s convert and save the movieInfo we met earlier using our most recent implementation:

In a same fashion we can do the opposite, and initialize a MovieInfo object by loading and converting it like so:

Undeniably, both the above two methods are much simpler to use comparing to what we had at first. Not only that, but they also hide the all the complexity from the client code, and the latter is no more depending directly on the Converter and Storage classes. If something gets changed in the future on any of these two types, we’ll need to update the facade class only; any related code in the client’s part will be left untouched.

Conclusion

The primary goal of the facade design pattern is to hide from the client code the complexity of combining APIs that manage specific tasks. It achieves that by providing a new simpler interface to use on the client side, while it keeps all the details enclosed in the implemented facade type. An additional and quite important benefit we gain is that the client code as an entity often stops being tightly coupled to the types and APIs whose functionality is transferred to the facade type, if we consider the latter a different entity and not part of the former. But don’t take that for granted, because it depends on the way facade is implemented, and it’s also not the pattern’s purpose.

Before closing, note that in this content I demonstrated two custom types which were replaced by the facade type. But that’s not a rule; a facade can be implemented targeting APIs from the system SDKs, third party libraries, or code existing in the codebase itself. Moreover, the facade does not have to be a standalone type as shown here. It can be anything that serves that purpose, such as a single function or method that contains a series of statements, expressions, and calls to APIs, which all together constitute the required steps towards achieving a specific task.

With that being said, I hope you’ve learnt something new and useful here today. Thanks for reading! ????

Stay Up To Date

Subscribe to my newsletter and get notifiied instantly when I post something new on SerialCoder.dev.

    We respect your privacy. Unsubscribe at any time.