Writing in the front

In terms of App architecture and componentization, this article doesn’t cover the code level or how to componentize using Cocoapods. Instead, from the perspective of software engineering and combined with my years of experience in front-line development, I analyzed how to make App architecture, how to consider what kind of architecture is reasonable and suitable for my business, and what problems should be avoided in the process of architecture implementation.

The architecture mentioned in this article is not an actual engineering code architecture (MVC, MVVM, MVP), but rather an application layered architecture. The ESSENCE of MVC, MVVM and MVP is a software architecture mode, which is a coding mode or coding specification in the process of App implementation.

Review of iOS architecture

As shown in the figure above, the classic iOS system architecture is divided into four layers, including the core operating system layer, core service layer, media layer and user interaction layer from bottom to top.

  • Cocoa Touch: Provides capabilities related to user interaction, including Touch, etc. The most commonly used UIKit libraries are located in this layer; In addition to MapKit, Address BookUI, PhotosUI and so on.
  • Media Layer: provides graphics, audio and video functions, such as Core Animation and OpenGL ES.
  • Core Services: The most commonly used are Core Foundation, Foundation, CFNetwork, CoreData, etc. Provides basic capabilities such as arrays, dictionaries, HashMaps, sockets, and other basic data structures.
  • Core OS: Includes Mach, Kernel, BSD, Socket, Sandbox, etc. It mainly provides the interface of low-level operation, which is not directly used for application development.

Everyone says iOS is awesome. What’s awesome about it? What’s cool is that it has the right architecture layering and Api design so that you can do iOS development while lying on your back. Its awesome file management and file isolation mechanism allows you not to worry too much about iOS security, except for reverse development, which is always buggy 😄.

Q: How do the four layers of iOS system architecture communicate and interact with each other? Is it reasonable?

A: Directly reference the header file and call the Api provided by the lower layer for interaction. As for whether it is reasonable, I would say that as long as the Api design is reasonable enough to cope with the possible changes within the SDK in the future, or the SDK itself is a very basic library, such as the Foundation library, I don’t think it is a good idea to introduce headers directly. We will discuss this later.

Design a reasonable application layer architecture

Although the sparrow has all its internal organs, every link is indispensable if it wants to fly high. As for how to design a reasonable application layered architecture, here we take building building as an analogy. The author has worked in building and moved bricks, so he is relatively familiar with building building process.

  • The first step: laying the foundation, supporting the formwork, pouring the cement, putting up the shelves and moving the bricks to build the wall. This is the foundation of everything. The tall building needs the strong support of these modules for a long time. Abstracted into the application architecture, we call it the foundation module, which mainly provides the most basic capabilities of the application.

  • The 2nd pace: spread the ground, make a door, among them the door can be used possibly in bedroom, dining-room. Abstract to the application architecture, we call it common business modules, which mainly provide some common business modules or common components.

  • Step 3: Empower the building with bedrooms, dining rooms, bathrooms, etc., so that the building can be truly meaningful. The function such as bedroom should use the basic module such as brick, wall, door. In the application architecture, independent functions such as bedroom, kitchen and washing are abstracted into common service modules. Each service module represents a specific function and there is no strong correlation between service modules.

Q: Apart from the above, is there anything else missing?

A: There is an elevator connection between floors, and A passage between the bedroom and the kitchen. Similarly, for applications, the communication between modules also needs to be connected by a medium, which is called Bus. More on how to implement a bus that allows your modules to work separately and communicate seamlessly with each other.

After analysis, we can easily draw the following application architecture diagram, where each layer Outlines what the layer contains.

In the figure, we further abstracted the structures that an App should contain according to the idea of “building a building”.

Implementation of application architecture

On iOS, we use Cocoapods to manage and integrate our own components. According to the concept of factory production App, I drew the following App integration diagram in combination with Cocoapods.

  • Basic module: Since the module is highly independent and frequently used, it is recommended to create a private library for the company with multiple apps that need to be relied on at the same time.
  • Common business modules: Functions are relatively independent, and private library Specs are created separately depending on business requirements.
  • Cocoapods Public Library: All internal company apps. It is strongly recommended not to introduce public Specs directly. This has two advantages: 1. Effective isolation from the external environment, third-party library problems, the company’s internal control. 2. The public library is too large, each REPO update takes too long, you know the domestic environment, there is no scientific Internet, at least one hour after the REPO may not be updated. Therefore, the general solution is that if a third-party library is referenced internally by the company, it is recommended to encapsulate a layer and put it into Basic Specs for use by the business side according to the principle of dependency inversion. Here is a recommended scientific web tool, can build their own VPS->Vultr.

It’s time for the annual QA session.

Q: How to grasp the granularity of component separation?

A: There is no measurable standard, which needs to be combined with specific business scenarios. Those with high reusability and relatively independent functions can be considered for splitting. It is also important to note that component splitting does not have to be separated into a POD library. Instead, a group of common components with certain features can be grouped into a POD library (let’s define it as CommonUIKit). As we know, pod libraries will generate static libraries and reference them to the main project, that is, they will eventually go through the link process. Too many POD libraries will bring a certain performance cost of App startup. Secondly, too many POD libraries will also lead to the problem of chaotic POD management.

Q: For example, if I need to decouple a small function, just a popbox, I can select a POD library and others can reference it directly.

A: Before we answer that, let’s think about two questions. How likely will the frame components change in the future? Are your apis designed to make sense and meet the needs of future products? Second question, do the benefits of decoupling cover the disadvantages of these possible changes? By thinking about these two issues, we can know if we need to decouple a component and remove dependencies with intermediate services.

Resolving horizontal dependencies

  • Horizontal dependencies for the common component layer.

As can be seen from the figure above, the home page component actually only obtains the login state, but the login module does not provide corresponding services, so the component can only be imported by referring to header files, and the two are coupled together.

Using the concept of middleware, we can create a service layer between two modules that is dedicated to data communication between modules, or data communication between small-grained components that are not interface hops. This solves the problem of horizontal dependencies between the two components.

  • Horizontal dependencies between business modules.

We are talking about horizontal dependencies between lines of business that are functionally independent. For example, the home page module may have the entrance of service A, service B, and service C. If the home page module is not componentized, the home page module is coupled with service A, B, and service C. Several common routing solutions are recommended here.

Jlroutes-url Routing Library for iOS with a simple block-based API.

Beehive-ios App modular programming framework implementation scheme, absorbing the concept of Spring framework Service to achieve API coupling between modules.

CTMediator- Based on Mediator mode and target-Action mode.

Q: How do I design a route for jumping between modules?

A: There are several principles to follow when designing A route.

First, it is easy to integrate, and a route can be implemented with minimal changes. Second, verify the correctness of parameters as early as possible, not at run time if it can be verified at compile time. Third, as far as possible to support a variety of registration, static registration, dynamic registration, service configuration and so on.

In the next article, we will write a service component for module communication step by step.

Architecture and componentization series: from 0 to 1 implementation of a module to module communication service component, step by step with you to write a module to communication service component.

The article was first posted on GitHubGithub.com/Lobster-Kin…