Generic in Swift. Real examples and use cases in real projects
Generic code enables us to write flexible, reusable code. It helps us to avoid duplication and take our code consistent and more universal. I like statically typed languages like Swift because you need to understand where and how to use generics. In dynamically typed languages like PHP or Python, all functions work like generic code and you can put any variable of any type to function and wait on the result🤞. Of course, you can avoid unexpected work of function with some documentation like “this function works only with Int” and it works, but not ideally. In Swift, you need to understand when you need to use Generic. Actually it was super confusing for me when I tried to understand the Generic code. I think the main problem was that I didn’t face the problem or real cases. Generic isn’t for beginners, because in this period of your work you aren’t clear about duplications, refactoring, etc, and it is not a problem for you in this period of your life.
I want to share real cases of using Generics in my real work and I hope it can be useful for programmers whos has questions like these “It can be done better?”, “How to avoid these duplications?”.
You need to have one rule for using Generics. You need to see that your code uses the same part of the functionality, but with different types. The interesting part — you are always using generics but you don’t know or think about this. I am talking about default collections data structures — Arrays, Dictionaries, and Sets. Just remember that you can create an array of each data type that you want.
My Real Generic Cases:
- Network pagination Decodable class
- Decoding the API response to a specific Type
Network pagination Decodable class
I face the generic problem in one of the audits on my real project. Auditors wrote to me that I need to refactor my Network layer and remove or minimize the duplications.
Problematic code before the Generics magic
As you can see, here we have 3 different network managers with similar code, when I try to decode some data from the network to a specific Type. In a real project, I had more than 11 network managers and 4–5 handler functions in each. It was terrible 😨!
Okay, so here we have tons of duplications and all changeable parts in this code are a Types in which we want to decode our response.
Generic way code after refactoring
As we can see, I changed the handleDecoding function to Generic function, and right now it can work with any type we want. Only Constraint here that the Element must be a Decodable (Because only to Decodable Type we can decode a response). (Also I added a new input variable responseType in which I will put the needed Type of expected model in the current request.
And this is how I removed 30+ duplications with this simple generic function. Of course, my coding skills were low at that time, but without facing the real cases you don’t understand where to use all this stuff like Generics of Protocols for example.
Decoding the API response to a specific Type
The pagination is a way to load data from the server by some small parts for example by 10, 20 items per request. Usually, pagination response looks like below:
And it is a good example. But in a real app you have a few pagination models — five maybe, it depends on your project and functionality. And in my project, all pagination models look like in this example. It always was a class with an array of needed items and some meta keys like currentPage and totalPages.
A real example from my project 😨:
Here we have a similar problem. One changeable part here is an array’s element type. (Also we have another problem here, that the array always has a different key name on server: pets, vets, users).
Generic way to solve these duplications
At first, I replaced the actual type of element in the list on Generic Element Type (which also needs to be Decodable by the same reasons).
The second problem — different key names or arrays on the server. I talked to my backend developers and we changed them to a unified “list” key. (Talk with your teammates, it will improve not only your code, and their 🙂)
I think that generics examples are very abstract in documentation and tutorials and I hope that my real experience cases will be useful for people who understand how to use Generics, but don’t know in which cases and places. 🤞