2014年4月29日星期二

开发与工具

今天在网上随便逛了一下,看了看一些人在osChina里面对于编程语言与技术的一些争论。让我有了一些想法。

其实我觉得编程技术的发展其实和人类社会在其他领域上技术的发展本质上来说没有大的区别。而技术的发展方向本质上来说是从效率和质量这两个方向上进化的,也就是说,新的技术总是能够带来更好的质量,或者更好的效率,不过使用起来可能会更复杂一些。而从根本上来说新技术总是依托在某种工具上来实现的。比如,现在在土木工程上面,随处可见的大大小小的工程机械,特别是挖掘机,大大小小,种类俱全。而挖掘机的工作实际上就是替代了铁锹和镐头。但是它使用起来要比铁锹和镐头要复杂很多。挖土这种工作显然,质量上很容易保证,但显而易见,挖土机的工作效率比人高多了。软件开发基本也是如此,我们和其他工业领域,没有本质上的差别。

开发技术的发展其方向大体上也基本等同于工具的发展,总是向利于高效的方向来发展的。因此我们也应该看到,技术在很大程度上不可能一成不变,发展与进步是一种必然。

软件开发一个有趣的地方在于,你所使用的语言和工具很大程度上也是一种材料,一旦你使用了某一种,就不太容易换另一种。所以现代的开发平台,大体上都允许你使用多种语言来开发,比如微软的开发平台,上面支持很多种语言。Java也是走的这个路线,Java平台上现在已经有很多的语言实现了。

人类,总是趋向于使用某种工具的。人类总是趋向于使用抽象的,易于理解的,高效的工具。开发也是一样。因此我趋向于应用规范标准的类库,而不是私有的类库。类库的维护成本是很高的,而且,我刚才简单论证过了,编程工具化的过程基本是无法避免的。无论是从组织要求上来说,还是从技术要求上来说,都是一样的。

抽象度高的代码,显然更容易让人理解,从而也容易维护。

说白了,就是因为人类本质上善于发现和认识,这也是人类的一个很基本的特征。所谓的知识往往就是人类识别出来的这些模式与认识的一种集合和积累,有的完善,有的不完善。在哲学上来说,我记得认识还有两次飞跃。从感性认识到理性认识的飞跃,从理性认识到实践的飞跃。而开发工作其实就是在第二次飞跃上工作,也就是说理论在指导实践。

总之语言的发展必然会不断的提高其抽象程度,和机器有关的细节会越来越少。另外也应该看到,这个过程不可能是一两个人或者几个公司能完成的,需要整个社会的共同努力。

2014年3月24日星期一

clojure调用javaFX

知其然,不知其所以然,大概我就是这种人。不多说直接上代码:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(ns myproject.core
  (javafx.embed.swing.JFXPanel.)
  (:import [javafx.application Application]
           [javafx.event ActionEvent EventHandler]
           [javafx.scene Scene]
           [javafx.scene.layout VBox StackPane]
           [javafx.stage Stage]
           [javafx.scene.control Button])
  (:gen-class :extends javafx.application.Application)
  )

(defn -start [this stage]
  (def pane (StackPane.))
  (def btn (Button. "xxxx"))
  (.setOnAction btn (proxy [EventHandler] [] (handle [event] (println "click" event))))
  (.. pane (getChildren) (add btn))
  (def scene (Scene. pane 300 200))
  (doto stage (.setScene scene) (.setTitle "zxxxxz") (.show))
  )
(defn -stop [app]
  (println "Exiting now"))

(Application/launch myproject.core (into-array String []))

注意命名空间里面的:(javafx.embed.swing.JFXPanel.);这句话非常重要,如果没有你会得到一个运行错误,说什么Toolkit如何如何。加上就好了。至于原因,over stack网站上似乎有解释,但是我是一个不求甚解的人,所以其实就是基于某些原因,普拉普拉普拉。

注意如果你使用的是intellij,注意配置:










2014年2月27日星期四

Angular 组件

在angular里面,指令其实和组件的意思是完全不同的,但是多数人并没有很好的区分它们。并把指令提升到了完全和组件相当的高度去了,这大大加剧了指令的编写难度。事实是指令和组件完全是两个概念。

Angular的核心思想应该是以数据为中心的,但是方法是否应该是数据的一部分,这个问题还是值得商榷的。就算从比较纯的函数观点来看的话,完全无副作用的函数似乎也不应个视为与数据等同。Angular解决方法与数据间隔阂的方法其实就是通过事件完成的,说的更直白一点其实就是scope中的$watch方法。这个方法让我们得知了数据的变化,可用从容的对数据进行处理,并把视角从处理数据的方法上转回到数据本身上来。

但是如果从数据的视角(也就是angular的视角)来看的话,组件就十分的复杂。因为组件会牵扯复杂的DOM变化,和相应的数据变化,这些数据变化可能十分的剧烈,而似乎这些数据的变化也可能并不需要知会angular所感知的数据模型部分(也就是scope)。因为组件从来都不是以数据为中心的,恰恰相反,组件往往就是来操作数据的,比如说增查删改。数据在组件这里往往都是从属的对象无法被视为中心枢纽。所以组件的视角和angular的视角总是矛盾的。这也是往往在使用指令来卡法组件时让我们感到不利索的原因。此外,指令的嵌套也会使数据模型之间的关系变得复杂。因为指令往往也会有一个scope以及和它相关的作用域。这些原因导致使用指令的组件不但设计实现困难,且使用起来也很不方便。归根结底就是因为指令并不是实现组件的好方式,特别是复杂的组件。

个人认为,一个比较好的做法是把页面的组件干脆封装成独立的JS对象,把对scope的数据操作彻底的封装成相应的事件。这样似乎能够好一点。这个对象自己决定在何时传递数据。

不过我一向不认为纯粹的就好,恰恰相反,我认为简单,直接,有效的才是好的。繁复的做法一定要有原因,如果仅仅是为了契合某种说不清道不明的哲学,我认为是完全不值得的。最后审视一下我们的项目,我觉得require js的作用远远大于angular js。事实上,我倒觉得,angular并不是一个好的系统框架,而是应该作为某个前台系统框架的一部分,这样应该是比较好的。不过这个系统得多复杂呀。我的经验告诉我,复杂的设计注定不能长久。

2014年2月25日星期二

过渡设计

过渡设计其实是一个很有趣的主题,因为设计是一种人为的主观行为,并不太容易受到制约。而且设计也很难界定,大体上当你打开你的开发工具,并在键盘上敲下第一个字母的时候,设计的内容已经开始在你的头脑中展开了。但其实在软件领域里面,提到的设计大约都是指的架构设计,架构设计是没有什么所谓过渡设计这么一说的,因为架构设计和业务场景关联的十分紧密(适用一切的架构是不存在的),否则就是失败的,而且这一点也十分的容易发现,并不需要软件方面的专家。

而我们所说的过渡设计其实存在于实现的设计中。是的,实现的设计,这个设计在软件工程中似乎并没有太大的地位,但也并非不被重视。主要是这个阶段的设计比较难做,同时也很难管理和控制。个人觉得,在多数的公司中,都没有明确的提出实现设计,并将其列为软件质量的一个重要指标。

但其实实现设计中的过度设计也并不难发现,首先要明确一点,不能因为可能过度设计就不去设计了。并从而否定面向对象思想或者面向方面的开发方式。毕竟我们总是需要一种可以思考的方式并且需要能够和别人沟通和交流。因为实现的过程不可能是孤立的,任何软件都几乎不可能一个人完成。除非你是特殊材料制成的,我们一般管这种人叫天才。不过这种人太少见了,不必考虑他们对于实现的影响。

首先,设计是为了应对变化。也就是说,我们通过各种手段去进行所谓的设计,其目的就是为了让我们的代码有潜在的被改动或者被扩展的这种可能性。比如我们引入了某个接口,这样我们就有了替换实现的可能性。接口在设计中其实就是为了隔离实现的。另外我也可以使用多态性通过改变子类的行为的方式来扩展我们的业务。没有人可以保证业务是永远不变化的,其实业务或者业务的实现方式或多或少都会随着时间而改变,而且时间越长,这种变化就可能会越剧烈。因此支持变化往往是很有必要的。

其二,设计总是为了更好的和业务契合,也就是固化某些核心的逻辑。换一种说法就是在创造某一种DSL语言,这让我想起了格林斯潘第十定律。这也是非常重要的,核心业务往往就是某种产品或者某家公司赖以生存的根本。因此通过一些手段固化这些业务是十分重要的。而且核心业务往往很久都不会发生变化。比如QQ的聊天功能,office的编辑功能,游戏的价值观等。所以设计总是需要为业务来提供便利,越复杂的业务,这个需要就越发的明显。

第三,设计是为了更容易的扩大开发的规模。通过适当的抽象和合理的封装以及分层,把系统的核心和外延分离,以便于能够通过增加人手来提高开发的效率,同时也要避免初级程序员的破坏性。这也是为什么很多的系统喜欢使用spring来开发的原因。使用spring的系统从这个意义上来说,应该不是非常重要的系统。

最后,设计往往应该能够更好的支持测试。开发者往往都不怎么喜欢测试,一般来说他可能更相信自己的直觉。当然,直觉有的时候准确的可怕,但有的时候却错的离谱。所以用多种手段来保证开发的正确性是十分必要的。而测试往往具有很多的层次,对于实现的设计来说,测试更多的指的是单元测试。为了能过更好的支持单元测试,往往需要在设计上进行一些让步。越核心的功能,单元测试就越重要。特别是类库的设计,必须要考虑各种各样的情况,如果没有单元测试,根本无法保证类库的健壮性。

除此之外的设计大多数都是过渡的设计,比如我们为何使用依赖注入技术?因为我们有很多的依赖关系需要管理,而且在不同的层次上希望能够降低耦合性。IOC并不会带来代码阅读或者维护上的便利,因此如果你的系统是一个层次分明,功能确定的系统,IOC其实就是一种过渡设计。所以我发现大多数应用了spring框架的系统往往都是过度设计了的。因为其实你的系统完全不需要那种千篇一律的层次划分和解耦方式。

过渡设计还有一个有趣的特征,那就是一旦有了过渡的设计,为了让这个设计看起来合情合理,那么往后的设计就会有越来越过渡的趋势,直到被废弃。这时你会发现所谓框架的代码量比你业务的代码量要大得多。我把这种情况称为过度设计漩涡,一旦卷入,就无法脱身,并且随着代码的增加,设计的填补,设计会越来越过渡。

使用spring和hibernate这样的框架来解决问题,似乎已经成了java开发的一种趋势。但其实这些框架掌握起来并不容易,而且一旦使用,往往都会陷入过渡设计的漩涡。严重影响系统的可读性和运行性能。而且你一旦学会了spring或者hibernate的思考方式就更为的可怕,因为他们总是把问题搞的很复杂。复杂的框架以及其运作的方式会把你的业务搞得杂乱无比,你甚至可能还需要去学习一种框架专用的DSL。我觉得这种行为其实就是舍本逐末。

2009年7月28日星期二

jdk 字体设置

Ubuntu 下jdk字体设置

 

    在ubuntu下面安装jdk的时候,会发现字体很差。其实解决的方法非常的简单:


 

打开终端:

输入:sudo gedit 以管理员方式进入gedit。

打开jre下面的fontconfig.properties

 





注意选中部分,把uming.ttf改成uming.ttc就可以了。我这个是改过的。


2009年5月11日星期一

没有激情

最近心情很不好。不知道是为了什么。大概是因为自己的能力问题吧。很多想干的事情干不了。很多想避免的问题,无法避免吧。如果说错误。我觉得自己是真的有错误。如果说心态,我觉得自己的心态也的确不好。没有士气,没有激情。

2009年2月11日星期三

2009-02-12 感悟-告别浮躁

生活多现在的我来说有一丝丝的平淡。我今年已经年过30了,内心有很多的愧疚。现在看来,茫茫不知自己的未来在何方。于是又有了一丝丝的遗憾。