见到了各式各样的魔方爱好者和各式各样的魔方。
2009年4月26日星期日
2009年4月16日星期四
Lose Count 数不清
一夜中睡了三次,起来三次,我不知道该怎么计算。
这些混乱的日子,无休无止,我数不清。
Do we really need to count?
有时候简单的数几个数也总是数不对,计算机如此擅长此事,而我们却没有给以足够的信赖。
TCountState = classprivateXes: TList;FXCount: Integer;publicprocedure AddX(X: XClass);procedure Reset;property XCount: Integer read FXCount;end;TCountState.AddX(X: XClass);beginif not Xes.Has(X) thenbeginXes.Add(X);Inc(XCount);end;end;TCountState.Reset;beginXCount := 0;// However, nothing be done with Xes here.end;
毫无疑问,在这千头万绪的岁月中,AddX()会在不同的线程中调用,即使算上脚指头,我们也无法数清楚XCount到底是什么了。好歹我们知道有个东西叫InterLockIncrement。
很好,似乎学会数数了,但是,看起来有时候还是会数错,尤其是在一次次的麻木与苏醒之后,也许想忘记过去,却不够彻底,忘了一些东西而记住了另一些东西,这会混乱不堪。所以,在醒来之前把过去消除掉吧,它可能是美好的回忆,但也可能是沉重的包袱,或者兼而有之。
Xes.Clear;这一次,可以坚信不用手指头也可以正确数数了。
等等,我们真的需要数吗?
这些混乱的日子,无休无止,是度日如年、一日三秋还是十年一梦,谁也数不清,只有日历最清楚。
还是直接问问它们吧。
TCountState = classprivateXes: TList;function GetXCount: Integer;publicprocedure AddX(X: XClass);procedure Reset;property XCount: Integer read GetXCount;end;TCountState.AddX(X: XClass);beginif not Xes.Has(X) thenbeginXes.Add(X);end;end;TCountState.GetXCount;beginResult := Xes.Count;end;TCountState.Reset;beginXes.Clear;end;
数数真的很难,曾经QQ空间这样跟我说
共 126 个签名,第 22 页/共 21 页
曾经我们在邮件列表中这样计算
K = 12
AVE = 23.45k=13
average=23.57k=13AVG=23.49出现了互斥问题,修正一下当前k=14,ave=23.60
2009年4月15日星期三
思维与行为的灵魂
两本好书。
一本是The Pragmatic Programmer ,道理不只为程序设计而言。文章也写得很好,言简意赅,读来学英文也很不错。这不得不让我想起了一本商业英语写作与演讲的书 Plain English at Work ,讲述了如何使用简洁的英文高效的传递信息,而书本身就是一个极佳的范例。前一本书远不止对程序设计有益处,而后一本也远不止对写作演讲有帮助。代码和文章的字里行间处处是思维与行为的灵魂,绝不仅仅是技巧与规则的躯壳。
Care About Your Craft
除非你在乎能否漂亮地开发出软件,否则其它事情都是没有意义的。
2、思考!你的工作
Think!About Your Work
在你做某件事情的时候思考你在做什么。不间断地思考,
3、提供各种选择,不要找蹩脚的借口
Provide Options,Don't Make Lame Excuses
不要说事情做不到;要说明能够做什么来挽回局面。
4、不要容忍破窗户
Don't Live With Broken Windows
不要留着“破窗户”(低劣的设计、错误的决策、或者糟糕的代码)
如果你发现你所在团队和项目的代码十分漂亮——编写整洁、
5、做变化的催化剂
Be a Catalyst for Change
你不能强迫人们改变。相反,要向他们展示未来可能会怎样,
设计出你可以合理要求的东西,好好开发它。一旦完成,
6、记住大图景
Remember the Big Picture
如果你抓一只青蛙放进沸水里,它会一下子跳出来。但是,
不要像青蛙一样。留心大图景。要持续不断地观察周围发生的事情,
7、使质量成为需求问题
Make Quality a Requirements Issue
你所制作的系统的范围和质量应该作为系统需求的一部分规定下来。
8、定期为你的知识资产投资
Invest Regularly in Your Knowledge Portfolio
让学习成为习惯。
持续投入十分重要。一旦你熟悉了某种新语言或新技术,继续前进,
是否在某个项目中使用这些技术,或者是否把它们放入你的简历,
如果你自己找不到答案,就去找出能找到答案的人。
9、批判地分析你读到的和听到的
Critically Analyze What You Read and Hear
不要被供应商、媒体炒作、或教条左右。
10、你说什么和你怎么说同样重要
It's Both What You Say and the Way You Say It
作为开发者,我们必须在许多层面上进行交流。
如果你不能有效地向他人传达你的了不起的想法,
知道你想要说什么;了解你的听众;选择时机;选择风格;
交流越有效,你就越有影响力。
11、DRY原则——不要重复你自己
DRY - Don't Repeat Yourself
系统中的每一项知识都必须具有单一、无歧义、权威的表示。
12、让复用变得容易
Make it Easy to Reuse
你要做的是营造一种环境,在其中要找到并复用已有的东西,
13、消除无关事物之间的影响
Eliminate Effects Between Unrelated Things
我们想要设计自足(self-contained)的组件:
你得到两个主要好处:提高生产率与降低风险。
14、不存在最终决策
There Are No Final Decisions
没有什么永远不变——而如果你严重依赖某一事实,
15、用曳光弹找到目标
Use Tracer Bullets to Find the Target
曳光弹能通过试验各种事物并检查它们离目标有多远来让你追踪目标
曳光弹代码含有任何一段产品代码都拥有的完整的错误检查、结构、
16、为了学习而制作原型
Prototype to Learn
任何带有风险的事物。以前没有试过的事物,
原型制作是一种学习经验,其价值并不在于所产生的代码,
17、靠近问题领域编程
Program Close to The Problem domain
计算机语言会影响你思考问题的方式,以及你看待交流的方式。
18、估算,以避免发生意外
Estimate to Avoid Surprises
在着手之前先进行估算。你将提前发现潜在的问题。
1)要选择能反映你想要传达的精确度的单位;
2)基本的估算诀窍:去问已经做过这件事情的人;
3)理解提问内容;
4)根据对问题的理解,建立粗略、就绪的思维模型骨架;
5)把模型分解为组件,找出描述这些组件怎样交互的数学规则,
6)给每个参数指定值,找出哪些参数对结果的影响最大,
7)进行多次计算,改变关键参数的值,
8)在被要求进行估算时说的话:“我等会回答你”。
19、通过代码对进度表进行迭代
Iterate the Schedule with the Code
实行增量开发。追踪你的估算能力,提炼对迭代次数、
20、用纯文本保存知识
Keep Knowledge in Plain Text
保证不过时;
杠杆作用:每一样工具,都能够在纯文本上进行操作;
更易于测试;
你需要确保所有各方能够使用公共标准进行通信。
21、利用命令shell的力量
Use the Power of Command Shells
GUI环境通常受限于它们的设计者想要提供的能力。
22、用好一种编辑器
Use a Single Editor Well
选一种编辑器,彻底了解它,并将其用于所有的编辑任务。
23、总是使用源码控制
Always Use Source Code Control
总是。即使你的团队只有你一个人,你的项目只有一周时间;
源码控制是你的工作的时间机器——你能够回到过去。
把整个项目置于源码控制系统的保护之下具有一项很大的、
24、要修正问题,而不是发出指责
Fix the Problem,Not the Blame
要接受事实:调试就是解决问题,要据此发起进攻。
25、不要恐慌
Don't Panic
做一次深呼吸,思考什么可能是bug的原因。
要总是设法找出问题的根源,而不只是问题的特定表现;
搜集所有的相关数据;
开始修正bug的最佳途径是让其可再现;
使你的数据可视化;
跟踪:观察程序或数据结构随时间变化的状态;
找到问题的原因的一种非常简单、
26、“Select”没有问题
"Select" Isn't Broken
Bug有可能存在于OS、编译器、或是第三方产品中——
27、不要假定,要证明
Don't Assume it - Prove It
不要因为你“知道”
28、学习一种文本操作语言
Learn a Text Manipulation Language
你用每天的很大一部分时间处理文本,
应用示例:
数据库schema维护;
Java、C#属性(Property)访问;
测试数据生成。
29、编写能编写代码的代码
Write Code That Writes Code
代码生成器能提高你的生产率,并有助于避免重复。
30、你不可能写出完美的软件
You Can't Write Perfect Software
这刺痛了你?不应该。把它视为生活的公理,接受它,拥抱它,
31、通过合约进行设计
Design with Contracts
什么是正确的程序?不多不少,做它声明要做的事情的程序。
这里,强调的重点是在“懒惰”的代码上:
使用DBC的最大好处也许是它迫使需求与保证的问题走到前台来。
32、早崩溃
Crash Early
死程序不说谎。
当你的代码发现,某件被认为不可能发生的事情已经发生时,
33、如果它不可能发生,用断言确保它不会发生
If It Can't Happen,Use Assertions to Ensure That It Won't
断言验证你的各种假定。在一个不确定的世界里,
不要用断言代替真正的错误处理。
34、将异常用于异常的问题
Use Exceptions for Exceptional Problems
异常表示即使的、非局部的控制转移——这是一种级联的(
35、要有始有终
Finish What You Start
只要可能,分配某资源的例程或对象也应该负责解除其分配。
36、使模块之间的耦合减至最少
Minimize Coupling Between Modules
编写“羞怯”的代码;
函数的得墨忒耳(Demeter)法则规定,
1)它自身;
2)传入该方法的任何参数;
3)它创建的任何对象;
4)任何直接持有的组件对象。
物理解耦。
37、要配置,不要集成
Configure,Don't Integrate
细节会弄乱我们整洁的代码——特别是如果它们经常变化。
要用元数据(metadata)描述应用的配置选项:调谐参数、
38、将抽象放进代码,细节放进元数据
Put Abstractions in Code,Details in Metadata
但我们不只是想把元数据用于简单的偏好。
也许你在编写一个具有可怕的工作流需求的系统。
39、分析工作流,以改善并发性
Analyze Workflow to Improve Concurrency
时间是软件架构的一个常常被忽视的方面。
我们在编写程序时,通常并没有把这两个方面放在心上。
这样的方法不那么灵活,也不那么符合实际。
我们需要容许并发,并考虑解除任何时间或者次序上的依赖。
40、用服务进行设计
Design Using Services
实际上我们创建的并不是组件,而是服务——位于定义良好的、
通过把你的系统架构成多个独立的服务,你可以让配置成为动态的。
41、总是为并发进行设计
Always Design for Concurrency
首先,必须对任何全局或静态变量加以保护,使其免于并发访问,
在被调用时,对象必须总是处在有效的状态中,
一旦你设计了具有并发要素的架构,
42、使视图与模型分离
Separate Views from Models
也就是常说的MVC模式(Model-View-
模型。表示目标对象的抽象数据模型。
视图。解释模型的方式。
控制器。控制视图、并向模型提供新数据的途径。
通过松解模型与视图/控制器之间的耦合,
43、用黑板协调工作流
Use Blackboards to Coordinate Workflow
用黑板协调完全不同的事实和因素,
现代的分布式类黑板(blackboard-like)系统,
44、不要靠巧合编程
Don't Program by Coincidence
总是意识到你在做什么。
不要盲目地编程。试图构建你不完全理解的应用,
按照计划行事。
依靠可靠的事物。如果你无法说出各种特定情形的区别,
为你的假定建立文档。“按合约编程”有助于澄清你头脑中的假定,
不要只是测试你的代码,还要测试你的假定。
为你的工作划分优先级。
不要做历史的奴隶。不要让已有的代码支配将来的代码。
所以下次有什么东西看起来能工作,而你却不知道为什么,
45、估算你的算法的阶
Estimate the Order of Your Algorithms
在你编写代码之前,先大致估算事情需要多长时间。
46、测试你的估算
Test Your Estimates
对算法的数学分析并不会告诉你每一件事情。
47、早重构,常重构
Refactor Early,Refactor Often
在需要时对代码进行重写、重做和重新架构。要铲除问题的根源。
关于重构,详见Martin Fowler的《重构》一书。
48、为测试而设计
Design to Test
在你还没有编写代码时就开始思考测试问题。测试驱动开发?
49、测试你的软件,否则你的用户就得测试
Test Your Software,or Your Users Will
测试是技术,但更是文化。一点预先的准备可以大大降低维护费用、
50、不要使用你不理解的向导代码
Don't Use Wizard Code You Don't Understand
向导很了不起。只需要点击一个按钮,回答一些简单的问题,
51、不要搜集需求——挖掘它们
Don't Gather Requirements - Dig for Them
需求很少存在于表面上。它们深深地埋藏在层层假定、
52、与用户一同工作,以像用户一样思考
Work with a User to Think Like a User
要了解系统实际上将如何被使用,这是最好的方法。
53、抽象比细节活得更长久
Abstractions Live Longer than Details
“投资”于抽象,而不是实现。
54、使用项目词汇表
Use a Project Glossary
如果用户和开发者用不同的名称指称同一事物,或是更糟,
55、不要在盒子外面思考——要找到盒子
Don't Think Outside the Box - Find the Box
在遇到不可能解决的问题时,问问自己以下问题:
有更容易的方法吗?
你是在设法解决真正的问题,还是被外围的技术问题转移了注意力?
这件事情为什么是一个问题?
是什么使它如此难以解决?
它必须以这种方式完成吗?
它真的必须完成吗?
很多时候,当你设法回答这些问题时,你会有让自己吃惊的发现。
你所需要的只是真正的约束、令人误解的约束、
56、倾听反复出现的疑虑——等你准备好再开始
Listen to Nagging Doubts - Start When You're Ready
你的一生都在积累经验与智慧。当你面对一件任务时,
57、对有些事情“做”胜于“描述”
Some Things Are Better Done Than Described
你应该倾向于把需求搜集、设计、以及实现视为同一个过程——
58、不要做形式方法的奴隶
Don't Be a Slave to Formal Methods
如果你没有把某项技术放进你的开发实践和能力的语境中,
59、昂贵的工具不一定能制作出更好的设计
Expensive Tools Do Not Produce Better Designs
小心供应商的炒作、行业教条、以及价格标签的诱惑。
60、围绕功能、而不是工作职务进行组织
Organize Around Functionality,Not Job Functions
把你的人划分成小团队,分别负责最终系统的特定方面的功能。
但是,只有在项目拥有负责的开发者、以及强有力的项目管理时,
要记住,团队是由个体组成的。
61、不要使用手工流程
Don't Use Manual Procedures
shell脚本或批处理文件会一次次地以同一顺序执行同样的指令
62、早测试,常测试,自动测试。
Test Early.Test Often.Test Automatically.
与呆在书架上的测试计划相比,每次构建时运行的测试要有效得多。
63、要等到通过全部测试,编码才算完成
Coding Ain't Done 'Til All the Tests Run
就是这样。
64、通过“蓄意破坏”测试你的测试
Use Saboteurs to Test Your Testing
在单独的软件副本上故意引人bug,以检验测试能够抓住它们。
65、测试状态覆盖,而不是代码覆盖
Test State Coverage,Not Code Coverage
确定并测试重要的程序状态。只是测试代码行是不够的。
66、一个bug只抓一次
Find Bugs Once
一旦测试员找到一个bug,这应该是测试员最后一次找到它。
67、把英语当作又一种编程语言
Treat English as Just Another Programming Language
像你编写代码一样编写文档:遵守DRY原则、使用元数据、68、把文档建在里面,不要拴在外面
Build Documentation In,Don't Bolt It On
与代码分离的文档不太可能被修正和更新。文档和代码是同一底层模型的不同视图,
69、温和地超出用户的期望
Gently Exceed Your Users' Expectations
要设法让你的用户惊讶。请注意,不是惊吓他们,
70、在你的作品上签名
Sign Your Work
我们想要看到对所有权的自豪。“这是我编写的,
订阅:
评论 (Atom)