1.Flowable 介绍
2.技术干货!源码DPDK新手入门到网络功能深入理解
3.git flow使用规范
4.多master/develop分支如何使用gitflow版本控制
5.flow 使用详解 + 小结
Flowable 介绍
Flowable 是源码一个基于 Java 的轻量级业务流程引擎,它支持BPMN 2.0流程定义的源码部署与执行,包括流程实例的源码管理和查询。核心引擎提供API以管理流程并执行相关操作,源码同时支持CMMN用于案例管理,源码php娱乐网教程源码DMN进行决策规则处理。源码它的源码灵活性使其能轻易融入各种Java环境,如Java SE、源码Servlet容器或Java EE服务器,源码还可通过REST API进行调用。源码Flowable框架也包含一系列UI应用,源码如Modeler用于流程设计,源码Admin进行引擎管理,源码IDM负责人员和组织,源码以及Task处理任务执行。
Flowable源自Activiti5.x的重构,引入了CMMN、DMN和表单等功能。其特点是高效且实战验证,提供了流程设计插件,以及以Angular构建的可扩展用户界面。关于软件包,它包含了database脚本、文档、jar包、war文件等,如Admin、IDM、Modeler、REST和Task应用,分别用于引擎管理、beandefine源码人员管理、流程设计、API暴露和任务处理。源码包则包含了各种模块结构,如SpringBoot启动类、配置文件、服务层、控制层等,以及用于编译和快速入门的脚本和教程,如运行IDM来创建用户权限,使用Modeler创建流程模板,通过Task应用查询并完成任务。
技术干货!DPDK新手入门到网络功能深入理解
DPDK新手入门
一、安装
1. 下载源码
DPDK源文件由几个目录组成。
2. 编译
二、配置
1. 预留大页
2. 加载 UIO 驱动
三、运行 Demo
DPDK在examples文件下预置了一系列示例代码,这里以Helloworld为例进行编译。
编译完成后会在build目录下生成一个可执行文件,通过附加一些EAL参数可以运行起来。
以下参数都是比较常用的
四、核心组件
DPDK整套架构是基于以下四个核心组件设计而成的
1. 环形缓冲区管理(librte_ring)
一个无锁的多生产者,多消费者的FIFO表处理接口,可用于不同核之间或是逻辑核上处理单元之间的通信。
2. 内存池管理(librte_mempool)
主要职责是在内存中分配用来存储对象的pool。 每个pool以名称来唯一标识,并且使用一个ring来存储空闲的对象节点。 它还提供了一些其他的服务,如针对每个处理器核心的缓存或者一个能通过添加padding来使对象均匀分散在所有内存通道的对齐辅助工具。
3. 网络报文缓冲区管理(librte_mbuf)
它提供了创建、firebase 源码释放报文缓存的能力,DPDK应用程序可能使用这些报文缓存来存储数据包。这个缓存通常在程序开始时通过DPDK的mempool库创建。这个库提供了创建和释放mbuf的API,能用来暂存数据包。
4. 定时器管理(librte_timer)
这个模块为DPDK的执行单元提供了异步执行函数的能力,也能够周期性的触发函数。它是通过环境抽象层EAL提供的能力来获取的精准时间。
五、环境抽象层(EAL)
EAL是用于为DPDK程序提供底层驱动能力抽象的,它使DPDK程序不需要关注下层具体的网卡或者操作系统,而只需要利用EAL提供的抽象接口即可,EAL会负责将其转换为对应的API。
六、通用流rte_flow
rte_flow提供了一种通用的方式来配置硬件以匹配特定的Ingress或Egress流量,根据用户的任何配置规则对其进行操作或查询相关计数器。
这种通用的方式细化后就是一系列的流规则,每条流规则由多种匹配模式和动作列表组成。
一个流规则可以具有几个不同的动作(如在将数据重定向到特定队列之前执行计数,封装,解封装等操作),而不是依靠几个规则来实现这些动作,应用程序操作具体的硬件实现细节来顺序执行。
1. 属性rte_flow_attr
a. 组group
流规则可以通过为其分配一个公共的组号来分组,通过jump的流量将执行这一组的操作。较低的值具有较高的优先级。组0具有最高优先级,且只有组0的规则会被默认匹配到。
b. 优先级priority
可以将优先级分配给流规则。像Group一样,较低的组合 源码值表示较高的优先级,0为最大值。
组和优先级是任意的,取决于应用程序,它们不需要是连续的,也不需要从0开始,但是最大数量因设备而异,并且可能受到现有流规则的影响。
c. 流量方向ingress or egress
流量规则可以应用于入站和/或出站流量(Ingress/Egress)。
2. 模式条目rte_flow_item
模式条目类似于一套正则匹配规则,用来匹配目标数据包,其结构如代码所示。
首先模式条目rte_flow_item_type可以分成两类:
同时每个条目可以最多设置三个相同类型的结构:
a. ANY可以匹配任何协议,还可以一个条目匹配多层协议。
b. ETH
c. IPv4
d. TCP
3. 操作rte_flow_action
操作用于对已经匹配到的数据包进行处理,同时多个操作也可以进行组合以实现一个流水线处理。
首先操作类别可以分成三类:
a. MARK对流量进行标记,会设置PKT_RX_FDIR和PKT_RX_FDIR_ID两个FLAG,具体的值可以通过hash.fdir.hi获得。
b. QUEUE将流量上送到某个队列中
c. DROP将数据包丢弃
d. COUNT对数据包进行计数,如果同一个flow里有多个count操作,则每个都需要指定一个独立的id,shared标记的计数器可以用于统一端口的不同的flow一同进行计数。
e. RAW_DECAP用来对匹配到的数据包进行拆包,一般用于隧道流量的剥离。在action定义的时候需要传入一个data用来指定匹配规则和需要移除的内容。
f. RSS对流量进行负载均衡的操作,他将根据提供的数据包进行哈希操作,并将其移动到对应的队列中。
其中的level属性用来指定使用第几层协议进行哈希:
g. 拆包Decap
h. One\Two Port Hairpin
七、常用API
1. 程序初始化
2. 端口初始化
3. 队列初始化
DPDK-网络协议栈-vpp-ovs-DDoS-虚拟化技术
DPDK技术路线视频教程地址立即学习
一、DPDK网络
1. 网络协议栈项目
2.dpdk组件项目
3.dpdk经典项目
二、dmskin源码DPDK框架
1. 可扩展的矢量数据包处理框架vpp(c/c++)
2.DPDK的虚拟交换机框架OvS
3.golang的网络开发框架nff-go(golang)
4. 轻量级的switch框架snabb(lua)
5. 高效磁盘io读写spdk(c)
三、DPDK源码
1. 内核驱动
2. 内存
3. 协议
4. 虚拟化
5. cpu
6. 安全
四、性能测试
1. 性能指标
2. 测试方法
3. 测试工具DPDK相关学习资料分享:点击领取,备注DPDK
DPDK新手入门原文链接:DPDK上手
git flow使用规范
1. Git Git 是目前世界上最先进的分布式版本控制系统,关于 Git 不做过多的介绍,想仔细学习的可以参考廖雪峰的 Git教程。顺便推销一下正哥的 Git常用指令与操作。
2. Git Flow
2.1 Git Flow 是什么 Git Flow 是一个基于 Git 的开发流程管理的模型,因极其适合多人协作有效地进行并行开发而被广泛用于项目流程的源代码管理。这里推荐一个光速入坑的教程: Gitflow Workflow Git Flow 的核心优势体现在以下几点:
Git Flow常用的命令如下:
$ git flow init # 初始化git flow配置,建立master和develop分支
$ git flow feature start xxx # 开始新特性开发,在本地新建一个feature/xxx的分支
$ git flow feature publish xxx # 发布新特性分支,将本地的feature/xxx推到远端,并建立一个merge request.
$ git flow feature finish xxx # 结束一个新特性开发,将本地的feature/xxx合并到develop.
2.2 Git Flow 流程 一个 Git Flow 全流程图如下. [我是图]( nvie.com/img/git-model@...)
2.3 Git Flow 分支 Git Flow 流程中包含一下几种分支。
1) master分支 主分支,随项目一直存在的长期分支。master分支HEAD所在的位置,永远是当前生产环境的代码。master分支不允许直接提交代码,仅允许从release或者hotfix分支通过merge request合并代码。
2) develop分支 开发分支,随项目一直存在的长期分支。develop分支的HEAD所在的位置,永远是下一个版本中已开发完成的新特性的最新代码。develop分支的代码每天自动构建并部署到测试环境。develop分支不允许直接提交代码,仅允许从feature, release或者hotfix分支通过merge request合并代码。当develop分支中下一个版本的新特性已经全部开发完毕后,从develop分支开出release分支,进入测试阶段。在下个版本的release分支创建之前,非下个版本的feature分支不允许向develop分支合并。
3) feature分支 feature分支是一类以feature/为前缀(gitflow默认值, 可以更换)的分支的统称。每一个feature分支从develop分支新建,进行==某一个功能==的开发。功能开发并测试稳定后,feature分支将合并回develop分支。同一个人可以同时开发多个feature分支,同一个feature分支也可以同时被多个人开发。多个feature同时开发的情形,后开发完的分支在最后合并回develop时,往往会遇到冲突的情况。此时一般遵循以下两种方法解决冲突。
4) release分支 release分支是一类以release/为前缀(gitflow默认值, 可以更换)的分支的统称。develop分支上的下一个版本的所有新特性开发完毕,从develop分支开出一个该版本的release分支,并进行测试。release分支不允许进行新特性开发,而只进行bug修复和更新版本mata信息(如版本号, 构建日期, 更新日志等),并且可以不定期将新的bug修复改动合并回develop。当release充分测试稳定后,同时合并进入master分支和develop分支,并在master分支上的建议该release版本的TAG。
5) hotfix分支 当生产环境发现bug时,可以通过新建hotfix分支,来修复bug,修复后双向合并到develop和master。
3. Git Commit Message 规范 Git 每次提交都要写 commit message,否则就不允许提交。一般来说,commit message 应该清晰地说明本次提交的内容或目的。程序猿作为最具创造力的物种,他们甚至可以在commit的时候写诗。我是图 规范 git commit message,能够:
个人觉得认真规范的写commit message是对自己这次辛苦工作的总结和回顾。如果你够骚包,也可以加点仪式感进去。当下最流行的git commit 规范莫过于 angular规范。Angular规范的模板如下。
(): // 空一行 // 空一行
其中,header 是必须的,body 和 footer 可以省略。
3.1 Header Header 必须在同一行,包含3部分: type, scope, subject。其中type和subject必须写,scope可不写。
3.2 Body Body 部分是对本次提交代码的详细描述,主要描述本次提交的动机和需要同步给团队的信息。
3.3 Footer Footer 部分只用于两种情况。
3.4 Revert 有一种特殊情况,如果当前 commit 用于撤销以前的 commit,则必须以revert:开头,后面跟着被撤销 Commit 的 Header. Body部分的格式是固定的,必须写成This reverts commit <hash>., 其中的hash是被撤销 commit 的 SHA 标识符。例如: revert: feat(pencil): add 'graphiteWidth' option This reverts commit eccaabdff。
4. Code Review 摘抄自知乎问题的回答,有兴趣的可以去知乎看看原问题。
4.1 Code Review有什么用 通过参与实战和团队成员讨论思考,我们认为CodeReview最终的作用将归到促进工程师日常代码交流和人员的成长上面来,与此同时作为辅助手段来对产品质量进行把关。
4.2 Code Review适合什么团队 从代码质量提升的角度上看,以下类型的团队,笔者建议把CodeReview活动有效运作起来:
4.3 如何有效的Code Review 1、代码规范:明确Coding规则2、检视指南:制定一个checklist, 消除困惑和迷茫3、总结优化:透明问题,持续优化(非常重要)4、激励机制:激发主观能动性
4.4 哪种方式进行Code Review 最后组合一下,笔者个人推荐的CodeReview方式是强制+事前+小片段+线上交流+高频率,同时,如果能结合线下的大模块方式开展代码交流活动,效果会更好,这个经验来自手机管家高权限应用组的接地气实践。
5. 开发规范 必须遵守的规范.
推荐遵守的规范.
6. 示例
多master/develop分支如何使用gitflow版本控制
在使用 gitflow 做版本控制系统,发现gitflow的时候只能指定一个master/develop,如果要多分支使用要如何操作呢?那么来看看我是如何给gitflow加料的。
公司都是git作为版本控制,公司一些项目组在用gitflow,但是我们组没有强制, 但是我上月出了一次事故,总结就是分支管理问题,所以开始强迫自己使用gitflow, 以前的项目是一个master和一个develop,自己checkout一个分支,然后merge(不理解的可以看看a-successful-git-branching-model).
问题出现了: 项目有几个主分支和开发分支,比如master_sina, master_qq. master_buzz ,而gitflow的时候只能指定一个master/develop, 这样你start一个feature/hotfix之前就要去.git/config里面修改 [gitflow “branch”]项的相关主分支和开发分支,so不方便。看了下源码,给gitflow加点料
添加功能
当你打开了feature/hotfix分支,但是你不想要它了(当然你可以直接git branch -D xx),使用git flow hotfix/feature delete ,自动帮你删除这个分支,以便你新建其他分支(git flow只容许你一次存在一个hotfix/feature分支)
你想使用gitflow删除其它存在分支嘛?不需要 git branch -D ,你还可以git flow hotfix/feature delete XX
比如我在init的时候指定了master为master_sina, 而当我想创建master_qq的hotfix,我只需要在start的是否给它取名字是’qq_‘开头的即可,要是有其它的需要你可以直接在源码里面添加对应的内容
例子 git-flow-hotfix 我主要标记我修改的部分
代码如下
复制代码
init() {
require_git_repo
require_gitflow_initialized
gitflow_load_settings
VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`")
PREFIX=$(git config --get gitflow.prefix.hotfix)
}
# 增加help的选项说明
usage() {
echo "usage: git flow hotfix [list] [-v]"
echo " git flow hotfix start [-F] version [base]"
echo " git flow hotfix finish [-Fsumpk] version"
echo " git flow hotfix publish version"
echo " git flow hotfix delete [branch]"
echo " git flow hotfix track version"
}
cmd_default() {
cmd_list "$@"
}
cmd_list() {
DEFINE_boolean verbose false 'verbose (more) output' v
parse_args "$@"
local hotfix_branches
local current_branch
local short_names
hotfix_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
if [ -z "$hotfix_branches" ]; then
warn "No hotfix branches exist."
warn ""
warn "You can start a new hotfix branch:"
warn ""
warn " git flow hotfix start version [base]"
warn ""
exit 0
fi
current_branch=$(git branch --no-color | grep '^* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$hotfix_branches" | sed "s ^$PREFIX g")
# determine column width first
local width=0
local branch
for branch in $short_names; do
local len=${ #branch}
width=$(max $width $len)
done
width=$(($width+3))
local branch
for branch in $short_names; do
local fullname=$PREFIX$branch
local base=$(git merge-base "$fullname" "$MASTER_BRANCH")
local master_sha=$(git rev-parse "$MASTER_BRANCH")
local branch_sha=$(git rev-parse "$fullname")
if [ "$fullname" = "$current_branch" ]; then
printf "* "
else
printf " "
fi
if flag verbose; then
printf "%-${ width}s" "$branch"
if [ "$branch_sha" = "$master_sha" ]; then
printf "(no commits yet)"
else
local tagname=$(git name-rev --tags --no-undefined --name-only "$base")
local nicename
if [ "$tagname" != "" ]; then
nicename=$tagname
else
nicename=$(git rev-parse --short "$base")
fi
printf "(based on $nicename)"
fi
else
printf "%s" "$branch"
fi
echo
done
}
cmd_help() {
usage
exit 0
}
parse_args() {
# parse options
FLAGS "$@" || exit $?
eval set -- "${ FLAGS_ARGV}"
# read arguments into global variables
VERSION=$1
BRANCH=$PREFIX$VERSION
# 这里就是我多master/develop的技巧,我这里会判断要新建的分支的前缀,
# 要是qq_开头就会基于master_qq和develop_qq创建分支。所以你可以根据你的需要在这里加一些方法
test `expr match "$@" "qq_"` -ne 0 MASTER_BRANCH="$MASTER_BRANCH"_qq
DEVELOP_BRANCH="$DEVELOP_BRANCH"_qq
}
require_version_arg() {
if [ "$VERSION" = "" ]; then
warn "Missing argument version"
usage
exit 1
fi
}
require_base_is_on_master() {
if ! git branch --no-color --contains "$BASE" 2/dev/null
| sed 's/[* ] //g'
| grep -q "^$MASTER_BRANCH$"; then
die "fatal: Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."
fi
}
require_no_existing_hotfix_branches() {
local hotfix_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
local first_branch=$(echo ${ hotfix_branches} | head -n1)
first_branch=${ first_branch#$PREFIX}
[ -z "$hotfix_branches" ] ||
die "There is an existing hotfix branch ($first_branch). Finish that one first."
}
# 添加delete 参数,函数需要cmd_开头
cmd_delete() {
if [ "$1" = "" ]; then
# 当不指定参数自动去找存在的未关闭的gitflow分支
local hotfix_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
test "$hotfix_branches" = "" die "There has not existing hotfix branch can delete" exit 1
else
# 指定参数先判断参数是不是的数量格式
test $# != 1 die "There only need one parameter indicates the branch to be deleted" exit 1
hotfix_branches="$1"
fi
# 当要删除的分支就是当前分支,先checkout到develop分支
test "$hotfix_branches" = "$(git_current_branch)" echo 'First checkout develp branch'; git_do checkout "$DEVELOP_BRANCH"
git branch -D ${ hotfix_branches} /dev/null echo 'Delete Successed'|| die "Did not find branch: [$hotfix_branches]"
}
cmd_start() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
parse_args "$@"
BASE=${ 2:-$MASTER_BRANCH}
require_version_arg
require_base_is_on_master
require_no_existing_hotfix_branches
# sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
require_tag_absent "$VERSION_PREFIX$VERSION"
if flag fetch; then
git_do fetch -q "$ORIGIN" "$MASTER_BRANCH"
fi
if has "$ORIGIN/$MASTER_BRANCH" $(git_remote_branches); then
require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
fi
# create branch
git_do checkout -b "$BRANCH" "$BASE"
echo
echo "Summary of actions:"
echo "- A new branch '$BRANCH' was created, based on '$BASE'"
echo "- You are now on branch '$BRANCH'"
echo
echo "Follow-up actions:"
echo "- Bump the version number now!"
echo "- Start committing your hot fixes"
echo "- When done, run:"
echo
echo " git flow hotfix finish '$VERSION'"
echo
}
cmd_publish() {
parse_args "$@"
require_version_arg
# sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git_do fetch -q "$ORIGIN"
require_branch_absent "$ORIGIN/$BRANCH"
# create remote branch
git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
git_do fetch -q "$ORIGIN"
# configure remote tracking
git config "branch.$BRANCH.remote" "$ORIGIN"
git config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
git_do checkout "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote branch '$BRANCH' was created"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo "- You are now on branch '$BRANCH'"
echo
}
cmd_track() {
parse_args "$@"
require_version_arg
# sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
git_do fetch -q "$ORIGIN"
require_branch "$ORIGIN/$BRANCH"
# create tracking branch
git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote tracking branch '$BRANCH' was created"
echo "- You are now on branch '$BRANCH'"
echo
}
cmd_finish() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean sign false "sign the release tag cryptographically" s
DEFINE_string signingkey "" "use the given GPG-key for the digital signature (implies -s)" u
DEFINE_string message "" "use the given tag message" m
DEFINE_string messagefile "" "use the contents of the given file as tag message" f
DEFINE_boolean push false "push to $ORIGIN after performing finish" p
DEFINE_boolean keep false "keep branch after performing finish" k
DEFINE_boolean notag false "don't tag this release" n
parse_args "$@"
require_version_arg
# handle flags that imply other flags
if [ "$FLAGS_signingkey" != "" ]; then
FLAGS_sign=$FLAGS_TRUE
fi
# sanity checks
require_branch "$BRANCH"
require_clean_working_tree
if flag fetch; then
git_do fetch -q "$ORIGIN" "$MASTER_BRANCH" ||
die "Could not fetch $MASTER_BRANCH from $ORIGIN."
git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH" ||
die "Could not fetch $DEVELOP_BRANCH from $ORIGIN."
fi
if has "$ORIGIN/$MASTER_BRANCH" $(git_remote_branches); then
require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
fi
if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then
require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
fi
# try to merge into master
# in case a previous attempt to finish this release branch has failed,
# but the merge into master was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH"; then
git_do checkout "$MASTER_BRANCH" ||
die "Could not check out $MASTER_BRANCH."
git_do merge --no-ff "$BRANCH" ||
die "There were merge conflicts."
# TODO: What do we do now?
fi
if noflag notag; then
# try to tag the release
# in case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
local tagname=$VERSION_PREFIX$VERSION
if ! git_tag_exists "$tagname"; then
local opts="-a"
flag sign opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] opts="$opts -u '$FLAGS_signingkey'"
[ "$FLAGS_message" != "" ] opts="$opts -m '$FLAGS_message'"
[ "$FLAGS_messagefile" != "" ] opts="$opts -F '$FLAGS_messagefile'"
eval git_do tag $opts "$VERSION_PREFIX$VERSION" "$BRANCH" ||
die "Tagging failed. Please run finish again to retry."
fi
fi
# try to merge into develop
# in case a previous attempt to finish this release branch has failed,
# but the merge into develop was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH"; then
git_do checkout "$DEVELOP_BRANCH" ||
die "Could not check out $DEVELOP_BRANCH."
# TODO: Actually, accounting for 'git describe' pays, so we should
# ideally git merge --no-ff $tagname here, instead!
git_do merge --no-ff "$BRANCH" ||
die "There were merge conflicts."
# TODO: What do we do now?
fi
# delete branch
if noflag keep; then
# 这个问题很奇怪,在完成分支删除它也会存在当前分支是
# 要删除的分支删除报错的问题,所以先切换走
test "$BRANCH" = "$(git_current_branch)" git_do checkout "$DEVELOP_BRANCH"
git_do branch -d "$BRANCH"
fi
if flag push; then
git_do push "$ORIGIN" "$DEVELOP_BRANCH" ||
die "Could not push to $DEVELOP_BRANCH from $ORIGIN."
git_do push "$ORIGIN" "$MASTER_BRANCH" ||
die "Could not push to $MASTER_BRANCH from $ORIGIN."
if noflag notag; then
git_do push --tags "$ORIGIN" ||
die "Could not push tags to $ORIGIN."
fi
fi
echo
echo "Summary of actions:"
echo "- Latest objects have been fetched from '$ORIGIN'"
echo "- Hotfix branch has been merged into '$MASTER_BRANCH'"
if noflag notag; then
echo "- The hotfix was tagged '$VERSION_PREFIX$VERSION'"
fi
echo "- Hotfix branch has been back-merged into '$DEVELOP_BRANCH'"
if flag keep; then
echo "- Hotfix branch '$BRANCH' is still available"
else
echo "- Hotfix branch '$BRANCH' has been deleted"
fi
if flag push; then
echo "- '$DEVELOP_BRANCH', '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
fi
echo
}
flow 使用详解 + 小结
flow 是一种用于静态检查 JavaScript 项目的工具,尤其适用于这种语言的弱类型和动态类型特性。在大型项目中,流类型注解能有效避免数据类型不匹配导致的问题。
以重构 .NET 项目至 React 为例,源码与后端 API 传来的数据类型不匹配,导致使用时需不断转换数据类型,增加了开发难度。使用 flow 可以通过类型注解确保数据一致性,减少类型错误。
安装和配置 flow 非常简单,通过 npm 或 yarn 建立项目并将其添加到 package.json。使用 babel 编译器移除 flow 语法,确保代码可正确运行。在项目中添加注释,flow 会检查类型是否符合预期。若类型不符,会报错提示。
VSCode 集成了 flow 插件,可以直观地显示错误,通过设置关闭 JavaScript 校验功能以避免干扰。flow 的语法包括原始类型、数组类型、对象类型、函数类型及混合类型、any 类型和 maybe 类型等。
原始类型如 boolean、string、number、null、undefined 和 symbol。数组类型使用 Array 或数组语法声明,只读数组使用 $ReadOnlyArray。对象类型使用 { } 格式,键值对数量未知时可使用数组声明。函数类型定义参数和返回值类型。
混合类型使用 | 符号或 mixed 关键字表示变量可能为多种类型之一。any 关键字表示完全不进行类型检查,仅在特定情况下谨慎使用。maybe 类型允许接受 null 和 undefined 之外的其他类型。
其他类型如 tuple、class 和 tuple 类型用于更细粒度的限制。flow 提供了强大且灵活的类型系统,以增强 JavaScript 项目的类型安全性和可维护性。