Swift Enums as namespace

Sergey Gavrilyuk
Swift Programming
Published in
3 min readApr 18, 2016

While moving from objective-c to swift many developers have found swift’s enums to be much powerful tool than it used to be before. It’s algebraic nature (data exclusivity) and excellent native compiler support (powered by pattern match) made it so much easier to do a lot of routine stuff. Also, people noticed that it’s now easier to leverage static type checks that come along with these enums to bring more API safety and consistency. That all is great, until we start abusing this tool.

I came across this approach to define RESTful services endpoints using enum, first employed by Moya framework. The idea of wrapping list of endpoints in enum looked fresh and tempting to try. It provided the way of creating clean API, simple abstraction:

By making makeCall method to accept arguments of enum type we could limit the set of endpoints it supports. Furthermore, enum type would provide code completion after typing “.” which would be very handy. Also worth mentioning, any additional endpoint-specific data would be carefully handed but that specific case, no untyped parameters list.

I didn’t like Moya’s implementation though. The idea is simple, but they ended up with massive implementation, even adding data mocking support into their core. I think that feature would be nice-to-have, through some sort of plugin or extension, but not in the core. So I took the idea and implemented my own HTTPEndPoints micro-framework.

First I defined enum with endpoints names and custom data, then I provided extension where I defined all the specifics of those endpoints: HTTP method, encoding, data and so on.

It was fine at the beginning, but while developing my app, I kept adding new endpoints. Until I got around 20+ endpoints and the code became messy.

A couple of days ago stumbled upon this post where author is talking about using enum in other very similar use case. He’s arguing against enums in cases data is scattered across different places. He says that sometimes it is still better to use old-school approaches with protocols defining module functionality and a set of concrete module implementations.

Better enums

Let’s reflect on why we get something wrong here. The main problem with defining our endpoints as single enum is that fulfilling actual implementation requires several methods, and information related to a particular endpoint (which one enum’s case) is now distributed across several methods (or variable getters). We can solve that by using technique described in this post: wrap information related to each endpoint into private struct or even tuple. That would solve the problem of data being scattered and would definitely simplify updating our enum while refactoring.

Enum as namespace

When think about this further I asked myself: this private struct or tuple that is going to wrap all information related to particular enum’s case really fulfills my HTTPEndpoint interface, why not making that private struct to conform the that interface and not my initial enum? By this we effectively come to the idea of using protocol and multiple implementations as in this post I mentioned. But we could still use enum to construct those implementations. In this case enum work just like a namespace. Consider this example:

I used a little trick here, I made my enum holding implementations of the protocol to be convertible to that protocol. I still have to make separate implementations for my protocol LoginProvider in separate classes, but I can alias them with enum cases, and that convertibility is what bridges enum approach and protocol-implementation approach. I have clean functionality implementation and neat namespace-like grouping of those implementations so I can restrict APIs to accept only implementations from that group and enum’s autocompletion.

As to my HTTPEndpoint micro-framework that I used in one of my apps, I decided to construct a small DSL:

and with that I can add the following extension to my Endpoints enum:

Update: some code have been update with typos fixed thanks to Lasha Efremidze

--

--