Fork me on GitHub

Go-Agenda

Go-Agenda

会议管理系统

Go-Agenda 为简单的会议管理系统,采用 Go 语言进行开发,开发者为xwy27SiskonEmilia,开发基础与要求参阅pmlpml 课程要求

Github for Go-Agenda

目录

项目架构解读

  • Go-Agenda
    • cmd (存储指令处理文件)
      • root.go
      • *.go (指令与其参数解析)
    • data (存储数据文件)
      • meetings.json
      • session.json
      • users.json
    • global (存储全局文件)
      • logger.go (Error 处理)
    • model
      • meeting.go (会议模型与相应数据操作)
      • session.go (登陆会话模型与相应数据操作)
      • storage.go (数据读入写入)
      • user.go (用户模型与相应数据操作)
    • operation
      • meetingOperation.go (会议相关操作)
      • userOperation.go (用户相关操作)
    • samples (样例数据)
      • sample_Meetings.json
      • sample_Session.json
      • sample_Users.json
    • main.go

项目使用 cobra 进行命令行参数解析。所以,main.go 与 cmd 文件夹为 cobra 项目初始化自动生成。

  1. model 文件夹存储数据模型,项目的底层结构,直接进行数据读写
  2. operation 文件夹定义模型的抽象操作,调用 model 包导出函数完成数据同步。其中,operation 进行部分抽离,调用数据同步前的进行参数合法性校验,保证底层数据操作可以无需关心数据合法性
  3. cmd 文件夹内每个go文件对应一条指令,并解析各自命令行参数;解析完毕后调用相应 Operation 包导出的函数

源码解读

  • 命名

    常用变量名与函数名采用驼峰式命名(除 Go 要求包导出变量与函数的首字母必须大写,其余均符合)

    循环变量等暂时变量采用单字母命名

  • 注释

    本次编程注释采用 Go Comment 规范,保证源码可读性。依据项目架构解读进行理解后,可阅读源码进行深入了解或维护。

    包内导出函数包含函数注释说明,了解函数用途与返回值

    1
    2
    3
    4
    5
    6
    // ValidateMeeting validates meeting time properties and returns, if something wrong, an error
    // Valid meeting contains start time and end time and the time interval is right while,
    // sponsor and participators only attend this new meeting in the meeting time interval
    func ValidateMeeting(meeting *model.Meeting) error {
    /* Code here */
    }

    函数内执行过程,采用注释说明当前执行逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    func AddMeeting(Title string, Participators []participator, StartTime string, EndTime string) error {
    // Check log in
    currentUser, err := model.GetCurrentUserName()
    if err != nil {
    return err
    }

    // Validate Title
    if len(Title) == 0 {
    return errors.New("Meeting Title is required")
    }

    // Check Title existence
    m, err := model.FindMeetingByTitle(Title)
    if err != nil {
    return err
    }
    if m != nil {
    return errors.New("Meeting: " + Title + " is existed")
    }

    // Validate participator
    if len(Participators) == 0 {
    return errors.New("Meeting Participator is required")
    }
    for _, p := range Participators {
    user := model.FindUserByName(p.Username)
    if user == nil {
    return errors.New("Participator: " + p.Username + " does not exist")
    }
    }

    // Check Sponsor without in participator
    for _, p := range Participators {
    if currentUser == p.Username {
    return errors.New("You could not attend meeting sponsored by you as a participator")
    }
    }

    // Check valid time
    s, err := time.Parse(timeFormat, StartTime)
    if err != nil {
    return errors.New("Start Time is invalid")
    }
    start := s.Unix()

    e, err := time.Parse(timeFormat, EndTime)
    if err != nil {
    return errors.New("End Time is invalid")
    }
    end := e.Unix()

    newMeeting := &model.Meeting{
    Title: Title,
    Sponsor: currentUser,
    Participators: Participators,
    StartTime: start,
    EndTime: end,
    }

    if err := ValidateMeeting(newMeeting); err != nil {
    return err
    }

    err = model.AddMeeting(newMeeting)
    return err
    }
  • Robust

    所有函数出错均返回 Error,并在顶层 cmd 调用中通过 PrintError 进行错误处理

后记

在使用与调用开源库以来,一直存在的痛苦:开源代码无注释/文档不清不楚,导致耗费大量时间去理解与调试。己所不欲勿施于人,所以,即使这次开发过程略显仓促,但依旧强迫着保持代码规范与 robust,保证代码可读性与维护性。希望之后能一直这么保持下去吧。

开发期间由于个人原因出去参加比赛了,导致项目进度一度拖后,十分感谢 SiskonEmilia 的包容。