如何成为一个现代程序员:使用你的CPU,而不是内存
这两天看到不少.NET面试的帖子, 说实话, 那些问题中凡是涉及细节的, 我一概答不上来: 就算今天知道了明天肯定就忘; 事实上, 这些问题在我具体工作中全都处理过. 因为要算计的事太多, 没那个脑子记这些了. 不过我敢保证, 这些问题任何一个也不可能对我的工作造成哪怕一点点的阻碍, 因为在我的能力和理解力覆盖面之内.
尖酸刻薄的说, 我个人认为, 那些问题如果用来面试, 只能用来判断对方对工具(没错, 不只只有IDE是工具, 语言, 库, 都是工具而已)使用的程度, 这似乎和高级/架构, 根本挂不上钩.关键是我们在哪个层面工作. 现在的工作, 无论是程序员还是其他的, 哪怕卖保险的, 处理的信息量要远远超过以往; 所以比知道具体信息更关键的是, 如何快速获取并应用信息. 这个只能靠有意识的学习, 体会别人的思路.
比如原文中的兄弟说到: "道理很简单,因为对于一次运行,很可能只用到一个程序集中极少数类型和对象,而大部分可能并不会被使用,此时CLR傻乎乎的给整个程序集都给Compile了,CLR不是傻疯了么"
这个就是个忒别好的方式. 只是那些道理不简单的, 要通过二阶和三阶的知识把他们变成简单的. 比如关于一些工具箱和框架的使用, 看似量很大, 那些红皮书一本700页还是少的. 但是说实话, 把10年的时间用来学习和实践十几本红皮书, 不如学学如何设计更合理, 收集一些不同流派程序员的风格, 练习一下猜测他们进行具体内部实现和设计外部接口使用方式时的心理.
在这些发散的地方有所收获之后, 就会发现, 配合现代IDE, 很多时候一些事情连帮助都不用看, 自然而然就能用得很好. 对于有疑惑的事情, 大不了写个小例子试验一下. 以我的经验, 这花不了多少时间, 忘了的东西(假设比较复杂), 第二遍再用的时候, 一般连例子都不用写, 一见到就能记起的差不多了.
很多事情说白了, 按照我以前的说法, 属于别人设定了这样, 你就得这么用的; 这些我一般不把它看作知识. 比如老赵对其中一个问题的答案: 由于Equals和==操作符都可以重载, 所以不确定. 但是假设C#不提供操作符重载, 这个问题的答案就不一样.
关键是思路, 比如还是这个Equals和==的问题. 你可以连C#提不提供操作符重载都不知道, 遇到这个问题, 首先应该想到的是: 我会不会遇到操作符重载的问题? 这个问题拿屁股想都知道, 会涉及到C#提不提供这个功能. 然后自然就会去查, 查这个事, 用不了5秒钟, 因为连网页和快照都不用打开, 一般瞅一眼搜索引擎出示的片段就知道了. 查到以后, 自然就知道该注意什么问题.
上面的最后一句话, 其实有待商榷. 因为是不是"自然就知道", 取决于你平时有没有收集哪些问题可能是由操作符重载引起的信息. 但是收集这些信息, 并不是要非常细化的, 而是留一个模糊的印象即可. 有了一个线索, 还可以再查嘛. 更多的是感觉: 由于脑子里记得东西少了, 不清晰了, 我们就要加强找感觉的能力. 比如, 我们碰到一个问题, 是由操作符重载引起的可能性为10%, 甚至1%, 我们必须有办法注意到这1%.
不放弃每一个可能的同时, 保证干活的效率, 这个技巧在于遍历: 但是被遍历的数组必须排序, 有优先级的排序; 这个数组中的元素, 则是你要问自己的问题. 如何排序, 看起来只能由具体的情况决定. 这个属于经验范畴, 只能求助于练习和撞墙了. 不过, 我相信, 记住大量的细节和情况, 照样可能因为这些细节犯错误. 有一个会想问题的大脑, 反而比一个面面俱到的记忆, 更加节约时间.
养成了在正确的时候提出正确的问题的习惯(这个动作消耗的时间肯定在0.1秒之内), 接下来就是猜测作者的意图了. 这个事情的关键在于, 我们广泛的观察在生活中, 人们一般如何解决问题. 当然既然干的是软件构件, 对程序设计领域, 更要广撒网的去获取样本: 你知道他们有几种可能方式设计, 并且能快速辨别出来, 自然就能使用的随心所欲.
这个地方主还要锻炼的是联想问题的能力. 因为一个具体领域的问题, 我们可能从来没见过; 但是它很可能和另一领域相似. 当然, 有的时候很可能一点点不相似, 就导致问题的解法集合产生非常大的差异, 怎么办呢? 再拔高一层, 继续收集不同的变化下, 解的集合如何变化的规律呗. 这个实际上是进行了更高阶的抽取.
关键的一个假设我们要有的是, 人都是相似的, 所以脑子和想法也是相似的. 哪怕性格迥异, 最多也就分成几类人, 最后对应的就是几类解法, 基本就是几类人对同一问题, 对应的构思不同. 所以第一件事就是找感觉: 我们现在使用的框架/工具箱的作者是个什么类型的人, 他的构思会是怎么样的? 然后找寻预期中特点, 验证答案; 最后我们确定的很可能是一个混合的风格, 但这没关系, 我们可以观察一下针对一个大问题下的不同子问题, 他做出的选择是什么, 自然就知道他是如何混合使用不同思路的, 为什么混合; 于是在各种场景下, 我们都能很快的找到问题的答案.
对于我来说, 相当关注的就是别人的程序设计风格, 越是刚进入一个领域, 就越在乎和我使用的框架/工具箱的风格保持统一. 哪怕这个风格和我的习惯抵触的很厉害. 因为只有你象他那样做, 你才能做到真正的象他那样想. 当然, 针对"C#是否提供操作符重载"这类问题, 我们要关注的不仅仅是程序设计风格, 更多的是语言设计的理念这些问题. 平时在自己的领域之外, 多关心一下这些问题, 我们不需要实现自己的语言, 也可以逐步的练就熟悉环境的能力. 比如, 一个以类为依托的语言, 提供的特性肯定是一篮子, 这些篮子里一般都会有什么, 这个概念就必须有.
在一个完全陌生的领域, 经过锻炼, 可以把这个Clone期(Clone的是人家身上那股子劲儿), 控制在半个月左右. 过了这半个月, 爱怎么写程序, 就可以怎么写了; 不过恐怕这时候咱们已经进入状态, 除非是特别费时的习惯, 其它的宁愿和咱们Clone的对象保持统一, 而不愿意再改了. 在这里需要注意的一个重点是: 也许你的问题, 和你所使用的框架和工具箱的设计及使用方式, 是格格不入的, 但确实这个第三方的东西又能大幅增加你的效率; 这时候你就要花点时间, 对你的大脑和具体实现做些Adpater了.
我觉得这样的学习和进步的方式, 最大的好处是, 同样的脑力, 获得了更多的东西; 同样的时间, 以"不知道"的方式, 就覆盖更多的内容. 不知道大家看过那些什么16kb展现一个带纹理的3D场景的DEMO没有? 其实道理是相似的, 只是如果3D游戏都那么优化, 反而要花费大量的时间和精力, 这是因为, 对于场景, 纹理, 这些东西, 变化太多, 无法归纳出一个或几个普遍的规律. 而我们人类做事的方式确是可以总结的: 除非是神经病, 否则对于一个人和一类问题来说, 做对的方式一共就那几种.
我们要看到, 人的特征是, 超频容易, 同时人的CPU组属于可编程的硬件, 而且比现在稍微具备类似功能的显卡要强得多: 我们可以针对各种各样的问题对我们的CPU进行优化, 提供捷径, 这就仿佛可以通过编程手段增加MMX/SSE/3DNOW!, 而且可以无限制的扩展. 但是我们的内存却极其有限, 而且我们的机箱太硬: 当然, 即使打开它, 也未必有内存插槽. 不过如果你要是一个过目不忘的家伙, 那么我应该在文章开头提示你点击右上角的x的; 现在只能对你表示强烈抱歉, 以及更多的嫉妒了.
说到底, 在你不可能用到什么重载的时候, 你就不需要关注它; 你只要知道它和它的一帮可能给你造成障碍或帮助的兄弟在那儿, 同时知道干掉它们或驱使它们的秘籍在哪儿得到, 也许还需要知道怎么去拿这个秘籍, 和使用秘籍的几种咒语. 但是, 就像我们设计软件的原则一样, 相比具体问题, 这些能力是可以大规模的重用的.
这就好比玩星际或者魔兽时, 速抄(谁理解这个词? 你们那习惯上怎么叫的?)的话, 当一局结束时, 一般来说一个地图上大多数地方是还是黑的. 当然, 如果是开分矿, 搞堆兵的主儿, 最后地图基本全亮了. 不过我们需要注意的是, 当你的单位不在一个已经探过的地方时, 那里还是罩着战争迷雾. 但这不要紧, 只要你会"探路". 很显然, 不会"探路"的人, 无论他掌握多少极其牛B的技巧, 也不可能赢.
当然, 和"探路"相似和同样必要的技能还有很多, 这里只是拿它做一个代表符号. 我们需要注意到一个现象: 相比一个知道如何造奇美拉或大核的人, 一个在C&C中会"探路"的家伙, 经常玩个几天, 还没有记住各种数据, 就可以开始狂菜前者了. 不要和我说Grrrr或者谁谁数据记得也很熟: 毕竟, 他们需要处理的细节是有限的, 在这方面吃亏不值得; 而生活和软件构件工作中则不是. 这又是一个如何进行选择和交换的问题, 处理这个问题的能力, 是基础之中基础.
当然, 并不是所有的问题, 是会"探路"或者一些其它基本技巧就可以解决的. 分辨一个知识属于哪个范畴, 又是一个话题了. 这个话题更没有想好, 这篇文章已经够长了, 放以后, 或者大家讨论一下吧. 另外, 如果大家觉得我说的话没份量, 也可以看看真正的大师怎么说的(不是原话): 在Stroustrup的访谈和其它一些人的发言中也曾经提到, 不要去关注细节, 而是关注更高层面. 当你真正的理解了问题, 做出了正确的决定和设计, 细节自然而然的会"Fall into place".
当然我不赞成人人都采用这样的方法提高能力: 如果所有人都等着用到的时候再查, 恐怕每一个人都什么也查不到, 最后就便宜出版社了^^. 嗯, 这篇文章只是随便说说. 其实关于怎样成为一个现代程序员, 至少也能写出一本700页的红皮书. 谁要是有兴趣共同创作, 或者帮助这个话题联系出版赚钱等适宜, 不妨联系我, 嘿嘿.
尖酸刻薄的说, 我个人认为, 那些问题如果用来面试, 只能用来判断对方对工具(没错, 不只只有IDE是工具, 语言, 库, 都是工具而已)使用的程度, 这似乎和高级/架构, 根本挂不上钩.关键是我们在哪个层面工作. 现在的工作, 无论是程序员还是其他的, 哪怕卖保险的, 处理的信息量要远远超过以往; 所以比知道具体信息更关键的是, 如何快速获取并应用信息. 这个只能靠有意识的学习, 体会别人的思路.
比如原文中的兄弟说到: "道理很简单,因为对于一次运行,很可能只用到一个程序集中极少数类型和对象,而大部分可能并不会被使用,此时CLR傻乎乎的给整个程序集都给Compile了,CLR不是傻疯了么"
这个就是个忒别好的方式. 只是那些道理不简单的, 要通过二阶和三阶的知识把他们变成简单的. 比如关于一些工具箱和框架的使用, 看似量很大, 那些红皮书一本700页还是少的. 但是说实话, 把10年的时间用来学习和实践十几本红皮书, 不如学学如何设计更合理, 收集一些不同流派程序员的风格, 练习一下猜测他们进行具体内部实现和设计外部接口使用方式时的心理.
在这些发散的地方有所收获之后, 就会发现, 配合现代IDE, 很多时候一些事情连帮助都不用看, 自然而然就能用得很好. 对于有疑惑的事情, 大不了写个小例子试验一下. 以我的经验, 这花不了多少时间, 忘了的东西(假设比较复杂), 第二遍再用的时候, 一般连例子都不用写, 一见到就能记起的差不多了.
很多事情说白了, 按照我以前的说法, 属于别人设定了这样, 你就得这么用的; 这些我一般不把它看作知识. 比如老赵对其中一个问题的答案: 由于Equals和==操作符都可以重载, 所以不确定. 但是假设C#不提供操作符重载, 这个问题的答案就不一样.
关键是思路, 比如还是这个Equals和==的问题. 你可以连C#提不提供操作符重载都不知道, 遇到这个问题, 首先应该想到的是: 我会不会遇到操作符重载的问题? 这个问题拿屁股想都知道, 会涉及到C#提不提供这个功能. 然后自然就会去查, 查这个事, 用不了5秒钟, 因为连网页和快照都不用打开, 一般瞅一眼搜索引擎出示的片段就知道了. 查到以后, 自然就知道该注意什么问题.
上面的最后一句话, 其实有待商榷. 因为是不是"自然就知道", 取决于你平时有没有收集哪些问题可能是由操作符重载引起的信息. 但是收集这些信息, 并不是要非常细化的, 而是留一个模糊的印象即可. 有了一个线索, 还可以再查嘛. 更多的是感觉: 由于脑子里记得东西少了, 不清晰了, 我们就要加强找感觉的能力. 比如, 我们碰到一个问题, 是由操作符重载引起的可能性为10%, 甚至1%, 我们必须有办法注意到这1%.
不放弃每一个可能的同时, 保证干活的效率, 这个技巧在于遍历: 但是被遍历的数组必须排序, 有优先级的排序; 这个数组中的元素, 则是你要问自己的问题. 如何排序, 看起来只能由具体的情况决定. 这个属于经验范畴, 只能求助于练习和撞墙了. 不过, 我相信, 记住大量的细节和情况, 照样可能因为这些细节犯错误. 有一个会想问题的大脑, 反而比一个面面俱到的记忆, 更加节约时间.
养成了在正确的时候提出正确的问题的习惯(这个动作消耗的时间肯定在0.1秒之内), 接下来就是猜测作者的意图了. 这个事情的关键在于, 我们广泛的观察在生活中, 人们一般如何解决问题. 当然既然干的是软件构件, 对程序设计领域, 更要广撒网的去获取样本: 你知道他们有几种可能方式设计, 并且能快速辨别出来, 自然就能使用的随心所欲.
这个地方主还要锻炼的是联想问题的能力. 因为一个具体领域的问题, 我们可能从来没见过; 但是它很可能和另一领域相似. 当然, 有的时候很可能一点点不相似, 就导致问题的解法集合产生非常大的差异, 怎么办呢? 再拔高一层, 继续收集不同的变化下, 解的集合如何变化的规律呗. 这个实际上是进行了更高阶的抽取.
关键的一个假设我们要有的是, 人都是相似的, 所以脑子和想法也是相似的. 哪怕性格迥异, 最多也就分成几类人, 最后对应的就是几类解法, 基本就是几类人对同一问题, 对应的构思不同. 所以第一件事就是找感觉: 我们现在使用的框架/工具箱的作者是个什么类型的人, 他的构思会是怎么样的? 然后找寻预期中特点, 验证答案; 最后我们确定的很可能是一个混合的风格, 但这没关系, 我们可以观察一下针对一个大问题下的不同子问题, 他做出的选择是什么, 自然就知道他是如何混合使用不同思路的, 为什么混合; 于是在各种场景下, 我们都能很快的找到问题的答案.
对于我来说, 相当关注的就是别人的程序设计风格, 越是刚进入一个领域, 就越在乎和我使用的框架/工具箱的风格保持统一. 哪怕这个风格和我的习惯抵触的很厉害. 因为只有你象他那样做, 你才能做到真正的象他那样想. 当然, 针对"C#是否提供操作符重载"这类问题, 我们要关注的不仅仅是程序设计风格, 更多的是语言设计的理念这些问题. 平时在自己的领域之外, 多关心一下这些问题, 我们不需要实现自己的语言, 也可以逐步的练就熟悉环境的能力. 比如, 一个以类为依托的语言, 提供的特性肯定是一篮子, 这些篮子里一般都会有什么, 这个概念就必须有.
在一个完全陌生的领域, 经过锻炼, 可以把这个Clone期(Clone的是人家身上那股子劲儿), 控制在半个月左右. 过了这半个月, 爱怎么写程序, 就可以怎么写了; 不过恐怕这时候咱们已经进入状态, 除非是特别费时的习惯, 其它的宁愿和咱们Clone的对象保持统一, 而不愿意再改了. 在这里需要注意的一个重点是: 也许你的问题, 和你所使用的框架和工具箱的设计及使用方式, 是格格不入的, 但确实这个第三方的东西又能大幅增加你的效率; 这时候你就要花点时间, 对你的大脑和具体实现做些Adpater了.
我觉得这样的学习和进步的方式, 最大的好处是, 同样的脑力, 获得了更多的东西; 同样的时间, 以"不知道"的方式, 就覆盖更多的内容. 不知道大家看过那些什么16kb展现一个带纹理的3D场景的DEMO没有? 其实道理是相似的, 只是如果3D游戏都那么优化, 反而要花费大量的时间和精力, 这是因为, 对于场景, 纹理, 这些东西, 变化太多, 无法归纳出一个或几个普遍的规律. 而我们人类做事的方式确是可以总结的: 除非是神经病, 否则对于一个人和一类问题来说, 做对的方式一共就那几种.
我们要看到, 人的特征是, 超频容易, 同时人的CPU组属于可编程的硬件, 而且比现在稍微具备类似功能的显卡要强得多: 我们可以针对各种各样的问题对我们的CPU进行优化, 提供捷径, 这就仿佛可以通过编程手段增加MMX/SSE/3DNOW!, 而且可以无限制的扩展. 但是我们的内存却极其有限, 而且我们的机箱太硬: 当然, 即使打开它, 也未必有内存插槽. 不过如果你要是一个过目不忘的家伙, 那么我应该在文章开头提示你点击右上角的x的; 现在只能对你表示强烈抱歉, 以及更多的嫉妒了.
说到底, 在你不可能用到什么重载的时候, 你就不需要关注它; 你只要知道它和它的一帮可能给你造成障碍或帮助的兄弟在那儿, 同时知道干掉它们或驱使它们的秘籍在哪儿得到, 也许还需要知道怎么去拿这个秘籍, 和使用秘籍的几种咒语. 但是, 就像我们设计软件的原则一样, 相比具体问题, 这些能力是可以大规模的重用的.
这就好比玩星际或者魔兽时, 速抄(谁理解这个词? 你们那习惯上怎么叫的?)的话, 当一局结束时, 一般来说一个地图上大多数地方是还是黑的. 当然, 如果是开分矿, 搞堆兵的主儿, 最后地图基本全亮了. 不过我们需要注意的是, 当你的单位不在一个已经探过的地方时, 那里还是罩着战争迷雾. 但这不要紧, 只要你会"探路". 很显然, 不会"探路"的人, 无论他掌握多少极其牛B的技巧, 也不可能赢.
当然, 和"探路"相似和同样必要的技能还有很多, 这里只是拿它做一个代表符号. 我们需要注意到一个现象: 相比一个知道如何造奇美拉或大核的人, 一个在C&C中会"探路"的家伙, 经常玩个几天, 还没有记住各种数据, 就可以开始狂菜前者了. 不要和我说Grrrr或者谁谁数据记得也很熟: 毕竟, 他们需要处理的细节是有限的, 在这方面吃亏不值得; 而生活和软件构件工作中则不是. 这又是一个如何进行选择和交换的问题, 处理这个问题的能力, 是基础之中基础.
当然, 并不是所有的问题, 是会"探路"或者一些其它基本技巧就可以解决的. 分辨一个知识属于哪个范畴, 又是一个话题了. 这个话题更没有想好, 这篇文章已经够长了, 放以后, 或者大家讨论一下吧. 另外, 如果大家觉得我说的话没份量, 也可以看看真正的大师怎么说的(不是原话): 在Stroustrup的访谈和其它一些人的发言中也曾经提到, 不要去关注细节, 而是关注更高层面. 当你真正的理解了问题, 做出了正确的决定和设计, 细节自然而然的会"Fall into place".
当然我不赞成人人都采用这样的方法提高能力: 如果所有人都等着用到的时候再查, 恐怕每一个人都什么也查不到, 最后就便宜出版社了^^. 嗯, 这篇文章只是随便说说. 其实关于怎样成为一个现代程序员, 至少也能写出一本700页的红皮书. 谁要是有兴趣共同创作, 或者帮助这个话题联系出版赚钱等适宜, 不妨联系我, 嘿嘿.