随笔:杂念纷呈

      虽然没有任何证据明确指出“一切皆对象的”概念,但如果采用了面向对象思想来分析并模拟一个系统的行为时,就最起码必须要遵守“尽量把一切转化为对象”的原则。即便是不能转化的也要试图转化,否则问题无法得到解决。通常的设计思路是根据需求决定问题的领域,然后再领域之中细划,按照直观认识与经验,先弄清系统的行为有哪些,它需要做些什么,做这些事情需要些什么东西,出于扩展性、安全性等因素,这些东西哪一些可以尽量简化,哪一些必须要繁杂。
       然后,才是要考虑如何把技术实现与纯意义的对象式解决模型结合起来,在这一些过程中,其中技术上的一些现实问题会交织于前面几步的原始的分析中,如果经验足够丰富,在前几步时,就应该适当考虑了一些技术上应该避免的设计问题。
        有一些问题不是纯粹的思想就能解决的,必须承认,我们即便是采用成熟的框架,成熟的复用式组件,它们也有可能是存在BUG或是历史时期一直遗留下来未能解决的BUG。典型的例如dotnet 2中的webbrowser托管控件设置忽略脚本错误时根本不起作用,而设计者的设计视图上又没有给代码书写者创建一个webbrowser继承类的权限,这样就会产生设计与实现的冲突。(顺便说一下,这只是举一个例子,在现实中,如果要求真那么变态,也可以使用反射获取nativeObject私有对象来处理,虽然在事实上,反射一样是破坏封装性的一种行为)
        分析与设计中需要OO的支持,在实际开发中,根据层次需要的不同,最底层代码是否是纯OO实现,是否是纯粹的完美对象主义都毫无意义,它的职责与要求是能够提供设计要求的实现,从理论意义上来说,这属于是封装性的一种,无论你内部的代码实现的是多少的不OO或是甚至是多么的不结构化,但你只要能最大程度保证你提供的函数运行能通过高指标的测试,并能精确地指出有哪些潜在的问题并加以注释,最后只要在抽象层次你能保证给出符合设计的接口形态,你就是成功的。
        所以,OO最大的意义是体现在分析与设计之上的,从某种意义上来说,OO形式代码书写,很大程序上会导致代码量的增加,如果不是OO具有重用性可以抵消这些消极因素的话,OO式的编程语言永远不会出现。(就目前的复用性情况,书写更多的这些代码看起来是非常值得的。)
        OO的特点就是将对事物模拟的理解分割为抽象与实现,通常开发语言中的类的概念是抽象与实现之间的一个桥梁,一类定义决定了一个创建出一个什么样的对象,创建出的对象处于什么样的状态,但它本身还是含糊而混乱的,为了清晰化,所以才会出现对纯抽象的热衷,也就是信奉基于接口编程的这种思想。
       接口这个概念定义并不明确,因为“接口”这个名词,很容易造成分析与设计上的概念混乱,尽管接口的最初出现是为了进行更好封装性,包装系统间对象之间的通信的视角大小及角度,从而能够明确分割一个类创建出的复杂对象种种方法属性等成员的归类。但实际上,在分析与设计上,接口有一些不相同的含义。
        在分析与设计中,我们可以认为,接口是一种最纯粹的抽象定义,它是所有抽象系统的基础抽象元素,例如我们只见过天使没见过鸟人的话,可以定义为“会飞的就是天使”,那么可以堂而皇之地创建一个“天使”类,但是现在知道了会飞的也有鸟人,于是乎就得再定义一个“鸟人”类,它们间公共拥有的就是Fly这样的能力,再从现实角度深入,Fly调用如果定性成为一个void方法是非常可恶的,因为有时候我们甚至不知道它是什么含义是成功地调用。解决方案如果是时时返回一个值的话,我们就不得不时时check它(如果不check还不如不要返回),可是每个函数都check,那还不得累死。所以异常概念的引入,大大减轻了我们的劳累程度,这也意味着,在一个系统定义一系列清晰的异常列表是非常有必要的--尽管异常有时有些不太仅人满意的地方(例如性能)。
        再深一步说,一个方法调用是否成功并不能决定目标的是否符合“是”与“否”的概念,举个例子说,像在C#中,要求接口必须提供强制实现,而Fly调用失败可能是天使或鸟人的翅膀断了,它失去了飞的能力,但不意味着它就不是天使或鸟人了,决定是否是天使还是鸟人的决定性因素,可以考虑采用抽象类来实现,并强制抽象类可以完全识别该符号自身。
        在java中与dotnet是不一同的,它的接口除非你思想中是乐意认为它是一个纯粹抽象,否则你是可以在接口中定义常量的,并且,接口的成员还可以不要求强制实现,这就让人郁闷不已了:实现接口的人如果忘记或忽略了一些接口中的必要存在的成员的话,在调用者一方可能会引起一起不必要的麻烦。可以假设这样一种情况,比如上面的Fly调用后,天使或鸟人也没飞起来,但经检查后,发现对象确实是满足了Fly的条件,但却没有任何行为产生,这就会导致很多混乱和一些不必要的处理措施。所以,类似于C#中的强制成员实现有诸多的好处(就一点上,更喜欢C#一些,当出现实在是没有任何理由需要实现该接口中的某个成员时,就非常值得怀疑了。
        设计应该遵循分析的结果来进行设计,在设计的过程虽然不免要进行一些更深入的分析工作,这两工作虽然连接紧密,但为了清晰的头脑,我们还是应该把它们区分开,起码要时刻知道自己是在干什么,究竟是在设计还是在分析,如果不弄清楚自己在干什么,就有可能越弄越乱(不排除这世界上有一种强人,多乱都能折腾得好)。区别清楚设计是在分析的基础之上,而更进一步的设计所导致的分析,反过来又会导致更进一步的设计。一般的软件工程会说这是概要设计与详细设计,实际上这样的说法又是分得太开了,以致于无从把握。
         很多人有这样的体验,没有太多的分析与设计,就靠着自己的经验与能力,拿来就写代码,大脑中直接想好了,一样可以做项目。其中有一部分人就对大张旗鼓地进行分析设计的必要性产生了怀疑,并试图认为那是拖延项目周期,增加开发周期以骗取利润的的一种政客式手法。
         软件工程的存在,按照课本上的说法是为了工业化生产软件,这不得不让人联想到冷冰冰的工厂里民工手式制鞋的无趣。相反的,我却认为,软件工程存在的目的是为了更有效率地开发高质量的软件,并且能够让分析-设计-代码融合一起,形成一种乐趣,尽量让开发者考虑的是创造些什么,控制些什么,毁灭些什么,营造一个开发者的世界,而开发者应当在软件开的世界成为上帝。圣经有“上帝说要光,于是就有了光”,软件工程开发的极致就是追求的这个,例如MDA的不懈努力(现在好像有点懈了?),层出不穷的代码生成器等,无一不是向工业化(我不喜欢这个词)开发进步。
         有人认为软件开发及相关工具的进步导致开发人员的贬值,这里需要正视的一点是,软件开发及相关工具的进步,大大提高了效率,在这种效率的基础上,我们应该去做更多创新性的事情,而不是仍然要一天到晚在困惑解决一些非合理性开发性思路以外的细节问题(例如一个函数调用要求的参数是ushort,实际上这里要求你传入的是一个string,严重一点来说这就是一种bug),更不应该沉迷于探究华不实的理论上。历史早就证明,每当理论过于脱离实践的时候或超越时代的时候,该理论不会存在现实的社会意义,也不会转化为现实的生产力,就如同于古代中国高度发达的思想却没有真正能配合现实思维的行动而导致闭关锁国这种行为。
         OO是一种有效的分割并模拟系统行为的方法,它是一种观察系统并解析系统的方式,由于我们的软件最终基本上是取决于符号化的编程方法来实现,而符号化正是对象思想的一种体现,具体有兴趣,可参看个人视角:抽象与实现中的概念解释。

        如果有朋友持有不同观点,欢迎批评指正,交流经验。

posted @ 2007-09-28 12:36  一根神棍研古今  阅读(3688)  评论(10编辑  收藏  举报
Web Counter