• 结对项目分析总结


    结对项目分析总结

    综述

    说实话这次的项目对我的提升并不大,无论是前端、后端我过去都有所经验,对于团队协作、版本控制、自动化CI/CD也有所了解。所以本篇博客我不会将主要的分析放在前后端的实现上,更多的着眼于部署等方面。

    附项目体验地址

    前后端实现

    我们完成的是典型的前后端分离项目,首先要做的就是落实前后端交互格式,我们采用了JSON这种轻量的数据交换格式,具体格式约定如下:

    {
      "status": "success",
      "data": interface{}
    }
    
    {
      "status": "error",
      "err_msg": "error message"
    }
    

    接下来我们要做的就是前后端的分别实现,前端的实现我们放到代码复用部分讲,这里我们看看后端。后端我们选择Python作为主要的开发工具,我们先来看APP的实例获取过程:

    from flask import Flask
    from flask_cors import CORS
    from app.config import FlaskConfig
    from app.controllers import register_routers
    from app.models import connect_db
    
    
    def new_flask_app() -> Flask:
        app = Flask(__name__)
        CORS(app, supports_credentials=True)
    
        # 添加配置文件
        app.config.from_object(FlaskConfig)
    
        # 注册路由
        register_routers(app)
    
        # 链接数据库
        connect_db(app)
    
        return app
    

    代码中的注释都比较详细,不想讲很多。大家注意一下Python中的类型注解这一个特性这样可以获得非常好的代码提示等IDE支持。

    接下来,我们分别看一个Model和Controller的例子:

    from app.models import db
    from app.models import session_commit
    
    
    class User(db.Model):
        id = db.Column(db.Integer, autoincrement=True, primary_key=True)
        username = db.Column(db.String, nullable=True)
        password = db.Column(db.String, nullable=True)
    
        def __init__(self, username, password):
            self.username = username
            self.password = password
    
        def __str__(self):
            return "User(username={})".format(self.username)
    
        @classmethod
        def check_password(cls, username: str):
            return cls.query.filter_by(username=username).first()
    
        @classmethod
        def change_password(cls, username: str, password: str):
            user = cls.query.filter_by(username=username).first()
            user.password = password
            return session_commit()
    
        def new_user(self):
            db.session.add(self)
            return session_commit()
    

    注意其中类方法的使用即可,其余的就是简单的Python的ORM的使用

      
    from flask import Blueprint, request, session
    from app.models.user import User
    import app.utils.return_warp as warp
    
    login_out_page = Blueprint('login_out', __name__, url_prefix='/log')
    
    
    @login_out_page.route('/in', methods=['POST'])
    def login():
        username = request.form.get('username')
        password = request.form.get('password')
        # 校验必须参数
        if username is None or password is None:
            return warp.fail_warp('params error')
    
        user = User.check_password(username=username)
    
        if user.password == password:
            session.clear()
            session['user'] = username
            return warp.success_warp('login success')
        else:
            return warp.fail_warp('user error')
    
    
    @login_out_page.route('/out', methods=['GET'])
    def logout():
        session.clear()
    
        return warp.success_warp('logout success')
    

    其余的内容便不再赘述,具体的代码实现也没有什么难懂的地方,也没什么讲解的必要。

    代码复用部分

    本次项目我们主要复用的是前端部分的代码,并在其基础上进行了优化。

    可以说本次结对编程,我的队友负责前端部分,因为复用的是我个人项目时的前端代码,所以我们采用的是React这样的技术。我的队友对于现在前端工程化的方法有了很大的理解,对于前端工作流的使用也初步进行了入门,对于流行的MVVM模型有了深入的理解。

    接下来举一个React的Context的例子说明是怎么进行代码复用的:

    // 个人项目代码
    import React, {createContext, useState} from 'react';
    
    export const TypeContext = createContext(null);
    
    export const TypeProvider = props => {
      let [userType, setUserType] = useState({
        name: '张三1',
        type: 1
      });
    
      return (
        <TypeContext.Provider value={{userType, setUserType}}>
          {props.children}
        </TypeContext.Provider>
      )
    };
    
    export const TypeConsumer = TypeContext.Consumer;
    
    //结对项目
    import React, {createContext, useState} from 'react';
    
    export const UserContext = createContext(null);
    
    export const TypeProvider = props => {
      const [user, setUser] = useState('');
      const [errorMessage, setErrorMessage] = useState('');
    
      return (
        <UserContext.Provider value={{user, setUser, errorMessage, setErrorMessage}}>
          {props.children}
        </UserContext.Provider>
      )
    };
    
    export const TypeConsumer = UserContext.Consumer;
    

    可以看到两者的代码基本上是一致的,只是我们所需要共享的数据不太一样,所以对外提供了不同的Provide

    有兴趣的可以了解一下React Hooks的原理和使用

    部署部分

    Docker

    Docker是一个开放源代码软件项目,让应用程序部署在软件货柜下的工作可以自动化进行,借此在Linux操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制。 Docker利用Linux核心中的资源分离机制,例如cgroups,以及Linux核心名字空间,来创建独立的容器。

    我们的后端项目即采用Docker进行部署,具体的命令等大家可以查看Docker官网,下面给出Dockerfile:

    # 基础镜像
    FROM python:3.7
    
    WORKDIR /app
    
    ADD . /app
    
    RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    CMD ["gunicorn", "main:app", "-c", "gunicorn.conf.py"]
    

    Nginx

    Nginx是异步框架的网页服务器,也可以用作反向代理、负载平衡器和HTTP缓存。该软件由伊戈尔·赛索耶夫创建并于2004年首次公开发布。 2011年成立同名公司以提供支持。2019年3月11日,Nginx公司被F5 Networks以6.7亿美元收购。 Nginx是免费的开源软件,根据类BSD许可证的条款发布。

    我们的服务器只在443、80两个端口运行,其余的部署通过Nginx反代进行:

    #PROXY-START/pair
    location /pair
    {
        expires 12h;
        if ($request_uri ~* "(php|jsp|cgi|asp|aspx)")
        {
             expires 0;
        }
        proxy_pass http://内网IP:6000/;
        proxy_set_header Host localhost;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header REMOTE-HOST $remote_addr;
        
        add_header X-Cache $upstream_cache_status;
        add_header Cache-Control no-store;
    
        proxy_cache cache_one;
        proxy_cache_key $host$uri$is_args$args;
        proxy_cache_valid 200 304 301 302 1m;
    }
    
    #PROXY-END/pair
    

    注意其中因为使用了Docker不可以使用localhost,必须使用内网IP,记得作为API服务器应该设置不开启浏览器缓存。

  • 相关阅读:
    41 快速的复制一张表
    4 cdh 5.12 centos 6.10三节点安装
    40 insert语句的锁
    oracle 11g 数据库恢复技术 ---02 控制文件
    05 使用bbed跳过归档恢复数据文件
    Springboot 配置文件与对象之间进行映射之@ConfigurationProperties
    @ConditionalOnProperty来控制Configuration是否生效
    Oracle 服务名/实例名,Service_name 和Sid的区别
    @Value中冒号的作用
    springboot读取配置不存在报错
  • 原文地址:https://www.cnblogs.com/wangjq4214/p/11601388.html
Copyright © 2020-2023  润新知