惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The GitHub Blog
The GitHub Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
美团技术团队
Y
Y Combinator Blog
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
M
MIT News - Artificial intelligence
博客园 - Franky
V
Visual Studio Blog
I
InfoQ
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
博客园 - 司徒正美
L
LangChain Blog

博客园 - SamDragon

如何通过LangChain实现记忆功能的总结 基于LangChain的Ai应用开发平台 .net CPU和内存爆高的分析与处理01 前端导出Excel和打印介绍 ApiTemplate:.net后端项目模板完善与总结 Jenkins之Nunit的应用 jenkins发布application且并运行 Jenkins基础系统之完整的.net项目编译 Jenkins基础系统之更换镜像源 奉上简单的.Net后端开发模板 C#之委托如此简单 cordova环境搭建 Linux实现免密码登录 ElasticSearch安装及运行的坑 Autofac 应用于IIS托管的WEB程序,注册程序集被回收的问题 通过Thrift实现C#与Hbase交流 OpenLayer实现路径运动 对SVN的落地与实践总结 Jenkins配置从节点
记一次业余项目的敏捷开发实践
SamDragon · 2020-03-15 · via 博客园 - SamDragon

      本次是在原有ApiTemplate项目之上,增加一个用户登录权限控制模块,用于验证ApiTemplate项目在面对一些简单问题时,如何抽象并支持未来的扩展。用户登录权限控制模块看上去很简单,但由于业余时间总是有限的。所以借助此机会实践一次用户敏捷开发。首先拆分模块,本次只实现用户登录和登出。

apitemplate项目地址:https://github.com/cqhaibin/ApiTemplate

一、总结放前面

最小化任务范围

  • 本次任务只限定在了《用户名+密码登录》这个任务上,并且不包含数据的持久化, 这样在做的时候反复考查自己,不让自己超出范围。所以
  • 查询用户注册信息、在线用户存储相关接口只做定义和模拟实现,不做具体的存储实现
  • 考虑到业务逻辑是稳定的,而存储是可变的,所以数据库实体对象与业务实体对象分离

给任务一个期限

像本次就只列出了任务的期限,而没有列出每个子阶段的期限,如:一个需求必须要经过需求分析、模块设计、代码实现等阶段。这些子阶段也需要给出具体的期限。

从外向里逐层推进

  • 定义UI/服务层接口
    因为UI接口有多种提供方式(如:rest api, rpc等),所以基本以服务层接口为标准,UI接口层只是做了一次简单转换和调用。其中UI/服务层接口输入/输出参数的Moddel也随之定义(两层共享Model)
  • 实现服务层接口
    此步实现服务层接口,你会发现还需要依赖在线用户管理模块,以及数据库层(查询注册用户信息),在这里我只定义了查询注册用户信息的接口,而暂不做具体的实现。然后进入第三步
  • 定义在线用户模块的接口
    此步包含:在线用户管理实体接口、在线用户实体接口。定义好后先不实现。完善服务层实现中对此模块的依赖调用,在这里你可能会反复调整在线用户模块的方法输入/输出参数的Model,以达到与服务层的融合
  • 实现在线用户模块的接口
    此步实现 在线用户管理实体接口、在线用户实体接口。此时我们发现还要依赖在线用户存储接口(只定义,不做实现)

二、用户需求

实现根据用户名的登录、登出接口。

三、需求分析

  • 用户名:支持英文、数字、汉字、以及特殊字符;用户名不区分大小写
  • 密码:支持英文、数字、特殊字符,区分大小写
  • 提示:用户不存在与密码错误要区分提示
  • 此阶段不考虑数据持久化,因为要快速验证原型的可行性

四、系统设计

接口设计

接口统一使用rest api, 实现登录、登出两个接口

  • 登入接口
    • 接口名:PostLogin
    • 请求类型:post
    • 输入参数
    {
        userName<string>, //用户名
        password<string> //密码
    }
    • 返回参数
    {
        isSuccess<bool>, //请求是否成功
        resultCode<number>, //请求状态Code 200006:账号不存在;200001:账号被禁用;200002:密码错误
        data<object>:{
            token<string> //登录成功后,返回的token
            user<object>:{ //用户对象
                realName<string>, //用户名
                userName<string>, //登录名
                id<int>, //用户Id
                config<string>, //用户扩展信息,json字符串
                mobilePhone<string>, //电话号码
            }
        }
    }
  • 登出接口
    • 接口名称:LoginOut
    • 请求类型:get
    • 输入参数
      通过url, header, cookie的顺序获取token
    • 返回参数
    {
        isSuccess<bool>, //请求是否成功
        resultCode<number>, //请求状态Code
    }

详细设计

登入接口详细设计

  • 流程
    image
  • 在线用户管理
    • 在线用户管理接口类
    class IOnlineUserMgr{
        /// <summary>
        /// 将用户添加到在线用户列表,此方法需要对登入信息持久化
        /// </summary>
        /// <param name="entity"></param>
        void Add(IUserEntity entity);
        /// <summary>
        /// 根据token移除对应的用户,此方法需要对登出信息持久化
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        bool Remove(string token);
        /// <summary>
        /// 根据用户Id移除用户,此方法需要对登出信息持久化
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        bool Remove(int id);
        /// <summary>
        /// 从持久化层恢复在线用户
        /// </summary>
        void Load();
        /// <summary>
        /// 获取所有在线用户
        /// </summary>
        IList<IUserEntity>  GetAll();
    
        IUserEntity Get(int userId);
    }
    • 用户实体接口类
    class IUserEntity{
        UserInfo UserInfo { get; }
    
        string Token { get; }
    
        /// <summary>
        /// 客户端信息
        /// </summary>
        RequestClientInfo ClientInfo { get; }
    
        DateTime LoginTime { get; }
    
        DateTime ExpiredTime { get; }
        /// <summary>
        /// 用户登录配置
        /// </summary>
        UserAuthOption Option { get; }
    
        TokenEntity GetTokenEntity();
    }
  • 说明
    • token生成规则
      用户key = token_UserId_UserName_IP_OS_Time,然后将用户key通过MD5计算出的值作为token
    • UAParser
      实现UserAgent字符串到对象的转换。

登出接口详细设计

  • 流程

image

五、数据字典

  • 在线用户信息

image

  • 用户

image