current position:Home>Poor maintainability of front-end services? Practice sharing of minimum cost dismantling of eggs
Poor maintainability of front-end services? Practice sharing of minimum cost dismantling of eggs
2021-08-27 08:21:56 【Cao Jun_ Eren】
Hello everyone , I'm Cao Jun _Eren. This article may be more suitable for medium and large-scale projects developed by multiple people , Of course, if your project has a messy code file for various reasons , Also applicable .
Ryan Dahl since 2009 It's a year that creates nodejs It has been 12 year , There are already many mature frameworks in the industry , such as express、koa、egg etc. . When writing server-side code , It is often divided into router
layer 、controller
Layer and the service
layer , Of course, there will be some other layers , such as model
Layer and the view
layer .
- router: Listen to the routing of the page , And call Controller Layer routing processing function
- controller: to Router Layer provides services , call Service Data processing provided by layer
- service: To achieve specific functions
router Like the front desk , Guide customers into the store according to their needs ;controller Like a waiter , It's her job to order for customers ;service It's the cook , It's up to him to decide whether the food tastes good or not .
As mentioned above , The author has built... In the server router、controllr、service Three folders , Store the codes of each business module in it , This way is simple and quick , It is very suitable for the rapid start of the project . Later, the number of developers in the team slowly increased , Close to have 4~5 Personal development of this project .
Let's take a look at the overall structure of the project
You can see the application app There are controller、service and router, It is a typical monomer application . And then unfold controller The table of contents can be seen
Found that there are many different modules ( Or function ?) Gather in it .
Let me briefly summarize the problem in the figure above :
First , This project There is no strict module division , Each team member creates directories and files according to their own understanding , Over time, the structure is chaotic , Has smelled the smell of decay . A modular controller、service The files are in a large directory , When developing a module, you need to span multiple directories of the whole project , Bad development experience .
secondly , There is no distinction between public code and business code , Developers want to find 、 It's difficult to call some general logic , Newcomers have high learning costs .
Every developer has different working habits , Different understanding of module division . New developers may not be aware of the naming conventions for file directories , When writing tool classes, you may not notice the separation of public content and business content .
Word of mouth norms cannot be fully implemented , That's what we call “ Tribal knowledge ”( Unique knowledge in an organization ). If the confusion caused by developers is not limited to a certain range , Finally, you may need to refactor the entire project .
The above problems , In the final analysis The system architecture is not clear , Lack of module division or unclear module division , Low degree of aggregation 、 High coupling .
Just imagine , If we divide the project into multiple modules , When developing a module , All functions can be completed in its directory . If bad code appears , Just refactor the directory where the module is located , Without having to refactor the entire project , Wouldn't it be better ?
Good design
Microservices 、 Domain driven design is a very popular topic , But the complexity of front-end services is often not high . If split into multiple services , Not only need Invest a lot of manpower cost , You may also find that each service is more “ Thin ”, Most of the time, a slightly larger front-end service is “ It's more than enough ”.
stay The practice of Domain Driven Design in Internet business development Explain in detail how microservices are split , Mentioned in “ Divide and conquer ” The idea may be helpful to improve the maintainability of front-end Services .
Divide and conquer Divide the problem space into smaller and easier to deal with subproblems . The problem after segmentation needs to be small enough , So that one person alone can solve them ; secondly , It is necessary to consider how to assemble the divided parts as a whole . The more reasonable the division, the easier it is to understand , When assembled as a whole , The less detail you need to track . That is, it's easier to design collaborative ways of various parts . Judge what is good division , High cohesion and low coupling .
Therefore, according to business needs , It is very important to design business modules and the relationship between them . As the system gets bigger and bigger , Each module will be closer to one Micro applications . When many people work together , Each person in charge will have their own module , If each module is a micro application , Everyone can complete the development of all functions in the module , It's a very interesting thing .
If a business causes code corruption due to frequent changes , Just refactor the module , No impact on other modules .
egg frame
The author's project uses egg.js frame , This is one of its design principles
Develop as agreed , Pursue 『 Convention over configuration 』
egg It can automatically grab router 、controller、service、middleware And other files in the directory , Mount the method in a specific context variable .
The default directory structure is like this :
This is a structure for large monomer applications , It's hard to divide modules . How to use engineering means , The single application is divided into multiple micro applications ?
egg
A good function is to customize the upper framework , For details, please refer to the chapter on the official website Framework development , Let's take a closer look at
Implementation of micro application
To realize the requirement of dividing a single application into multiple micro applications , Need to be used egg Provided Framework inheritance and Custom loader The function of .
Framework inheritance
First you need to create a npm application , The project contains the following files and code
// package.json
{
"name": "my-framework",
"dependencies": {
"egg": "^2.0.0"
}
}
// index.js
module.exports = require('./lib/framework.js');
// lib/framework.js
const path = require('path');
const egg = require('egg');
const EGG_PATH = Symbol.for('egg#eggPath');
class Application extends egg.Application {
get [EGG_PATH]() {
// return framework route
return path.dirname(__dirname);
}
}
// covers Egg Of Application
module.exports = Object.assign(egg, {
Application,
});
Copy code
Then in our service application , adopt package.json introduce
// package.json
{
"scripts": {
"dev": "egg-bin dev"
},
"egg": {
"framework": "my-framework"
}
}
Copy code
In this way, the inheritance of a framework can be realized , But it still doesn't realize the functions we need . We can take advantage of inherited features , rewrite existing egg Features provided .
Custom loader
egg The reason why you can automatically grab the files in the directory , Because of it loader (Loader). If you want to automatically grab the directory under the module , You need to customize egg File loading function .
By inheritance Loader class , Rewrite its method , To realize Custom file loading .
// lib/framework.js
const path = require('path');
const egg = require('egg');
const EGG_PATH = Symbol.for('egg#eggPath');
+ class MyAppWorkerLoader extends egg.AppWorkerLoader { // AppWorkerLoader What is it? ?
+ load() {
+ super.load();
+ // Expand yourself
+ }
+ }
class Application extends egg.Application {
get [EGG_PATH]() {
// return framework route
return path.dirname(__dirname);
}
// Cover Egg Of Loader, Use this at startup Loader
get [EGG_LOADER]() {
return YadanAppWorkerLoader;
}
}
// covers Egg Of Application
module.exports = Object.assign(egg, {
Application,
+ // Self defined Loader Also needed export, The upper framework needs to be based on this extension
+ AppWorkerLoader: MyAppWorkerLoader,
});
Copy code
In code AppWorkerLoader Inherited from Loader Base class , On the official website loader The chapter says Loader There are the following methods :
- loadPlugin(): Add plug-ins
- loadConfig(): Load the configuration
- loadAgentExtend(): load agent Object's extend object
- loadApplicationExtend(): load app Object's extend object
- loadRequestExtend(): load request object
- loadResponseExtend(): load response object
- loadContextExtend(): load context object
- loadHelperExtend(): Loading tool method
- loadCustomAgent(): Load defined agent object
- loadCustomApp(): Load defined app object
- loadService(): load service
- loadMiddleware(): Loading middleware
- loadController(): load controller
- loadRouter(): Load the routing file
From the perspective of inheritance MyAppWorkerLoader -> AppWorkerLoader -> Loader It seems , We can be in MyAppWorkerLoader Customize all the above methods in
customized controller Loading
Loader Class loadController Method implemented controller Directory crawling , stay egg-core The bag can find it .
// egg-core/lib/loader/mixin/controller.js
const path = require('path');
const is = require('is-type-of');
module.exports = {
/**
* Load app/controller
* @param {Object} opt - LoaderOptions
* @since 1.0.0
*/
loadController(opt) {
opt = Object.assign({
caseStyle: 'lower', // Convert the first letter of the file name
directory: path.join(this.options.baseDir, 'app/controller'), // controller The position of
initializer: (obj, opt) => { // For each file export The value is processed
if (is.function(obj) && !is.generatorFunction(obj) && !is.class(obj) && !is.asyncFunction(obj)) { // Judge controller Is it a function
obj = obj(this.app); // Pass in app Object to controller Function
}
if (is.class(obj)) { // Judge controller Is it a class
obj.prototype.pathName = opt.pathName;
obj.prototype.fullPath = opt.path;
return wrapClass(obj); // It mainly defines the execution in controller Ahead middleware
}
if (is.object(obj)) {
return wrapObject(obj, opt.path); // It mainly defines the execution in controller Ahead middleware
}
// support generatorFunction for forward compatbility
if (is.generatorFunction(obj) || is.asyncFunction(obj)) {
return wrapObject({ 'module.exports': obj }, opt.path)['module.exports']; // It mainly defines the execution in controller Ahead middleware
}
return obj;
},
}, opt);
const controllerBase = opt.directory;
this.loadToApp(controllerBase, 'controller', opt); // take controller The exported object is hung in app In the context object
},
};
Copy code
As can be seen from the code above , By passing in parameters opt.directory
Can define controller Directory of
// lib/framework.js
const path = require('path');
const egg = require('egg');
const EGG_PATH = Symbol.for('egg#eggPath');
class MyAppWorkerLoader extends egg.AppWorkerLoader {
+ loadController(opt) {
+ super.loadController(Object.assign({ // Calling the loadController Method
+ directory: [
+ ...['your/controller/path'], // Self defined controller route
+ path.resolve(process.cwd(), 'app/controller'), // egg Of controller The default path
+ ],
+ override: false, // Whether to directly overwrite or throw an exception when encountering an existing file
+ }, opt));
+ }
class Application extends egg.Application {
get [EGG_PATH]() {
// return framework route
return path.dirname(__dirname);
}
// Cover Egg Of Loader, Use this at startup Loader
get [EGG_LOADER]() {
return YadanAppWorkerLoader;
}
}
// covers Egg Of Application
module.exports = Object.assign(egg, {
Application,
// Self defined Loader Also needed export, The upper framework needs to be based on this extension
AppWorkerLoader: MyAppWorkerLoader,
});
Copy code
Through the above code, you can realize controller Directory extension .
Besides , We can also expand router、service、middleware、extend Catalog , Students who want to understand the specific implementation , You can refer to the encapsulated npm package egg-micro-app . The core content is in the document lib/framework.js in , The code is less than 100 OK, it's very simple .
In this way, large projects can be disassembled into multiple independent modules , Each module is a micro application , You can put business modules and general files in different locations according to your own ideas , End of the flower .
copyright notice
author[Cao Jun_ Eren],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210827082149950n.html
The sidebar is recommended
- Crazy blessing! Tencent boss's "million JVM learning notes", real topic of Huawei Java interview 2020-2021
- JS JavaScript how to get the subscript of a value in the array
- How to implement injection in vuex source code?
- JQuery operation select (value, setting, selected)
- One line of code teaches you how to advertise on Tanabata Valentine's Day - Animation 3D photo album (music + text) HTML + CSS + JavaScript
- An article disassembles the pyramid architecture behind the gamefi outbreak
- BEM - a front-end CSS naming methodology
- [vue3] encapsulate custom global plug-ins
- Error using swiper plug-in in Vue
- Another ruthless character fell by 40000, which was "more beautiful" than Passat and maiteng, and didn't lose BMW
guess what you like
-
Huang Lei basks in Zhang Yixing's album, and the relationship between teachers and apprentices is no less than that in the past. Netizens envy Huang Lei
-
He was cheated by Wang Xiaofei and Li Chengxuan successively. Is an Yixuan a blessed daughter and not a blessed home?
-
Zhou Shen sang the theme song of the film "summer friends and sunny days" in mainland China. Netizen: endless aftertaste
-
Pink is Wangyuan online! Back to the peak! The new hairstyle is creamy and sassy
-
Front end interview daily 3 + 1 - day 858
-
Spring Webflux tutorial: how to build reactive web applications
-
[golang] walk into go language lesson 24 TCP high-level operation
-
August 23, 2021 Daily: less than three years after its establishment, Google dissolved the health department
-
The female doctor of Southeast University is no less beautiful than the female star. She has been married four times, and her personal experience has been controversial
-
There are many potential safety hazards in Chinese restaurant. The top of the program recording shed collapses, and the artist will fall down if he is careless
Random recommended
- Anti Mafia storm: He Yun's helpless son, Sun Xing, is destined to be caught by his dry son
- Introduction to flex flexible layout in CSS -- learning notes
- CSS learning notes - Flex layout (Ruan Yifeng tutorial summary)
- Today, let's talk about the arrow function of ES6
- Some thoughts on small program development
- Talk about mobile terminal adaptation
- Unwilling to cooperate with Wang Yibo again, Zhao Liying's fans went on a collective strike and made a public apology in less than a day
- JS function scope, closure, let, const
- Zheng Shuang's 30th birthday is deserted. Chen Jia has been sending blessings for ten years. Is it really just forgetting to make friends?
- Unveil the mystery of ascension
- Asynchronous solution async await
- Analysis and expansion of Vue infinite scroll source code
- Compression webpack plugin first screen loading optimization
- Specific usage of vue3 video play plug-in
- "The story of huiyeji" -- people are always greedy, and fairies should be spotless!
- Installing Vue devtool for chrome and Firefox
- Basic usage of JS object
- 1. JavaScript variable promotion mechanism
- Two easy-to-use animation JS that make the page move
- Front end Engineering - scaffold
- Java SQL Server intelligent fixed asset management, back end + front end + mobile end
- Mediator pattern of JavaScript Design Pattern
- Array de duplication problem solution - Nan recognition problem
- New choice for app development: building mobile applications using Vue native
- New gs8 Chengdu auto show announces interior Toyota technology blessing
- Vieira officially terminated his contract and left the team. The national security club sent blessings to him
- Less than 200000 to buy a Ford RV? 2.0T gasoline / diesel power, horizontal bed / longitudinal bed layout can be selected
- How does "heart 4" come to an end? Pinhole was boycotted by the brand, Ma Dong deleted the bad comments, and no one blessed him
- We are fearless in epidemic prevention and control -- pay tribute to the front-line workers of epidemic prevention!
- Front end, netty framework tutorial
- Xiaomi 11 | miui12.5 | android11 solves the problem that the httpcanary certificate cannot be installed
- The wireless charging of SAIC Roewe rx5 plus is so easy to use!
- Upload and preview pictures with JavaScript, and summarize the most complete mybatis core configuration file
- [25] typescript
- CSS transform Complete Guide (Second Edition) flight.archives 007
- Ajax foundation - HTTP foundation of interview essential knowledge
- Cloud lesson | explain in detail how Huawei cloud exclusive load balancing charges
- Decorator pattern of JavaScript Design Pattern
- [JS] 10. Closure application (loop processing)
- Left hand IRR, right hand NPV, master the password of getting rich