如何使用简单三层来给自己的系统更加高扩展/维护/项目进度安排呢?(React为例)

1,242 阅读9分钟

大家好,我是ReactBoot的React的框架使用开发者,为什么叫ReactBoot,因为有一个可以让你快速开发公认的框架叫做SpringBoot。如果你是一个热爱做框架的人,那么SpringBoot里面很多的理念都是很不错的,它具备做构建高效且可伸缩系统的必备条件。所以我把他的思路带到前端平时的开发过程,提高系统的扩展性。

希望看文章的同学,都思考一下为什么要这么设计系统,这么拆代码。

首先一个会对系统的进行拆分的进行封装的一定是一个好的系统设计师,一个只会简单封装而不会进行拆分的肯定不能做好的系统设计师。

我现在已经懒得理喷子们的话了,事情的来源。是来源于下面的文章。首先我的文章内容没人去思考为什么要这么写,也没有人考虑这么拆分的好处,上来就喷很简单的功能用map不久完事了?搞这么复杂。。。

你可能并不真正了解JSX真正的用意,怎么用JSX进行解耦...

然后后面慢慢的思考,为什么这些喷子们要么就喷我提出的那“三类人”的观点,要么就喷写这么多层搞笑吧。但是从来没有人细想文件的内容,这是设计的好处是什么? 感觉就没有人认真看过文章内容一样。

仔细想了一下发现大多人都是独立开发者,他们或许没考虑过项目的维护性和迭代升级。或者没试过把一个功能拆过func的形式分配给3个人去实现,最后整合代码进行集成测试。

无论喷子怎么说,我依然想呼唤开发者停止脚步去堆代码,在开发前多考虑开发原则,维护性真的比开发的重要性高太多了。除非你的项目做完后直接废掉又重现写一套!但是这种事情在外国是不允许的!!

在外国的程序员,项目的前期花的时间大多数考虑需求分析,架构讨论,技术讨论,写代码考虑比较长远,比较有时间去考虑开发原则,维护成本,领导也会乐意去安排版本来解决技术债务。还会使用设计模式对系统进行整体把控,设计好后把实现方法分配给不同的人进行实现。在拆分的过程只是为了更好的把控项目和code review。这种review并不是知识看你写法上的问题!而是查看你业务上是否存在问题

而国内节奏太快了,就没有人停下脚步考虑这些问题,先上线再说。在开发的过程中,大多数的开发者都是一个开发一个功能模块,甚至出现一个功能模块直接丢给毕业生进行开发。开发不完那是开发者的问题,领导置之不理,只会催进度。做不完,加班就是了。

我想改变这种状态,我也不想在未来的项目中接触更多的“烂代码”,不是说功能做得不好,而是前人栽树,后人维护真的凉。

code review有的时候看着一堆“烂代码”真的很烦。而且这些代码也不知道修改会不会系统造成什么结果。

为什么会出现这种现象,主要是现在都在堆代码,甚至有些开车对了2000行的代码。比如以下的代码,是市面大多数开发者使用最广泛的堆业务代码大法。

import React from 'react'

func App(){
    
    const [data,setData] = useS();
    
    func handleX(){
        setData(value)
        setDatabaseApi(value).then(r =>{
            r.code === 2000 ? message.success() : doSomeing code...
        })
    }
       
    useE(){
        asy init(){
            get Database().then(r=>{
                setData(r)
            })
        }
       
        init()
    }
    
    return(
        <div onClick="handleX">OnClick XXXX</div>
    )

}

这种代码是可以完成功能,但是他不高维护,因为耦合度太高了。我们做系统设计的时候需要做到一个出发点,单入口多出口。

为什么要单入口,多出口呢?这有这样我们才能保证我们进行维护的时候,依赖没这么大控制单入口实现多出口的把控,你改的地方只有一个入口。

我今天要分享的是,在React中使用asp.net webform中的简单三层,进行项目的管理。

通常我们的组件是都需要调用api接口,一般的开发者是如何做我们的业务呢?一般都是封装了axios的做一层取数据(在后端叫做database层/DB层)的封装,就直接去试图层的页面中做 handle 操作了,这么做是可以快速完成的你目前的工作量。 截屏2022-01-20 下午11.57.55.png

然后调用就是如下,直接components组件里面直接调用DB层。

image.png

这样做能完成功能是能完成功能,但是你们发现了吗?api2同时是三个组件1、组件2、组件3共同调用的。软件开发过程中,api是需要迭代升级的,你不可能直接废掉v1的版本,然后全部组件都去调用v2版本的接口吧?如果你的组件依赖DB过多,那你后面做的事情好玩了。你需要改多少个组件呢?

以后api升级 v1 到 v2的时候,你view的调用全部的都要跟着改。除非后端和你关系好帮你做聚合,要不你自己慢慢加班修改这个调用关系。

所以软件开发过程中,就有了简单三层,为什么叫简单三层?因为他很简单的三层调用关系。那是哪里三层呢? View Handle -> service -> database

但是简单三层并不是最好的,因为好的设计都是接口(interface)和更抽象的封装。

一般的调用关系如下。

截屏2022-01-21 上午12.12.12.png

使用Service来组合数据,就算以后你的项目api有v1和v2需要,我这里只需要返回我Service():Model对应的接口,那么你的多个业务组件的依赖无需要进行修改,你只需要把控好Service这一层的数据即可。为什么我需要在Service实现的方法加一个Model的type返回值?

  1. 没为什么只是方便以后我维护的时候,我要记得所有组件直接我需要返回那些字段做兼容避免系统出现undefind的问题,导致系统报错,test team又给你提交了一个bug。

  2. 我可以把写渲染层的同学自己写mock做渲染,然后service的数据逻辑组合层写完后,更好的数据集成。

  3. 更好的进行code review和业务审核

上面的代码我们修改一下

我们需要一个model type

// src/entity/User.tsx
export interface User {
    name: string
    emial: string
}

先编写的是第三层db层,也就是经常来获取后端数据的接口的数据底层。

import { useApp } from "core/context"
import { IRequest } from "core/request"

export function useGetReportMemberHomeGetTradeTally(
    params?: any,
) {
    const requst: IRequest = useApp().getContainer('request')
    return requst.Get("/template/adorn/webEnterprise/findColumn", params)
}

后面到我们的第二层,Service层,我们可以理解层数据组装层。我们可以在这一层进行数据组装丢给第一层。添加这一层我么的代码也提高了一层的复用,就算以后又v2代码我么都是在这里组合。其他地方调用v1/v2也可以在这里进行调用

// src/operation/index.tsx

import { User } from "../entity/user";
import { useGetReportMemberHomeGetTradeTally } from "../sources/ReportV2Api";

//因为用的hooks 规范use 开头或者 组件方式字母大写,自己选择
export function useReporMember(parmas:any):User {
    //为什么加一个User后面会说
    const { data: TradeTallyData } = useGetReportMemberHomeGetTradeTally(parmas)
    
    ... more api dabatase
    
    console.log(TradeTallyData)
    
    return {
        name: TradeTallyData?.code,
        emali: "rainbowmorel.com"
    }
}

最后是我们的渲染层,在软件设计中,我们可以层称为调用者或者视图层。

import React, { useEffect } from "react";
import {useReporMember} from "./operation";

function RequestApp() {

    const {name}= useReporMember({ templateId: 2 })

    useEffect(() => {
        console.log();
    }, [])


    return (
        <>
            {name}
        </>
    );
}

export default RequestApp;

我们看看效果

image.png

为什么这么设计?直接调用不好吗?

简单三层,之所以叫简单三层,因为他是最简单的调度关系。我们也比较好管理而已。但是很多的设计都是出者简单三层开始去设计的。然后添加各种设计模式进行添花。

我们国内的开发模式一般如下,一人开发一个模块,中间是怎么写,完全又开发者自己去堆。就算现在有些公司code review,但是不对代码进行才分,对与code review的同学真的太痛苦了,导致最后的人也就看业务有没有错,没有错就可以了。

image.png

这是导致我国开发者都是独立开发者的根本原因。我国提仓是一人一模块开发模式。

毕业生的工作经验本来就很缺失,你还指望他能写出好的功能模块?我真的不知道如何说好了。如果你对系统进行系统设计,那你的调用就变得非常清新。你在安排工作的时候也明白如何去做。使用简单三层是最简单处理两人工作量进度的一种方式。

我们把以上的工作方式图进行修改一下。

image.png

我么的开发工程中就很清晰的知道,那一层应该分配给谁去编写。在进行code review的同时因为你把代码拆分了,你审核的时候会变得更家客观,你会知道你需要重点审核哪部分的代码。

注意代码审核不是只单单看你写得规范不规范

我们做code review看你是不是按照规范只是最简单的一步,因为你规范写作。写的是范文,只是为了提高code review的清晰度和阅读而已,而好的code review是需要要自己的思路和对方说做的事,进行思考。他写得这一段代码业务是不是存在问题!!!这才是code review初衷。

我们对系统进行拆分,再进行code review的同时可以更加清晰的你要重点审查那一步的代码。而不是像市面大多数的开发,写了一堆代码,后面需要进行查阅的时候在一堆代码里面查找问题。

我们是程序员,是设计系统简化工作量的,而不是编写代码来提高我们维护加班的!!

希望大家能把设计模式还有软件设计这些理论多多用起来,而不是死命的往里面堆代码。