系列讨论初步考虑的备忘
先把一些相关的内容, 想到的目录记录一下。 这些标题是散乱的, 甚至不是一个层次的, 仅仅做一个备忘的笔记。
顺便说一句, 这个系列不是忽悠大家去用某一门“表达方式更丰富”的语言, 或者给出什么解决方案。 对于大多数程序员, 身处环境和项目当中, 更换语言是不现实的。 更何况说实在的, 现在还没有一门语言能够完美的达到我想要的效果或标准; 即使那些能够做到的语言, 我们可以采取的表达方式也是极其丑陋的。 并且, 在这系列文章的讨论所涉及的一些工作,如对语言本身的改进, 也不是大多数程序员任务。
但是我们仍然可以因为一些深入讨论, 知道问题的症结所在; 从而在能避开的时候避开, 在不能避开的时候, 不会殚精竭虑的去寻求不切实际的解决办法。 同时, 在这个系列中, 我们也可以找出一些外围辅助的方式处理好其中一些问题, 暂时不能治本, 指标也好。 更多的, 我们可以通过讨论,把现今那些浮躁的解决方案先放到一边,努力的去试着看清未来10年一些可能发展的方向。如果10年之后, 你我还在做技术, 即使没有预测准, 这样的尝试也不能说是无意义的。
这一部分可能不会明确的给出答案, 而是作为一个层层剥开外部现象的系列的开头,初步试着去提出问题。
这一部分用来分析一下OO方法论下, 两个宏观上的东西, 框架与工具箱的得失。
这一部分来看看这些流行元素都做了些什么, 同时看看哪些地方它们是它们鞭长莫及的。
这一部分我们来讨论一下在面向对象方法论使用时经常存在的错误抽象, 然后讨论根本上的抽象问题。
这一部分主要讨论对于FP风格的编程, 我们还需要什么; 进而看看FP解决掉的问题以外, 是否还有别的问题。
这一部分让我们来讨论强类型的得失, 并逐渐接触到问题的核心。
这部分让我们通过比较, 来看看为什么泛型这样重要的概念, 居然在我们流行语言中, 不堪大用。
这部分比较抽象, 也许是胡侃, 也许不是。
这部分讨论使用元数据的得失。
这部分让我们找出我们可以最大限度的不写的代码应该都有哪些, 而流行语言要求我们必须写的。
这一部分讨论一下选择动态语言的得失。
让我们来看看单元测试的前前后后吧。
通过合理的表达形式, 对于那些已经知道的事实, 我们至少可以最大限度的保障。
也许通过改进我们的表达手段, 也不一定呢。
这个作为《行为与过程》那一部分的延续, 具体的说说算法与数据的分离之美。
此列表随时更新。
最后再说一句, 有兴趣研究这些的, 请和联系, 急需交流 :); 我个人的能力还不足以从思考、 实践中, 得到我最想要的结果: 推动新的设计方法的发展。 无论是什么形式: 宣传或布道 、 影响某些在用语言的发展变化、 创造自己的语言作为示范等等。 我并不认为, “既然我们现在仅有这些”, 我们就应该忍受下去, 虽然不是大多数人, 但总有人可以做点什么。
另外, 那些不认为自己在忍受, 而是在享受(自己掌握的种种知识技巧)的兄弟, 有什么意见也可以直接提, 万一我真的是在裸泳而不自觉, 谁要是救了我, 那可真是不胜感激了 :)。
顺便说一句, 这个系列不是忽悠大家去用某一门“表达方式更丰富”的语言, 或者给出什么解决方案。 对于大多数程序员, 身处环境和项目当中, 更换语言是不现实的。 更何况说实在的, 现在还没有一门语言能够完美的达到我想要的效果或标准; 即使那些能够做到的语言, 我们可以采取的表达方式也是极其丑陋的。 并且, 在这系列文章的讨论所涉及的一些工作,如对语言本身的改进, 也不是大多数程序员任务。
但是我们仍然可以因为一些深入讨论, 知道问题的症结所在; 从而在能避开的时候避开, 在不能避开的时候, 不会殚精竭虑的去寻求不切实际的解决办法。 同时, 在这个系列中, 我们也可以找出一些外围辅助的方式处理好其中一些问题, 暂时不能治本, 指标也好。 更多的, 我们可以通过讨论,把现今那些浮躁的解决方案先放到一边,努力的去试着看清未来10年一些可能发展的方向。如果10年之后, 你我还在做技术, 即使没有预测准, 这样的尝试也不能说是无意义的。
不存在的精神包袱: 面向对象的问题到底在哪里
Linus在去年论战中, 提到C++是一门有精神包袱的语言, C#更差, 并明确的提到围绕一堆漂亮对象建立的系统是如何的差劲; 甚至还放下话说, 选择C的一个主要目的就是要把那些背着沉重精神包袱的程序员踢出去。 虽然在主流开发者社区中声音还不大, 但是明显的, 面向对象方法论和基于面向对象的语言, 现在已经到了结束“有没有问题”的争论的时候了。 但我认为, 无论是用新的方法论取代它, 还是解决问题, 现在都说不上, 第一件事是, 我们应该定位问题在哪里。这一部分可能不会明确的给出答案, 而是作为一个层层剥开外部现象的系列的开头,初步试着去提出问题。
框架的失败与工具箱的单薄
《设计模式》(DP95, GoF)一书的主要作者, Gamma, 在前几年的访谈中提到, 他认为10年前他们的很多观念是带有错误的。 尤其是他认为, 框架恐怕不是一个解决问题的合理帮助, 他现在更倾向于工具箱。 但是工具箱, 作为一块块外部存在的砖头(相对于我们构建的部分), 并不能规划结构、流程这样的东西。 更关键的是, 大多数工具箱往往是死的: 它们有固定的接口, 意味着输入和输出可以变化的范围有限; 同时,其粒度和完善程度很难把握。这一部分用来分析一下OO方法论下, 两个宏观上的东西, 框架与工具箱的得失。
设计模式、 IoC 、AOP : 补丁上打补丁
过去几年在FP社区,一些FP高手跳出来做了一个列表, 用以说明在FP中, 设计模式根本没有存在的必要。 而IoC、 AOP的出现, 从另一方面说明了在传统静态语言下, OO方法论的不足与额外的需求。 事实上, 如果说设计模式在静态OO语言上的应用, 在解决问题的同时, 最大程度上保持了静态语言所倡导的一切, 可以说IoC和AOP是在通过向这一切的对立面做出小小的、 不起眼的妥协, 换回了更重要的东西。 但也正是因为这种交换只在很小的一个范围内, 所以它们也解决不了更多、 更深刻问题。这一部分来看看这些流行元素都做了些什么, 同时看看哪些地方它们是它们鞭长莫及的。
接口真的是根本意义上的抽象吗?
好的抽象可以应对变化, 这是每一个OO实践者在学习前都被告知的, 而我们曾经深信不疑。 现在口水战已经打到了家门口: 作为一种契约, 似乎接口承载了太多的东西。 当我们在日常生活里说到“鸭子”, 它可能仅仅是一个代入句子中的词汇, 也可能包含着无限的概念。 相反, 在我们敬爱的OO中, 似乎没有这种变化的能力, 事实上, 接口往往只是一个过于具体的代表, 而且一经构造, 很难变化。 另外, 类本身就包含了一个接口, 类的实现是自己的问题, 而其它问题还在于如何抽象。这一部分我们来讨论一下在面向对象方法论使用时经常存在的错误抽象, 然后讨论根本上的抽象问题。
FP的引入能解决流行语言的多少问题?
Anders告诉我们说, delegate就是FP的全部。 也许确实是这样, 但是似乎我们还缺乏其它的东西, 哪怕是一些糖豆类型的东西。 能以FP风格完成所有的工作还不够, 关键是顺利的、 容易的完成工作。 另外, 当C#这样的静态强类型语言, 引入FP之后, 是不是OO的天花板就不存在了呢?这一部分主要讨论对于FP风格的编程, 我们还需要什么; 进而看看FP解决掉的问题以外, 是否还有别的问题。
强类型的迷思
我个人从来没质疑过强类型的作用, 这是保证软件正确性非常重要的一个手段。 事实上如果仅仅靠Unit Test和小心翼翼, McConnell的书中的资料表明, 这种做法能防止的bug数量非常有限。 而我也怀疑对于弱类型语言, 如果彻底贯彻Design by Contract的概念, 最后其繁文缛节会上升到一个什么样的地步。 问题是对于静态语言, OO中我们遇到的大多数问题, 都有强类型在其中扮演一个角色。 强类型到底是好是坏?这一部分让我们来讨论强类型的得失, 并逐渐接触到问题的核心。
泛型是如何被僵化的?
泛型是一个尝试, 让我们不被强类型紧缚手脚的道路, 很显然在这方面, C++这门天天被人唱尿的语言做的还是很到位的。 相比之下, 三个商业公司的两个平台上的语言, 其泛型体验却不那么到位。 到底差在哪儿了?这部分让我们通过比较, 来看看为什么泛型这样重要的概念, 居然在我们流行语言中, 不堪大用。
行为与过程: 各种似是而非的概念
“我日”, 主语谓语, “日”是一个行为。“我和小明去上学了”, “我和小明”是主语, 那么来个ICanGotoSchool的接口,在系统中是把我、小明塞进一个IEnumerable然后在某处foreach, 还是搞个团体对象套上接口然后在该对象内foreach呢? “干柴烈火”, 这两个东西凑在一起引发一个过程, 那么我们平时是让干柴准备好呢, 还是让烈火准备好, 还是让它们都准备好, 并分别实现一个接口?(我知道有些人会说具体问题具体分析, 呵呵) “我把你的名字写在大街小巷的每一个角落, 我靠, 我被警察带走了”, 我们用OO方法表达出这里面所有的东西, 付出什么样的代价呢? 也许有人会说, 我们没必要OO的如此严格, 你这是为OO而OO; 嗯, 很好, 不过我们是不是真的不需要表达这些,是不是一旦需要就要付出那么大的代价, 有待商榷。这部分比较抽象, 也许是胡侃, 也许不是。
被当作线索的元数据
罪案发生了, 我们才去使用我们知道的事实, 那么这些事实只是线索。元数据的引入, 为我们在OO之中施展拳脚做出了很大的贡献, 但是我们付出了很多的代价。这部分讨论使用元数据的得失。
大衍之数五十, 其用四十有九: 关键不在于写下的代码, 而在于没写什么
假设教室里有50套课桌椅, 坐满了学生, 如果我们要求每次只有一个学生能站起来, 那么他站起来再坐下去, 还是原来那个位置。 但是如果有一个位置空着呢? 玩过那种移来移去的拼图的小朋友都懂这个道理。 往往, 我们写下的代码都代表着固定了一件事, 变化蕴含在我们没写的代码之中。 接口后面的代码是我们没有写的, 还有什么是我们可以不写的?这部分让我们找出我们可以最大限度的不写的代码应该都有哪些, 而流行语言要求我们必须写的。
动态弱类型语言: 规避问题等于解决问题吗?
很显然, 相对于强类型的语言, 动态弱类型语言要求我们必须做的事情少很多。 黑客帝国里说到两个要素, 目的, 选择; 其实在这之外, 还存在着另外一个很重要的东西: 交换。 每次做出一个选择, 都意味着一个交换。 有时候我们为了达到目的, 需要作出这种交换; 但是我们往往忽视了另外一个潜在的东西: 一些我们未曾意识到的“目的”, 因为交换, 再也达不到了。这一部分讨论一下选择动态语言的得失。
单元测试: 乏力的补救之道
不从工程学的目的来讲, 仅仅说它的其中一个具体作用,单元测试可以挽回一些交换出去的东西。 但是这又是一个新的选择, 又会有新的交换, 不是吗? 我的原来一些比较幼稚的讨论见《扩散角模型》,《单元测试总是好的吗?》。 说实话, 我对这个话题还不足够熟悉, 也请有想法的兄弟, 无论是正面还是反面的经验, 走过路过提点一下。让我们来看看单元测试的前前后后吧。
正确性: try it or prove it
Knuth曾经说过这样一段话:I didn't try it correct, I only proved it. 在这里, 既不是要大肆宣扬机器自动证明或者检查程序正确性的前沿理念, 也不是说咱们要把那两行代码化成某种更严格的表达, 然后在纸上或脑子里找出结论; 而是看看什么样的表达方法更有利于我们直奔正确性的康庄大道。通过合理的表达形式, 对于那些已经知道的事实, 我们至少可以最大限度的保障。
敏捷的现在与未来: 何为敏捷, 如何敏捷
现在大家都知道了, 敏捷不见得就是XP, 也不是每一个敏捷分子都严格实施TDD。 既然敏捷是一种理念, 我们保障这种理念的方法, 难道只有不断的增加外围设置吗?也许通过改进我们的表达手段, 也不一定呢。
算法与数据
自从Oo流行以来, 算法作为行为和数据一起封装到对象内部, 似乎再合适不过了。 果真如此吗?GP开始进入广大程序员的视野, 是个好的开头。这个作为《行为与过程》那一部分的延续, 具体的说说算法与数据的分离之美。
动多态与静多态
静多态是个什么概念, 如何实现?它和动多态的各自领域都在哪里?白箱与黑箱
大话一下黑箱复用与敞开天窗说话的优劣。 如果与主题关系不大, 可以砍掉。没有对象、 没有函数: 面向概念的软件构建
这是一个重要的理念: 真正的抽象到底应该怎么做, 做到什么地步呢?运行: 之前与之后
在运行前做某些事情和在运行后做这些事情, 动静之间鸿沟究竟造成了什么样区别的呢? 上帝的归上帝, 凯撒的归凯撒, 让我们在运行前就知道的事实, 在运行前就可以处理和检查吧。实现: 起因经过结果
暂无介绍, 等待更新。设计: 时间地点人物事
暂无介绍, 等待更新。知识描述
暂无介绍, 等待更新。自动推导
暂无介绍, 等待更新。统一表达
暂无介绍, 等待更新。未来之路: 子语言或领域语言, 及它们应具备的特征
暂无介绍, 等待更新。此列表随时更新。
最后再说一句, 有兴趣研究这些的, 请和联系, 急需交流 :); 我个人的能力还不足以从思考、 实践中, 得到我最想要的结果: 推动新的设计方法的发展。 无论是什么形式: 宣传或布道 、 影响某些在用语言的发展变化、 创造自己的语言作为示范等等。 我并不认为, “既然我们现在仅有这些”, 我们就应该忍受下去, 虽然不是大多数人, 但总有人可以做点什么。
另外, 那些不认为自己在忍受, 而是在享受(自己掌握的种种知识技巧)的兄弟, 有什么意见也可以直接提, 万一我真的是在裸泳而不自觉, 谁要是救了我, 那可真是不胜感激了 :)。