記一次業余項目的敏捷開發實踐


      本次是在原有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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM