乐正

Actions speak louder than words.

一名菜鸟IT项目经理的成长笔记

是什么?

Q: 项目经理是什么?

项目经理是公司委派,负责实现项目目标的个人,是公司授权的项目负责人,是项目的直 接组织者和管理者。

Q:项目经理的职责是什么?

  • 对项目全过程进行组织和管理,按预期交付项目的成果
  • 管理客户关系,以取得客户对交付的成果和过程最满意的评价
  • 管理项目团队,使之高效而愉快的工作,并获得最满意的工作体验

Q:IT项目经理的主要任务是什么?

  1. 支持售前过程。IT项目一般比较复杂,交付风险大,需要在合同中约定工作范围,进度 计划要估算成本和人力资源,制定切实可行的实施方案。
  2. 负责项目交付。围绕目标,按照规范执行项目计划。按期汇报进度,保证项目在计划内 交付。
  3. 完成项目收尾。完成交付成果之后,要讲成果转移给客户,确保客户可以稳定地使用系 统。
  4. 管理干系人的关系。沟通各方人员信息,保持密切联系,解决矛盾冲突。
  5. 管理项目团队。寻找合适的资源,优化资源配置,建立合理的组织结构,确定清晰的职 责分工,打造高效的项目团队。

需要什么素质?

  1. 领导力。领导力是指通过他人来完成工作的能力。领导力并不意味着『官』,而应 该是『领头的』。不仅要求别人做的自己能做到,而且要知道『下一步』,目标在哪里。
  2. 责任心。出于对承诺的负责,会倾尽全力达成目标。
  3. 积极主动。善于利用自身的优势改变局势。
  4. 压力承受。需要在压力中仍能保持镇定,冷静思考。

需要的知识和技能

专业知识

  • 项目管理专业知识
  • IT技术
  • 行业知识

实践技能

  • 商务技能。要代表公司管理项目,履行合同。
  • 项目启动。真正进入项目的第一个阶段往往是最慌乱的,必须清楚知道每天要做什么,这 样才能有条不紊。
  • 计划的制定需要工具和平台,执行需要推进,质量需要把控。明确质量管理内容,以及在 什么情况下有权利喊『停』。

软技能

  • 沟通和协调。沟通包括识别沟通对象,建立沟通渠道,明确沟通信息。
  • 团队和激励。必须让成员能够团结,为了共同的目标而努力。
  • 政治和文化。

项目启动的第一周

项目启动时,需要做的事情:

  • 建立组织和制度。建立组织结构,确定职责分工,确定基本规章制度和工作流程。
  • 明确工作思路。一边是要确认工作范围,制定工作计划;另一边要确定开发方法,特别是 马上要确定需求文档格式和工作流程。

启动的准备工作

  1. 确认项目范围。项目中范围包括两大类:一类是产品范围,也就是应该覆盖的业务 需求;一类是为了实现项目目标所需要完成的工作。
    将功能层级进行约定:
    • 子系统:指相对比较独立、功能完整一组业务功能。
    • 功能集:指在子系统内,按照业务特性归集的一组操作。
    • 执行单元:一次完成的一个独立业务操作。
  2. 粗略工作量估算
  3. 人力资源的配置
  4. 确定开发过程。按照项目的实际情况,制定一个《项目开发过程》的文件。明确项 目的开发阶段,明确各阶段的交付物,制定交付物的模板。

群策群力,制定项目计划的方法

  • 根据WBS方法指定活动清单。
  • 确定活动之间的依赖,绘制网络图。
  • 根据网络图的依赖关系和工期需求,分配资源,确定进度计划和资源计划。
  • 根据资源和进度计划,制定项目预算。

通过需求矩阵,进行具体项目管理

需求矩阵按照子系统、功能集和执行单元的结构列出所有的功能需求,每列对应每项工作的 工作步骤以及每个步骤的工作量。

"需求矩阵"

制定活动清单

计划过程的步骤如下:

"计划流程"

排序和网络图分析

有了活动清单和依赖关系,就可以进行排序了。我们可以使用节点表示任务,用箭头表示依 赖关系。

"网络图"

通过对网络图进行分析,可以得到项目与时间相关的一些重要信息:

  • 给定项目的预计和开始时间,能够计算每项活动必须开始和完成的最早时间。
  • 给定项目的要求完工时间,能够计算每项活动必须开始和完成的最晚时间。
  • 确定项目的关键路径,也就是最长活动路径。

资源和进度计划

进度计划是将工作计划安排到日历上,它不仅规定了整个项目各个阶段的起止日期,还规定 了所有项目的开始和结束日期。可以使用甘特图进行项目中的进度管理。

进度计划排定时,重点考虑两点:

  • 资源的使用情况是否合理,是否存在资源冲突的情况。
  • 对于那些有较大浮动时间的活动,可以初步确定是越早开始越好,还是越晚开始越好。

执行和检查

对于辛苦制定地计划,如何让每个人按照计划工作?如果知道每个人的工作进展?

阻碍计划落地执行的原因

主要计划落地的主要原因有两点:

  • 没有将计划细分,个人和计划之间缺少一个桥梁。但是将计划拆分到每天做什么也不现实, 所以,这里是一个工作的难点。
  • 执行项目的人员之间水平有差异。

任务的分解和委派

为了解决上述问题,初步有了以下方案:

"任务分解"

  1. 每组安周一周作为单位指定落实到个人头上的计划,制定一份一周工作计划表。
  2. 一周工作计划表每天检查,如果出现了异常,随时修改。
  3. 周五大家根据一周的工作内容,整理工作周报。

这个方法是不错。但是如果将工作分解到每天的粒度呢?

基本思路是将工作按照工作的流程,分解为『关键步骤』,每项任务的一项关键步骤,作为 一个人的工作任务,也是最小的管理单元。个人工作任务只有『完成』和『未完成』两种状 态。

检查和调整

为了有效控制和掌握进度,检查和调整是很重要的一个环节。

每日记录

每天下班前,可由相关人员自己在标记当日工作计划的完成情况,有完成、延迟完成和延迟 中三种状态,并进行汇总统计。并且可以提出自己的问题,由相关人员讨论解决问题或者安 排时间专门讨论。

周例会

周例会检查和调整项目计划,需要一定的讨论,讨论的重点是:任务完成了吗?没完成的原 因是什么?怎么调整?

质量管理

管什么?

经过多年的发展,质量管理已经有了一套基本的理论和方法。质量管理包括质量保证和质量 控制两大类。质量保证是指在项目过程中实施的有计划、有系统的活动,确保满足相关的标 准,典型的例子是评审和审计。质量控制是指采取适当的方法监控项目结果,确保结果符合 质量标准,典型的例子就是测试以及之后的缺陷跟踪。

在IT行业软件开发领域中,常见的公认的质量活动包括:配置管理、评审、测试以及缺陷跟 踪。

  • 评审:检查项目中间产品,早期发现缺陷以减少后期项目返工和修改的工作量。
  • 测试:直接检测软件产品中的缺陷,确保符合质量要求。一般通过单元测试、集成测试、 系统测试和性能测试实现。
  • 缺陷跟踪:记录和追踪缺陷从发现到解决的整个过程,确保所有的结论都有结论。
  • 审计:对项目工作过程进行检查,确保所有活动按照规程进行。
  • 变更控制:版本本更控制,也是重要的一环。
  • 配置管理:记录中间和最终产品(配置项)的变更历史。

质量经理在项目中的职责如下:

  • 贯彻公司的质量管理规范,负责质量管理过程中的检查和指导。
  • 负责制定项目开发/测试环境的标准和规范。
  • 负责项目的配置管理,通过权限控制和备份机制确保交付物的完备和安全。
  • 负责组织同行评审,确保中间交付物的质量。
  • 制定测试策略和测试计划,组织测试,确保最终交付成果的质量。

项目配置管理

项目配置管理是一项看不见的财富,可以在无形中减少因为版本意外等开发中出现的问题导 致的返工、重做等资源浪费。

Q: 什么是项目配置管理?

配置管理是在某一特定时点,确定软件配置的一个过程,通过对已标识的软件配置的一个过 程,通过对已表示的软件的配置的变更进行系统控制,从而在整个软件生命周期中保持软件 的整体性和可追溯性。

Q: 配置管理的具体要做什么?

通常来说,软件配置管理主要通过计划、标识和控制变更和发布配置状态报告来协调软件开 发,目的是使错误率达到最小并最有效地提高生产效率。

质量评审

评审的目的是尽早发现问题,一团和气的评审会完全达不到发现问题的目的。

Q: 评审中的角色有哪些?

首先要把评审中设计到的各个人员确认下来。评审过程中涉及的角色主要有四种:责任人、 主审人、评审专家和记录员。

主审人要先选定评审组的成员,然后再做评审的前期准备。在 评审过程中保证规范和高效, 评审结束后要将结果及时发布被评审相关人员。最后,还要对 评审中发现的问题追踪,直 到问题关闭。

责任人就是要被评审的对象。他们在评审之前准备好资料,在评审过程中解答提出的问题。 对于发现的问题要积极修正后提交给主审人。

记录员就是在评审过程中,把专家提出的问题都记录下来,还要记录责任人的回答信息,最 终要行程会议纪要,并且记录评审结果。

评审专家要彻底了解被评审的资料,其任务是寻找这些资料中的缺陷,侧重于发现问题而不 是解决问题。要保持客观。

Q: 评审的过程是什么?

评审的过程分为计划、预备会议、准备、评审会议和追踪几个阶段。

  • 计划阶段与项目计划同步,也就是说项目中有哪些要评审在项目计划中就已经提前定义好 了。
  • 预备会议,针对要评审的资料对评审组进行培训,并讨论评审资料。
  • 准备工作,是评审专家要彻底熟悉评审资料,以保证评审的质量和高效。
  • 评审会议,是主审人和评审专家对项目资料中的错误和缺陷进行确认。
  • 跟踪,主审人要确保责任人采取必要的措施修正发现的错误。

一个评审反馈表如下:

"评审反馈表"

让测试深入人心

保证质量最有效的措施就是测试。

Q: 为什么要有多种测试呢?

不同的测试是针对不同的开发活动来设置的。下面是软件测试的一个『V模型』:

"测试V模型"

  • 单元测试,主要是开发人员对编写的代码进行自测或相互进行交叉测试,用以检查代码是 否符合编码规范,是否存在逻辑错误。
  • 集成测试,将经过单元测试的模块组装成完整的程序。工作任务包括制定集成测试策略, 确定集成测试步骤,设计集成测试用例,然后逐一添加模块进行测试。
  • 系统测试,是为了验证需求分析确定的功能是否被正确的实现,同时还要对安装、部署、 适应性、安全性、界面等非功能性需求进行测试。
  • 性能测试,用来测试系统是否满足规定的性能需求。性能测试通常选择一些典型的功能, 检验这些功能在大量用户同时使用时是否稳定。
  • 用户验收测试,目的是验证需求与系统的匹配性,以及界面的友好性,响应时间等等。

缺陷跟踪

Q: 为什么要进行缺陷跟踪?

缺陷跟踪可以记录测试结果,确定代码质量,是确保问题得到解决的一个关键流程。其目的 是规范评审、测试、试运行等过程中发现缺陷的更改活动;跟踪缺陷处理的各个环节、避免 缺陷修改失控和遗漏;如实的反映缺陷处理过程。

Q: 怎么进行缺陷跟踪?

缺陷跟踪的起点是各种发现缺陷的活动,发现缺陷之后就进入了缺陷的跟踪流程,包括提交、 判断、分发、修改、复核和关闭几个关键步骤。

缺陷跟踪除了记录和跟踪缺陷的修复过程,很重要的还有对缺陷进行分类、统计和分析。

缺陷的类型一般分为一下几种:

缺陷类型 描述 可能的缺陷来源
用户界面 用户界面显示或者操作存在问题 详细设计
架构 系统存在架构方面问题 架构设计、概要设计
接口 系统内、外部接口错误,不能正常连接和工作 架构设计、概要设计
业务功能 业务功能不完善、未实现或者出现错误 需求分析、需求规格
系统功能 与业务无关,但是系统必须实现的功能不完整、未实现或者出现错误 架构设计、概要设计
性能 系统的响应时间、吞吐量、并发量等不满足需求 架构设计、概要设计、编码
可重用性 不满足被其他系统或者模块复用的要求 概要设计、编码
可移植性 不满足可跨平台移植或者部署的要求 概要设计、详细设计

缺陷的严重性说明了缺陷给最终交付的系统或者产品可能造成的影响程度。其中A级影响程 度最大,E级最小。

严重性等级 描述
A级(系统级) 系统整体崩溃,或者不能稳定地连续工作
B级(应用级) 部分应用或者子系统不能运行,或者不能稳定地连续工作
C级(业务级) 导致业务流程终止,或者因结果错误、数据不一致失败;因安全、容错性和性能问题等非功能性问题影响使用
D级(操作级) 不易于学习使用,界面操作困难;难以理解而不容易使用
E级(文档级) 安装手册、操作手册、在线帮助等文档不能提供帮助或者存在错误

从零搭建和配置OSX开发环境

对于每一名开发者来说,更换系统或者更换电脑的时候,都免不了花上不短的时间去折腾开 发环境的问题。我本人也是三番两次,深知这个过程的繁琐。所有,根据我自己以往的经验, 以及参考一下他人的意见,整理一下关于在Mac下做各种开发的配置,包含Java, Ruby, Vim, git, 数据库等等。欢迎补充与修正。

Terminal篇

这篇文章包含配置控制台环境,包括包管理工具, zsh, Vim, git的安装配置。

Homebrew, 你不能错过的包管理工具

包管理工具已经成为现在操作系统中不可缺少的一个重要工具了,它能大大减轻软件安装的 负担,节约我们的时间。Linux中常用的有yumapt-get工具,甚至Windows平台也 有Chocolatey这样优秀的工具,OSX平台自然有它独有的工具。

在OSX中,有两款大家常用的管理工具:Homebrew或者MacPorts。这两款工具都是为了解决同 样的问题——为OSX安装常用库和工具。Homebrew与MacPorts的主要区别是Homebrew不会破坏OSX 原生的环境,这也是我推荐Homebrew的主要原因。同时它安装的所有文件都是在用户独立空间内 的,这让你安装的所有软件对于该用户来说都是可以访问的,不需要使用sudo命令。

在安装Homebrew前,你需要前往AppStore下载并安装Xcode.

安装方式:

1
2
3
# OSX系统基本上都自带Ruby1.9
# 所以无需先安装Ruby,但是之后我们需要管理Ruby
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Homebrew常用命令:

1
2
3
4
5
6
7
8
9
10
brew list                 # 查看已经安装的包
brew update               # 更新Homebrew自身
brew doctor               # 诊断关于Homebrew的问题(Homebrew 有问题时请用它)
brew cleanup              # 清理老版本软件包或者无用的文件
brew show ${formula}      # 查看包信息
brew search ${formula}    # 按名称搜索
brew upgrade ${formula}   # 升级软件包
brew install ${formula}   # 按名称安装
brew uninstall ${formula} # 按名称卸载
brew pin/unpin ${formula} # 锁定或者解锁软件包版本,防止误升级

zsh,好用的shell

Shell程序就是Linux/UNIX系统中的一层外壳,几乎所有的应用程序都可以运行在Shell环境 下,常用的有bash, csh, zcsh等。在/etc/shells文件中可以查看系统中的各种shell。

1
2
3
4
5
6
7
8
9
10
11
12
cat /etc/shells

# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

而zsh是OSX系统原生的shell之一,其功能强大,语法相对于bash更加友好和强大,所以推荐 使用zsh作为默认的shell。

1
2
# 切换zsh为默认shell
chsh -s $(which zsh)

如果你想使用最新的zsh,你可以使用Homebrew,此方法也会保留原生的zsh,防止你在某个 时刻需要它。

1
2
3
4
5
6
7
8
9
10
11
12
# 查看最新zsh信息
brew info zsh

# 安装zsh
brew install --disable-etcdir zsh

# 添加shell路径至/etc/shells文件中
# 将 /usr/local/bin/zsh 添加到下面文件中
sudo vim /etc/shells

# 更换默认shell
chsh -s /usr/local/bin/zsh

下面贴上我的zsh配置以供参考

我的zsh配置 (zshrc) download
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
68
69
70
71
72
73
74
75
76
77
78
79
# modify the prompt to contain git branch name if applicable
git_prompt_info() {
  ref=$(git symbolic-ref HEAD 2> /dev/null)
  if [[ -n $ref ]]; then
    echo " %{$fg_bold[green]%}${ref#refs/heads/}%{$reset_color%}"
  fi
}
setopt promptsubst
export PS1='${SSH_CONNECTION+"%{$fg_bold[green]%}%n@%m:"}%{$fg_bold[blue]%}%c%{$reset_color%}$(git_prompt_info) %# '

# load our own completion functions
fpath=(~/.zsh/completion $fpath)

# completion
autoload -U compinit
compinit

# load custom executable functions
for function in ~/.zsh/functions/*; do
  source $function
done

# makes color constants available
autoload -U colors
colors

# enable colored output from ls, etc
export CLICOLOR=1

# history settings
setopt hist_ignore_all_dups inc_append_history
HISTFILE=~/.zhistory
HISTSIZE=4096
SAVEHIST=4096

# awesome cd movements from zshkit
setopt autocd autopushd pushdminus pushdsilent pushdtohome cdablevars
DIRSTACKSIZE=5

# Enable extended globbing
setopt extendedglob

# Allow [ or ] whereever you want
unsetopt nomatch

# vi mode
bindkey -v
bindkey "^F" vi-cmd-mode
bindkey jj vi-cmd-mode

# handy keybindings
bindkey "^A" beginning-of-line
bindkey "^E" end-of-line
bindkey "^R" history-incremental-search-backward
bindkey "^P" history-search-backward
bindkey "^Y" accept-and-hold
bindkey "^N" insert-last-word
bindkey -s "^T" "^[Isudo ^[A" # "t" for "toughguy"

# use vim as the visual editor
export VISUAL=vim
export EDITOR=$VISUAL

# load rbenv if available
if which rbenv &>/dev/null ; then
  eval "$(rbenv init - --no-rehash)"
fi

# load thoughtbot/dotfiles scripts
export PATH="$HOME/.bin:$PATH"

# mkdir .git/safe in the root of repositories you trust
export PATH=".git/safe/../../bin:$PATH"

# aliases
[[ -f ~/.aliases ]] && source ~/.aliases

# Local config
[[ -f ~/.zshrc.local ]] && source ~/.zshrc.local

好用的编辑器 Vim

对于Vim,无需溢美之词,作为与emacs并列的两大编辑器,早已经被无数人奉为经典。而它却 又以超长的学习曲线,使得很多人望而却步。长久以来,虽然拥有大量的插件,却缺少一个 确之有效的插件管理器。所幸,Vundle的出现解决了这个问题。

Vundle可以让你在配置文件中管理插件,并且非常方便的查找、安装、更新或者删除插件。 还可以帮你自动配置插件的执行路径和生成帮助文件。相对于另外一个管理工具pathogen, 可以说有着巨大的优势。

1
2
# vundle 安装和配置
git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
" 将下面配置文件加入到.vimrc文件中
set nocompatible " 必须
filetype off     " 必须

" 将Vundle加入运行时路径中(Runtime path)
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()

" 使用Vundle管理插件,必须
Plugin 'gmarik/Vundle.vim'

"
" 其他插件
"

call vundle#end() " 必须
filetype plugin indent on " 必须

最后,你只需要执行安装命令,即可以安装好所需的插件。

1
2
3
4
5
# 在vim中
:PluginInstall

# 在终端
vim +PluginInstall +qall

下面列出我的Vim插件和配置

Vim插件 (vimrc.bundles) download
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
if &compatible
  set nocompatible
end

filetype off
set rtp+=~/.vim/bundle/vundle/
call vundle#rc()

" Let Vundle manage Vundle
Bundle 'gmarik/vundle'

" Define bundles via Github repos
Bundle 'christoomey/vim-run-interactive'
Bundle 'croaky/vim-colors-github'
Bundle 'danro/rename.vim'
Bundle 'kchmck/vim-coffee-script'
Bundle 'kien/ctrlp.vim'
Bundle 'pbrisbin/vim-mkdir'
Bundle 'scrooloose/syntastic'
Bundle 'slim-template/vim-slim'
Bundle 'thoughtbot/vim-rspec'
Bundle 'tpope/vim-bundler'
Bundle 'tpope/vim-endwise'
Bundle 'tpope/vim-fugitive'
Bundle 'tpope/vim-rails'
Bundle 'tpope/vim-surround'
Bundle 'vim-ruby/vim-ruby'
Bundle 'vim-scripts/ctags.vim'
Bundle 'vim-scripts/matchit.zip'
Bundle 'vim-scripts/tComment'
Bundle "mattn/emmet-vim"
Bundle "scrooloose/nerdtree"
Bundle "Lokaltog/vim-powerline"
Bundle "godlygeek/tabular"
Bundle "msanders/snipmate.vim"
Bundle "jelera/vim-javascript-syntax"
Bundle "altercation/vim-colors-solarized"
Bundle "othree/html5.vim"
Bundle "xsbeats/vim-blade"
Bundle "Raimondi/delimitMate"
Bundle "groenewege/vim-less"
Bundle "evanmiller/nginx-vim-syntax"
Bundle "Lokaltog/vim-easymotion"
Bundle "tomasr/molokai"

if filereadable(expand("~/.vimrc.bundles.local"))
  source ~/.vimrc.bundles.local
endif

filetype on
Vim配置 (vimrc) download
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
" Use Vim settings, rather then Vi settings. This setting must be as early as
" possible, as it has side effects.
set nocompatible

" Highlight current line
au WinLeave * set nocursorline nocursorcolumn
au WinEnter * set cursorline cursorcolumn
set cursorline cursorcolumn

" Leader
let mapleader = ","

set backspace=2   " Backspace deletes like most programs in insert mode
set nobackup
set nowritebackup
set noswapfile    " http://robots.thoughtbot.com/post/18739402579/global-gitignore#comment-458413287
set history=50
set ruler         " show the cursor position all the time
set showcmd       " display incomplete commands
set incsearch     " do incremental searching
set laststatus=2  " Always display the status line
set autowrite     " Automatically :write before running commands
set confirm       " Need confrimation while exit
set fileencodings=utf-8,gb18030,gbk,big5

" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
if (&t_Co > 2 || has("gui_running")) && !exists("syntax_on")
  syntax on
endif

if filereadable(expand("~/.vimrc.bundles"))
  source ~/.vimrc.bundles
endif

filetype plugin indent on

augroup vimrcEx
  autocmd!

  " When editing a file, always jump to the last known cursor position.
  " Don't do it for commit messages, when the position is invalid, or when
  " inside an event handler (happens when dropping a file on gvim).
  autocmd BufReadPost *
    \ if &ft != 'gitcommit' && line("'\"") > 0 && line("'\"") <= line("$") |
    \   exe "normal g`\"" |
    \ endif

  " Cucumber navigation commands
  autocmd User Rails Rnavcommand step features/step_definitions -glob=**/* -suffix=_steps.rb
  autocmd User Rails Rnavcommand config config -glob=**/* -suffix=.rb -default=routes

  " Set syntax highlighting for specific file types
  autocmd BufRead,BufNewFile Appraisals set filetype=ruby
  autocmd BufRead,BufNewFile *.md set filetype=markdown

  " Enable spellchecking for Markdown
  autocmd FileType markdown setlocal spell

  " Automatically wrap at 80 characters for Markdown
  autocmd BufRead,BufNewFile *.md setlocal textwidth=80
augroup END

" Softtabs, 2 spaces
set tabstop=2
set shiftwidth=2
set shiftround
set expandtab

" Display extra whitespace
set list listchars=tab:»·,trail:·

" Use The Silver Searcher https://github.com/ggreer/the_silver_searcher
if executable('ag')
  " Use Ag over Grep
  set grepprg=ag\ --nogroup\ --nocolor

  " Use ag in CtrlP for listing files. Lightning fast and respects .gitignore
  let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'

  " ag is fast enough that CtrlP doesn't need to cache
  let g:ctrlp_use_caching = 0
endif

" Color scheme
colorscheme molokai
highlight NonText guibg=#060606
highlight Folded  guibg=#0A0A0A guifg=#9090D0

" Make it obvious where 80 characters is
set textwidth=80
set colorcolumn=+1

" Numbers
set number
set numberwidth=5

" Tab completion
" will insert tab at beginning of line,
" will use completion if not at beginning
set wildmode=list:longest,list:full
function! InsertTabWrapper()
    let col = col('.') - 1
    if !col || getline('.')[col - 1] !~ '\k'
        return "\<tab>"
    else
        return "\<c-p>"
    endif
endfunction
inoremap <Tab> <c-r>=InsertTabWrapper()<cr>
inoremap <S-Tab> <c-n>

" Exclude Javascript files in :Rtags via rails.vim due to warnings when parsing
let g:Tlist_Ctags_Cmd="ctags --exclude='*.js'"

" Index ctags from any project, including those outside Rails
map <Leader>ct :!ctags -R .<CR>

" Switch between the last two files
nnoremap <leader><leader> <c-^>

" Get off my lawn
nnoremap <Left> :echoe "Use h"<CR>
nnoremap <Right> :echoe "Use l"<CR>
nnoremap <Up> :echoe "Use k"<CR>
nnoremap <Down> :echoe "Use j"<CR>

" vim-rspec mappings
nnoremap <Leader>t :call RunCurrentSpecFile()<CR>
nnoremap <Leader>s :call RunNearestSpec()<CR>
nnoremap <Leader>l :call RunLastSpec()<CR>

" Run commands that require an interactive shell
nnoremap <Leader>r :RunInInteractiveShell<space>

" Treat <li> and <p> tags like the block tags they are
let g:html_indent_tags = 'li\|p'

" Open new split panes to right and bottom, which feels more natural
set splitbelow
set splitright

" Quicker window movement
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-h> <C-w>h
nnoremap <C-l> <C-w>l

" configure syntastic syntax checking to check on open as well as save
let g:syntastic_check_on_open=1
let g:syntastic_html_tidy_ignore_errors=[" proprietary attribute \"ng-"]

autocmd Syntax javascript set syntax=jquery " JQuery syntax support

set matchpairs+=<:>
set statusline+=%{fugitive#statusline()} "  Git Hotness

" Nerd Tree
let NERDChristmasTree=0
let NERDTreeWinSize=40
let NERDTreeChDirMode=2
let NERDTreeIgnore=['\~$', '\.pyc$', '\.swp$']
let NERDTreeShowBookmarks=1
let NERDTreeWinPos="right"
autocmd vimenter * if !argc() | NERDTree | endif " Automatically open a NERDTree if no files where specified
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif " Close vim if the only window left open is a NERDTree
nmap <F5> :NERDTreeToggle<cr>

" Emmet
let g:user_emmet_mode='i' " enable for insert mode

" Search results high light
set hlsearch

" nohlsearch shortcut
nmap -hl :nohlsearch<cr>
nmap +hl :set hlsearch<cr>

" Javascript syntax hightlight
syntax enable

" ctrap
set wildignore+=*/tmp/*,*.so,*.swp,*.zip     " MacOSX/Linux"
let g:ctrlp_custom_ignore = '\v[\/]\.(git|hg|svn)$'

nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>

" RSpec.vim mappings
map <Leader>t :call RunCurrentSpecFile()<CR>
map <Leader>s :call RunNearestSpec()<CR>
map <Leader>l :call RunLastSpec()<CR>
map <Leader>a :call RunAllSpecs()<CR>

" Vim-instant-markdown doesn't work in zsh
set shell=bash\ -i

" Snippets author
let g:snips_author = 'Yuez'

" Local config
if filereadable($HOME . "/.vimrc.local")
  source ~/.vimrc.local
endif

新世代的版本管理工具 git

Git是一个分散式版本控制软件。最初的目的是为了更好的管理Linux内核开发而设计。与CVS、 Subversion等集中式版本控制软件不同,Git不需要服务器端软件就可以发挥版本控制的作用。 使得代码的维护和发布变得非常方便。

Git库目录结构

  • hooks : 存储钩子文件夹
  • logs : 存储日志文件夹
  • refs : 存储指向各个分支指针的(SHA-1)的文件夹
  • objects : 存储git对象
  • config : 存储配置文件
  • HEAD : 指向当前分支的指针文件路径
1
2
# 安装git
brew install git

Git安装完毕后,只需要使用git config简单配置下用户名和邮箱就可以使用了。

为了使Git更好用,对Git做一些配置,.gitconfig文件中可以设置自定义命令等,.gitignore 文件是默认被忽略版本管理的文件。

(gitconfig) download
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
[push]
  default = current
[color]
  ui = auto
[alias]
  aa = add --all
  ap = add --patch
  ca = commit --amend
  ci = commit -v
  co = checkout
  br = branch
  create-branch = !sh -c 'git push origin HEAD:refs/heads/$1 && git fetch origin && git branch --track $1 origin/$1 && cd . && git checkout $1' -
  delete-branch = !sh -c 'git push origin :refs/heads/$1 && git branch -D $1' -
  merge-branch = !git checkout master && git merge @{-1}
  pr = !hub pull-request
  st = status
  up = !git fetch origin && git rebase origin/master
[core]
  excludesfile = ~/.gitignore
  autocrlf = input
[merge]
  ff = only
[include]
  path = .gitconfig.local
[commit]
  template = ~/.gitmessage
[fetch]
  prune = true
[user]
  name = zgs225
  email = zgs225@gmail.com
[credential]
  helper = osxkeychain
[github]
  user = zgs225
(gitignore) download
1
2
3
4
5
6
7
8
9
10
*.DS_Store
*.sw[nop]
.bundle
.env
db/*.sqlite3
log/*.log
rerun.txt
tags
tmp/**/*
!tmp/cache/.keep

自动集成 ternimal 环境

感谢thoughtbot组织发布的开源项目,可 以轻松的完成上述配置。这是我fork项目的地址(https://github.com/zgs225/dotfiles), 欢迎fork并完善成属于你自己的配置。

安装步骤:

1
2
3
4
5
6
7
8
9
10
11
12
# 更改为zsh, 详细参考上面zsh部分
chsh -s $(which zsh)

# clone 源码
git clone https://github.com/zgs225/dotfiles.git

# 安装rcm
brew tap thoughtbot/formulae
brew install rcm

# 安装上述环境并且完成配置
rcup -d dotfiles -x README.md -x LICENSE -x Brewfile

语言篇

编程语言五花八门,它们各自的版本也是万别千差。各种语言之间或多或少都存在着向前, 或者向后的不兼容。因为版本不兼容导致的bug也是格外的招人烦。所以,在语言篇这篇,也 是侧重与到编程语言版本管理已经环境控制。

简洁优美的类Lisp语言 Ruby

以Ruby作为语言篇的开篇,足以看得出来我对Ruby的喜爱。虽然它有着这样或者那样令人诟 病的缺点,不过作为让我体会到Web世界美妙的第一门语言,我对Ruby一直有着别样的感情。

目前,Ruby的常用版本是1.9,2.1和最新的2.2。最新版本并不是完全向后兼容,所以如果你 的电脑中存在着老版本的Ruby项目,这时候又想切换到新版本中来,那可就头疼了。好在, 有像rvmrbenv这样的Ruby版本管理软件。它们各有优劣,而我喜欢更为自动化的rvm。

一个完整的Ruby环境包括Ruby解释器、安装的RubyGems以及它们的文档。rvm用gemsets的 概念,为每一个版本的Ruby提供一个独立的RubyGems环境。可以很方便的在不同的Ruby环境 中切换而不相互影响。

1
2
3
4
5
6
# 安装rvm
# 设置mpapis公钥
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

# 安装稳定版rvm
\curl -sSL https://get.rvm.io | bash -s stable

由于网络原因,可以将rvm的Ruby安装源修改为国内淘宝的Ruby镜像服务器。 该镜像服务器15分钟以此更新,尽量保证与官方同步。这样能提高安装速度。

1
2
# 出自 http://ruby.taobao.org
sed -i .bak 's!cache.ruby-lang.org/pub/ruby!ruby.taobao.org/mirrors/ruby!' $rvm_path/config/db

推荐一篇关于rvm的文章: https://ruby-china.org/wiki/rvm-guide

同样,由于网络原因,需要将RubyGems的安装源修改到镜像服务器上。

1
2
3
4
5
6
7
8
9
10
# 切换源
gem sources --remove https://rubygems.org/
gem sources -a https://ruby.taobao.org/

# 查看源列表
gem sources -l

*** CURRENT SOURCES ***

https://rubygems.org/

以上,你就拥有了一个相对舒适的Ruby开发环境,不用为版本和网络问题发愁。啊!天空都 清净了。

操作系统笔记: 计算机系统概述

学习目标:

  • 了解计算机系统的基本组成及它们之间的内部关系。
  • 理解处理器执行一条指令时的每一步骤。
  • 掌握中断的概念,以及处理器如何及为何利用中断。
  • 列举并描述典型的计算机存储体系的每一层。
  • 理解多处理器和多核计算机组织结构的基本特性。
  • 讨论局部性概念,分析多级存储体系的性能。

基本组成

计算机系统有四个主要的结构化部件:

  • 处理器(Prosessor)
  • 内存(Main memory)
  • 输入/输出模块(I/O modules)
  • 系统总线(System bus)

CPU的一种功能是和内存交换数据,为此,它通常使用两种寄存器:存储器地址寄存器( Memory Address Register)和存储器缓冲寄存器(Memory Buffer Register)。同理,输 入/输出地址寄存器(I/O Address Register)和输入/输出缓冲寄存器(I/O Buffer Register) 用于确定一个特定的输入/输出设备与处理器之间交换数据。

指令的执行

程序执行是由不断重复的取指令和执行指令的过程组成的。一个单一的指令需要的处理称为 一个指令周期。取到的指令被放置在存储器的一个寄存器单元内,这个寄存器被称为指 令寄存器(Instruction Register)。指令中包含确定处理器将要执行操作的位和处理器解 释指令并执行对应的操作。大体上,这些动作可以分为四类:

  • 处理器-存储器:数据在处理器和存储器之间交换。
  • 处理器-I/O:CPU可以从外部设备中输入或者输出数据。
  • 数据处理:处理器可以执行很多与数据有关的算数操作或者逻辑操作。
  • 控制:某些指令可以改变执行顺序。

指令的执行涉及这些行为的组合。

中断

所有计算机都提供了允许其他模块(I/O,存储器)中断处理器正常处理过程的机制。中断是 一种用于提高处理器性能的手段。

中断的分类:程序中断、时钟中断、I/O中断和硬件失效中断。

中断和指令周期

利用中断功能,处理器可以在I/O操作的过程中,执行其他指令。当外部设备做好服务的准备 时,该外部设备的I/O模块给处理器发送一个中断请求的信号。这时处理器会做出响应,暂停 当前程序的处理,转去处理服务于特定I/O设备的程序,这个程序称之为中断处理程序

为适应中断产生的情况,在指令周期中增加了中断阶段。

中断处理

当I/O设备完成以此I/O操作时,发生了下列硬件事件:

  1. 设备给处理器发送一个中断信号。
  2. 处理器在响应中断信号前,结束当前指令的执行。
  3. 处理器对中断进行测定,确定存在未响应的中断,开始对提交中断的设备发送确认信号, 确认信号允许该设备取消它的中断信号。
  4. 处理器需要为把控制权转移到中断程序中去做准备。需要保存从中断点恢复当前程序所 需要的信息,至少包括程序状态字(PSW)和保存在程序计数器(PC)中的下一条要执行 指令的地址。

PSW中包含当前运行进程的状态信息,包括内存使用信息、条件码和其他注入允许中断/禁止 中断位、内核/用户模式位等状态信息。

  1. 处理器把响应此中断的中断处理程序地址装入程序计数器中。
  2. 中断处理程序开始处理中断,其中包括检查与I/O操作相关的状态信息或其他引起中断的 事件,还可能包括给I/O设备发送附加命令或者应答。
  3. 中断程序结束后,被保存的寄存器值从栈中释放并恢复到寄存器中。
  4. 最后操作是恢复PSW和程序计数器的值,继续执行被中断的程序。

多个中断

处理多个中断有两种方法。

  • 处理一个中断时,禁止再发生新的中断。当中断处理程序完成后,才允许中断。这种方法 很简单,缺点是没有考虑相对优先级和时间限制的要求。
  • 定义中断优先级,允许高优先级的中断打断低优先级的中断。

"CPU指令周期"

存储器的层次结构

实现存储器系统会用到各种技术,但各个技术之间存在一下关系:

  • 存取时间越快,每『位』的价格越高
  • 容量越大,每『位』的价格越低
  • 容量越大,存取速度越慢

为了既满足大容量存储需求,又能够兼顾性能需求,不能依赖于单一的存储组件,使用存 储器的层次结构

"存储器层次结构"

这个层次结构从上往下看,会出现下列情况:

  • 每『位』价格递减
  • 容量递增
  • 存取时间递增
  • 处理器访问存储器频次递减

容量较大,价格便宜的慢速存储器,是容量较小,价格较贵的告诉存储器的后备。这种存储 结构能够成功的关键在于:低层访问频率递减

处理器访问存储器频次递减有效的基础是访问的局部性原理。在执行程序期间,处理器 的指令访存和数据访存呈现『簇』状。典型的程序包含许多迭代循环和子程序,一旦程序进 入一个循环或子程序执行,就会重复访问一小范围内的指令集合。同理,对表和数组的操作 涉及存取『一簇』数据。

高速缓存

长期以来,由于处理器和内存的速度不匹配,这个限制已经称为很严重的问题。解决方法是 利用局部性原理,即在处理器和内存之间提高一个容量小而速度快的存储器。

高速缓存原理

高速缓存包含一部分内存数据的副本。当处理器试图读取存储器中的一个字节或者字时,要 进行一次检查以确定这个字是否在高速缓存中。如果在,则该字节从高速缓存传递给处理器。 如果不在,则先将由固定数组的字节组成的一块内存数据读入高速缓存,然后该字节从高速 缓存传递给处理器。由于访问局部性现象的存在,当一块数据被读入高速缓存以满足一次存 储器访问时,很可能紧接着的多次访问的数据是该块中的其他字节。

直接内存存取

针对I/O操作的技术:

  • 编程I/O操作
  • 中断驱动I/O
  • 直接内存存取