中国浏览器市场份额统计

根据缔元信网络数据公司的最新统计,中国最新浏览器市场份额如下:

  1. MSIE/6: 59.16%
  2. MSIE/8: 20.29%
  3. MSIE/7: 14.95%
  4. Safari: 3.41%
  5. Firefox: 1.79%
  6. MSIE/9: 0.15%
  7. Opera: 0.14%
  8. Google Chrome: 0.05%
  9. Mozilla: 0.03%
  10. MSIE/5: 0.01%
  11. 其它: 0.01%

而前段时间有消息报道称微软高管称中国是IE6消亡最大障碍,互联网分析公司Net Applications的数据显示,截至今年11月,45.2%的中国互联网用户仍在使用IE6,是全球其他地区的五倍以上。这款浏览器在除中国以外其他地区的用量仅为7.6%,全球用量为14.6%。

不知道为什么还有那么多人用ie6,我想没有哪个网页设计者会不骂它的。而用ie6的人可能会说,能用就好,我为什么要升级呢?

WordPress的Permalinks与guid

这几天研究wordoress的时候,纠结在Permalinks和guid究竟有什么区别,官方对于这两个东西的解析是这样的:

Permalinks:

Permalinks are the permanent URLs to your individual weblog posts, as well as categories and other lists of weblog postings. A permalink is what another weblogger will use to link to your article (or section), or how you might send a link to your story in an e-mail message. The URL to each post should be permanent, and never change — hencepermalink.

guid:

(string) A link to the post. Note: One cannot rely upon the GUID to be the permalink (as it previously was in pre-2.5), Nor can you expect it to be a valid link to the post. It’s mearly a unique identifier, which so happens to be a link to the post at present.

据此,所以我认为Permalinks就是文章的链接,而guid只不过是一个唯一标识,也可能是pre-2.5以前的遗留物…所以如果你需要得到文章的链接,也就是需要获得permalink,而不是guid,因为它甚至可能不是一个合法的链接。

在Google里搜了很久,发现guid几乎只在WordPress的RSS中用到,在WordPress的fr:Marqueurs de Modele里可以找到这个函数

Description:
Affiche le nom d’une ou plusieurs catégories auxquelles appartient l’article au format RSS (en anglais). Ce marqueur doit être utilisé à l’intérieur de la Boucle.

Utilisation:
<?php the_category_rss(‘type’) ?>

在官方的Forums里(http://wordpress.org/support/topic/70616)也看到有一位高人这样描述:

Simply put, the GUID can be thought of as an unique ID — WP uses URIs and if you happen to change your URI, the GUID will not update because simply put, it does not need to.

However ‘sloppy’ this may appear it will not matter because as an example where the GUID appears in your RSS2 feed you will note: isPermaLink="false" which as stated by the spec:

isPermaLink is optional, its default value is true. If its value is false, the guid may not be assumed to be a url, or a url to anything in particular. (http://blogs.law.harvard.edu/tech/rss#ltguidgtSubelementOfLtitemgt)

So fear not, the GUIDs in your DB (though they may look sloppy because of a URI change) will not hurt you 🙂

另外当需要把blog迁移域名的时候也需要修改guid。

我们在WordPress的”设置”->”固定链接”里可以找到对Permalinks的设置,不过需要对配置文件作一些修改,否则一般情况下都会出现404错误,我在这里做一个总结:

1. WrodPress的.htaccess文件要开放写权限,这个可通过FTP工具进行设置

2. 在Apache的httpd.conf文件中找到LoadModule rewrite_module modules/mod_rewrite.so,取消前面的#

3. 同样在httpd.conf中查找指向WordPress安装目录的Directory tag,对其中的AllowOverride参数设置为FileInfo,关于AllowOverride的详细介绍,可参见http://www.phperz.com/server/Apache/102H05320092053.html

Wanna be Your Code

If you are a programmer.

If you hearts have bounded together.

I’m not advertising for ms. But if you match the conditions above, you may share the feeling with me…

(To watch the movie you have to Install Silverlight(windows, mac) and knowledge about Persian Password if you want to know more)


Get Microsoft Silverlight

Treasure everything you have.

大话西游学习笔记

策略模式:策略模式是一种定义一些列算法的方法,从概念上来看,所有的这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合关系——策略模式封装了变化!

策略模式就是用类封装算法的,但在实践中,我们可以发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的规则,就可以考虑使用策略模式处理这种变化的可能性。

单一职责原则:就一个类而言,应该仅有一个引起它变化原因——手机不应该有过多的功能,否则就可能会削弱或则抑制它本身完成其职责的能力

1.改进程序结构可以考虑的问题:不同硬件环境下运行(一个核心驱动,与界面层分离)——界面层、逻辑层分离

软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离,其实要去判断是否应该分离出类来,也不难,那就是如果你能后想到多于一个的动机去改变一个类,那么这个类就具有多余一个的职责。在编程时,我们是要在类的职责分离上多思考,做到单一职责,这你的代码才是真正的易维护、易扩展、易复用、灵活多样。

考研求职两不误——开放——封闭原则

这里研究的问题其实就是:怎样的设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本呢?

其实员工迟到不是主要的问题,每天保证8小时的工作量是老板最需要的,甚至8小时工作时间也不是主要问题,业绩目标的完成或超额完成才是最重要的指标,于是应该改变管理方式,比如,弹性上班工作制,早到早下班,晚到晚下班,或者没人每月允许三次迟到,迟到之恶当天下班补时间等等,对市场销售人员可能就更加以业绩为标准,工作时间不固定了——这其实就是对工作时间或业绩成效的修改关闭,而对时间制度扩展的开放。

这就需要老板自己很清楚最希望达到的目的是什么,制定的制度才最合理有效。

用古人的理论来说,管理需要中庸之道!

开放——封闭原则的意思就是说,你设计的时候,时刻要考虑,尽量让这个类是足够好,写好了就不要去修改了,如果新的需求来,我们增加一些类就完事了,原来的代码能不动则不动。

2.改进程序可以考虑的角度:能否在业务中增加一些类似的功能

“开放——封闭原则”的精神所在:面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。

对原则性目标性的问题应该雷打不动的,在不影响原则问题的时候,可以对外开放,这就是对扩展的开放新,对修改关闭的意义。

对痛苦关闭,对快乐开放

第五章:会修电脑不会修收音机?——依赖倒转原则

依赖倒转原则:要针对接口编程,不要对实现编程。

i.             高层模块不应该依赖低层模块。两个都应该依赖抽象。

ii.            抽象不应该依赖细节,细节应该依赖抽象。

CPU、内存,硬盘都是针对接口进行设计的,封装了内部的复杂性,但是要考虑到,如果主板坏了,那么CPU、内存或者硬盘所有部件都没用了这显然就不合理。例如数据库的连接设计是可以更换的。反过来,如果内存坏了,也不应该造成其他部件不能用才对。

——上面的问题的结论就是:不管高层模块还是低层模块,它们都依赖于抽象,具体一点就是接口或者抽象类,只要接口是稳定的,那么任何一个的更改都不用担心其他受到影响,这就使得无论高层模块还是低层模块都可以很容易地被复用,这才是最好的办法。

依赖倒转其实可以说是面向对象设计的标志,用那种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止与抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。

第六章:穿什么有这么重要?——装饰模式

穿着顺序是很讲究的,比如说,先穿外裤再穿内裤,这叫凡人,内裤穿到外裤外面,那就是超人了。

破解fs2you连接失败

今晚志伟突然说,他知道了为什么他的Windows 7有时右键会弹出了一个错误框了,是因为一个叫fs2you的专用下载工具惹的祸,可能这个东西并不支持Windows 7,然后我说,为什么一定要用这个东西下载!破解它就是了嘛,我信誓旦旦地说,连接地址一定是用base64编码的,因为根据我的经验,无论快车,迅雷,旋风的专用链都是用base64编码的,他说,那你就试试看啊!

哼,打开熟悉的eclipse之后就立即开始破解,简单的几行代码之后

 import sun.misc.BASE64Decoder;
  
 public class Fs2you {
  // 将 s 进行 BASE64 编码
  public static String getBASE64(String s) {
   if (s == null)
    return null;
   return (new sun.misc.BASE64Encoder()).encode(s.getBytes());
  }
 
  // 将 BASE64 编码的字符串 s 进行解码
  public static String getFromBASE64(String s) {
   if (s == null)
    return null;
   BASE64Decoder decoder = new BASE64Decoder();
   try {
    byte[] b = decoder.decodeBuffer(s);
    return new String(b);
   } catch (Exception e) {
    return null;
   }
  }
 }

之后做了一个测试:

原地址:

fs2you://Y2FjaGVmaWxlMTEucmF5ZmlsZS5jb20vemgtY24vZG93bmxvYWQvYmY4NGRhZjY5MzQ2ZGE2NDdmOWE1YzE0MzU1N2Q4OWYvMiUyMC0lRTYlOUMlQUElRTYlOUQlQTUlRTMlODElQjglRTMlODElQUUlRTYlODklODklMjAlRUYlQkQlOUUlRTMlODElODIlRTMlODElQUUlRTUlQTQlOEYlRTMlODElQUUlRTYlOTclQTUlRTMlODElOEIlRTMlODIlODklRUYlQkQlOUUlN0UlMjhPcmlnaW5hbCUyMEthcmFva2UlMjkubXAzfDQyNjgxNjU=

真实地址:

首先将原地址头”fs2you://”去掉,然后用程序解码,得到不带”http://”的后半段真实地址,显然,感觉十分良好,初步成功了,然后我打开旋风2尝试下载。结果十分沮丧,很快就”叮”的一声,下完了,得到长度为134B的文件,显然不是要下载的文件,阶段性失败。

不过在这个时候,脑里突然闪出了一件事,前天某咪说在博济里面下载东西要设置迅雷的,好采当时做了一下实训,设置过程还有印象,于是我尝试在旋风里面做同样的设置,我很兴奋,以为网管们就这么几招,我再次尝试,但是!!没用的旋风还是很快的叮了一声,再次得到134B的无用文件,又失败了。

我以为这个134B的文件可能有用,不过它的后缀依然是.mp3,我将它改成了.html结尾,再次打开,浏览器立即跳转到fs2you的首页,我再将它改成.txt结尾,一看,原来是很简单的<meta>关于refresh的代码,

<HTML><HEAD><meta http-equiv=”Refresh” content=”1;url=http://www.rayfile.com/files/e4ad4a525e1e5e43f430b10764d00635/1/”></HEAD></HTML>

没任何作用,至此,我很肯定是服务器检测到我的下载软件有问题,或者说不是用它专用的下载器下载,然后就扔了这个垃圾文件给我。

接着,我开了自己编的数据包截取器,得到如下数据:

1253545391:305316 /192.168.1.103->/218.75.151.4 protocol(6) priority(0) hop(128) offset(0) ident(29838) TCP 53124 > 80 seq(2487998415) win(8192) S

1253545391:306676 /192.168.1.103->/124.115.0.182 protocol(6) priority(0) hop(128) offset(0) ident(29839) TCP 53123 > 443 seq(3957074316) win(8192) S

1253545391:400766 /218.75.151.4->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(0) TCP 80 > 53124 seq(265189548) win(5840) ack 2487998416 S

1253545391:400930 /192.168.1.103->/218.75.151.4 protocol(6) priority(0) hop(128) offset(0) ident(29842) TCP 53124 > 80 seq(2487998416) win(16560) ack 265189549

1253545391:411322 /192.168.1.103->/218.75.151.4 protocol(6) priority(0) hop(128) offset(0) ident(29843) TCP 53124 > 80 seq(2487998416) win(16560) ack 265189549 P

1253545391:416760 /124.115.0.182->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(0) TCP 443 > 53123 seq(1757360990) win(5840) ack 3957074317 S

1253545391:416907 /192.168.1.103->/124.115.0.182 protocol(6) priority(0) hop(128) offset(0) ident(29844) TCP 53123 > 443 seq(3957074317) win(16560) ack 1757360991

1253545391:423941 /192.168.1.103->/124.115.0.182 protocol(6) priority(0) hop(128) offset(0) ident(29845) TCP 53123 > 443 seq(3957074317) win(16560) ack 1757360991 P

1253545391:482756 /218.75.151.4->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(27748) TCP 80 > 53124 seq(265189549) win(27) ack 2487998949

1253545391:502806 /124.115.0.182->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(28817) TCP 443 > 53123 seq(1757360991) win(1728) ack 3957074693

1253545391:508741 /124.115.0.182->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(28818) TCP 443 > 53123 seq(1757360991) win(1728) ack 3957074693 P

1253545391:524465 /192.168.1.103->/124.115.0.182 protocol(6) priority(0) hop(128) offset(0) ident(29848) TCP 53123 > 443 seq(3957074693) win(16526) ack 1757361125 F

1253545391:644862 /218.75.151.4->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(27749) TCP 80 > 53124 seq(265189549) win(27) ack 2487998949 P

1253545391:646798 /218.75.151.4->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(27750) TCP 80 > 53124 seq(265189702) win(27) ack 2487998949 F

1253545391:646893 /192.168.1.103->/218.75.151.4 protocol(6) priority(0) hop(128) offset(0) ident(29850) TCP 53124 > 80 seq(2487998949) win(16521) ack 265189703

1253545391:656606 /192.168.1.103->/218.75.151.4 protocol(6) priority(0) hop(128) offset(0) ident(29851) TCP 53124 > 80 seq(2487998949) win(16521) ack 265189703 F

1253545391:664758 /124.115.0.182->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(28819) TCP 443 > 53123 seq(1757361125) win(1728) ack 3957074694 F

1253545391:664864 /192.168.1.103->/124.115.0.182 protocol(6) priority(0) hop(128) offset(0) ident(29852) TCP 53123 > 443 seq(3957074694) win(16526) ack 1757361126

1253545391:716762 /218.75.151.4->/192.168.1.103 protocol(6) priority(0) hop(57) offset(0) ident(0) TCP 80 > 53124 seq(265189703) win(27) ack 2487998950

1253545392:188729 /192.168.1.103->/58.61.164.228 protocol(6) priority(0) hop(128) offset(0) ident(29857) TCP 53126 > 443 seq(2066269166) win(8192) S

1253545392:216758 /58.61.164.228->/192.168.1.103 protocol(6) priority(0) hop(56) offset(0) ident(0) TCP 443 > 53126 seq(2310667683) win(5840) ack 2066269167 S

1253545392:216918 /192.168.1.103->/58.61.164.228 protocol(6) priority(0) hop(128) offset(0) ident(29858) TCP 53126 > 443 seq(2066269167) win(16560) ack 2310667684

1253545392:222867 /192.168.1.103->/58.61.164.228 protocol(6) priority(0) hop(128) offset(0) ident(29859) TCP 53126 > 443 seq(2066269167) win(16560) ack 2310667684 P

1253545392:264769 /58.61.164.228->/192.168.1.103 protocol(6) priority(0) hop(56) offset(0) ident(10874) TCP 443 > 53126 seq(2310667684) win(7672) ack 2066270263

1253545392:264869 /58.61.164.228->/192.168.1.103 protocol(6) priority(0) hop(56) offset(0) ident(10875) TCP 443 > 53126 seq(2310667684) win(7672) ack 2066270263 P

1253545392:280160 /192.168.1.103->/58.61.164.228 protocol(6) priority(0) hop(128) offset(0) ident(29861) TCP 53126 > 443 seq(2066270263) win(16544) ack 2310667746 F

1253545392:306739 /58.61.164.228->/192.168.1.103 protocol(6) priority(0) hop(56) offset(0) ident(10876) TCP 443 > 53126 seq(2310667746) win(7672) ack 2066270264 F

1253545392:306846 /192.168.1.103->/58.61.164.228 protocol(6) priority(0) hop(128) offset(0) ident(29862) TCP 53126 > 443 seq(2066270264) win(16544) ack 2310667747

期间与三个服务器发生通信:

218.75.151.4、124.115.0.182、58.61.164.228

最后与58.61.164.228通信完毕以后就下载完毕了,我猜测大概这134B的文件就是从这个地方扔来的,前面两个应该是fs2you的服务器,过程应该是,经过这两个服务器检测发现非法下载方式以后就转到58.61.164.228让它来给我们扔垃圾。

没计,所有的东西几乎都研究了一遍,什么东西都没有发现,突然想起,志伟开始的时候用fs2you下载,没次下载之前都会比一般下载软件要慢一些才有速度的,我想,大概问题就在这里了,fs2you一定是先发一些验证数据包给服务器,然后服务器验证通过以后才打开闸门放数据,如果直接请求文件数据的话,服务器就拦截,然后通知58.61.164.228放垃圾,这样,要解决这个问题,就只有一个办法,把fs2you发送的验证数据包截取下来,写成文件,然后每次下载文件前,先发送这些数据包,然后再立即下载文件,应该就没问题了,不过,如果这样做就像自己写一个仿fs2you的软件,这样就浪费脑力,所以,最终就这样放弃了…

Java 是否真的即将被取代?

对于最近有关 Java? 即将退出历史舞台的传言,您可能想知道在这个时候放弃使用 Java 平台并转而使用更新的技术是否时机成熟?在作出您的判断之前,请先回顾并查看一下 Java 生态系统以及它的竞争者,看看这些传闻是否站得住脚。换而言之,了解整个 Java 世界目前的现状,并客观公正地评判这个平台。

在学生时代,我们可能会想起 Thomas Malthus 所做的预言,他认为人类赖以生存并继而形成人类文明的农业体系,可能无法再承受人口数量的不断攀升,另一方面,这种情况将不可避免地造成严重的后果,通常会引起巨大的灾难或其他自然灾害。他这样写道:若对人口数量不加限制,将呈几何级数增长。而人们赖以生存的物质则以代数级数增长。与后者相比较,如果稍微了解一下这些数字,就会意识到人口增长是多么惊人。这意味着,针对生存物质的匮乏,需要对人口增长进行严格而持久的控制。物质匮乏终究会发生在某些地方,并且必定会严重影响到大部分人类。

Thomas Malthus 在 1798 年发表了 “人口论”(参见 参考资料)。从那时开始,我们一直在等待着验证有关人口增长的 “Malthusian 检验”。

编程人员,特别是使用 Java 平台和语言的人员,可能已经注意到,随着使用难度不断增加,人们的种种预测和统计暗示着他们所选择的平台即将没落。而大量候补接任者跃跃欲试:人们提名 .NET、Ruby 甚至是 Python 作为 “下一代重要技术”。

这两种 “Malthusian 学说” 之间存在着惊人的相似之处。

Malthus 认为,由于食物对人类的生存非常重要,而地球的产出有限,并且繁殖所需的生物体系是不会改变的,我们终将达到一个极限,那时地球将无法承受人口负担。换句话说,如果继续以现在这样的方式生存,将注定灭亡的结局。那么在 1798,很难推翻 Malthus 的学说。

同样,在过去十八个月中,Java 社区出现了一种新趋势:即预测 Java 平台的消亡日期。从一些低级的新闻杂志将其称为 90 年代的技术,到夸大其辞的技术演讲者宣传它的现状,再到各种书籍宣称我们正在 “超越” Java 时代,不难发现一点:通过合理的暗示、代码演示、逻辑或统计性说明,Java 正在走向没落。

Malthus 忽略的是那个时候正兴起的工业革命。在 Malthus 一生中,他能够目睹到人类农业生产力的巨大飞跃,这要感谢蒸汽机和轧棉机这些发明。这些发明为他的学说提供了必然的“缺少的一环(missing link)”,它们使粮食产量成倍增长,从而使农业系统能够拟制由“两性激情”制造的沉重的人口负担 。随后,人口控制方面的技术创新对降低人口增长起到了相同的作用,减轻了人口负担,从而造成了很多西方国家出现人口 增长,因此情况与 Malthus 的相当合理的逻辑完全相悖。而所有这一切在 Malthus 撰写其论文时是无法预见的,使人类能够超过他所预测的农业系统的承受极限而继续存活,并且避免了由此而来的一系列灾难。

而技术批评家所忽略的则是 Java 虚拟机的替代语言的兴起引发了巨大的变化。不过不要轻易相信我的一家之言,让我们逐一查看支持这种说法的论证,看看它们是否站得住脚。

Malthusian 式的 Java 预测

一些人仅仅引用了一些统计性描述,说明 Java 不再是程序员中最重视的语言,就简单的判定 Java 已经在走下坡路。其他人指出 Java 缺乏其替代环境所提供的某些特殊特性,这些特性被标榜为用户及其应用程序的 “需求”。还有一些人发表(毫无事实依据)诸如 “大企业不会再使用 Java” 等言论,从而明确地暗示,如果大企业不使用 Java,那必定是因为这种技术不值得使用。

Java 语言,从更大的程度来讲,Java 平台及其生态系统,很早以前就超过了 Simon Peyton-Jones 所谓的 “生存阈值(The Threshold of Immortality)”,就像 C++、C、COBOL 和其他语言所经历的一样。这些工具几乎可以永远存在下去,这是因为它们将继续提供有用的功能,或者是因为重写代码的尝试可能要比继续按原样使用和维护系统付出更多的代价(有关特定语言或系统究竟属于这两个原因的哪一种,存在很多的争议,而这对于本文的目的则无关紧要)。

另一个论据让所有聪明人都放弃 Java 而转向平台 X 或语言 Y。在 2005 年的一篇 BusinessWeek 文章 “Java? It’s So Nineties”(参见 参考资料)中,引用了很久以前就倒闭的应用服务器公司 NetDynamics 的前 CTO Peter Yared 的话,“Java 像恐龙一样古老”。可是,还未来得及搞清楚利益冲突和推理逻辑,这篇文章就写到 Yared 所有的公司正在尝试在 LAMP(Linux?/Apache/MySQL/P-language)栈之上重新创建应用服务器体验。

(这样做可能有些无礼,但我还是要指出 Ruby 的构想实际上早于 Java,同样还包括 Perl 和 Python,更不要说 Linux、Apache 和 MySQL……这里我就不便再多做解释了)。

引用我喜欢的一部电影,“生活是痛苦的,殿下。持不同观点的人一定有所企图”。或者,为了更恰当地解释这个主题,可以这样说:“过渡到一个新的平台是痛苦的,CTO 先生。持不同观点的人一定有所企图”。也许并不令人惊讶,对于一些已经重新定位到其他技术领域的 Java 专家来说,情况确实如此。

来看看另一个论据,它说 “Java 的顶级语言的位置已经不保,因此它的衰退必定非常悲惨,因此最好避开这场灾难”。这种论据所依据的是一个最基本的前提,即如果 Java 不再是世界上最畅销的技术,则不值得再提供该语言的支持。而这种说法若经过逻辑推理,则根本毫无道理。

统计信息很久以来一直被认为是不可靠的(如果使用不当的话),正如 Benjamin Disraeli 的巧妙解释,他说:“世界上有三种谎言:谎言,诅咒和统计”。统计信息可以用来论证最靠不住脚的论据,只需要根据论据仔细挑选所需的统计信息。注意 BusinessWeek 一文中使用的引用:“调查……显示 Java 的使用逐渐没落,而 LAMP 和 Microsoft? 的 .NET 技术势头强劲”。喔,听上去情况不妙。但是,请继续读下去,“根据 Evans 的秋季调查显示,在北美使用 Java 作为其首选编程语言的开发人员的比例已下降到 47.9%,而 2002 年秋为 51.4%”。因此,在过去六年中,在使用 Java 作为其首选 编程语言的开发人员中,使用率下降了 3.5 个百分点。

请注意,这里使用了 “首选” 编程语言一词,这意味着开发人员自己需要区别什么是他们的 “首选” 语言。考虑到大量的 XML 配置,使用 Spring/Hibernate/JSP Java 栈的开发人员可能可以很好地判断出 Java 不再是他们的首选语言。

注意过去六年中 Java 平台之上兴起的动态语言(Jython、JRuby、Groovy 甚至是 JavaFX),根据我和我的同事(“No Fluff Just Stuff” 的演讲者)在 NFJS 活动的非正式投票中获得的应用数字,这些动态语言可以很轻松地解释这三个百分点的下降。

考虑同样摘取自同一篇文章的引用:“在另一份调查中,今天秋季,PHP 在北美的采用已经上升到 36.1%,而 2002 年同期为 26%。其增长速率几乎和欧洲和亚洲一样快”。考虑到这是一个不同的调查系列,它只是为了显示 PHP 的增长,而不是 Java 市场的萎缩。祝贺 PHP,但是任何研究过企业环境的开发人员都可以证明,生产软件部署并不像这篇文章的作者力图暗示的那样是一个零和(zero-sum)游戏。大型 IT 环境通常由种类繁多的工具、平台、语言和产品组成。事实上,我们几乎可以在这里实现 整合,特别是那些大型机组件。

谈到主机,事实上,COBOL 在几十年前就不再是最重要的语言了,但是,它现在仍然继续用于现金支付、转移存款、支付信用卡等业务并运行主要的金融网络,尽管很多行业权威早已经宣布了它的 “死亡”。对于本应在坟墓里腐烂的技术,这实在是不错;这使我想起 Mark Twain,当他看到家乡报纸上他的讣告时说:“先生们,关于我死亡的报道被严重夸大了。”

然而,撇开统计数字的问题不谈,第二个问题更严重:为什么仅仅因为所选的工具不是最好的就弃而不用?Java 占据软件开发的首要地位近十年,仅仅由于它 “下降” 到第二位,游戏就结束了?甚至认为仅仅因为人们的惰性就会阻止 Java 重新恢复首要语言的位置,事实是,10 个程序员里面有 4 个会继续使用这种语言,这将保证 Java 在未来几十年里仍然保持活跃的生命力。更荒谬的说法是,Java 的增长将面临急刹车,并且再也不会出现 Java 部署,然而,Java 目前在整个行业内得到了广泛的部署,这可以保证 Java 继续出现相当长的时间。

尽管 COBOL 被宣布已经死亡,但是要求使用它的人每年达到 6 至 7 位数。

检查证据

然而指出一个论点的缺点并不能证明另一个观点,对于本文也是一样的。相反地,我们应该用批评的眼光看待 Java 语言和平台,而其强项和劣势经受住了严格的分析。Java 之所以长寿在于它能满足未来十年的需求,而不是由任何作者或批评家来决定它的生死。

最后,我们考虑一下构成 Java 平台的那些组件:

  • Java 编程语言。坦率地讲,这是平台中最能体现其长寿的部分,特别是与一些诸如 C#、Groovy、(j)Ruby 或 Scala 等更 “现代的” 语言比较时。近来涌现出大量关于改善该语言的建议,诸如为该语言添加闭包等极具竞争力的提议,证明了程序员非常渴望 Java 能够具备其他语言的一些特性。然而,Java 5 中最新语言增强功能所带来的联合成功应该成为所有新的重大语言变更的“注意刹车”的提示。某些增强,比如 de style=”font-style: normal; “>forde> 循环或注释,得到(相对)普遍的支持。然而其他一些增强,比如泛型,则受到(相对)普遍的嘲笑和批评。事实是没有任何一种语言功能能得到它本应帮助的开发人员社区的普遍接受,这个事实告诉我们:为一个已存在十年多的语言添加新的语言特性是很棘手的事情,如果完成,也很可能会导致语言自身的崩溃。在 Java 平台的地图中,这个区域标注着“老水手”的警告:“此处有怪物!”
  • 非 Java JVM 编程语言。在 Java 止步不前的地方,其他语言提供改进和增强的解决方法。Groovy 围绕 Java 对象提供了一个动态、客观的脚本解决方案。(j)Ruby 在 JVM 之上提供 Ruby 实现,为 Java 程序员开辟了 Rails 和 ActiveRecordoffers 的世界。Scala 和 Jaskell 给 JVM 引入了函数编程概念,为所出现的并发性问题提供可行的解决方案。诸如此类。由于所有这些语言要么编译成字节码,要么通过 javax.script API 作为解释语言在 JVM 上运行,因此 Java 生态系统的所有财富都是可以利用的— 而这是 Ruby 开发人员无法做出同等声明的一个方面。在 Java 平台的地图中,这个区域被标注为“机遇之国”。
  • Java 虚拟机。 幸运的是,Java 语言已经做出了重大修订和根本性的变化,而 JVM 作为 Java 平台的底层基础,变化并不多。近来,在博客世界中,许多人建议使 JVM 对动态语言更友好,这使 Sun 公司的一名工程师(John Rose)提供了 JVM 的修订版,最初称为多语言虚拟机( Multi-language virtual machine,MLVM), 现改名为 Da Vinci Machine(因为紧密地包装在代码中)。此处的关键在于被提议的 JVM 更改要避免任何有可能使 Sun 公司在 JVM 优化上的庞大投资作废的事件。那些提出建议的人在设计细节时一直将这一点牢记于心。
  • Java Standard Edition 库。 Java Standard Edition 附带了巨大的函数集,数量级比 C++ 标准库更大,甚至许多因素比它前身 Java 1.0 都大,并且这还没有考虑 Enterprise Edition 库(接下来讨论)。表面上,这看起来像 Java 开发人员的自然优势,但仔细考虑就会发现一些细微的问题。对初学者而言,库的庞大意味着许多 Java 开发人员认识不到他们在写一些实际已经存在的代码,这些代码收藏在一个在此之前未知的包中。根据存在时间的不同,库本身有时也会遇到 API 设计时间的烦恼,其中有许多 都源于 90 年代中期,那个时候开发人员设计类和库的方式与 2008 年的设计方法截然不同。一部分开发人员也深受抽象过多之苦,正如创建对象构建者的工厂所例证的一样,这些对象构建者创建的接口实例不一定能实现开发人员感兴趣的方法。然而,虽然 JSE 库有缺陷,但从整体来说 JSE 依然有优势,尤其是当它与像 Groovy 提供给 JDK 的扩展(称为 GDK)这样的语言支持增强结合时。
  • Java Enterprise Edition 库。 没有任何技术能够比 EJB 对其社区产生更大的冲击,并且幸运的是,Java 社区看到了轻量级替代方案的兴起,Spring 和 Hibernate 提供了最后的例证,对这些场景来说,轻量级替代方案是理想选择。然而,如果暂时不考虑 EJB,Java EE 库就是非常成功的 — servlets 和 servlet 容器为遍及 Internet 和企业内部网的大量 Web 应用程序提供动力,JMS 提供对多种面向消息中间件系统的访问,JEE 领域中其他不太知名的参与者(如 JNDI) 毫无怨言地执行自己相应的任务。JEE 库很有可能受益于 API 重新设计,JSE 库就是这样,总体来说 JEE 库将满足 Java 程序员的需要。最大的问题往往在于认识何时首先需要 JEE 库。我们将在另一篇文章中讨论相关内容。
  • Java-API-for-XML (JAX) 库。 尽管名义上是 JEE 库的一部分,但 JAX API 的数量和规模都在以与 JEE 其他部分不相称的速率增长,值得脱离 JEE 的上下文来考虑 JAX API。在近十年,尽管对 XML 支持的需求是巨大并且普遍的,但目前已经有所缓解,尤其是 Web services (WS-*) 周边领域和规范阵营(这些规范允许与其他技术之间实现普遍、轻松的互操作,包括 .NET)。在这里,Java 无疑需要某种类型的修订,由于 SAX、DOM 和 StAX API 经常需要更多的代码来完成重要任务,尤其是和具有更灵活的 XML 支持的语言相比时,比如 E4X、Ruby 或 Scala。此处,以 XML 为中心的思想有了明显的改变,从早期的 WS-* 实现中“不接触 XML”到基于 RESTful 方法的“我希望直接接触 XML 并将其定址为形式良好、有意义的 URI”,这种方法也强调了 JAX 领域内重构的必要性。在 Java 世界的地图中,这个区域被标注为“(应该)弃用的”。
  • 客户端 Java。Sun 公司最近修订的“Java客户端”系统的测试版有个相当糟糕的名字 “Java SE 6 Update 10 Beta”,它提供了增强的客户端特性,包括新的 Swing 外观,称为 Nimbus。遗憾的是,在客户端度量 Java 的使用一直都存在问题,主要是因为专门用于度量的 applet 在 Internet 上已经使用了很长一段时间,还因为众多对 Web 托管应用程序的设计和架构关注点都以 HTML 的生成为中心,而不是生成现在所说的“富客户端”应用程序。随着采用速率的提高,Java 要经过漫长的旅程,追赶它在这个领域中的主要竞争对手,Flash 和微软在该领域新引入的技术 Silverlight 使情况变得更加复杂。Java 可能也会彻底失去阵地,这并不代表着这种平台的“消亡”,但会使问题恶化,当业内学者和商业杂志将其称为“Java 技术弱点的明显例证”时,一定要鼓舞自己!
  • 服务器端 Java。 这实在不容争议:Java 毫无疑问是服务器领域内既定的参与者,特别是在查看非 Windows? 后端系统环境的选项时。LAMP 系列产品可能提供一个前端或垂直竖井的替代方案,包括 Ruby on Rails 也是一样,但观察重要的服务器计算基础设施时,Java 系列产品将占据显著的位置。事实上,正是这种领先地位促使微软最先积极地寻求 WS-* 规范,以使 .NET 代码至少能调用和配合既定的 Java 基础设施。微软最近认可了使互操作性向更正式的水平发展,他们在剑桥大学设立的“Interoperability Lab”也体现了这一点。
  • 生态系统。 没有其他的平台拥有像 Java 平台一样如此丰富多样的生态系统,然而这经常会给 Java 开发人员带来一些麻烦(“我该使用哪种 Web 框架?”),事实上,很多 Java 生态系统都渗入其他环境,尤其是.NET。考虑 .NET 近来在微软内外获得的进步:ObjectBuilder(依赖性注入框架)、ASP MVC(基于 MVC 的 Web 框架)、NHibernate(Hibernate 的一部分)、NAnt 和 MSBuild(在句法或概念上与 Ant 相似的基于 XML 的构建系统)甚至 Silverlight 本身(在浏览器内部托管 CLR,允许执行更丰富的客户端)。在许多方面,.NET 生态系统为 Java 社区做了将近五年的后盾,因为 .NET 开发人员发现了与 Java 开发人员在五年前遭遇的相同痛点。而 Java 仍然坚持向 .NET 社区学习(比如统一通信 API 的有用性或显式轻量级工作流引擎的强大力量)。这只用来说明这些环境都正在互相学习这一事实,而且也表明,.NET 并没有使 Java 成为不必要的能力。

毫无疑问,Java 开发人员可以将他们自己的条目添加到这个列表中,证明这个论点:在 Java 平台中留有太多的优良的东西被认为“死亡了”或“将要死亡”或者甚至在“崩溃的边缘”。

王者终将归来

最简单的事实是:Java、平台、生态系统、环境和开发社区与死亡相去甚远,至少和目前正在使用的其他语言或平台距离一样远。即使是最严格的统计事实筛选也不能否认 Java 的领先地位。

此外,即使 Sun Microsystems 公司倒闭,平台也不会消亡。全世界的 Java 开发人员,联合起来!不要惧怕束缚的铁链:最终您将看到,这些铁链其实并不存在。多亏 Java 平台的开源,它现在被称为 OpenJDK,更不要说 Java 的其他开源“净室(clean room)”实现(Apache Harmony 和 Soy Latte 只是其中之二),即使 Sun 公司彻底从地球上消失,包括 IBM?、Apache、BEA 和 Oracle 在内的其他实体也能继续提供 JVM、库和工具,来支持整体生态系统。

Java 总有一天会消亡?绝对会的,但是我坚信 Java 的寿命会超过今天的程序员所使用的大部分语言,正如 COBOL 做到的那样。它甚至能比刚刚走出大学校园的第二代 Java 程序员走的更长。

“恐龙”,确实如此。