CornerJob is a startup dedicated to a very specific type of job search called “blue collar.” Basically, those jobs are mainly seasonal or with a high rotation rate. The main advantage of CornerJob has always been to be oriented towards the Mobile world and to eliminate the middle process bureaucracy to connect the candidate with the company. To accomplish their objectives, they created Android and iOS objective-c apps.
Apiumhub started to collaborate with them in September 2016 to be able to accomplish task related with the improvement of their iOS Objective-c App, for which the main goal is to decouple and modularize a Parse app.
CornerJob had already developed a roadmap of how they wanted the app to evolve and the architecture that they wanted to apply to iterative cycles to be able to accomplish the task that they had in mind in their iOS objective-c application.
iOS Objective-C Architecture
The first version of the app, which was created using the iOS Objective-C language, was developed using the Parse framework (a mobile backend as a service that was bought by Facebook and turned into an open source project), without a clearly defined architecture, since the objects of Parse predominated throughout the application.
The main part of the code was strongly coupled and Parse was present in all the parts of the app. Furthermore, the views were all created by a code, which often made a specific flow hard to read or understand; because the logic that manages the client’s and company’s side is merged.
A visual representation of the app at that time could look like this:
The first task concerning CornerJob guidelines was to create a business model where the business logic and Parse code were separated. At this stage, the base for the network layer and local storage was created.
At the same time, Continuous Integration system was being created, from which a first version already existed based on XCode Server and bots that had the mission of executing each one of the life cycle and deployment. In this case, to go faster, they decided to try the new Fastlane solution. This solution was not exempt from certain complexities due to the different versions of ruby and certificates issues.
By following Agile processes applying Scrum and working with Sprints, they were completing the task of migrating all entities, as well as extracting the functionality of the views and replacing them with Xib files, where the responsibilities of the view were clearer.
To be able to design the views, the auto layout was used in a very intense way to be able to manage all the variety and sizes of the devices which could support the app under any circumstances.
Once this phase was finished, the application already had a bigger number of software components which allowed to have a global vision of the layers that formed the application and allowed to make a better separation of responsibilities.
From this starting point, we had a much easier process to know how to add the next layers and increase the modularization, reduce the coupling and add the unit tests.
Now, due to the ViewController had a certain level of responsibility and the existence of the entities, the reduction of the use of Parse was increased. This allowed creating components in a quicker and clear way.
The architecture designed by CornerJob had an intermediate phase, where special emphasis was placed on modularizing the part of the model. For that, they thought to add a layer named “Interactors” which contain the use cases from a business perspective, and so the only response from the viewControllers was to paint the data. To do that, the Interactors collaborated with the Repository objects which allowed them to execute the business activities needed. A repository receives a type of settings, called Query, this is passed to Datasource Manager who is the one who decides which type of source will be used (network, local storage or cache) based on the Query provided. At this stage, is when the intensive use of unit tests starts and also when the first interface tests are created. The great advantage of this solution is that it allows creating workflows by configuration since most of the code is common between layers and the variable part is the Query part that tells the system how to work.
Parallel to this, they introduce the use of Realm as a local storage system that brought two big advantages to the app, reduce the number of API calls to servers and turn certain part of the data flow into a reactive system. Thanks to the entity object system mounted in the CornerJob application (each object has a corresponding for local storage and business entity) each time the local database is modified, the views are updated reactively through Realm notifications.
The process is as follows, the user triggers an event, if that event, by configuration should be saved at some point Realm, once the API returns the response of the backend, the data is updated in the local storage (Realm) and the view is updated automatically reactively.
The picture is the following:
As we can see in the graphic, we have a high modular app with unit tests in the logic business part and in the Core of the App(interactor, data source, query, entity, CJObjectBase, Layers…)
The coupling with Parse has been greatly reduced and a flexible and modular application has been achieved in order to be able to apply any of the current architectures at the lowest possible cost, such as the MVVM architecture with Swift, which is one of the possibilities which is being studied.
The application’s operations flows are now more atomic, allowing better tracking of them for debugging and enhancement tasks, adding new features.
What should be highlighted is that all this process that was made without changing the programing language, keeps being Objective-c, which has allowed to focus on the improvement tasks avoiding the different problems with the newest versions or languages mistakes such as Swift in this platform. Also, it is necessary to emphasize that the iterative process has allowed evolving the architecture while adding new functionalities and corrected errors which show the great achievement carried out to evolve the application always having a fully functional version.