程序员修炼之道

Posted on

每年寒假总是要读完一本书,去年寒假读的是白帽子讲Web安全.今年读的是程序员修炼之道:从小工到专家.去年那时候估计没有搭建好博客. 所以没有写点什么,今年还是写一下读完的感受吧.

这本书说实话我大一就买了,但是那时候没有一点项目经验.读起来宛如天书,没读一半就放弃了.因为那个看起来不知所云的目录让我顿时失去了兴趣. 大一的我确实无知,自负,浮躁,没有认真读下去.当时就沉迷于学习各种编程语言...没有审视到这本书的价值.如今我已大四,也算有了不少项目编程 经验,写过上万行代码,对于这本书的感受就是爱不释手.这本书用非常幽默的方式简述很多朴素而真挚,简单而有效的编程哲学.

全书基本是经验之谈,经验往往不能告诉我什么一定对,但是可以告诉我们什么一定不对.在提示36中讲述了需求之坑.告诉我们一个注重实效的程序员 应该需要挖掘需求而不是搜集它们.确实,客户往往不能很好的阐述需求,需要程序员进行深入挖掘才能使项目顺利进行.文中也举了很简单的例子进行阐述. 我一开始做项目的时候很顽固的要求需要明确的需求文档,现在想想这完全就是个笑话.因为客户自己都不清楚到底要做成什么样子.

本书的涉猎范围很广,也有很多专业名词.每个章节都可以延展出很多内容.我不认为这是一本只需读一遍的书.在每个编程阶段去读这本书都会有不同的感受. 这本书我肯定会珍藏,以后也会反复读的.这是一本程序员必须读的书,希望大家可以耐心的读一下这本书.

这本书的精彩之处只可意会不可言传,本人文采不好,但是极力推荐.最后摘抄下这本书阐述的注重实效的程序员的特征:

  • 早期的采纳者/快速的改编者. 你具有技术和技巧上的直觉,你喜欢试验各种事物.给你一样新东西,你很快能把握它, 并把它与你的知识的其余部分结合在一起.你的自信出自经验.
  • 好奇. 你喜欢提问.那很漂亮--你是怎么做的? 你用那个库时有问题吗?我听说的这个BeOS是什么? 符号链接是怎样实现的?你是收集小知识的林鼠(pack rat), 每一条小知识都可能会影响今后几年里的某项决策.
  • 批判的思考者.你不会不首先抓住事实而照搬别人的说法.当同事说"因为就该那么做"或者供应商允诺为你的全部问题提供解决方案时,你就会嗅到挑战的气息.
  • 有现实感.你会设法理解你面临的每个问题的内在本质.这样的现实主义给了你良好的感知能力:事情有多困难,需要多长时间?让你自己了解某个过程会有困难,或是 要用一点时间才能完成,能够给予你坚持不懈的毅力.
  • 多才多艺. 你尽力熟悉广泛的技术和环境,并且努力工作,以与各种新发展并肩前行.尽管你现在的工作也许只要求你成为某方面的专才,你却总是能够转向新的 领域和新的挑战.

最后,你是一个注重实效的程序员吗?

关于程序运行效率的一点见解

Posted on

最近在看计算机组成原理等4本考研书籍...发现其实回过头来看这些当年没认真学的书的话还是有不少收获的. 当年小白的我只知道编程看语言类的书籍,无法理解数据结构,计算机组成原理一类书对编程的影响. 刚开始学这本书的时候就感觉我一个搞软件编程的看硬件干嘛.又是指令又是寄存器啥的,还有那可怕的电路图... 看的真头大啊,不过其实想想,这门课要是真没用学校也不会开考研也不会考啊!当年真是图样图森破啊...

大一的时候一直以为搞软件的就要多学点编程语言...我现在倒是学了不少.到头来没一个拿的出手的,还真是可悲 广度是有了但是没深度,同样的语言人家编程风格和效率就是比你高.这个是在什么C#本质论 C++ primer里面学不到的 东西,说深了就是加编程素养.是不断积累的,不是看一本书就能迅速提升的东西.只上过培训班的程序员永远也不可能明白 学习计算机组成原理会对编程有更深入的了解.最终写的代码也只是知其然而不知其所以然.

编程素养是通过各方面计算机知识的综合培养才能得到提高的.接下来我就举个例子来谈谈学过组成原理对编程的理解和 提高.例子很简单,就是关于数组的遍历.一个二维数组,假定是10*10的吧.那么遍历输出的话,大家肯定都会的,很简单.

for(i=0;i<10;i++)
    for(j=0;j<10;j++)
       printf(a[i][j]);

这个是很简单的两层for循环,我写的是伪代码,变量定义输出什么的就不要吐槽了.学过数据结构的同学应该都明白虽然二维 数组都用矩阵来表示,但是实际储存的时候一般都是按照行优先的方式储存的.我的这个版本是先行遍历再列遍历的.

    for(j=0;j<10;j++)
            for(i=0;i<10;i++)
               printf(a[i][j]);

那么先列遍历再行遍历呢?大家一般都会觉得这个其实没什么差别吧.用数据结构的思想来说,空间复杂度和时间复 杂度都是一样的,运行起来没啥区别的.当然对于现在的高速CPU和这个元素比较少的数组来说其实也没多大差别,但是不能 因为这个就去忽略程序的效率问题.

为了讲述这个问题,首先的了解计算机的基本运行原理.首先程序是放在内存中的,但是执行程序需要用CPU来计算.因为CPU运行 速度极快,但是内存速度却没有显著的提高.所以引入了高速缓存也就是Cache,首先把内存中的程序调入高速缓存中.然后CPU再从 Cache中取出数据进行运算.但是因为Cache的容量极小,但是内存很大,根据程序访问的局部性原理.指令通常是顺序存放, 顺序执行的,数据一般也是聚集的存储在一起的.所以调入Cache中的数据基本上会是一段时间内CPU欲调用的数据.

当CPU发出度数据的请求时,如果访问的地址在Cache中即命中,那么直接从Cache中读取数据,和主存无关;如果Cache不命中, 则仍需访问主存,并把此地址所在的块一次性都调入Cache内.

显然,如果命中率高的话,那么程序直接的速度就更快.对比行遍历和列遍历.发现行遍历每次都是按顺序取数据的,因为是按照行优先方式 进行存储的嘛,所以命中率必然高.而列遍历的话每次取的都不是相邻的数据,会导致命中率大大降低,运行效率低.所以一会写程序的话 遇到数组遍历的话肯定要使用行遍历更好.

类似的问题还有GOTO语句,大一的时候老师明令禁止不准在程序中使用GOTO语句,但是就是不说为什么...学过计算机组成原理也就 明白了,因为GOTO语句违反了程序顺序执行的原则,使程序运行效率不高,而且程序读起来也很麻烦.

到此,对编程效率的见解就结束了,如果有什么纰漏的地方,还请大家指正,感谢您能读到最后~