Loading

软件工程-个人阅读作业 #2

项目 内容
这个作业属于哪个课程 2021春季软件工程(罗杰 任健)
这个作业的要求在哪里 个人阅读作业#2
我在这个课程的目标是 掌握并实践利用软件工程方法构建大规模高质量应用的技术,提升自身工程能力
这个作业在哪个具体方面帮助我实现目标 了解软件开发过程中可能遇到的各个方面的问题,尝试CI/CD等新型构建管理方式

Part 1: 《构建之法》阅读中的问题

Q1:敏捷开发在大型项目中的应用

书中提到关于敏捷开发的知识。在中小型的软件项目中,这些技巧可以非常好的提高开发效率,但是在大型软件的开发过程中,人员数量规模巨大,经常会出现开发者跨地区、跨时区工作的特性。这样,敏捷开发提倡的“交流”几乎无法实行。即使通过切分,将应用切分成为一个一个的小模块,但在一个复杂的系统中,各个小模块之间必然有着大量相互重叠的部分。在这样成规模的项目中,敏捷开发又应当如何应用呢。

Q2:关于goto语句的使用

作者提出:

函数最好有单一的出口,为了达到这一目的,可以使用goto

我在这点上与作者有一定的不同认知。根据我学习的经验和网上查到的资料,goto语句在正常的程序中基本上是绝对不能使用的。在我个人的实践中,也尽量避免采用goto语句。

性能方面的影响其实不大,主要是可读性方面的问题,goto语句会极大的打乱程序结构性,大大提高阅读代码的开销。作者显然是知道这一问题的,但是提出,为了满足单一出口原则,可以适当的妥协,允许这种情况下goto的使用。所谓的单一出口原则,出自《重构——改善既有代码的设计》这本书,讲的是一个函数最好只有一个return语句。这样做有一定道理,可以使程序员一目了然程序的出口和返回值的来源。但是,近年来,这一原则也在受到质疑,如这篇博客中提到《The Art of Readable Code》中就对这一原则提出了批评。而在个人实践的经验中,很多时候不遵守单一出口原则(例:函数开头判断参数非法直接退出)能更好的提高代码可读/可维护性。

从我的角度来看,一切规范都是服务于开发效率的。因此,从代码可读性出发考虑,我们需要比较单一出口带来的收益和goto语句带来的负面效果。单一出口不是万能灵药,比如对于罕见错误情况处理时,早早退出是一个好选择。事实上,这正是书中goto语句的用法示例。在我个人看来,此时放弃单一出口原则是比引入goto更好的做法。而且,近年来出现的新型语言都引入了专门的错误处理机制,通过精心设计的机制,可以更好地完成错误处理的功能,因此在一些新语言中,goto语句的用处进一步降低,甚至直接从语言本身就没有goto语句。

当然,一切都是从可读性/可维护性的角度出发,因此如果使用goto能提高可读性,仍然可以使用。具体而言,我认为有以下规则:

  • 只有在需要错误处理而语言本身没有提供错误处理功能的情况下使用goto语句

Q3:关于类的使用

作者提出:

仅在必要时,才使用“类”

在OO课程的学习中,我接触了Java。Java的一个重要思想就是,“一切都是对象”。有对象,就必然有类,Java作为纯粹的面向对象语言,非常鼓励程序员对类的使用。因此,我对此有一定疑问。

我目前认为,作者针对的语言主要是C++,这方面的差异可能是不同编程范式的差异。但是我查询资料,发现C++属于一门多范式语言,自然也支持面向对象编程。此外,尽管作为编译型语言,C++针对类和对象的支持不如Java自然,但是C++有RTTI,虚函数,虚基类等多种不同的方法实现运行时类型,只要选择合适的方法,开销都能控制在可以接受的范围内。

我目前的猜测,一是在多范式编程中,面向对象模式与其他对象模式有一定的不兼容之处(但是是什么呢?),二是纯粹的开销方面原因。但我仍觉得不足以完全解释这一问题,因此在此提出希望与大家讨论。

Q4:关于多人合作中的代码同步问题

书中11.5.4中提到了代码签入过程中的种种冲突问题,最后给出的解决方案是对不同的代码实行不同的规则和流程控制,并给出了例子。但是,我仍然没能看出来这样如何解决了问题。在我的开发实践中,我曾见过两位同学针对4个issue同时对代码进行修改,然后merge冲突,花费了很长时间,经历多次merge/rebase才成功合并。这还仅仅是两位同学,发现问题后一起合并的结果。在软件公司,一份代码同时修改的人相比更多,冲突也更多。我觉得即使如书中一样限定在一个固定的时间段签入代码,仍然会发生冲突。

我目前能想到的解决办法就是,将构建过程自动化,只允许能通过构建的代码签入。这样可以保证签入不会导致构建失败,可以省去“合并版本后构建并测试”的时间,减少冲突的可能性。但是这并没有解决代码冲突频繁的问题,且在项目工程庞大的情况下,自动构建和测试也要花费大量的算力和时间,因此希望与大家讨论。

Q5:Beta期间,修复Bug的门槛要逐渐提高

书中提到

在Beta测试期间,修复Bug的门槛要逐渐提高

我对此存在疑惑,一个软件进入Beta阶段,应该是一个逐渐稳定的阶段。这种情况下,程序的Bug数应当类似于一段下降曲线,影响巨大的Bug应该会越来越少,在这种情况下,不应该正好有更多的时间修复小Bug,来提升如软件的细节么。书中指出是为了稳定性,避免频繁改动代码而引来新的Bug,但是对代码的修改都有可能引入Bug。一般来说,严重的Bug修复所需的改动更多,而小Bug所需的改动更小,带来Bug的可能性也相对有多少之分。因此,我对此条准则有一定的怀疑,希望与大家一起讨论。

Part2:源代码版本管理软件调研

2.1 三大源代码版本管理软件相同之处

  • 都使用git这一源代码管理系统
  • 都不同程度的支持权限管理、项目计划、在线基本编辑能力、代码质量监测、代码安全管理、持续集成和审计功能
  • 都支持通过第三方服务扩展功能

2.1 三大源代码版本管理工具特色

  • Github:托管了大量开源项目和代码片段(gist),有较完整的社区功能,用户基数最大
  • BitBucket:可方便的与Atlassian公司的其他效率软件(如Jira)配合使用,支持无限的免费私有仓库
  • GitLab:本身开放源代码,可以自行部署。对持续集成等操作支持相对较早也较完善

Part3:调研持续集成/部署工具

3.1 GitLab CI

采用我在数据库大作业中的前端项目作为实验项目,配置GitLab CI/CD,自动进行语法检查,语法检查通过后自动build并将结果打包成artifact以供下载

项目地址

image
image

看图可知此人没有外接显示器(

对应的.gitlab-ci.yml文件如下

image: node:alpine

stages:
    - lint
    - build

cache:
    paths:
      - node_modules

lint 1/2:
    stage: lint
    script:
        - echo "Test Lint"

lint 2/2:
    stage: lint
    script:
        - npm install
        - npm run lint

build_dist:
    stage: build
    script:
        - npm install
        - npm run build
        - apk add zip
        - zip dist.zip -r ./dist
    artifacts:
        paths:
            - dist.zip
        expire_in: 1 week

3.2 GitHub Actions

同样采用我在数据库大作业中的前端项目作为实验项目,配置GitHub Action,自动进行语法检查,语法检查通过后自动build并将结果打包成zip文件,然后利用社区市场提供的ncipollo/release-action@v1自动生成Release。

项目地址

image
image

对应配置文件如下

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run. 
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  lint:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Runs a single command using the runners shell
      - name: Install Dependencies
        run: npm install
      - name: lint
        run: npm run lint
        
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Runs a single command using the runners shell
      - name: Install Dependencies
        run: npm install
      - name: Build
        run: npm run build
      - name: Zip
        run: zip dist.zip -r ./dist
      
      - name: Release file
        uses: ncipollo/release-action@v1
        with:
          artifacts: "dist.zip"
          body: Release ID ${{github.run_id}}
          token: ${{ secrets.GITHUB_TOKEN }}
          # Name of Release to add file to
          tag: ${{github.run_id}}

简单Actions使用介绍:

image

image

image

image

image

3.3 总结

无论是GitLab CI/CD还是Github Actions,都提供了相当方便的持续集成、持续部署功能。通过自动化代码提交后的一套流程,可以有效地提高开发的质量,减轻手动作业的负担。

在使用过程中明显可以看出,GitLab CI/CD对流水线的管理要更加顺畅,包括各阶段的定义和阶段之间的依赖关系,而Github Actions则显得略微繁琐。同时。GitLab CI/CD的runner可以以多种方式灵活配置,而Github Actions就显得不那么灵活。但是,Github Actions提供了大量社区插件,可以轻松地完成一些常见任务,对于中小型项目来说可以极大的提高效率、

总而言之,GitLab CI/CD更加灵活,更适合商业化使用。而Github Actions则易于上手,可以在中小型项目中方便的应用。

参考文献

  1. 《构建之法——现代软件工程》,邹欣,人民邮电出版社,第三版.
  2. 单一出口原则 Peter87
  3. https://about.gitlab.com/devops-tools/github-vs-gitlab/
  4. https://about.gitlab.com/devops-tools/bitbucket-vs-gitlab/
  5. https://docs.gitlab.com/ee/ci/
posted @ 2021-03-15 10:37  VOIDMalkuth  阅读(315)  评论(4编辑  收藏  举报