以下摘自《人月神话》,讨论了开发团队的组建以及运作。

在计算机领域的会议中,常常听到年轻的软件经理声称,他们喜欢由一流人才组成的小型、精干的队伍,而不是那些几百人的大型团队,这里的“人”当然暗指平庸的程序员。其实我们也经常有相同的看法。

软件经理很早就认识到优秀程序员和较差程序员之间生产率的差异。

我常常重复这样一个观点,需要协作沟通的人员数量影响着开发成本,因为成本的主要组成部分是相互的沟通和交流,以及更正沟通不当引起的不良结果(系统调试)。这一点,也暗示系统应该由尽可能少的人员来开发。

如果在一个200人的项目中,有25个最能干和最有开发经验的项目经理,那么开除剩下的175名程序员,让项目经理来编程开发。

阅读全文 »

Shader - 着色器,是可以在GPU上运行的程序,分为顶点着色器和片段着色器(像素着色器)。

编写Shader的编程语言主要有三种:

  • GLSL - 用于OpenGL
  • HLSL - 用于Direct3D
  • Cg - 微软和NVIDIA合作开发的,可用于OpenGL和Direct3D

Cg教程:可编程实时图形权威指南

摘自前言

从前,有位咨询顾问造访客户调研其开发项目。系统核心是个类继承体系,顾问看了开发人员所写的一些代码。他发现整个体系相当凌乱,上层超类对于系统的运作做了一些假设,下层子类实现这些假设。但是这些假设并不适合所有子类,导致覆写(override)工作非常繁重。只要在超类做点修改,就可以减少许多覆写工作。在另一些地方,超类的某些意图并未被良好理解,因此其中某些行为在子类内重复出现。还有一些地方,好几个子类做相同的事情,其实可以把它们搬到继承体系的上层去做。

这位顾问于是建议项目经理看看这些代码,把它们整理一下,但是经理并不热衷于此,毕竟程序看上去还可以运行,而且项目面临很大的进度压力。于是经理说,晚些时候再抽时间做这些整理工作。

顾问也把他的想法告诉了在这个继承体系上工作的程序员,告诉他们可能发生的事情。程序员都很敏锐,马上就看出问题的严重性。他们知道这并不全是他们的错,有时候的确需要借助外力才能发现问题。程序员立刻用了一两天的时间整理好这个继承体系,并删掉了其中一半代码,功能毫发无损。他们对此十分满意,而且发现在继承体系中加入新的类或使用系统中的其他类都更快、更容易了。

项目经理并不高兴。进度排得很紧,有许多工作要做。系统必须在几个月之后发布,而这些程序员却白白耗费了两天时间,干的工作与要交付的多数功能毫无关系。原先的代码运行起来还算正常,他们的新设计看来有点过于追求完美。项目要交付给客户的,是可以有效运行的代码,不是用以取悦学究的完美东西。顾问接下来又建议应该在系统的其他核心部分进行这样的整理工作,这会使整个项目停顿一至二个星期。所有这些工作只是为了让代码看起来更漂亮,并不能给系统添加任何新功能。

阅读全文 »

CEED: CEGUI Unified Editor

学习OGRE时接触到一个界面库:CEGUI。

CEED是一个CEGUI资源编辑器,使用Python和PySide(Qt for Python)写的。

Qt有两个Python绑定,一个是PyQt,另一个是PySide。

这么优秀的源代码对于学习Python是个不可多得的资源啊,记录一下。

https://bitbucket.org/cegui/ceed

看《程序员的呐喊》、《软件随想录》的时候,大师们常常会提到一门古老的编程语言Lisp。今天有兴趣学习了一下Scheme的语法。Scheme是Lisp的一种方言。

另外,摘一段《软件随想录》中很有意思的一段话:

顺便说一句,我有充分理由在这里说,那些使用grep命令过滤简历的招聘经理真是荒谬可笑。我从来没有见过哪个能用Scheme语言、Haskell语言和C语言中的指针编程的人,竟然不能在两天里面学会Java语言,并且写出的Java程序的质量竟然不能胜过那些有5年Java编程经验的人士。不过,是无法指望人力资源部里那些平庸的懒汉听进去这些话的。

参考:
Scheme 语言概要(上)
Scheme 语言概要(下)
函数式编程初探

工作需要,修改一些项目配置,重复、枯燥、乏味,所以用Python写了个自动化脚本,记录一下:

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
#!/usr/bin/env python
# coding: utf-8

import os
import re

files = []
current_config = '' # e.g. Debug2010

def main():
global current_config

get_files()
for filepath in files:
print filepath
tmp_file = filepath + '.tmp'
try:
os.remove(os.path.abspath(tmp_file))
except:
pass

os.rename(filepath, tmp_file)
with open(tmp_file, 'r') as tmp_f:
with open(filepath, 'w') as f:
for line in tmp_f.readlines():
# 确定当前配置
m = re.search(r'''<PropertyGroup Condition=.*=='(.*)\|''', line)
if m is not None:
current_config = m.group(1)
f.write(line)
continue

m = re.search(r'''<ItemDefinitionGroup Condition=.*=='(.*)\|''', line)
if m is not None:
current_config = m.group(1)
f.write(line)
continue

# 替换
line = replace(line)
if line:
f.write(line)

os.remove(os.path.abspath(tmp_file))

def get_files():
for dirpath, dirnames, filenames in os.walk('.'):
for filename in filenames:
_, ext = os.path.splitext(filename)
if ext != '.vcxproj':
continue
filepath = os.path.join(dirpath, filename)
files.append(filepath)

def replace(line):
arx_version = ''
lib_suffix = ''
ret = line
is_debug = False

if current_config == 'Debug2010':
arx_version = '2013'
lib_suffix = '19'
is_debug = True
elif current_config == 'Release2010':
arx_version = '2013'
lib_suffix = '19'
elif current_config == 'Debug2012':
arx_version = '2015'
lib_suffix = '20'
is_debug = True
elif current_config == 'Release2012':
arx_version = '2015'
lib_suffix = '20'

if arx_version == '':
return ret

# 附加包含目录
regex_str = r'<AdditionalIncludeDirectories>.*OBJECTARX\\.+</AdditionalIncludeDirectories>'
m = re.search(regex_str, line)

if m is not None:
ret = re.sub(r'(OBJECTARX\\)([0-9]+?)(\\)', r'OBJECTARX\\%s\\' % arx_version, line)
return ret

# 附加依赖项
regex_str = r'<AdditionalDependencies>.+</AdditionalDependencies>'
m = re.search(regex_str, line)
if m is not None:
if is_debug:
ret = re.sub(r'ZW([a-zA-Z]+?)d\.lib', r'ZW\g<1>%sd.lib' % lib_suffix, line)
else:
ret = re.sub(r'ZW([a-zA-Z]+?)\.lib', r'ZW\g<1>%s.lib' % lib_suffix, line)

return ret

if __name__ == '__main__':
main()

第一本Docker书

简介

Docker是一个能够把开发的应用程序自动部署到容器的开源引擎。

Docker容器拥有很高的性能,同时同一台宿主机中也可以运行更多的容器,使用户可以尽可能充分地利用系统资源。

Docker设计的目的就是要加强开发人员写代码的开发环境与应用程序要部署的生产环境的一致性,从而降低那种“开发时一切都正常,肯定是运维的问题”的风险。

Docker的目标之一就是缩短代码从开发、测试到部署、上线运行的周期,让你的应用程序具备可移植性,易于构建,并易于协作。

容器是镜像的实例。容器是基于镜像启动起来的。镜像是Docker生命周期中的构建或打包阶段,而容器则是启动或执行阶段。

阅读全文 »
0%