Preface
Although iOS componentization and routing of the conversation in the industry for a long time, but seems to be a lot of people to the misunderstanding, don't even understand "components", "module", "routing", the meaning of the "decoupling",
Related blog also pretty is much, except that a few actually written by famous artists, has the reference value of the very few, besides famous view is not entirely correct, all architecture often need to weigh the business scenario, learning costs, development efficiency, etc., so the architecture scheme can objectively explain the but again brought some subjective factors, combined with some modification of personal characteristics is particularly easy to put the cart before the horse,
So to keep the mind clear, dialectical view of the problem, the following is the comparison of the industry has the reference value for article:
IOS application architecture about modular solution
Mushroom street App componentized path
IOS componentization routing design analysis
-Application Category features in iOS componentization and controls
IOS componentized solution to explore
This paper is the author's understanding of iOS groupware and routing, makes every effort in a more objective and concise way to explain the pros and cons of various solutions, welcome criticism and corrections,
In this paper, the DEMO
One, the difference between the component and module
Image. The PNG
"Component" emphasizes the reuse, it is directly dependent on various modules or components, is infrastructure, it generally does not include or contain weak business, belong to the vertical stratification (such as network request component, images are downloaded components),
"Modules" emphasizes the encapsulation, it more refers to independent business module functions, belong to the horizontal layered (such as a shopping cart module, personal center module),
So from the point of view we implement the purpose of "modular", called "modular" seems to be more reasonable,
But "component" and "modules" predecessors is defined, the significance of the concept of "iOS modular" has first impressions are most lasting, so only need to understand that "iOS modular" more is to do a business module of decoupling between line,
Second, the meaning of the routing
Must first clear is that routing is not only refers to the interface jump, include data acquisition, almost all businesses such as
(a) simple routing
The way internal call
Follow web routing, the original iOS native routing looks like this:
[Mediator gotoURI: @ protocol://detail? Name="xx"].
Shortcomings are obvious: string URI does not represent the iOS primitive types, to read the corresponding module using document, a lot of hard coded,
Code implementation is probably:
+ (void) gotoURI: (nsstrings *) analytical URI URI {nsstrings * aim the target and the parameters=... ; NSDictionary * parmas=... ; If ([aim isEqualToString: @ "Detail"]) {DetailController * vc=[DetailController new]; Vc. Name=parmas [@ "name"); [... pushViewController: vc animated: YES]; } else if ([aim isEqualToString: @ "list"]) {... }}
Image:
Image. The PNG
After get the URI, always have converted to target and parameters (aim/params) logic, then the real call native modules, obviously, for internal call, parse the URI this step is to gild the lily (casa said in a blog post the problem),
Simplify routing method is as follows:
+ (void) gotoDetailWithName: (nsstrings *) name {DetailController * vc=[DetailController new]; Vc. Name=name; [... pushViewController: vc animated: YES]; }
It's easy to use:
[Mediator gotoDetailWithName: @ "xx"];
So, the method of parameter list can replace additional documentation, and the compiler checks,
How to support external URI call
For outside calls, only need to add a URI parsing for adapter can solve a problem:
Image. The PNG
Where is the routing method to write
Unified routing calls to facilitate the management and use, so usually need to define a Mediator, and considering the different module maintainer are need to modify the Mediator to add routing methods, there may be a conflict of workflow, so the use of decorative pattern, add a classification for each module is a good practice:
@ interface Mediator (Detail) + (void) gotoDetailWithName (nsstrings *) name; @ end
Corresponding routing method of module is then written to the corresponding category,
The role of simple routing
The encapsulation, remove the direct coupling between the business module, but they are indirect coupling (because routing class you need to import the specific business) :
Image. The PNG
However, a simple routing does not need to care about the coupling problem, even such a simple processing also has the following advantages:
The caller clear argument list, easy to use,
To solve the coupling between the business module, business change may interface does not need to change, the external call wouldn't have to change the code,
Even business changes, routing method have to change, thanks to check the compiler, can also position the call directly to make changes,
(2) support the dynamic invocation of routing
Dynamic invocation, just as its name implies is the invocation path in the case of not update App changes, such as clicking on A trigger to jump to B interface, at some point and have to click on A jump to C interface,
To ensure the minimum size of the dynamic invocation, you need to target complete information of the business, such as the aim and params said above, the objectives and parameters,
Then need a set of rules, this rule has two sources:
Did the server configuration,
Some of the local judge logic,
To predict the dynamic invocation of
+ (void) gotoDetailWithName: (nsstrings *) name {if abnormal) (local protection logic DetailController {jump to DetailOldController return; } DetailController * vc=[DetailController new]; Vc. Name=name; [... pushViewController: vc animated: YES]; }
Developers need to clearly know that "a business" to support the dynamic invocation and dynamic invocation target is "a business", that is to say, this is a kind of "pseudo" dynamic invocation, is to write code logic die, just trigger point is dynamic,
Automated dynamic invocation
Just think, that way above + (void) gotoDetailWithName (nsstrings *) name; Can support the automatic dynamic invocation?
The answer is no, to achieve real "automation", will be required to satisfy a condition: need all routing method of a plane,
The purpose of this section is to intercept the routing objectives and parameters, then dynamic scheduling, the mention of AOP you might think of Hook technology, but for the following two routing method:
+ (void) gotoDetailWithName (nsstrings *) name; + (void) pushOldDetail;
You can't find the similarities between them, it is difficult to hit,
So, get a plane method I can think of only one: unified routing approach entrance,
Define a method like this:
- (void) gotoAim: (nsstrings *) aim params: (NSDictionary *) params {1, dynamic invocation logic judge (issued by server configuration) 2, through the aim and specific business params dynamic invocation}
(how about dynamic invocation after the implementation of the specific business technique can speak, no need to worry about here, just need to know here there are these two parameters to dynamic positioning to the specific business,)
Then, routing method inside so wrote:
+ (void) gotoDetailWithName: (nsstrings *) name {[self gotoAim: @ "detail" params: @ {@ "name" : name}]. }
Note @ "detail" is agreed upon good Aim, can internal dynamic positioning to the specific business,
Unified entrance routing method, therefore, it need hard coding, for this solution automated dynamic invocation necessarily hard-coded,
Here, then, the use of a classification method + (void) gotoDetailWithName (nsstrings *) name; Hard-coded packing up is a good choice, the hard code to corresponding business go to maintenance engineers,
Casa CTMediator classification is to do so, and it also is the place of mushroom street componentization scheme can be optimized,
Routing summary
Can be found that the author used the great length about the routing, but did not mention modular, that is because there are routing does not necessarily need componentization,
Routing design is mainly consider need not to need to do the whole link automated dynamic invocation, enumerate several scenarios:
Native page appear problem, need to switch to the corresponding wap page,
Wap traffic is too large to switch to the original page to reduce consumption,
Dynamic invocation can be found, the entire real link cost is very high,
Three, the significance of componentization
Right in front of the parameters used by analysis of the mentioned goals and dynamic positioning (aim/params) to the specific technical points of the business, in fact, iOS Objective - C about reflection and dependency injection two ideas:
Specific aim can be converted to the Class and SEL, use the runtime run-time use specific business,
For the code, the process space is Shared, so maintain a global mapping table, map the aim to a piece of code in advance, call to perform specific business,
Can be clear that these two approaches have been let Mediator was relieved from the dependence on business module:
Image. The PNG
And these decoupling technology, to the heart of the iOS modular,
Componentization main purpose is to let each business module independently, each other, so completely decoupling between business module is inevitable, at the same time for business module split is also very fastidious, should pursue more functionally independent rather than the smallest size,
(a) the Runtime decoupling
Defines a unified entrance for the Mediator method:
///this method is a blocker, fault-tolerant and dynamic scheduling can do - (id) performTarget: (nsstrings *) target action: (nsstrings *) action params: (NSDictionary *) params {Class CLS. Id obj. SEL SEL. CLS=NSClassFromString (target); if (! CLS) goto fail; nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull