A Demo of Frontend Business Code Architecture in MVVM Pattern
After reading this article, you should have a deep understanding of the MVVM pattern. However, some may still have doubts, feeling that this architecture is somewhat idealistic. Others may perceive the content as theoretical and struggle with its practical implementation. In the following example, I will guide you through the step-by-step design of a code architecture using the MVVM pattern, using a hypothetical product development iteration to ensure a complete understanding of the MVVM pattern.
Iteration One: Membership Functionality
Let's take the example of implementing a membership feature for a supermarket, a business scenario that everyone is familiar with.
Requirements
Background:
- This is a medium-sized supermarket.
- The supermarket currently has a simple cash register system.
- The system involves roles such as the owner, cashier, and shop assistant.
Functional Requirements:
- Customers can become members of the store.
- Members can recharge with amounts of 100, 200, or 500dollar.
- When a member makes a purchase, a discount is applied based on the recharge amount: 5% for 100dollar, 10% for 200dollar, and 15% for 500dollar.
Business Process Analysis:
- Member Registration: Add a member registration entry to the system, click to enter the member registration page, enter information such as phone number and nickname, click confirm, and complete the registration.
- Recharge Function: Add a recharge entry to the system, click to recharge, enter the member's phone number, select the recharge amount, click confirm to create a recharge order, enter the existing payment process, and complete the recharge after successful payment.
- Consumption Function: Add a member card payment option to the existing payment page, click to enter the member's phone number, and complete the payment.
Design
Designing Models
Clearly, we should abstract a member model - MemberModel
. Additionally, as it involves member management (creation in this case), abstract a member manager model - MemberManagerModel
. To handle different amounts of recharge with varying discounts, abstract a recharge card model - CardModel
(100dollar card, 200dollar card, 500dollar card). Also, abstract a card manager model - CardManagerModel
. Lastly, as the recharge process involves placing an order, abstract an order model - OrderModel
, and an order manager model - OrderManagerModel
.
CardModel:
card
Properties
id
balance // Balance
discount // Discount
Methods
consume(amount) // Spend a certain amount of money
recharge() // Recharge
CardManagerModel:
cardManager
Properties
cardList[] // List of cards
Methods
listCard(params) // Request the list of cards
createCard(cardInfo, memberId) // Create a card
MemberModel inherit cardManagerMoel
member
Properties
cardList[] // List of cards
Methods
listCard(params) // Request the list of cards
createCard(cardInfo, memberId) // Create a card
MemberManagerModel:
memberManager
Properties
memberList[] // List of members
Methods
listMember(params) // Request the list of members
createMember(memberInfo) // Create a member
OrderModel:
order
Properties
id
type // Differentiates between recharge orders and product sales orders
status // Status
info // Sales information for the order, varies for different types of orders
payInfo // Order payment information
Methods
getStatus(id) // Get the latest status
getInfo(id) // Get complete order information
OrderManagerModel:
orderManager
Properties
orderList[] // List of orders
Methods
listOrder(params) // Request the list of orders
createOrder(info) // Create an order
Designing ViewModels
Designing viewModel directly based on the business process:
CreateMember
corresponds to the member registration process. Maintain an instance ofMemberManagerModel
and have acreate
method to callMemberManagerModel
'screateMember
method for registration.Recharge
corresponds to the recharge process: Maintain an instance ofMemberModel
, an instance ofOrderManagerModel
, and an instance ofOrderModel
.- Implement a method
queryMemberInfo
to accept a phone number as a parameter and callMemberModel
'sgetInfo
andlistCard
methods to retrieve the member's basic information and card list. - Implement an order method that accepts recharge amount and member ID as parameters, calls
OrderManager
's create order method, initializes theOrderModel
instance with the returned order information. - Finally, implement a recharge method that accepts an amount parameter, determines the type of card to recharge, checks if the member has that type of card, initializes a
CardModel
with the card information, and executes its recharge method. If not, callMemberModel
'screateCard
method to create a card, initialize the returned card information as aCardModel
, and execute its recharge method.
- Implement a method
Consume
corresponds to the consumption process: Maintain an instance ofMemberManagerModel
.- Implement a method
queryMemberInfo
to accept a phone number as a parameter and callMemberModel
'sgetInfo
andlistCard
methods to retrieve the member's basic information and card list. - Implement a consumption method that accepts an amount parameter and card type parameter, retrieves the corresponding card from the member's card list, initializes a
CardModel
, and executes the consumption method.
- Implement a method
Designing Views
UI components:
Name | Purpose | Description |
---|---|---|
MemberInfo | Display member information | In objects/member/components |
MemberForm | Membership configuration form, including validation | In objects/member/components |
MemberChoice | Select or input member | In objects/member/components |
CardInfo | Display card | In objects/card/components |
CardList | Display and select card from the list | In objects/card/components |
MoneySelector | Amount selection | In objects/card/components |
Logical components:
- Create Member Component: Mainly displays
MemberForm
(membership configuration form). When the form is submitted, call thecreate
method ofCreateMember
. Upon success, use theMemberInfo
component to display member information; otherwise, display a prompt. - Recharge Process Component, including a member selection page, amount selection page, and payment page.
- The member selection page uses
MemberChoice
to select a member. Then callRecharge
'squeryMemberInfo
to retrieve member information and proceed to the amount selection page. - The amount selection page uses
MemberInfo
to display member information, usesMoneySelector
to select recharge amounts, adds a confirm button, and callsRecharge
's order method when clicked. Upon success, proceed to the payment page, wait for payment completion usingRecharge
'sorderModel
'sgetStatus
method, and then callRecharge
's recharge method (excluding payment-related processes for simplification).
- The member selection page uses
- Consumption Process Component
- Use
MemberChoice
to select a member. Then callConsume
'squeryMemberInfo
to retrieve member information and proceed to a verification page. - Display member information using
MemberInfo
, useCardList
to display all member cards, and add a confirm button. After selecting a card and clicking the confirm button, callConsume
's consumption method.
- Use
At this point, the membership and recharge functionality is complete, providing a clear and straightforward structure.
Iteration Two: Membership Password
Requirements
After the membership functionality is launched, the owner quickly identifies a security issue - the possibility of unauthorized use of the recharged amount by others. Therefore, the owner requests the addition of the following features:
- Members can set a password during registration.
- Members need to input their password before making a purchase.
Design
Changes to the model involve adding a password validation method - validatePassword
to MemberManagerModel
.
Changes to the viewModel include adding a password field to the create
method's parameters in CreateMember
, and adding a method in Consume
to call validatePassword
for password validation.
Changes to the view involve adding a password form item to the MemberForm
component and adding a password input component to be used in the consumption process.
Iteration Three: Shop Assistant Incentives
Requirements
After the introduction of the membership feature, which increased user stickiness and repeat purchases, the owner is satisfied. However, the shop staff is not very enthusiastic about promoting memberships. Therefore, the owner wants to implement the following feature:
- Record the recommending staff during member registration and recharge. The owner will reward based on this information.
Design
Changes to the model involve adding an employee model (inheriting from MemberManagerModel
) and an employee management model. Add employee ID parameters to the member registration and recharge order creation methods.
Changes to the view involve adding an employee selection component and adding an employee selection form item in the member registration form and the recharge page.
Iteration Four: Client Mini Program (mini program is a software on wechat in China)
Requirements
The owner notices that other stores have a mini-program where members can view their cards and recharge amount by themselves. The owner wants to implement the following features:
- Members can view their cards and balances when they open the store's mini-program.
- Members can recharge themselves using the mini-program.
Design
Discovering that most of the mini-program's features have already been implemented in the existing model and viewModel files, you decide to reuse these files in both the mini-program and the cash register system. The following actions are taken:
Model layer remains unchanged.
Changes to viewModel involve adding a MemberInfo
viewModel, maintaining a MemberModel
, and implementing a getInfo
method that calls MemberModel
's getInfo
and listCard
methods.
View layer: Implement mini-program versions of MemberInfo
, CardInfo
, CardList
, and other components. Implement a logic component for information display (MemberInfo
), where CardList
is used to display member information. Implement a recharge component, which is almost similar to the cash register system's recharge logic component, calling the Recharge
viewModel too. The only difference is the absence of member selection interactions at the beginning, and payment uses the payment feature provided by WeChat.
Conclusion
Through the above example, it is expected that you understand how to design a code architecture using the MVVM pattern. If you were to design a backend to manage information such as members, cards, and orders, you would quickly realize that by reusing the existing models and developing the corresponding view and viewModel, you could efficiently develop the backend.
At the same time, you may deeply appreciate the advantages of this pattern. Code developed using it is highly scalable, with code reuse being straightforward, leading to an increasing development speed.
Moreover, you may realize that this development pattern heavily relies on your understanding of the business. The business in the above example is common and easy to understand. However, for some specialized businesses, as a frontend developer, you may not have a deep understanding. Therefore, it is essential to discuss and understand the business with the product manager or backend developer during development. Another direct approach is to ask the backend developer for the data model they have designed, this usually is a reliable way to design the model; if you can't get, you can refer to the database's table structure to abstract the data model.