Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the misunderstandings of MVC/MVP/MVVM

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article is to share with you what are the misunderstandings about MVC/MVP/MVVM, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

Using MVP and MVVM patterns in Android development is nothing new, and all kinds of MVP/MVVM-related articles and open source libraries are common, even dazzling, so why should I paint on this blackboard that has already been doodled? I would also like to warn those of you who have read this article: your understanding of MVX may not be entirely correct!

Note: in this article, I will use MVX as a general term for MVC, MVP and MVVM.

We all know that the evolution of MVX is from ball beasts to MVC, then from MVC to MVP, and then from MVP to MVVM. So next, according to the usual routine, I should introduce what is MVC, what is MVP, and what is MVVM, and introduce the respective responsibilities of M, V, and C/P/VM.

My goal is to correct some misunderstandings about MVX, so the premise is that you have some knowledge of MVX. In order to avoid detours when using MVX, I decided to summarize and correct some of the misunderstandings I saw about MVX. The reason for these misunderstandings, according to my analysis, is that I do not really understand the core values of MVX ism! In fact, the core idea of MVX is also very simple, do not get me wrong, not rich and strong, democratic, but to separate the performance layer from the business layer.

Separation of presentation layer and business layer

The presentation layer is separated from the business layer, and Matin Fowler calls it Separated Presentation. The presentation layer here is VX, and the business layer is M. If someone sees here and finds that it is different from what you think of MVX, then your understanding of MVX is likely to be wrong, and seriously, it may be that you have taken the revisionist line!

From the perspective of the separation of the presentation layer and the business layer, M, V and X are not equal identities, but M and Vmurx. From the beginning to the end, the responsibility of M has not changed, but VmurX has changed. with the development of software development technology and the continuous change of interactive forms or interactive media, the logic of the presentation layer is becoming more and more complex. The evolution process of MVX is a process of constantly exploring to deal with the complex logic of the presentation layer. Of course, evolution from one form to another is not necessarily to solve more complex interaction logic, but also to have a "more elegant" way to deal with presentation logic.

Now that there is the concept of separation between the presentation layer and the business layer, the first misconception is easy to explain.

Error 1: Presenter or ViewModel is responsible for handling business logic

This is a common misconception, as many articles about MVP or MVVM have said. As mentioned earlier, business logic belongs to the M layer, so what does Presenter or ViewModel do, dealing with presentation layer logic? Yes, or most of the presentation layer logic is handled in Presenter or ViewModel. I used to call this logic above the business layer view logic, but now it's called presentation layer logic for unification.

I'll just talk a little bit about what presentation logic is and how View and Presenter/ViewModel work together. Suppose your application has a profile page of personal data, which has two states, one is browsing state, the other is editing state, the transition of state is triggered by an edit button, and some information items can be edited when editing state. Then there is an obvious presentation logic, which is to click the button to switch the browsing / editing state.

The popular form (or variant) of MVP today is called Passive View, and like MVVM, it now tends to hand over almost all presentation layer logic to Presenter or ViewModel. The View layer needs to do very little, basically accepting user events and passing them to Presenter or ViewModel. Explained by the example of the profile page above, the View layer is responsible for receiving the click event of the edit button, then notifies the Presenter/ViewModel, and the Presenter/ViewModel tells the View whether to display the view of the browse state or the view of the edit state. The sample code for MVP looks something like this:

Public class ProfileView {void initView () {/ / registers the click event listener and notifies presenter editStateButton.setOnClickListener (new OnClickListener () {presenter.onEditStateButtonClicked ()) of the click event. }).} / / display the browsing status view. If you can't think of a good name, call it showNormalState () public void showNormalState () {/ / Edit button prompt text is "edit", all items are not editable editStateButton.setText ("edit"); nickName.setEditable (false) .} public void showEditState () {/ / Edit button prompt text is "done" in browsing state, and some items should be set to editable editStateButton.setText ("done"); nickName.setEditable (true);.} public class ProfilePresenter {private State curState = State.NORMAL When the public void onEditStateButtonClicked () {/ / button is clicked, it is judged that the View should switch the displayed state according to the current state / / this is the presentation layer logic if (isInEditState ()) {curState = State.NORMAL; view.showNormalState ();} else {curState = State.EDIT; view.showEditState () } private boolean isInEditState () {return curState = = State.EDIT;} @ VisibleForTest void setState (State state) {curState = state;}}

Note: this sample code is only to show the presentation layer logic, does not involve the Model layer, and the compilation will not pass!

Can you feel what I'm trying to say? It is Presenter/ViewModel that decides what to display based on the current interaction state, and what View does is how to display them. For example, for a drop-down refresh scenario, View tells Presenter/ViewModel that it received the drop-down event, and then Presenter/ViewModel tells View to display the refresh prompt view, and it is up to View to decide what the refresh prompt looks like. Of course, Presenter/ViewModel may also determine that the current network is unavailable, and let View display a prompt view of the network unavailable.

Why let Presenter/ViewModel handle almost all the presentation layer logic? The main purpose is to improve testability by bringing as much presentation layer logic as possible into the scope of unit testing. Because it is too difficult to unit test the display of view controls, and so on, it is almost impossible for View to do unit testing, but Presenter/ViewModel can do unit testing:

Public class ProfilePresenterTest {private ProfilePresenter presenter; private ProfileView view; @ Test public void testShowEditStateOnButtonClick () {/ / click the edit button in the browsing state to verify that View displays the edit status view / / that is, to verify that the view.showEditState () method has been called presenter.setState (State.NORMAL); presenter.onEditStateButtonClicked (); Mockito.verify (view). ShowEditState () } @ Test public void testShowNormalStateOnButtonClick () {/ / Click the finish button in the editing state to verify that View displays the browsing status view / / that is, to verify that the view.showNormalState () method has been called presenter.setState (State.EDIT); presenter.onEditStateButtonClicked (); Mockito.verify (view). ShowNormalState ();}}

You see, all this presentation layer logic can be unit tested! I guess you see what I mean?

OK, now that you know the presentation layer, what is the business layer for? Now we're going to talk about M.

What is M? M refers to those who like to get sex from abuse. Oh, I'm sorry, I'm confused! Ah, a great deal of knowledge is trouble! M, Model, a little longer is Domain Model, the Chinese name is domain model. Let's take a look at Wikipedia's definition of Domain model:

In software engineering, a domain model is a conceptual model of the domain that incorporates both behaviour and data.

How is it? is it easy to understand? Of course not! I just started to understand that the Model layer deals with business logic, but now there's a MMM. Domain, I don't even know where to think! Domain, to put it simply as a business, I think there's nothing wrong with it. I quote this sentence here mainly to emphasize that the Model layer contains business data and operations on business data (behaviour and data), but also to lead to the second misconception.

Error 2: Model is static business data

When we do business module development, we often define some data structure classes, such as personal data may correspond to a UserProfile class, an order data may correspond to an Order class, these classes do not have any logic, only some simple getter, setter methods. Some people would think that a data structure class like UserProfile or Order is Model.

We have emphasized that the Model layer contains business data and operations on it. Instances of data structure classes like UserProfile or Order can't even be called objects. Take a look at Uncle Bob's Classes vs. Data Structures article, objects have behavior. An instance of a data structure has no behavior and can't even be called an object. How can it represent the Model layer?

Static business data can not represent the Model layer, business data and operations against business data together constitute the Model layer, which is the business logic. For another example, let's say you're working on an app called "Iron digging", which now has only one page to display a list of recommended blogs. OK, how do we write it in the form of MVP? Regardless of the fact that there is no View interacting with the Model layer at all, the Presenter layer not only deals with the presentation layer logic, but also issues business instructions to the Model layer. Note that Presenter does not deal with business logic, and the real business logic is completed by the Model layer. The sample code looks something like this:

Public class RecommendBlogFeedPresenter {private RecommendBlogFeedView view; private BlogMode model; public void onStart () {view.showLoadWait (); model.loadRecommendBlogs (new LoadCallback () {@ Override public void onLoaded (List blogs) {view.showBlogs (blogs);}})} public interface BlogModel {void loadRecommendBlogs (LoadCallback callback) } public class BlogModelImpl implements BlogModel {private BlogFeedRepository repo; @ Override public void loadRecommendBlogs (LoadCallback callback) {/ / BlogFeedRepository.fetch () is probably a time-consuming operation, so when it is actually written, it will be executed on a non-main thread. Here is just a sample callback.onLoaded (repo.fetch ("recommend"));}} public interface BlogFeedRepository {List fetch (String tag);}

What? This is the only line of code in your BlogModelImpl, and you told me this is business logic? Everybody calm down and put down the bricks, machetes and mace in your hands. Although the logic in the BlogModelImpl class is simple, it is indeed business logic, and it is precisely because the business logic is relatively simple that the BlogModelImpl class is very concise.

Then look at why loadRecommendBlogs () belongs to business logic from the perspective of Presenter. The concept of blog undoubtedly belongs to the business concept. According to the previous explanation, it should be concluded that "getting the list of recommended blogs" does not belong to the presentation layer logic, then the implementation of this logic is not what Presenter needs to care about, it should be the responsibility of the Model layer, since it is the Model layer, it should be the business logic. Furthermore, since blog is a business concept, Blog is the data structure of business data, and loadRecommendBlogs () involves operations such as the creation and assembly of business data Blog, so it should also be business logic.

Seeing here, some people may have some misunderstandings: the so-called business logic processing is data acquisition logic such as network requests and database queries, that is, the Model layer is responsible for data acquisition. This is also the third wrong point I would like to say. Just a moment. I'll write a title ⬇ first.

Error 3: the Model layer is responsible for data acquisition

To put it bluntly, those who have this misunderstanding still do not understand the business logic. Of course, business logic itself is a very abstract concept, difficult to understand and difficult to distinguish, and I dare not go into details, because I am afraid that you will find out that I am also swimming naked.

The business logic layer is not responsible for data acquisition, and the responsibility for data acquisition lies in the lower layer of the Model layer, which is why I write the implementation logic of BlogModel so simply, because all the responsibility for data acquisition is assigned to the BlogFeedRepository class, and the Model layer only deals with business logic. BlogFeedRepository is a repository of blog lists, and BlogModel uses the fetch () method of BlogFeedRepository to get the list of blogs labeled recommend, that is, the recommended list of blogs. BlogModel does not care how BlogFeedRepository obtains the corresponding blog data, it can be obtained through network requests or from the local database, and any change in the data source should not affect the business logic in BlogModel.

So since the business logic in BlogModel is so simple, why forcibly add such a Model layer instead of letting Presenter use the BlogFeedRepository class directly to get the data?

Of course there's a reason! Assuming that the "dig iron" app we just introduced still attracts a lot of users even though there is only one blog list page, the product manager decides to try to explore the means of cashing in, starting with adding advertising data to the blog recommendation list. Suppose again, because the advertising data and blog data belong to different back-end teams, the two sides of the data have not yet been integrated, and the client is temporarily responsible for adding advertising data to the blog list. At this time, BlogModel finally highlighted the necessity of its existence. The presentation layer is not responsible for the acquisition and integration of advertising data, and BlogFeedRepository is not responsible for the acquisition and integration of advertising data. The integration of advertising data is the business logic, which is responsible for by BlogModel, and the acquisition of advertising data is responsible for special data warehousing. The sample code is as follows:

Public class BlogModelImpl implements BlogModel {private BlogFeedRepository blogRepo; private AdRepository adRepo; private BlogAdComposeStrategy composeStrategy; private AdBlogTransform transform; @ Override public void loadRecommendBlogs (LoadCallback callback) {List ads = adRepo.fetch ("recommend"); List blogs = blogRepo.fetch ("recommend"); / / integrate advertising data into the blog list here blogs = composeStrategy.compose (blogs, ads, transform); callback.onLoaded (blogs) }} public interface AdRepository {List fetch (String tag);} public interface BlogAdComposeStrategy {List compose (List blogs, List ads, AdBlogTransform transoform);} public interface AdBlogTransform {Blog transform (BlogAd ad);}

Considering that advertisements and blogs may have different integration strategies and can replace different implementations as needed, the integration strategy is encapsulated in the BlogAdComposeStrategy interface. The integration strategy also belongs to business logic, but since there is no need to pay attention to the implementation details of the integration strategy here, I think it's okay not to write it out. I made it up anyway.

What I want to say here is that getting advertising data and integrating it into the blog list is also part of the business logic. Omitting the Model layer will result in putting the integration logic of advertising into the Presenter or Repository layer, which must not be appropriate. Putting the business logic into the wrong level is bound to cause subsequent maintainability and scalability problems.

Error 4: the Model layer depends on the Presenter/ViewModel layer

There are some people do not understand the dependency between the Model layer and the upper layer, the dependency is written in both directions, which is wrong, the business layer should not rely on the presentation layer, but the other way around.

In fact, Presenter/ViewModel should rely on the Model layer in the form of interfaces, while the Model layer does not rely on Presenter/ViewModel at all. As in my previous sample code, the Model layer must not have any words like presenter, the upper layer listens for data changes in the Model layer through the observer mode (the LoadCallback interface is also a kind of), and the Model layer does not care about whether the upper layer is Presenter or ViewModel.

These are the misunderstandings of MVC/MVP/MVVM, and the editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report