When we start to design the architecture of the View layer, it is often the case that the App has not yet been developed, or that the App has been released in several versions, and then needs to do a very thorough refactoring.

Generally speaking, these two kinds of time opportunities are used to do View layer architecture. Based on the particularity of this time, we must clearly realize that once the View layer architecture is realized or finalized, there is very little room for modification after App release. Because it is most closely related to the business, the butterfly effect caused by the slightest movement is not necessarily something that the business side can handle. In this case, the code must be changed diligently and not lazy when implementing the architecture. You also have to have plenty of self-doubt, and you have to be careful when you make decisions.

The architecture of the View layer is very important. Why?

The View layer architecture is one of the factors that affects the iteration cycle of the business side

Product managers can generate demands very quickly, especially when the company is still in the initial stage of entrepreneurship. In larger companies, product managers also like to dig big pits to impress their presence in front of the leader, such as Ali. This leads to heavy tasks for business engineers. It’s not normally possible for a product manager to cut down on requirements, so as an architect, there are some things you can or can’t do in the architecture, and it’s best to do them when you can. This helps the business side take a load off their shoulders and focus more on the business when writing code.

When I talk to some of my friends, they all complain at one point or another that their teams aren’t iterating fast enough, or that they’re iterating unreasonably slowly. In my opinion, it is not easy to mention the iteration speed. There are many factors affecting the iteration speed. The amount of tasks and the complexity of tasks in the first PRD will affect the degree of iteration cycle. External issues aside, one of the internal reasons for iterations not being as fast as they should be is that the View layer architecture is not doing a good job of allowing business engineers to handle too much extra work to complete a non-complex requirement. Of course, too many meetings and poor engineers also belong to the internal reasons that the iteration speed cannot be improved, but this is not the scope of this article. Also, overtime is not the right way to optimize the iteration cycle, HMM.

Generally speaking, there are five main reasons why a View layer architecture is not good enough:

  1. The code is messy and non-standard
  2. Complex dependencies resulting from excessive inheritance
  3. The modularity degree is not high enough, and the granularity of components is not fine enough
  4. Transverse rely on
  5. Architectural design loses its heritage

These five areas can affect the efficiency with which business engineers implement requirements, thus slowing down the iteration cycle. Other flaws in the View architecture also play a part, but in my opinion these five are the most important. If you think there are any factors that are higher than these four, feel free to mention them in the comments section and I’ll fill them in.

As for the fifth point, I would like to emphasize that architecture design must have inheritance. Architecture with inheritance will be very harmonious on the whole. However, the actual situation may be that when one person leaves, another takes over. Even if the task handover is complete, different people inevitably have different architectural ideas, thus affecting the smoothness of the entire architecture. To solve this problem, on the one hand, try to avoid a single point of view and have the architect bring a second person to work on the architecture. On the other hand, the architecture should be as simple as possible to smooth out the learning curve for the person taking over.

Therefore, when ctos, TECHNICAL directors and Teamleaders feel that the iteration cycle is not fast enough, you can take your time and hire new people. “The Myth of man-month” has long said that adding new people cannot completely solve the problem. At this point, if you can go back and see if the View layer architecture doesn’t make sense, getting this right is one way to optimize the iteration cycle.

The View layer architecture is the underlying architecture closest to the business

The View layer architecture is low-level, but not that low-level. It has the most interaction with the business and affects the business layer code the most. Pulling on the View architecture causes the business layer to move the largest area of the entire body while all the layers are pulling.

So, of all the architectures, the View architecture has the least room for modification once it’s finalized, and when we first started thinking about view-related architectures, we had to think about more than just functionality, but also specifications. The purpose of the specification is not only to prevent the business engineers’ code from corroding the View architecture, but also to preserve heritage. According to the norms, it is not so easy to go wrong.

Began to think of something there is, the architect will also have a lot of, can’t achieve them all in the first edition, for has yet to send a version of the App, the first edition of architecture tends to be the smallest complete feature set, then in the second version of the process of the development of the third edition, the architecture of the iterative task is not only very likely you one thing, I don’t think you can do it all by yourself. So you have to make a deal with your collaborators. In addition, after the first version is released, business engineers will also have a lot of revision opinions in the process of use. Which opinions are reasonable and which are not reasonable, they will also be screened through the agreed norms in advance, and finally decide how to adopt them.

Norms are not immutable. It depends on your skills and experience when to reject your opinions and when to change them.


That’s the foreword.

What is the passage about?

  • View code structure specification
  • About the layout of the View
  • When to use storyboard, when to use NIB, when to write views in code
  • Is it necessary for the business side to derive viewControllers uniformly?
  • Convenient View layout widgets
  • MVC, MVVM, MVCS, VIPER
  • This door method
  • View processing across businesses
  • Leave it to the comments section
  • conclusion

View code structure specification

The architect doesn’t just write an SDK and deliver it to the business. Every company must have a code specification, and the architect’s responsibility includes defining the code specification. By definition, the code specification should be generic, and the reason for this is simply that I need to add a specification for View.

Writing code specifications is not strictly a View layer architecture thing, but it will have a significant impact on the future of the View layer architecture and is something that architects need to consider when designing the View layer architecture. The importance of specifying the View layer is:

  1. Improve the readability and maintainability of the business View layer
  2. Prevents architecture corrosion by business code
  3. To ensure the inheritance
  4. To keep the direction of the framework from being easily influenced by unreasonable opinions

In this section, I am not going to define a set of specifications from scratch. Apple has a set of Coding Guidelines. When we decide the code structure or specifications, we must first comply with this specification.

However, I believe that you have your own set of specifications in your company, and the specific specifications are based on the experience of your architects. I just suggest that you add the following to your specifications.

The viewController code should look something like this:

The main points are as follows:

All properties use getters and setters

Don’t initialize your view in viewDidLoad and then add it, that’s ugly code. In viewDidload you just do the addSubview thing, then you do the layout thing in viewWillAppear (Errata 1), and then you do the Notification listening thing in viewDidAppear and so on. The initialization of the property is left to the getter.

Like this:

#pragma mark - life cycle - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:self.firstTableView]; [self.view addSubview:self.secondTableView]; [self.view addSubview:self.firstFilterLabel]; [self.view addSubview:self.secondFilterLabel]; [self.view addSubview:self.cleanButton]; [self.view addSubview:self.originImageView]; [self.view addSubview:self.processedImageView]; [self.view addSubview:self.activityIndicator]; [self.view addSubview:self.takeImageButton]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; CGFloat width = (self.view.width -30) / 2.0f; CGFloat width = (self.view.width -30) / 2.0f; self.originImageView.size = CGSizeMake(width, width); [self.originImageView topInContainer:70 shouldResize:NO]; [self.originImageView leftInContainer:10 shouldResize:NO]; self.processedImageView.size = CGSizeMake(width, width); [self.processedImageView right:10 FromView:self.originImageView]; [self.processedImageView topEqualToView:self.originImageView]; CGFloat labelWidth = self.view.width - 100; self.firstFilterLabel.size = CGSizeMake(labelWidth, 20); [self.firstFilterLabel leftInContainer:10 shouldResize:NO]; [self.firstFilterLabel top:10 FromView:self.originImageView]; . . }Copy the code

So even if you have a lot of properties, you can keep your code clean, and the getter does all the initialization of the view. In short, try not to appear the following situation:

- (void)viewDidLoad { [super viewDidLoad]; self.textLabel = [[UILabel alloc] init]; self.textLabel.textColor = [UIColor blackColor]; self.textLabel ... . self.textLabel ... . self.textLabel ... . [self.view addSubview:self.textLabel]; }Copy the code

That’s not clean enough, just throw it all in the getter. There is an article in Tang Qiao’s technology blog about this approach that is different from what I advocate, which I will discuss in more detail later.

Getters and setters are all at the end

Because a ViewController can have a lot of views, like the code sample above, if you write the getters and setters first, you’re dragging the main logic behind, and everyone else is going to have to go through a long list of getters and setters first, which is not a good idea. The business engineer is then asked to assign the location of the code block in order when writing the code, first the Life Cycle, then the Delegate method implementation, then the Event response, then the getters and setters. This will save a lot of effort for later comers to read the code.

Each delegate has the corresponding protocol name attached to it, and the delegate method should not be written all over the place

For example, UITableViewDelegate’s set of methods and just say #pragma mark – UITableViewDelegate. One advantage of this is that when someone else is reading a Delegate implementation method that he or she is not familiar with, he or she can simply hold down command and click on the protocol name, and Xcode will immediately jump to the code that corresponds to the Delegate’s protocol definition, saving him or her from having to look around.

Event Response opens a code area

All button and gestureRecognizer response events are stored in this area.

As for private methods, normally you shouldn’t write them in ViewController

It’s not a delegate method, it’s not an Event response method, it’s not a Life Cycle method, it’s a private method. Yes, normally there is no private methods in ViewController. This private methods are usually used for date conversion, image cropping and other small functions. This little function can either be a category, or it can be a module, even if the module has only one function.

The ViewController is basically the carrier of most of the business, and the code itself is quite complex, so don’t put anything that is not relevant to the business in the ViewController. In addition, the private method function is only available to you at this time, but may be used in other places in the future. It is independent from the beginning, which is conducive to future code reuse.

Why do you ask for that?

I’ve seen a lot of viewControllers, and the code layout is all over the place, a delegate here and a getter there, and the ViewController code tends to be all over the place, and it’s a pain to look at.

By defining this specification, viewControllers are organized so that business programmers can distinguish between what is appropriate and what is not in a ViewController. It also improves the maintainability and readability of your code.

About the layout of the View

Business engineers cannot escape this proposition when writing a View. Use Frame and Autolayout as well, if not carefully designed, the layout will look terrible.

If you use CGRectMake directly, it’s not very readable, and you can’t tell the position relationship between views just by looking at the numbers. Autolayout is a little more readable, but the generated Constraint is too long and the code doesn’t look good.

For Autolayout, I would like to retrieve the next post. If you still use Frame, consider using this project.

This project provides a convenient method (UIView+LayoutMethods) related to Frame, which basically covers all layout requirements and is very readable. After using it, you can say goodbye to CGRectMake.

This project also provides a convenient way to produce Constraints under the Autolayout scheme (UIView+AEBHandyAutoLayout), which is much more readable than native. I would like to post all these articles without knowing it. Knowing that I would like to retrieve all the items I would like to retrieve, I would like to retrieve all the items I would like to retrieve. These methods are not as powerful as those I would like to retrieve, but they can be used. At that time, all the View layout of anjuke iPad App was done by Autolayout, which is the method used in this project. Very readable.

Having business engineers use good tools to lay out views increases their productivity and reduces the chance of bugs. Architects should not only care about the high profile content, but also provide business engineers with easy-to-use gadgets to maximize the value of architects.

Here I would like to add something else:

IOS development teams of a certain size (more than 10 people) have the following characteristics:

  1. The same code file can have many authors, and it is not uncommon for different authors to modify the same code at the same time. Therefore, Conflict is more likely to occur when using Git for code versioning.
  2. Requirements change so frequently that the product manager makes tweaks to existing code in order to fulfill requirements, and to existing codePart of the reuseIs also more.
  3. Complex interface elements, complex animation scene development tasks are more.

If these three features are obvious to you at first glance, you can skip the explanation below. If you would like to discuss further my preference, you can read my explanation below first.

The same code file can have many authors, and it is not uncommon for different authors to modify the same code at the same time. Therefore, Conflict is more likely to occur when using Git for code versioning.

During iOS development, the two most painful conflicts are project. Pbxproj and StoryBoard or XIB. Because the contents of these files are very unreadable, apple has made some improvements to the way StoryBoard files are described in XCode5 (now I’m not sure if that’s the version), but it’s only improved the readability from very bad to very bad.

However, storyboards often contain multiple pages, and it is almost impossible for one person to complete all of these pages. If another person moves a page that does not belong to him for some purpose, such as changing the position for aesthetic purposes. Then someone else changes the position of some other page in the Storyboard to add a page. All I can say in response to the situation is: Good luck. Take a look at it. It’s not even touching the page.

But if you draw the View in code, Conflict will also happen, but it’s a lot easier to solve, you know.

Requirements change so frequently that the product manager makes a whim, fine-tunes existing code to meet requirements, and reuses parts of existing code.

I don’t think it’s the product manager’s fault that he has a sudden idea. He’s probably forced to do it. For example, everyone in the company, from the CEO down to the junior staff, can comment on the product design. Whenever he has a personal problem (most likely a personal preference) and happens to be familiar enough with the product manager to be relevant, he will offer a variety of opinions. Product managers can’t hide, can’t provoke, and sometimes can’t help it. Yeah.

But when it comes to engineers, it’s a pain in the ass. Because of this change, sometimes not only the UI, but also the logic corresponding to the UI may need to be changed, and engineers will change both files. The view that you used to link is no longer linked, and your outlet correspondence also needs to be deleted. As long as one of these two parts is not done, after the compilation passes, run the App, and then crash. It doesn’t seem like a big deal, but it can affect your mood.

In addition, if part of the code is reused, for example, a View on one page also wants to be placed on another page, the related operation is not so easy to copy and paste, you have to link again. It also affects your mood.

Complex interface elements, complex animation interactive scene development tasks are more.

If you want to do an animation in a storyboard-based project, it’s annoying. Making several complex interface elements is also annoying. Sometimes we’ll put a Custom View on it, but it looks like a blank View in our StoryBoard. The other thing is that when you have a layout problem that needs to be adjusted, it can be very difficult to find the problem, especially in the case of complex interface elements.

So when it comes to requirements on the View side, I also recommend not using storyboards. To implement simple things, it’s as simple as Code, to implement complex things, Code is simpler than StoryBoard. So I’m more of a proponent of drawing views in code rather than storyboards.

Is it necessary for the business side to derive viewControllers uniformly

Sometimes we derive our own ViewController from UIViewController to perform some general logic for the purpose of recording user behavior data, or for uniform page configuration purposes. For example, tmall client requires that all viewControllers inherit from TMViewController. There are some Settings in this unified parent class for all of a ViewController’s life cycles, which are not important for this article. What I want to discuss here is, when designing a View architecture, is it necessary to use a derivative approach in order to be able to achieve uniform setup or perform uniform logic?

I don’t think it’s necessary. Why not?

  1. It is easier to increase the cost of use by the business side using derivation than not using derivation
  2. Uniform Settings can be achieved without derivative means

These are the two reasons I don’t think derivations are necessary, and if you understand both of them, you can skip the rest. If you’re still a little confused, let me explain why.

Why does derivation increase the cost to the business side?

In fact, not only the cost of using the business side, but also the maintenance cost of the architecture will go up. So where does the cost come from?

  • Integrated cost

The cost of integration is this: If the business side opens a separate demo, quickly completes a separate process, and now wants to integrate the existing process. So the problem is, he needs to change all of his individual UI view controllers to TMView Controllers. So why not use TMViewController right from the start? Because if you want to introduce TMViewController, you need to introduce all the business lines of the whole Tmall App and all the basic libraries, because this parent class involves a lot of content only available in the Tmall environment, the so-called pull out the radish and bring out the mud, if you want to simply inherit things, it will take a long time to build the environment. And then this little Demo can run.

For business layer exists all the parent class, they are easily entangled with other code in the project, which makes the business party development faced a dilemma: either to fix all rely on, and then based on the environment (such as Tmall) under development Demo App, or write their own Demo, in accordance with the requirements for environmental change code. Each of these dilemmas carries a cost and affects the iteration schedule of the business side.

I am not sure whether your company will have such a situation, but I can give you a real example here: in the development of a filter Demo and related page process, it will be merged into the App of Tmall. Using the Tmall environment for development, it takes about 10 minutes for pod install to complete all dependencies, and then after opening workspace, it takes about another minute for Xcode to complete indexing before starting work. However, if the Tmall environment is updated, you have to repeat the above process again, otherwise it is very likely to compile the failure.

Please, I just want to make a Demo. I don’t want to get complicated.

  • Acceptance cost

New business engineers sometimes don’t remember that every ViewController must be derived from TMViewController and not directly from UIViewController. The new engineer couldn’t do things the way Apple did them. He had to learn something extra. For example, all viewControllers must inherit from TMViewController.

  • Maintenance difficulty of the architecture

Use inheritance as little as possible to improve the maintainability of your project, as described in “Beyond Object-oriented Thinking (I) Inheritance,” but I don’t want to repeat what I said in that article.

In fact, for the business side, the first integration cost is mainly a pain, because it is a constant pain, every time you want to do something. The second one was okay. It hurt a little bit. The third point has nothing to do with business engineers.

So what should we do if we don’t use derivation?

My recommendation is to use AOP.

Before an architect can implement a specific solution, several questions must be thought through before deciding which solution to adopt. What are they?

  1. What is the effect of the program and the ultimate goal to achieve?
  2. Do you have the ability to realize this project in your own knowledge system?
  3. Is there a wheel that you can use directly from the existing open source components in the industry?

After these three questions are answered one by one in order, the specific plan can come out.

Let’s look at the first question: what is the effect of the program and what is the ultimate goal to achieve?

The effect of the scheme should be:

  1. The business side can do without the inheritance method, and then the framework can do uniform configuration of the ViewController.
  2. The business side can run the code without modifying any code even if it is outside the framework environment. Once the business ViewController is dropped into the framework, the framework does what it’s supposed to do without any code changes.

In fact, it is to achieve the function that the business can be perceived by the framework without actively catering to the framework through the business code. There are two problems, the framework needs to be able to intercept the ViewController’s lifetime, and the other problem is when to define the intercept.

Method Swizzling is an easy way to think about Method interception, so we could write an instance and add Method interception for UIViewController at App startup, that’s one way to do it. Another way to do this is to use NSObject’s load function, which automatically listens when the application starts. The advantage of using the latter is that the module works as long as it is included in the project, without adding any code to the project.

The other thing to consider, though, is that the original TMViewController (the so-called parent class) also provides extra methods for subclasses to use. Method Swizzling only supports operations on existing methods, extending methods with, well, categories, of course.

I personally disapprove of the overuse of categories, but since they are the most typical means of inheritance to composition, they are appropriate in this scenario. Also, there is an open source library for Method Swizzling to implement Method interception: Aspects that we can use directly.

And then the other thing to remember is that the purpose of this scheme is to eliminate unnecessary inheritance, although it’s not limited to UIViewController, it does have scope, and where inheritance does apply, you should use inheritance honestly. For example, if you have a data model, which is a set of models derived from the base model, then use inheritance honestly. As for deciding when to use inheritance, I’m sure architects can handle it well.

Lots of ideas about MVC, MVVM, etc

In fact, these are relatively general ideas, and the three roles I mentioned in the opening paragraph remain the same: data manager, data processor, and data presenter. These various ideas are nothing more than a specification of how data should be exchanged between the three roles. But these are also the most controversial topics, so I’m here to sort out a few mainstream ideas, when you do the View layer architecture, can have a good reference.

MVC

MVC (Model-view-Controller) is the most old idea, so old that it is classified as a mode in the gang of four books, in which Model is the data manager, View is the data show, and Controller is the data processor. Both Model and View are deployed by the Controller according to business requirements, so the Controller also bears a function of data flow deployment.

How should we divide MVC in iOS development?

There are really two problems:

  1. Why are we obsessed with the MVC division in iOS development?
  2. What’s the right way to divide in iOS development?

Why are we obsessed with the MVC division in iOS development?

Everyone may have a different point of view on this, and I don’t know your opinion. But let me guess: is it because the UIViewController comes with a View, and controls the View of the whole life cycle (viewDidLoad, viewWillAppear…). , and we all know that the Controller should not be so closely related to the View, so it leads to confusion about the division. Right? Here’s my take on the speculation.

In server-side development, controllers and views interact like this, such as Yii:

/ *... Database fetch data... Processing data... * / / / here $this is Controller $this - > render (" the plan ", array (' planList '= > $planList,' plan_id = > $_GET [' id '],));Copy the code

The distinction between Controller and View is very clear. After the Controller does its job, it leaves all the work of the View to the rendering engine. The Controller does not do anything about the View, including generating the View, which is done by the rendering engine. This is a difference, but the real difference between the server View concept and the Native app View concept is: Conceptually, there is no View at all on the server. Thanks to the HTTP protocol, the View we usually talk about is just a string that describes the View (more essentially, it should be called data).

So the server only generates the description of the View, as for the View’s appearance, UI event monitoring and processing, are generated and maintained by the browser. But from Native’s point of view, tasks that belong to the browser can’t be avoided without doing them yourself. So who’s the best person to do it? The answer from apple is UIViewController.

Given that Apple has done a lot of hard work in this layer, iOS engineers don’t have to implement it themselves. And what’s more, it puts all the functionality on UIView, and it makes UIView not only to display the UI, but also to be an object in the container.

Do you see what I mean here? Another UIView is actually a container! The view that comes with UIViewController, its main job is to be a container. If all its associated names were changed to ViewContainer, the code would look like this:

- (void)viewContainerDidLoad { [self.viewContainer addSubview:self.label]; [self.viewContainer addSubview:self.tableView]; [self.viewContainer addSubview:self.button]; [self.viewContainer addSubview:self.textField]; }... .Copy the code

With just a name change, does it feel a lot clearer now? To be a bit more specific, what we normally think of as server-side MVC is divided like this:

               ---------------------------
               | C                       |
               |        Controller       |
               |                         |
               ---------------------------
              /                           \
             /                             \
            /                               \
------------                                 ---------------------
| M        |                                 | V                 |
|   Model  |                                 |    Render Engine  |
|          |                                 |          +        |
------------                                 |      HTML Files   |
                                             ---------------------
Copy the code

But in fact, the MVC division of the whole process looks like this:

--------------------------- | C | | Controller | | \ | | Render Engine | | + | | HTML Files | --------------------------- / \ / \ HTML String / \ ------------ --------------- | M | | V | | Model | | Browser | | | |  | ------------ ---------------Copy the code

As can be seen from the figure, our server-side development under this concept only involves the development of M and C. As the container of View, the browser is responsible for the display of View and the monitoring of events. So the MVC division corresponding to iOS client is like this:

               ----------------------------
               | C                        |
               |   Controller             |
               |           \              |
               |           View Container |
               ----------------------------
              /                            \
             /                              \
            /                                \
------------                                  ----------------------
| M        |                                  | V                  |
|   Model  |                                  |    UITableView     |
|          |                                  |    YourCustomView  |
------------                                  |         ...        |
                                              ----------------------
Copy the code

The only difference is that the View container is on the server and Browser is responsible for it. It makes perfect sense for the View container to be in Browser during the process of the site. On the iOS client, the View container is handled by the View in UIViewController, and I think Apple made the right choice.

Because the relationship between the browser and the server is loose, and they belong to two different camps, the server will be after the description of the View to generate, to the browser is responsible for the show, but what are the events, once the View on basically is seldom passed to the server (that is, the so-called Controller) (to pass can also: AJAX), do all the work on the browser side, so in this case, the View container fits on the browser side (V).

However, in iOS development, there is a practice of having a View listen for events, but this practice is very rare. Instead, the View sends the event back to the Controller, and then the Controller dispatches it. So in this case, the View container is perfectly appropriate for the Controller. The Controller can easily change the contents of the container due to different events, such as changing the contents of the container to the View of the failed page in case of a load failure, or to the View of the container in case of no network, etc.

What is the right posture for MVC division in iOS development?

This question has been partially answered above, so the answer to this question is a summary of the above question.

M should do:

  1. Feed the ViewController data
  2. Provides an interface for the ViewController to store data
  3. Provides abstracted basic business components for Controller scheduling

C Should do:

  1. Manage the View Container lifecycle
  2. Responsible for generating all View instances and putting them into View Containers
  3. Listen for business related events from the View and work with Model to complete business for the corresponding events.

V should do:

  1. Respond to non-business events, animate them, click on feedback (if appropriate, try to do it in View), and so on.
  2. Interface element expression

I answered both of these questions by comparing them to the server-side MVC partition, because I know a lot of iOS engineers who made the switch from the server side.

MVCS

Apple itself adopts this kind of architecture idea, which, as can be seen from its name, is also a set of architecture derived from MVC. Conceptually, the part it splits is the Model part, a Store. This Store is dedicated to data access. But from a practical point of view, it takes apart the Controller.

This is a solution to the thin Model, which is only dedicated to expressing data, and then handing over storage and data processing to outsiders. The premise of MVCS is that it assumes that you are a thin Model and that the data is stored and processed in the Controller. So with MVCS, it starts out as a split Controller. Because a Controller does the job of storing data, it becomes so large that it takes the part of the Controller that is responsible for accessing data and gives it to another object, the Store. After this adjustment, the entire structure becomes a true MVCS.

About fat Model and thin Model

I found that not many people knew the concept of fat Model and thin Model. There have been heated discussions about Fat Model and Skinny Controller in the foreign industry. The industry has not yet decided which one is better, so it is an open debate in the industry right now. I rarely see the domestic discussion of this material, so HERE I intend to add what is called fat Model what is called thin Model. And where their arguments come from.

  • What is fat Model?

The fat Model contains some of the weak business logic. The goal of the fat Model is that once the Controller gets the data from the fat Model, it can apply it directly to the View with very little or no extra action. Here’s an example:

Raw Data: timestamp:1234567 FatModel: @property (nonatomic, assign) CGFloat timestamp; - (NSString *)ymdDateString; // 2015-04-20 15:16 - (NSString *)gapString; // 3 minutes ago, 1 hour ago, 1 day ago, 2015-3-13 12:34 Controller: self.datelabel. Text = [FatModel ymdDateString]; self.gapLabel.text = [FatModel gapString];Copy the code

Convert TIMESTAMP into a string required by the specific business, which belongs to the business code, is weak business. After FatModel does the weak business, the Controller can become very skinny, and the Controller only needs to focus on the strong business code. As we all know, strong businesses are much more likely to change than weak businesses, and weak businesses are relatively stable, so it is no problem for weak businesses to be stuffed into the Model. On the other hand, weak services repeat more frequently than strong services and require higher reusability. If this part of the business is written in Controller, similar codes will be scattered everywhere. Once weak services are modified (low frequency of modification does not mean that there is no modification), this will be a disaster. If you put it in the Model, you can change a lot of things and avoid this disaster.

However, its disadvantage lies in that the fat Model is relatively difficult to transplant, although it only contains weak business, but it is still business, and it is easy to pull out the radish and bring out the mud when migrating. On the other hand, the MVC architecture is more inclined to Model as a Layer, rather than an Object, and it is not right to give an Object what a Layer should do. Last but not least, software will grow, FatModel may become more and more Fat with the growth of software, and finally difficult to maintain.

  • What is a skinny Model?

The thin Model is only responsible for the expression of business data, and all business, strong or weak, is thrown to the Controller. The goal of a thin Model is to write as fine-grained a Model as possible, and then use helper classes or methods to abstract the weak business, leaving the strong business to the Controller. Here’s an example:

Raw Data:
{
    "name":"casa",
    "sex":"male",
}

SlimModel:
    @property (nonatomic, strong) NSString *name;
    @property (nonatomic, strong) NSString *sex;

Helper:
    #define Male 1;
    #define Female 0;
    + (BOOL)sexWithString:(NSString *)sex;

Controller:
    if ([Helper sexWithString:SlimModel.sex] == Male) {
        ...
    }
Copy the code

Since SlimModel has nothing to do with business, its data can be handed over to any Helper or other object that can process its data to complete business. During code migration, independence is strong, and radish is rarely pulled out. In addition, as SlimModel is only data expression, it basically costs zero to maintain it. No matter how much software expands, SlimModel will not be much bigger.

The downside is that Helper doesn’t do a very good job of criticizing this. In addition, because the operation of Model will appear in various places, SlimModel violates the idea of DRY (Don’t Repeat Yourself) to a certain extent, and Controller is still inevitably bloated with code to a certain extent.

My attitude? Well, I’ll talk about it in this section on the mind method.

After all, MVCS is an architectural idea based on thin Model. It abstracts part of the code about data storage into Store, which reduces the pressure of Controller to some extent.

A small summary

To be continued…

Sharing:IOS development of all kinds of books to download

Since the | address