Speed Up your iOS Development: The Modules’s Paradigm
Pieces of Advice to build your iOS Apps, making easier the creation and reuse of small modules
Writing down this article I’m not trying to discover the philosopher’s stone of the iOS Development, I’m just collecting some tricks, patterns, and functionalities that after almost 8 years continuously developing in iOS, I used to follow in every single iOS project that I have created.
One of the first things that I try to do when I join to new companies is, present these ideas to my new workmates, and honestly, for now, everyone that gave a try became new lovers to this paradigm.
So after a few years taking advantage of it, I have decided to create a post here. I have to really thank my previous workmates from BV, for being the ones that pushed me to write this article.
Designs over the world
Probably the best way to start is just taking a look at some views of the most used apps in the world:
If you didn’t notice yet, all of them they have one thing in common, they are probably built using UITableViews
. Creating ViewControllers
with a UITableView
as the main component is a common decision; this is something that even Apple noticed creating the component UITableViewController
some years ago.
The use of tables has a lot of advantages: performance, scrolling, animation, edition… but has one of the worst things that you could have in the iOS Development, usually tends to create massive ViewControllers.
Discover the marvelous world of the modules
Here is where the Modules start to make sense.
What is a Module?
- A Module is just a Powerful Section of a UITableView, with the main idea to create something that works as an isolated component, reusable and scalable.
What’s a Module is composed of?
We can say that a Module, is like a mini ViewController, therefore it is composed of:
- Module class
- Header and Footer,
UITableViewHeaderFooterView
- Rows,
UITableViewCell
- Additional logic, as requests/responses, data models…
If we take a look at the graphic the concept is quite easy to understand.
We just need to see your app as a collection of small components that could appear in any place on our ViewControllers
.
It means, that if we want to reuse the “Module 1” in a different ViewController
it should be as easiest as possible.
Then we deduce that ViewController
is going to be composed by Modules
FTMTableSectionModules
In order to start to use the Modules, there is a workaround needed, that is why I have created a Cocoapod
library that helps us to implement this marvelous paradigm
The FTMTableSectionModules contains basically 2 classes:
- ModulesViewController, a subclass of the
UIViewController
. This class is just a proxy that has implemented all the methods of theUITableViewDelegate
andUITableViewDataSource
.
The main functionality is based to redirect the responsibility to the proper Module depending on the selected section. Additionally expose the methods to deal with the Modules, like add/remove/insert… - TableSectionModule, AKA Module is a subclass of the
NSObject
. This class contains some logic to improve the UITableView’s life cycle and make easier the isolation and the reusability of TableView’s sections.
Here we have described the most important steps of the Module’s life cycle:
I think that to start giving a try we already have enough information, so we can jump to the interesting things…. CODING TIME!.
Hello World! I’m a Module
As usual, the best way to give a try to something new in the development is, to do a “Hello World!”.
The first step, create a HelloWorldModule as a subclass of the TableSectionModule
The HelloWorldModule contains 4 methods:
registerClassForCell
: The use of the dequeue of theUITableViewCells
requires a previous registration. In our case, we have decided to use a basic and native cell UITableViewCellcreateRows
: This method is where usually we define the DataSource of our module. In our example, we have a single row, so we are just appending one element.heightForRowAtIndexPath
: The typicalUITableViewDelegate’s
method to define the height of the rows.cellForRowAtIndexPath
: Method from UITableViewDelegate to dequeue and return the cells.
Finally in order to see our first Module
on our app we just need to add it in one of the ModulesViewController
. So, let’s go and create our MyFirstModulesVC with NIB file, as a subclass of ModulesViewController
.
Now, before proceeding to add the Module
, into the ViewController
, let’s configure the NIB file, for the tableview, delegate, and datasource.
As the final step, we miss adding the HelloWorldModule in the MyFirstModulesVC. The superclass ModulesViewController
, invoke automatically a method called createModules
, so we need to override this method:
After running our fancy App with our HelloWorldModule, we have the next result:
Divide and Conquer
One of the main keys in the Modules’s paradigm is, to split the responsibility across the different parts that the app is composed of. This can be summarised in 2 rules.
- What happens inside the module, stays in the Module.
- What happens outside of the module, stays in the ViewController.
Rather than explain with boring theory, let’s put real examples.
What happens inside the Module, stay in the Module.
Imagine that we have the typical part of the application where you can show and hide details.
As I mentioned at the beginning, is very important try to see the apps as a collection of Modules; in this case, we are in front of a clear example where we need to create a new Module.
Here we can see an example of how this new Module could look like:
As we can guess from the GIF
, we are inserting and removing UITableViewCells
when we are expanding and collapsing the information. Following the first rule, the Module
has enough grants and responsibilities how to achieve this alone, so it means, that the folding and unfolding is going to be totally transparent for the ViewController
.
Here you are the code to implement the new FoldUnfoldModule
.
If we inspect the code (it is obviously more complex than the previous ones), we see how we have implemented the Section’s Header (view and height), the Section’s Cells (view and height) and the didSelect.
An interesting part is refreshSection()
function, called inside of the didSelectRowAtIndexPath
method. That function is exposed by the TableSectionModules
and automatically refresh just the current Module
,(what means refreshing a Section of a UITableView
).
What happens outside of the module, stay in the ViewController.
Turning back to our HelloWorldModule
example, let’s provide it more functionality:
When the user clicks our cell, let’s go to present a UIAlertController, showing what module and section was selected.
Following the second rule previously described, this is something that must be done in the ViewController
. The best way to communicate the Module
with the ViewController
is creating a delegate.
Now, we need to update the ViewController
, adding himself as the delegate of this HelloWorldDelegate
protocol.
Easy-peasy right? Time to run our app once more.
Summing up
- The
ViewController
just contains the list ofModules
and theDelegates
if they have them. - The
Module
contains the views (Header/Footer/Cells) and every single logic that is needed to fully complete theTableViewSection
Do the Modules work as real isolated components?
Since we started, has been mentioned several times that is so important to create components that can be reused everywhere in the easiest way as possible. The best way to demonstrate this is again with real examples.
We have created 2 Modules
so far, the HelloWorldModule
and the FoldUnfoldModule
, so let’s mix both Modules few times on the same ViewController
.
Our ViewController
now has 6 Modules, 3 HelloWorldModules
and 3 FoldUnfoldModules
totally jumbled.
Should it work? Let’s bet!
Amazing!
We must highlight a really important annotation, the lines required in the ViewController
to achieve this behavior was of 35.
Could you imagine, how many lines would you need to integrate everything into one single ViewController
? and obviously losing the possibility to reuse it later in different ViewControllers
.
The Modules’s Paradigm in your Project & Team?
Before trying to use a paradigm we need to go one step back and check how this is affecting to us, from the development point of view to business point of view, and passing through QA .
The fact to have the code better separated between the Modules
and the ViewControllers
, helps to reduce the development conflicts. The probability to have several members working in the same Module
is tight.
and the conflicts that you could deal for the ViewController
are so easy to solve, they usually just add methods.
Besides this, the Pull Request
are easier to read, we can notice without effort if they are creating/changing/removing Modules
for specific ViewControllers
If we start to raise why it could be useful for our business, how many times did we received new features where they propose something as?:
The same thing that we have in whatever part of the app, but just making a small change like….
You know what? Modules can be subclassed as well. So we can create inheritance between our Modules putting things in common in the superclass
and just doing the specific changes in the subclasses
. There is no better way to represent the Scalability & Reusability.
Next is a huge & important point as well, QA.
When we are working with Modules, we can easily enumerate the ones that we have been changing for the new release.
It helps to reduce the amount of test that we need to run for the regression and increase the confident about the quality of our product.
Are they enough benefits like to give it a try? I think so mate!
Useful Material
If you just want to include the Modules in your project, you just need to include in your Podfile
the line
pod 'FTMTableSectionModules'
The concrete repository for this Pod
that also include some examples is:
If you wanna have the same examples that we have been using here, or even more elaborated examples I have an additional repository that maybe is interesting for you.
It contains several Modules, and few of them look like some components used in WhatsApp and Facebook apps.
Just download it, and click on the play button, you will not regret!
If you try the Modules’ Paradigm, I’d love to hear about it. Or, hey, if you think this doesn’t make sense let me know it as well. Comments are very welcome, don’t be shy!
As the title of this entry properly said, this is the First Part, my idea is to create a Second Part, where I will try to demystify complex
UITableViewCell