0%

Git Flow 是什么?

2010 年 5 月,在一篇名为 “A successful Git branching model” 的博文中,Vincent Driessen 介绍了一种构建在 Git 之上的软件开发模型。通过利用 Git 创建和管理分支的能力,为每个分支设定具有特定的含义名称,并将软件生命周期中的各类活动归并到不同的分支上,实现了软件开发过程不同阶段的相互隔离。这种软件开发的活动模型被 Vincent 称为 “Git Flow”。

Git Flow 流程图

这是 Vincent 博文中的 Git FLow 流程图,该图从右向左,从上到下看:

git-flow-model

Git Flow Branches

Git Flow 的核心就是分支(Branch),通过在项目的不同阶段对 Branch 的不同操作(包括但不限于 create、merge、rebase 等)来实现一个完整的高效率的工作流程。Git Flow Branches 主要分为两大类:Main Branches(主分支)Supporting branches(辅助分支)。 其中 Main Branches 中又包含了 MasterDevelop,而 Supporting branches 中包含了 FeatureReleaseHotfix 以及其他自定义分支。

Master

  • master 分支上存放的是最稳定的正式版本,并且该分支的代码应该是随时可在生产环境中使用的代码(Production Ready state)。当一个版本开发完毕后,产生了一份新的稳定的可供发布的代码时,master 分支上的代码要被更新。同时,每一次更新,都需要在 master 上打上对应的版本号(tag)。

  • 任何人不允许在 master 上进行代码的直接提交,只接受其他分支的合入。原则上 master 上的代码必须是合并自经过多轮测试且已经发布一段时间且线上稳定的 release 分支(预发分支)。

Develop

阅读全文 »

Preface

因为阿里云服务器在七月初即将过期,以及生活上的一些琐事,博客已经近一个月没有更新了。考虑到十月份域名也将过期,以及阿里云非学生用户太贵,遂考虑国外的云服务器 Vultr,优点是绑定域名不需要备案,以及按时计费也很方便,缺点是国内访问网速确实比不上阿里云,但同时也跟同学了解到可以使用锐速进行优化,这个以后再研究。此外,为将来迁移方便,使用 Docker 重新部署 Ghost 博客并制作成镜像上传到云端。这也算我迁移博客后的第一篇文章了。

Prefaring

  • 在 Vultr 的 Servers 界面先新增一个实例,如果能抢到每月 $2.5 的服务器是最好的,然而我没有抢到,所以选择了每月 $5 的服务器,系统为 Ubuntu 16.04,机房在新加坡

  • 在添加实例成功后第一件事是ping一下公网 IP 是否是通的,有些时候分配的 IP 是被大陆给墙了的。ping通后我习惯的首件要事就是添加我的 ssh 公钥以及修改 ssh 的一些策略,比如修改默认端口号、禁用密码登陆之类的,一切都是为安全考虑(吃了第一次的亏,一夜之间异常登陆三十次)

  • 迁移 Ghost 博客之前需要先将原先服务器上的相关文件下载到本地,再上传到新的服务器上。主要包含文章内容,图片以及主题。所幸 Ghost 博客提供了 Export/Import 功能,而且是所有文件导出到一个大 Json 文件中,很方便迁移
    14070DA1-C3CD-4A9F-AE52-D4D2DE4A2CDB主题也很方便,我之前就将代码上传至 GitHub,克隆下来压缩上传就行。图片稍微麻烦点,需要将 Ghost 目录下的整个content/images文件夹scp到本地,再scp到 Vultr 服务器上,可能要花些时间

  • 接下来去修改你的域名设置,我是在 GoDaddy 上购买的域名,所以去狗爹网修改配置如下
    64F8A358-E544-4FA3-819C-7F38F5327A5A

  • 准备工作已经做好,剩下的就是在新服务器上搭建环境和部署博客了。必要的东西也就三个,Nginx 用于做端口映射,Docker 用于运行 Ghost 容器,Certbot 用来配置 Https。Nginx 在 Ubuntu 上安装很简单,使用apt-get命令即可。Certbot 安装在我的另一篇博客Certbot配置Https中有详细介绍。我们着重介绍一下如何安装 Docker

Installing Docker

参考 Docker官方网站,选择自己的操作系统,我的是 Ubuntu 16.04

  • Update the apt package index, Install packages to allow apt to use a repository over HTTPS

    1
    2
    3
    4
    5
    6
    $ sudo apt-get update
    $ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
  • Add Docker’s official GPG key

    1
    $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  • Set up the stable repository

    1
    2
    3
    4
    $ sudo add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) \
    stable"
  • Install the latest version of Docker CE

    1
    2
    $ sudo apt-get update
    $ sudo apt-get install docker-ce

Deploying Ghost

  • 拉取 Ghost 最新的 Docker 镜像

    1
    $ sudo docker pull ghost
  • 运行一个容器实例,-d后台运行,-p 2368:2368绑定宿主机 2368 端口至容器内 2368 端口(必须显式的绑定,不然不会自动映射),这也是 Ghost 默认占用的端口号

    1
    $ sudo docker run -d -p 2368:2368 ghost
  • 运行后访问{IP}:2368可以成功进入 Ghost 主页,但是现在还有一些问题,就是点击 Home 键跳转的地址为 localhost:2368,我们需要进入到容器内部修改 Ghost 配置文件

    1
    $ sudo docker exec -it 16 bash

    上述命令表示以交互式终端执行容器的bash命令,其中 16 是刚才启动的容器 ID 前两位,可以使用docker ps查看,通常使用可以唯一标识的前几位即可

  • 进入容器后默认在/var/lib/ghost即 Ghost 安装路径下,修改其下的config.production.json配置文件,其实该文件链接到config.development.json,所以修改哪一个都一样,只需要修改 url 和 server 即可

    1
    2
    3
    4
    5
    "url": "https://s2mple.xyz/",
    "server": {
    "port": 2368,
    "host": "0.0.0.0"
    },

    退出容器后使用docker restart 16重启容器

  • 主题可以在网页上直接上传。图片还需要我们拷贝到容器中,使用如下命令

    1
    $ sudo docker cp images/ 16:/var/lib/ghost/content

Nginx & Https

阅读全文 »

前言

函数式编程是一种编程范式,我们常见的编程范式有命令式编程(Imperative programming)函数式编程(Functional Programming),常见的面向对象编程也是一种命令式编程。相比之下,函数式编程更关心数据的映射,命令式编程则关心解决问题的步骤

命令式编程是面向计算机硬件的抽象,有变量(对应着存储单元),赋值语句(获取,存储指令),表达式(内存引用和算术运算)和控制语句(跳转指令)。简单来说,命令式程序就是一个冯诺依曼机的指令序列。以下代码就是典型的命令式编程:

1
2
3
4
5
6
7
8
9
void sumOfPrices() {
List<Integer> prices = Arrays.asList(10, 30, 17, 20, 15, 18, 45, 12);
Double total = 0.0;
for (Integer price : prices) {
if (price > 20) {
total = total + (price * 0.9);
}
}
}

而函数式编程是面向数学的抽象,将计算描述为一种表达式求值。函数式编程希望程序员用计算(函数)来表示程序,用计算(函数)的组合来表达程序的组合。而非函数式编程则习惯于用命令来表示程序,用命令的顺序执行来表达程序的组合。比如如下的 Scala 代码,通过filter()、map()、reduce()这些函数的组合,完成了从 prices 到 total 的映射关系

1
2
3
4
5
6
7
8
9
object Prices {
def main(args: Array[String]): Unit = {
val prices = Array(10, 30, 17, 20, 15, 18, 45, 12)
val total = prices.filter(x => x > 20)
.map(x => x * 0.9)
.reduce((x, y) => x + y)
print("total is: " + total)
}
}

什么是函数式编程

说到底,什么是函数式编程呢?这里借用廖雪峰老师在 Python函数式编程 中的定义。

我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计,函数就是面向过程的程序设计的基本单元。而函数式编程(请注意多了一个“式”字)—— Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。

我们首先要搞明白计算机(Computer)和计算(Compute)的概念。在计算机的层次上,CPU 执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如 C 语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如 Lisp 语言。

阅读全文 »

前言

该系列源于张逸总监的 Clean Code 培训,包涵了如何写出高质量代码的思想、代码案例以及重构代码的实际演练。上一篇我们通过报表参数填充案例复习了迪米特法则(最小知识法则)、信息专家模式:数据和行为应该封装在一起。本篇我们将通过 PartDB 案例来见识 IDEA 中 Extract Superclass 等强大的重构功能,以及与案例相关的设计模式:模版方法模式

准备工作

  • IntelliJ IDEA,相比 Eclipse,IDEA 在重构方面十分优秀,结合快捷键,使用起来让人赏心悦目。
  • 示例代码地址 https://github.com/agiledon/cleancode.git ,进行实际操作有助于加深理解和记住快捷键。代码有两个分支,master 分支为重构前的代码,after-refactoring 分支为重构后代码,可以使用快捷键 Cmd + D 查看代码差异
  • 活用快捷键,本人使用的 IDEA 快捷键为 Mac OS X 10.5+ 。Windows 用户将 Cmd 替换成 Ctrl,或者在 IDEA 的 Refactor 菜单中查看快捷键。
快捷键 作用
Ctrl + T 重构菜单
Shift + F6 重命名方法、属性、文件
Cmd + Alt + M 提取方法(extract method)
Cmd + Alt + N 内联(Inline),与 extract 相反
Cmd + Shift + 上下箭头 上下移动声明体(statement)

案例代码

我们定义好了一个汽车零件类 Part,现在要通过 PartDB 去访问数据库执行select * from part,并将返回结果填充成一个 PartList。

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
public class PartDB {
private static final String DRIVER_CLASS = "";
private static final String DB_URL = "";
private static final String USER = "";
private static final String PASSWORD = "";
private static final String SQL_SELECT_PARTS = "select * from part";
private List<Part> partList = new ArrayList<Part>();

public void populate() throws Exception {
Connection c = null;
try {
Class.forName(DRIVER_CLASS);
c = DriverManager.getConnection(DB_URL, USER, PASSWORD);
Statement stmt = c.createStatement();
ResultSet rs = stmt.executeQuery(SQL_SELECT_PARTS);
while (rs.next()) {
Part p = new Part();
p.setName(rs.getString("name"));
p.setBrand(rs.getString("brand"));
p.setRetailPrice(rs.getDouble("retail_price"));
partList.add(p);
}
} finally {
c.close();
}
}
}

上述代码大概是每一个 Java 程序员都会接触到的:使用 JDBC 访问数据库。加载驱动、创立连接、执行 SQL 返回结果集并且填充到 Java 类中。显然,如果每一步都需要我们手动编写,那若是新增了一个类,比如 CustomerDB 是不是还要去 getConnection 等等,这必然会造成许多冗余代码。而现在许多的持久层框架,例如 MyBatis、Hibernate 都是基于 JDBC 进行再封装,避免了重复繁琐的工作。下面我们看看如何重构上述代码。

重构

阅读全文 »

前言

该系列源于张逸总监Clean Code 培训,包涵了如何写出高质量代码的思想、代码案例以及重构代码的实际演练。上一篇我们介绍了迪米特法则(最小知识法则)、信息专家模式:数据和行为应该封装在一起,并且通过 Paperboy 案例实操在 IntelliJ IDEA 中如何重构代码。本篇我们将通过报表参数填充案例来加深理解,并见识 IDEA 中更为强大的重构功能。

准备工作

  • IntelliJ IDEA,相比 Eclipse,IDEA 在重构方面十分优秀,结合快捷键,使用起来让人赏心悦目。
  • 示例代码地址 https://github.com/agiledon/cleancode.git ,进行实际操作有助于加深理解和记住快捷键。代码有两个分支,master 分支为重构前的代码,after-refactoring 分支为重构后代码,可以使用快捷键 Cmd + D 查看代码差异
  • 活用快捷键,本人使用的 IDEA 快捷键为 Mac OS X 10.5+ 。Windows 用户将 Cmd 替换成 Ctrl,或者在 IDEA 的 Refactor 菜单中查看快捷键。
快捷键 作用
Ctrl + T 重构菜单
Shift + F6 重命名方法、属性、文件
Cmd + Alt + M 提取方法(extract method)
Cmd + Alt + N 内联(Inline),与 extract 相反
Cmd + Shift + 上下箭头 上下移动声明体(statement)

案例:报表系统之参数处理

在示例项目中,需要对客户发出的 Web 请求进行处理,获得需要的参数。参数的值放在 Request 中,实现根据配置文件获得了参数的类型信息。根据项目需求,将参数划分为三种:

  • 单一参数(SimpleParameter)
  • 元素项参数(ItemParameter)
  • 表参数(TableParameter)

因为参数的属性是在配置文件中已经配好,所以定义了 ParameterGraph 对象。它能够读取参数的配置信息,并根据参数的类型创建不同的参数类,这些参数类共同实现了 Parameter 接口。

最初的实现代码为:

阅读全文 »