﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-Venus神庙</title><link>http://www.cnblogs.com/duguguiyu/</link><description>The flying fly is flying in the high and big sky...</description><language>zh-cn</language><lastBuildDate>Thu, 28 Aug 2008 09:54:01 GMT</lastBuildDate><pubDate>Thu, 28 Aug 2008 09:54:01 GMT</pubDate><ttl>60</ttl><item><title>Doxygen简单经验谈。。。</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/06/29/1231852.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Sat, 28 Jun 2008 18:13:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/06/29/1231852.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1231852.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/06/29/1231852.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1231852.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1231852.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;"><a title="Doxygen" href="http://www.doxygen.org/" id="bi2l">Doxygen</a>，
大名鼎鼎的文档生成工具，被Boost、OpenCasCade等诸多项目作为文档生成的不二人选。人说，才华横溢往往是高深莫测，这句话放在
Doxygen这里显然是不适用的。十八般武艺样样精通的Doxygen，却十分的简单易用，从头到尾看一下它随机的文档，想不会用都难。。。<br id="ykrp" />
嫌看英文麻烦的，这里有一篇中文的<a title="入门介绍" href="http://www.fmddlmyy.cn/text21.html" id="vi4j">入门介绍</a>。
简单的说，如果你准备在项目中采用Doxygen作为文档生成的工具，首先，你需要了解，Doxygen需要什么样的代码结构才能够生产文档。
Doxygen基本上对光秃秃的代码不感兴趣，你需要在所有的类、函数、成员函数、公共变量、名字空间等代码已有表示的结构上方添加上指定格式的注
释，Doxygen才能识别出来。此外，你还可以按照指定格式的注释添加附加的信息，用以生成模块的分类，架构图之类的信息。Doxygen支持的注释格
式多种多样，强烈建议制定一个统一的标准，否则会给项目中其他的人员或者后来的人员带来很多的困扰。。。<br id="e.nj" />
按照指定的格式书写了注释之后，就需要写一个Doxygen的配置文件，依照此配置文件，Doxygen可以生产HTML、Tex、XML等多种格式输出
文档。Doxygen的配置文件，有辅助的GUI工具帮助书写，你只需要改几个选项，点几下按钮就信手拈来了。但在此强烈建议，你应该把Doxygen每
一个配置值的含义都了解一下，写一些简单的例子实践一下，这样一则你可以清楚的明白你需要的格式该如何配置出来，二则你可以充分了解Doxygen可以做
到什么程度，以备不时之需。。。<br id="g2:8" />
Doxygen通常是用作生成英文文档的，生成中文文档需要修改输入和输出的码制，这样可以改变解析方式，生成中文文档。但是，你必须意识
到，Doxygen在从注释中抽取信息是需要做语法解析的，这些解析都是基于英文的基础，不可能在这个层面上支持中文。比如，一个类的简明信息和详细信息
的分隔，是通过英文的句号&#8220;.&#8221;来识别的，如果你用中文的句号&#8220;。&#8221;，Doxygen就分辨不出来了。再比如，在某个类的注释中，你写 Created
by xxx
function，其中xxx是某个方法名，Doxygen会在生成的文档中，自动为该函数添加上链接。当如果你用中文：该类是被xxx方法构造出来的。
Doxygen就无法抽取出该信息并添上链接。你要按如下格式来写：该类是被 xxx
方法构造出来的。用强行的人肉空格帮助Doxygen。所有类似的问题都可以以此类推。。。<br id="ydak" />
我们说，Doxygen无法识别光秃秃的代码信息，这并不意味着代码结构对Doxygen来说不重要。Doxygen可以对各种语言书写的代码进行优化，
比如你开启C++代码优化后，Doxygen会解析你写的C++代码，添加更多更具体的信息，并依照之间联系为你添加链接。这也就是说，Doxygen会
产生真实的代码结构表示出来的东西，你在写注释的时候也应该按照严谨的代码结构去写。比如，你在某个类A的注释中写道：此类用到了 B
类中的方法。假设B这个类，在名字空间N1内，如果，你的A类同样也是在N1内，这个链接Doxygen会为你自动添加，但是，如果B这个类在名字空间
N2内，Doxygen会无视你的请求。你必须严格的写它的全名 N2::A，Doxygen才会欣然接受这个娃。。。<br id="xj6x" />
我在做的项目比较小，因此我利用Doxygen的ToDo-List和Bug列表对项目进行简单的管理。比如，有一个类你有一些后续的工作没有完成，你可
以在其注释中加上@todo xxx，（这只是其中一种语法，不是唯一的规范...）Doxygen会将其链接添加到一个to do
list中，并为该to do list生成一个页面，查看起来颇为方便。同样，Bug标记也是这么用这么看的，举一反三大家都会，我就不多磨叽了。。。<br id="bh00" />
Doxygen中利用到很多第三方的基于编译的信息生成工具，辅助生成更为炫目的文档。比如，你可以在注释中嵌入符合tex标准的公式，Doxygen帮助你把这些显示到你的文档中来；你还可以为你的文档自动生成继承图，组合图，UML格式的图，等品种齐全的图，只要你把<a title="Graphviz" href="http://www.graphviz.org/" id="es_4">Graphviz</a>装
上，并打开相关参数即可。更漂亮的是，利用Graphviz的dot方法，你可以将符合其格式的画图指令写在注释中，场景图，架构图，流图，交互图，隔壁
校长含泪跳楼图，只要你能用Graphviz画出，Doxygen都能给你用上，图例想改就改想变就变，幸福生活，不过尔尔。而关于Graphviz，<a title="g9老大已经推荐" href="http://blog.csdn.net/g9yuayon/archive/2008/06/21/2574781.aspx" id="gb1c">g9老大已经推荐</a>过
了，再多的好话也就显得苍白。这东西无疑是好东西，方便的一塌糊涂，对于常年和代码打交道对直观之物缺失判断的程序员而言，这无疑是居家旅行杀人必备的水
果刀。但要把水果刀玩的和关公大刀似的，是需要不俗功力的，像我这样三脚猫的功夫，就只能关注功能而无法挑战美观了。。。<br id="xfvn" />
其他的信息，比如author，date，group，之类的，我都会要求写注释的时候加上，举手之劳，可以方便很多后续可能出现的问题。每一个简单到无
需注释的函数，也要加一个空的注释头，以便生成文档的时候，所有的方法都齐备；如果有需要，你可以修改配置文件的设置，把代码也绑定进文档，这样别人只要
拿着文档一看，几乎就完全不用在添一份代码放在手上了。。。<br id="d5.o" />
把文档与代码绑定在一起，这是用Doxygen之类工具的一个好处，它至少可以产生两个方面的生产力。一方面，它可以帮助你构建结构良好的文档，生成真正
可看好看的文档来；另一方面，它可以刺激你更新文档，把文档工具当作项目管理工具用起来。当然，如果文档就在你写的代码上面两行你都懒的看一眼，那么，啥
工具也挽救不了了。用这类工具，必须要文档代码配合着写，配合着看，把它提升到和写单元测试一个习惯级别来，看一眼注释，写一段代码，然后测一测，改改过
期注释，就像蘸酱卷饼吃黄瓜一样一气呵成，那么，Doxygen就可以今夜做梦也会笑了。。。<br id="m8d0" />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1231852.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41940/" target="_blank">[新闻]惠普139亿美元完成对EDS的收购</a>]]></description></item><item><title>Android大赛首轮获奖作品解析。。。</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/05/18/1201693.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Sat, 17 May 2008 16:41:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/05/18/1201693.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1201693.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/05/18/1201693.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1201693.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1201693.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">Android挑战赛第一轮<a title="前50的作品" target="_blank" href="http://android-developers.blogspot.com/2008/05/top-50-applications.html" id="i3_h">前50的作品</a>公布出来了，除了有4个暂时希望保密，<a title="其他46的介绍" target="_blank" href="http://code.google.com/android/images/adc1r1_deck.pdf" id="fnwk">其他46的介绍</a>都已放出。虽然我大大的名落孙山之后，但不妨碍翻看这些作品，尝试思考一些手机应用的问题，尽情期盼下明天。这些作品，是由<a title="上百位领域专家" target="_blank" href="http://code.google.com/android/adc_judges.html" id="g-r6">上百位领域专家</a>，经过一套<a title="还算复杂的流程" target="_blank" href="http://feeds.feedburner.com/%7Er/blogspot/hsDu/%7E3/289628814/challenge-in-more-than-one-way.html" id="mwh2">还算复杂的流程</a>评
选出来的。我想，从中不仅仅可以看到Android的发展方向，也可以看到手机应用的一个发展趋势。如果你想在Android这块地盘上分一碗羹，或者，
期望在手机应用领域有所建树，也许，你应该去看看这些作品。于是，管中窥豹了一圈，准备扯一点，但我未做过正二八经的手机开发，对手机应用的见识十分浅
薄，期待讨论，严重的。<br id="r2hv0" />
<br id="kf:u0" />
<p id="r2hv1" style="font-weight: bold;"><font id="r2hv2" size="5">所谓手机</font></p>
如果你还只是把手机看成打电话发短信的家伙，那么手机应用早不需要研究了。手机应用不但超越了打电话发短信如此本质的应用，并且已经翻过了拍照，听歌，玩单机游戏的境界，开始向各式各样的网络应用发展。这次获奖的作品中，基本所有的程序或多或少都和网络拉上了关系。。。<br id="i0yf0" />
我觉得这个问题要从多方面看。首先是手机硬件和无线网络越来越强大，而这正好能和用户用来用强的信息处理需求相匹配。<span id="udqh0" style="font-weight: bold; text-decoration: underline;">网络的使用能满足膨胀的信息需求</span>，它像一个永不熄灭的活火山永远孜孜不倦的喷涌着各式各样的全新信息。<span id="udqh1" style="font-weight: bold; text-decoration: underline;">网络也架设了一条更强大的人与人沟通的跨海大桥</span>，传统的短信服务在其面前，只能算是一根过小溪的独木桥。。。<br id="sxdp0" />
从另外一个角度看，网络的使用，<span id="udqh2" style="font-weight: bold; text-decoration: underline;">也为更好的商业模式铺平了道路</span>。虽然，与单机相比，手机上有稍微方便的付费方式（通过运营商...），但是，杯水车薪，解不了众人之渴。Google在web上做了一个活体的吸金机标本，移植过来，是自然而然的想法。。。<br id="v3z20" />
<br id="qniz0" />
<font id="h4qe0" size="5"><span id="h4qe1" style="font-weight: bold;">手机的优势</span></font><br id="lkf:0" />
如果有一天，正如Google所期盼那样，手机真的可以随时在线了。下一个问题就应该是，手机的优势在哪？电脑与之相比，运算速度快，存储量大，网速快，屏幕大等等优势是显而易见的。但同显而易见的，是手机具有<font style="text-decoration: underline;" id="yptx0" size="2"><span id="yptx1" style="font-weight: bold;">便携性</span></font>（并开着机...），24小时<font style="text-decoration: underline;" id="yptx2" size="2"><span id="yptx3" style="font-weight: bold;">随身相伴性</span></font>和<font id="yptx4" style="font-weight: bold; text-decoration: underline;" size="2">及时性</font>，等。在这次大赛中，优秀的获奖作品，很多，都充分的挖掘了这些优势。。。<br id="dymd0" />
当然，我们也不要忘了Android为手机带来的一些东西。<span id="a2h40" style="font-weight: bold; text-decoration: underline;">随时在线</span>的基础，一定的<span id="a2h41" style="font-weight: bold; text-decoration: underline;">硬件门槛</span>，<span id="a2h42" style="font-weight: bold; text-decoration: underline;">Google Map</span>和<span id="a2h43" style="font-weight: bold; text-decoration: underline;">Google XMPP</span>的引入，无疑都为很多很酷的应用提供了基础。。。<br id="f35v0" />
<br id="f35v1" />
<font id="oo:l0" size="5"><span id="oo:l1" style="font-weight: bold;">即时处理</span></font><br id="q0_l0" />
如果有一天你在街上看到一个中意的商品，你会怎么办？如果你觉得价格偏高？如果你不确定内容是否喜欢？如果...？AndroidScan和goCart
这两个作品为你带来了新的模式。你通过相机拍下商品的条形码，软件会自动识别，并从网上为你找来商品详细的图文介绍，甚至还有一小段介绍视频、音频之类
的；同时，还能够为你提供此商品在其他地方的售价，配上Google Map，它甚至能够告诉你你附近哪家店卖的比这家便宜。。。<br id="e9vf0" />
这样的快捷模式，放在家里的电脑不能给你，拍回家给LP参考的照片也不能给你，只有手机能够及时的处理这样的信息，为你提供全新的体验。这不是为谁做广
告，只是我觉得很cool，稍有点激动。用到这个特点的还有很多，比如Jigsaw可以快速的整理黑板上的数据（当然还是需要拍照片...）将它发给朋
友，PicSay可以让你拍下照片填上一两句话，立刻上传到网络上或者与朋友分享。这样的工作，你原来都需要回来家用电脑处理处理才能做到，通过随身携带
的手机，你可以把流程加速。。。<br id="m6n20" />
关于这点，我觉得还有很多可以挖掘的，比如对音频、视频的即时处理、更多更酷的图像处理等等，以此为入口，可以扩展成SNS，社会化网络，新搜索引擎之类的，这个方向之前没有很好的意识到，现在觉得，也许还真的大有可为。。。<br id="zx9g0" />
<br id="byeq0" />
<font id="byeq1" size="5"><span id="byeq2" style="font-weight: bold;">让我知道你在哪里</span></font><br id="q0_l1" />
<span id="vc_o0" style="font-weight: bold; text-decoration: underline;">Google Map + GPS + 随身携带的手机</span>，
这意味着什么？有了GPS（或者其他能获得你具体位置的方式，作为手机的一个部件存在）和随身携带的特点就可以随时更新地理位置信息，有了Google
Map（加上其他一些专业的网站，比如天气预报...）就可以了解这个位置所有可能需要了解的信息。在放出的46件作品中，<span id="vc_o1" style="font-weight: bold; text-decoration: underline;">有27件用到了Google Map</span>。
想创意的时候我说，这是一个火热的方向，不要趟这堆浑水，但我没想到能热成这样，能有那么多应用被琢磨出来。比较直白的，当你来到一个陌生地方的时候，城
市导航、叫车服务、天气提醒、旅程的安排、美食计划等等，都有应用及时为您送上。这样的内容，可能是不认识的朋友，通过社会化了的网络为你打造。在此基础
上，有很多潜在的信息也被挖掘出来，比如有应用帮你计算出这个地域的安全信息，帮助你保护家人；当你家人所在的区域遇到紧急天气情况的时候，会及时通知
你；当你有朋友来到你这个地方的时候（或你前往某个城市想查看这里的朋友），你也会被通知到；当你所处的位置发生改变，你的手机配置也会发生变动，使你不
会遭遇领导讲话手机铃声响起的尴尬；还有真实信息的友人信息的交流和游戏；基于地理位置的定向的广告投放等等。。。<br id="n0lx0" />
作品罗列的再多，也不会有更多的意思，如果再让我考虑做一个应用，这个方向我一定是优先考虑。我们通常在电脑上用Google
Map的时候，位置信息都是我们自己干巴巴的输入的，只有在手机上，这一维信息才真正的动了起来，不再需要手动的输入，使用越简单的应用肯定会越受欢迎
的。。。<br id="ydub0" />
<br id="ydub1" />
<font id="ydub2" size="5"><span id="ydub3" style="font-weight: bold;">沟通和协同</span></font><br id="ydub4" />
我很坚定的相信，迟早有一天我们会忘记短信。IM进驻手机占山为王是迟早的事情。短信的应用都是基于服务站的尽力转发模式，而基于互联网的，不但有更大的
带宽，更自然的接入方式，还可以进行更好的协同。因此，我们看到一些比较有特点的IM软件，比如基于手绘图片的聊天（IMEasy，这可能是唯一一个中国
人的获奖作品...），基于多媒体的聊天，都成为获奖者。Google
XMPP的提供，其实就是为了做这件事情的。而基于协同的绘图，日志安排等软件也相继出现。手机，在这里，是纯粹作为类似于电脑这样的信息处理节点的一个
便携延伸。。。<br id="nmni0" />
所以，电脑有一个，你也可以类似在手机上来一个，只要是可以消遣时间或需要及时处理的，我觉得都可以有一席之地。。。<br id="po.20" />
<br id="po.21" />
从手机的特点出发，我觉得，上面三点可以涵盖大部分的作品的特点。当然还有一部分作品，比如虚拟磁盘，基于生物信息的认证，单机概念的游戏等等，这是把手机作为一个单一机器来做的，肯定必须，但姑且不提。。。<br id="zx9g1" />
<br id="zx9g2" />
<font id="x:hd0" size="5"><span id="x:hd1" style="font-weight: bold;">聚合、SNS、社会化</span></font><br id="x:hd2" />
在我的概念里这都是web2.0的理念，将不同人创造的消息统一的推到你的面前。在我看来，搜索、聚合、社会化都一样，只不过搜索是把不规矩的信息收集起
来放在你面前，聚合是把规矩的信息推到你的面前，而社会化，是通过组织好的路径，把消息放到你的面前。我一直把SNS之类的社会化东西分成两类，一类是将
物理世界的人际关系映射到网络中来；另一类是根据人的兴趣建立一个全新的虚拟关系。我有两个离不开的SNS网站，一个是校内，一个是豆瓣。在校内，认识的
人都是我现实的朋友，或基于这些朋友扩展而来的朋友，我关注他们的生活，一切开心与不开心，如果是陌生人，我通常不会有很浓厚的兴趣；在豆瓣，大部分人在
生活中我都不认识，之所以成为好友，可能是因为一本书、一部电影、一张CD。在我看来，前者一定要做到庞大的，包含进所有朋友，我只希望用一个，使得一次
更新所有人都能够看到；而后者需要做到专业和专注，不同的兴趣在不同的网站分享（当然，网站不乐意了，他们希望他们什么都有，什么都有什么都好当然是最
好，这相当于合二为一，怕只怕，什么都有什么都不精...）。。。<br id="y80n0" />
在获奖的作品中，可以看到有很多希望通过某种兴趣来搭建的网络，比如通过共同喜好的菜，共同喜好的一段音乐，共同喜欢的一段旅途。不过，这个不是我想强调的重点。我想说，<span id="pmxr0" style="font-weight: bold; text-decoration: underline;">及时的位置信息更新，会像一根巨大的搅棒一样，加速虚拟与现实的人际关系的交融</span>，也许你们身处异地，互未谋面，因为某个兴趣相识，但某天你突然发现他来到你家门口的球场来看球了，很快认识成了真实的朋友。及时性，是这个搅棒力量的保障，手机，就会是这个搅棒的载体。当然，目前还是我YY的成果，没有任何理论支持。。。<br id="hs0j0" />
<br id="hs0j1" />
<font id="zjpu0" size="5"><span id="zjpu1" style="font-weight: bold;">差异</span></font><br id="he:o0" />
一路看下这Top50的作品。我会觉得有些想法匪夷所思，究其原因，有些可能是因为我个人的状况，更多的<span id="h3yc0" style="font-weight: bold; text-decoration: underline;">应该是因为中国与外国的经济、文化、信息化的差异所致</span>。。。<br id="ckdx0" />
在作品中，有好几个是关于汽车的管理，共同驾驶人的寻找之类，可能是因为我一个穷学生，我无法想象到这样的应用，但我更相信，这是由于中国普遍经济能力较
低，没有这类的需求；而有好几个作品是为了降低尾气而做的，环境，在中国还是一个很不受重视的方面；社会化，在这些应用中几乎是无处不在，我觉得这很重
要，但没想到如此频繁，我一直很歪曲的觉得，这是老外的倾诉欲望太强所致。。。<br id="diok0" />
总之，我觉得这Top50，要摆到中国来评，肯定会大大的不一样。而我们应该清醒的区分这种差异产生的原因，如果是因为信息化程度不同所致的，我觉得就应该及时跟上，走在前面；而如果是由于文化差异所致，就不要依葫芦画瓢，落一个东施效颦。。。<br id="i5a.0" />
<br id="i5a.1" />
<font id="sr0_0" size="5"><span id="sr0_1" style="font-weight: bold;">未来的路</span></font><br id="cid30" />
以下内容，纯属自言自语：我的Chamberlain（简单的，可以看成一个手机搜索...）最后的参赛平均分是B（每25%是一个档，B相当于前25%
至50%），除了在Effective
use里面拿了个A，在Polish，Indispensability和Originality中都是B。我想我搞错了主次关系，原来我觉得网络只是手
机信息的一个载体，搭建好平台比想好应用更重要，现在我觉得，<span id="txgw0" style="font-weight: bold; text-decoration: underline;">单机的检索应该作为网络的辅助而存在，有效的应用比平台更为重要</span>。因为网络不但可以带来更丰富的信息源，还可以带来有效的商业模式，而只有最好的应用作标签，所谓的平台才可能推广成规范。。。<br id="sr0_2" />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1201693.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41939/" target="_blank">[新闻]搜狗五笔输入法发布</a>]]></description></item><item><title>解决问题的思路beta。。。</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/05/03/1180015.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Fri, 02 May 2008 18:30:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/05/03/1180015.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1180015.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/05/03/1180015.html#Feedback</comments><slash:comments>33</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1180015.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1180015.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">最近，在波利亚GG的<a title="谆谆教诲" href="http://www.douban.com/subject/2124114/" id="cr3s">谆谆教诲</a>下，在pongba同学的<a title="循循善诱" href="http://blog.csdn.net/pongba/archive/2008/04/18/2302905.aspx" id="zqz3">循循善诱</a>下，在TopLanguage的<a title="今天我们思考系列" href="http://groups.google.com/group/pongba/search?group=pongba&amp;q=%E4%BB%8A%E5%A4%A9%E6%88%91%E4%BB%AC%E6%80%9D%E8%80%83&amp;qt_g=%E6%90%9C%E7%B4%A2%E6%AD%A4%E8%AE%BA%E5%9D%9B%E5%86%85%E5%AE%B9" id="eqts">今天我们思考系列</a>的
热情引导下，我终于痛下决心开始琢磨所谓的科学思考问题的方法。对大部分人而言，解题不是终极目的，只是希望在解题中培养的思考问题的方式能够广泛的应用
到其他领域。我依然觉得，思维这个抽象的可怕的东西，本质上还是个体化的，要因人而异，很难找到一招鲜吃遍天的套路。但其中，一些共性的东西还是可以抽取
出来，一起琢磨一起讨论一起研究，并规范化科学化。大师的书pangbo的文章和大家的讨论提供了足够的参考素材，在这里我只是写我自己这些日子来的一些
实践和思考。我混了20多年，还是一个解题白痴，可以想见，这段日子的集训也不会有质变的效果，所以写下一个beta，作为不成熟的挡箭牌。在今后的日子
里，我会继续的思考和实践，希望有一天，我可以有勇气在后面加个v1.0。。。<br id="bxr40" />
我一直以为，要想解决问题，除了所谓耐心勇气等人性方面的因素外，至少还需要两方面的储备。<span style="font-size: 12pt;"><strong>一面谓之硬件</strong></span><strong></strong>，指的是基本的知识。比如说你要设计一个算法，基
本的复杂度分析，分治法，二分法之类的知识应该需要储备起来；如果你要设计个软件架构，基本的模式，操作系统的原理，交互接口的设计也应该了解一些。不要
以为自需要很小的一点知识库，就可以像原子弹似的衍生出无限的能量，自己造轮子做汽车的生产方式，已被这个高效的社会淘汰了。牛顿GG很早就教育我们要站
在巨人的肩膀上才能站的高看得远，而如<a title="《费马大定理》" href="http://www.douban.com/subject/1322358/" id="oo7t">《费马大定理》</a>中描绘的一样，怀尔斯如果不是充分了解所有前人的思路深刻掌握许多高精尖的数学方法的话，从最原始的公理开始，我想再送他100年寿命估计也搞不定费马大定理。所以，一个人只有拥有了足够丰富的知识后，才有可能混得和机器猫的口袋似的，要啥有啥。。。<br id="c6yb0" />
<strong><span style="font-size: 12pt;">
另一面谓之软件</span></strong>，指的就是解决问题的基本思维。在<a title="《Why Programs Fail》" href="http://www.douban.com/subject/2036942/" id="ymcg">《Why Programs Fail》</a>中我<a title="了解到" href="http://www.cnblogs.com/duguguiyu/archive/2008/03/16/1108091.html" id="dbz5">了解到</a>，
调试这种貌似依靠经验和灵感的活也是可以有章可循的。与之类似，所有貌似只能靠灵感喷涌来搞定的问题，也不会是只有咣当咣当拍脑袋才能获得解决思路的。我
们需要信赖灵感，但很多时候，也可以不依靠灵感。我们有了足够的知识储备和运用知识的经验后，就像骑上了匹宝马良驹，有了一马平川奔向目的地的能力，但是
没有良好的驾驭，南辕北辙了，就算是汗血宝马估计也无奈了。。。<br id="hat40" />
从这段时间的实践来看，波利亚GG的解题框架是极具推广性的。不但在解题上会有效果，尝试推广到软件设计甚至其他方面上，也是可以行得通的。主要实践原料的来源，除了TopLanguage里面的一些题目外，还有来自<a title="《编程之美》" href="http://www.douban.com/subject/3004255/?rating=5" id="giu7">《编程之美》</a>的习题和高大爷仙书上的一些经典算法。在我这里，波利亚GG的框架被我抽取成下述样子，不过强烈建议自己去阅读原著，抽取属于自己的框架：<br id="q7a90" />
<strong><u><span style="font-size: 14pt;">
1.
首先是条件的提取</span></u></strong>。对于题目而言，就是把题设的条件一部分一部分抽取出来，然后牢牢把握住未知量，从始到终，同时，要对已有已知量是否能导出未知量有个评
估。对于其他问题而言，比如软件设计，条件就是做这个项目的一些要求和约束，未知量就是需要做到的效果，评估就是在这样的条件下能不能做到需要的效果。这
个问题说起来简单，把握起来却不容易。我在自己做题或者给别人出题的时候，我经常会发现，在做的过程中很多条件被遗忘了，或者没有被充分利用到。
pangba的一个实践方法很好，就是把所有的条件都一条条写下来，并尽可能的扩展开，毕竟，不是每个人都是欧拉。一个例子，可以看<a title="这里" href="http://groups.google.com/group/pongba/browse_thread/thread/c851bd8820a1d8f1" id="wt04">这里</a>。。。<br id="pihz0" />
<u><strong><span style="font-size: 14pt;">
2.
然后是寻找解决方案。</span></strong></u>摊开了讲，就复杂了，想了解，看书算是最好的方式。简单说，先要对题目进行归约，努力回想你做过的类似的题目。有一招就对题目转述，
我觉挺好的方式，有的东西说一下就更明晰了。比如，题目是找一组一维点中的最大距离。改下题，说找一组有序点的最大距离，问题就明晰多了。先变有序，再找
距离。而从思索的角度上看，从条件开始试错，或从未知量开始倒着做都是可以尝试的方式。有的时候，你需要把特化考虑问题，即考虑特殊的情况类推出普遍情
况，这种方式我们常用。还有一种是泛化，把特殊的问题变普遍了，不知不觉中也会常用。比如<a title="这里" href="http://groups.google.com/group/pongba/browse_thread/thread/4b7253560259dc48" id="kz-0">这里</a>的第二题，把那几个恐怖的数字抹平成了N，问题就清晰了。。。<br id="vmdh0" />
<u><strong><span style="font-size: 14pt;">
3.
做完了一定要验证。</span></strong></u>从小到大数学考试，我从来都是做完了就算，很公平，也被无数次惩罚了。验证可以是不完备的，用基本的逻辑和特例来验证一下，也可以是完
备的，用数学方法来证明。说这个就想起测试，写代码的时候，很多自以为完美无缺的逻辑，在测试下都显得脆弱不堪，所以无论如何，验证是必需的，这个懒，在
任何时候，还是不偷的好。。。<br id="t8qk0" />
<u><strong><span style="font-size: 14pt;">
4.
扩展。</span></strong></u>前面说的都很简单，客观原因大牛们已经写了很多了，主观原因我很懒。因此，这一点决定多写一点，理由是感触多些。<u>扩展，在我的定义下，有两层意思，
一个是对原有方法的改进，另一个是尝试挖掘一下为可能的问题做准备。</u>两者在实践上是一致的，因此归为一点。当你完成并验证了某个题或某件事，你还需要进一
步的反思和改进，这就是我所谓的扩展，实践包括以下几个步骤：<br />
<br id="ntmt0" />
<strong><em>
4.a.
列出所有你解决方案中用到的条件。</em></strong>这个条件和题设的条件可能是不一致的，因为你在具体解决过程中可能加入了有形或无形的约束。比如，打印一个树的前序遍
历。很有可能，你在解决这个问题的时候默认这个树是以最常见的左右链表的形式保存的，这个过程中，你就多添加了一个约束，有没有想过，如果你用穿线树的格
式存，解决方案就完全不一样了。这样的条件列举还是蛮不容易的事情，很多隐藏的条件（约束）不容易被挖掘出来，要努力的多想尽量的多列。比如做比较排序的
时候，你有没有发现，你可能添加了一个无形的约束，就是每次都是键和键直接比较，想一想，去除掉这个约束视野会更开阔的。<br id="gidf0" />
<strong><em>
4.b.
问自己一些问题，仔细思考你现行的解决方案中有没有做重复或多余或疑似复杂了的步骤。</em></strong>比如，KMP算法就是在降低一般算法的重复；再比如一题，找一个N位
二进制中的1的数目，如果你写了一个O(N)的算法，仔细想想你做了什么多余的工作呢；还比如，冒泡算法作为一种交换的排序算法，有没有做什么疑似复杂的
操作呢。<br id="cnni0" />
<strong><em>
4.c.
如果有重复步骤，尝试在原有条件不变的前提下，优化解决方案。</em></strong>比如，上面所提，找1数目的题目，你可以想到既然是找1的数目，那么应该能做到O(M)的算
法，其中M是1的个数。再继续，能不能够用一些其他策略，比如时间换空间，把算法复杂度降到常数级别呢。想知道答案，可以查看一下《编程之美》，呵呵。<br id="obno0" />
<strong><em>
4.d. 如果在原有条件上没有继续优化的空间，那么试图改变一些条件试试。</em></strong>这个条件如果是你在设计执行方案的时候添加进去的，那么这就是一个对已有的优化；如果，这个条件是题设的，那么就是对这个未知的扩展尝试。<br id="qisy0" />
<em><strong>
4.e. 在改进的过程中，你可能引入了新的约束，更新约束列表，继续尝试上述步骤。</strong></em><br id="l1px0" />
<br id="l1px1" />
最后，写个例子，我尝试按照这个思路把高大爷仙书第三卷的插入排序部分串了一下，本书的其他部分我也实践了一下，但还没有完全一体化，如果有兴趣不妨尝试一下^_^。<br id="oip70" />
<u><strong><span style="font-size: 12pt;"><u><strong>
a.</strong></u></span></strong></u> 根据打扑克牌得来的心得，设计了一个基于顺序数组存放的最最普通的插入排序，经验证正确，至此，上述1～3步的工作完成。<br id="tauv0" />
<u><strong><span style="font-size: 12pt;">
b.</span></strong></u> 提取了一下约束，包括：存储空间是连续的静态分配的；在排序的过程中，数组的前半部分是有序的；每次插入一个新元素的时候，并不能保证一定把这个元素插入到了最终位置；是基于键值比较来确定大小关系的；没有使用过多的额外空间。<br id="arnu0" />
<u><strong><span style="font-size: 12pt;">
c.</span></strong></u> 问自己一个问题，能不能提高插入的速度？很自然我们想到了二分，于是有了二分插入。<br id="pu.80" />
<u><strong><span style="font-size: 12pt;">
d.</span></strong></u> 再继续，发现在目前条件下没有太大改进空间（别说用斐波纳契分...），于是考虑改变一些条件。最简单的，如果我不保证前半部分有序，我能怎么做。于是有了二路插入，将点定在中间，减少移动次数。<br id="t10q0" />
<u><strong><span style="font-size: 12pt;">
e.</span></strong></u> 如果你和shell一样有更多的硬件储备（前面提到的，有时候是需要硬件储备的...），你会联想到去掉前半部分有序，可以运用局部化和分治的思想，于是就有了Shell排序。<br id="n_.w0" />
<u><strong><span style="font-size: 12pt;">
f.</span></strong></u> 如果，你开始问自己的问题是，能不能减少数据移动提高速度？一个答案是，改变的顺序存储，变链表，于是有了链表插入。<br id="usfb0" />
<u><strong><span style="font-size: 12pt;">
g.</span></strong></u> 能不能更快？于是，在原有基础上改变，我们添加一个哨兵指针，放在上次插入的位置。<br id="ufov0" />
<u><strong><span style="font-size: 12pt;">
h.</span></strong></u> 不要忘了，更新一下列表，我们发现添加了一个链式存储的约束，这个约束下，二分不能使用，查找速度降低。<br id="x0_j0" />
<u><strong><span style="font-size: 12pt;">
i.</span></strong></u> 自然而然，我们问自己，能不能查找又快又少移动呢？继续改变条件，还是变数据结构，于是有了树插入（又见硬件储备...）。<br id="y38y0" />
<u><strong><span style="font-size: 12pt;">
j.</span></strong></u> 想想，还有没有什么条件没有改变过。很显然，基于键的比较没变过，不能保证将元素插入到最终的位置也是一个。联想起来，能不能不基于比较基于计算，能不能尽量一次到位这样可以减少移动次数。如果足够幸运，你可以想出基于地址的排序。<br id="p5620" />
<u><strong><span style="font-size: 12pt;">
k.</span></strong></u> 其实，还有很多条件没有变过或可以继续变，有兴趣就继续下去吧：）。。。<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1180015.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41938/" target="_blank">[新闻]新学年开始 大学生适用的十大互联网应用</a>]]></description></item><item><title>Fortran与C/C++的混合开发。。。</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/04/19/1160688.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Fri, 18 Apr 2008 16:33:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/04/19/1160688.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1160688.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/04/19/1160688.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1160688.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1160688.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">最近在把一个Fortran的程序封成模块整合进一个C++的平台中。平生第一次做fortran，也算是第一次正二八经的做二进制的混合开发。简单写一些，算为前一段工作做个总结。。。<br id="bvau" />
Fortran90与C++的整合，可以基于静态链接。就是都生成obj，然后link在一起。当然也可以是动态链接的，把Fortran打成dll，然
后在C++中调用（windows下...）。当然，这都不会是本质性的问题，你可以根据需求自行抉择。在不同二进制模块中互调，更为关键的是ABI。说
英文的和说中文的总不能和谐的打成一片，要在一块玩就需要一些共同的语言。。。<br id="zzs7" />
Calling Conventions在这里显得很重要。首先就是Naming
conventions，Fortran和C++的函数名解析往往是不一样的。同样你取名叫functionA的，在C++里面（extern
"C"）编译完了可能叫functionA_，可到了fortran里，可能会叫_functionA@4。当然，这个问题并不可怕，查一下编译器的手
册，此问题即可迎刃而解。。。<br id="b2ye" />
然后是Stack considerations的问题，也就是说函数栈是由调用方管理还是被调用方管理，有兴趣的可以看下<a title="这里" target="_blank" href="http://blog.bcchinese.net/happyjet/archive/2005/05/24/22545.aspx" id="i9ze">这里</a>，同时在fortran中，参数的默认传递方式不同，它默认通过传址来进行传递，这一点需要注意。。。<br id="cf85" />
最后，最麻烦的问题是Argument passing
protocol，一个fortran的数据在C++中应该怎么表示呢？基本数据类型这都还好，但数组呢？自定义数据类型呢？在高层一些的语言里，我们根
据串行化的方式，自动将参数序列化和反序列化进行数据转换，一切都比较水到渠成。但基于二进制的接口，调用的基础只是栈的完全匹配，一点点差池对会缪之千
里。在fortran里，数组是列优先的，这正与C++相反，需要注意。而更恶心的是，fortran的数组及其强大，可以从任何脚标起，其间隔可以是任
意的，于是乎在intel的编译器下，一个普通的一维数组的指针，需要占用32个字节的空间。所有这些，都导致参数的传递在此类开发中成为最脆弱的环节。
它们彼此只是靠着栈中信息的一致性依偎在一起，一点点编译器的改动（或者用了一个其他的编译器...），或者是两边程序数据结构的改动（对于自定义类型而
言...），都可能导致崩溃性的后果。解决这个问题，需要依靠在设计层面上解决。需要传递复杂结构的接口都不要用，用一系列方法的调用来替代单一的方法，
将简单的数据依赖转换成为接口定义的依赖。因为基本数据类型总是像黄金一样坚挺，而复杂类型数据的解析总是像股票那般不靠谱。所以我们的原则是，只选简
单，不选复杂。。。<br id="yae-" />
当你做这样一件工作的时候，官方的手册和示例代码是你最好的帮手，而不要简单的依靠问人或Google一下来解决问题。因为别人涉及到的问题可能和你的不
完全一致，而一点点不一样可能就使得结果差的很远了。这也体现出一个人解决一个新的问题的方法了。对我而言，我会把所有可能用到的手段和所需的资料都罗列
一下，尽可能的详尽些。然后依照是绕过问题还是直面问题的差别分成两类，先考虑绕过。如果觉得代价可接受，也可以一劳永逸的话，那么先绕过再说，因为毕竟
是一个新问题，解决和绕过相比通常是难度更大。如果不能绕过，那么就将你所有的手段按照可靠性排个序，通常，源码总是比文档可靠，而文档有总比搜来的资料
可靠。如果一样可靠度的手段，就需要考虑一下它们实施的简单程度了，比如读文档（日文文档除外，我已经被恶心够呛了...）也许会比看源码简单一些，那么
先看看文档再说。总之，我个人觉得可靠度比简单性总会更重要一些，如果一些手段，比如从网上简单搜来的方法，你觉得不可靠，那么就不要先实施，往往是绕了
半天，你发现你又回到了原点。。。<br id="p:eq" />
<br id="nlh9" />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1160688.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41937/" target="_blank">[新闻]Google拟在9月发布自有浏览器 或采用火狐内核</a>]]></description></item><item><title>小扯一下调试。。。</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/03/16/1108091.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Sat, 15 Mar 2008 20:07:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/03/16/1108091.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1108091.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/03/16/1108091.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1108091.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1108091.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">前段时间陆陆续续读完了pangba老大力荐的<a title="Why Programs Fail" href="http://www.douban.com/subject/2036942/" id="lmt:">Why Programs Fail</a>，
一本关于程序调试的大作。给人最大的启发就是调试是一门科学而不是艺术。我从来不知道，原来调试还有那么多的千奇百怪的工具，可以写那么多的数学推导。从
小学开始我们就开始了解，作文没写好你可以说老师欣赏不了，而数学题算错了只能怪自己混的不够到位。于是我们总是很主观的把调试当成艺术来看待，调试能力
的高低不仅取决大量经验的积累也是天分所致。很遗憾的是，本书中告诉你，调试是有方法可以寻求的，像解数学题一样，用既定的方法套路去做，无论天赋高低经
验多寡，都能得到正确结果。恩，好像说的有点夸张了。但至少，调试是有章而寻的，是无须质疑的。我想我会努力去尝试使用一些书中提到的工具，但我依然不甘
心把一个充满所谓艺术性的活干的如此机械，书中的一些经验总结一下，同样可以在无足够工具支持下快速的进行调试。<br />
TRAFFIC。这是作者把调试各步骤首字母提取出来的得到的一个词。依次对应<span style="font-style: italic;">跟踪问题，重现问题，自动化和简化，寻找感染源，专注可能的来源，分离感染链</span>。<br />
问题跟踪，一个极其重要的内容是，错误是谁发现的。个人觉得，谁发现的直接影响到错误的可重现度。按可重现度高低来排，依次应该是自己发现》测试人员发
现》用户发现，而错误的可重现度，是影响调试时长（甚至是成功与否）的重要因素。换句话，如果想很好的调试，应该尽早的让潜在的错误跳出来和你对话，所有
为尽早发现错误进行的努力都是值得的。这些努力包括：断言，异常（<a title="你为什么不使用异常？" href="http://groups.google.com/group/pongba/browse_frm/thread/326bd576f7e37863?hl=zh-CN&amp;tvc=1&amp;q=%E4%BD%A0%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E7%94%A8%E5%BC%82%E5%B8%B8" id="fp9o">你为什么不使用异常？</a>），单元测试，重构，代码走查，静态分析等等。当你写下一些code的时候，你应该多考虑一点，如果出错，我是否能很快知道是这里出来的，这就是一个很好的习惯。<br />
日志，我觉得其最重要的作用是用于重现问题阶段。它不应该作为个人编码阶段定位错误点、分析bug的最优先选择（当然这有太多的意外情况，比如你有很好的
日志分析和记录系统，或者没有其他更好手段可以使用等等...），而是应该作为重现客户问题的重要手段。在问题重现中，我们总是希望错误能在我这里明明白
白再出现一次，但很多时候这样小小的渴望都沦落成为了奢求。我曾做一个外包项目，在这里跑的好好的程序到美国那边总是出错。介于保密的原因，很多东西我们
不能够过多的了解，甚至连真实的数据我们都拿不到。这时候我们能够依仗的就是各种日志文件。通过日志，你可以在不重现错误的前提下推断出错误，不知其然却
知其所以然，未必不是解决问题的方法。<br />
更多的时候，我们能够重现错误，但重现步骤过于繁杂（比如客户告诉你，他是一边倒立一边点鼠标发现这个错误的...），不能够帮我们很快定位在真实的错误
起始点上。这时候就需要进行简化，用到的是作者看家的兵器delta技术，有兴趣的可以翻书查看，而论其思想，主要是二分思路，或者说有条理有步骤的剔除
非相关因素。有条理有步骤是最关键的词汇，二分只是其中一种很步骤很条理的方式，而其他的，我觉得只要是够有规律，能够达到循序渐进，不走弯路的，都行。<br />
书中描述了所谓的科学调试的方法。基本是按照回溯的路线（及从错误的出现点出发寻找错误的发起点...），提出假设，观察，验证或推翻假设，一直将假设等同于错误的起点为止。我觉得这也只是有步骤有条理的方式的很好的一种，而不是全部。<br />
只是规规矩矩走路的人往往会错失捷径。我们很多时候看到这个错误出现，根本不用一步一步回溯，根据我们的经验和奔涌的肾上腺素，就能快速而准确的猜出问题
的原因，省时省力（该方法被称为快速而杂乱的调试...）。我想这是很多人（也包括我吧...）发掘问题起因的最习惯手段。而世界的残酷在于，一旦我们沉
迷于我们自己的猜测，会深陷其中，无法自拔，赌徒似的把大把大把的时间投进去，却血本无归。一个标准是，如果进行了十分钟的杂乱的调试依然没有找到问题的
话，就转入科学调试状态（把自己做成一个快表系统...），鱼和熊掌，就是这样来兼得。<br />
此外，我们还有很多调试的手段，我觉得从目的上看可以分成事前推测和事后分析（还是那个WS的比喻，套&amp;&amp;药...～_～）。一个错误出
来，我们可以先走查一下代码，看看编译器的warning等等。书中最NB的，是一种静态分析技术，通过工具解析代码结构，得到一些可能的错误起因。在我
眼里，这就是所有事前分析手段的专业版本，有空我一定要玩玩这些工具。可惜的是，我们总是不能聪明到看（或自动分析）代码就可以了解所有错误的程度。很多
东西只有run起来，才有恍然大悟的机会。所以我们需要很多事后分析手段。用的最多的还是调试器。日志，对，也可以用在这里。两者最大区别时，调试器是精
确慢速而局部的，日志是粗犷全面但部署困难的。两者的使用，和场合和工具的犀利程度有很大关系。对我个人来说，在二者皆宜的场合，我会动用调试器。<br />
说到调试器，不得不说测试（这里指的是程序员个人的单元测试...）。在此前一点概念需要说明。在很多人概念里，调试简单的对应使用调试器，与测试是格格
不入的。而在本书中，调试，指为了发现错误的起因所使用的所有手段，其中包含测试。测试最最最最优良的一点在于它是自动化的。或者说是可永远重现的。这就
是说，使用测试，可以帮你解决诱发错误，重现错误等及其麻烦的事情。但是，测试往往只是能够帮你找到错误的出现点，而不总是能快速的把你带到错误的起因
点，而为了部署这些测试你需要花费很多的精力。正是基于此，包括<a title="云风老大" href="http://blog.codingnow.com/2007/12/random_thinking.html" id="jp6.">云风老大</a>等很多人不屑使用测试（再次强调，这是指个人的单元测试...）。但是，这部以为这测试不重要，而成为你可以肆意偷懒放低代码质量的借口。而是因为其带来的好处被其他的一些技术抵消了，这样的话，为其付出的代价就会显得很沉重。<br />
但是无论你使用什么样的手段进行调试。代码结构的质量才是最最最根本的内容。一个函数划分很细致，不大量滥用全局变量的代码，使用很多无副作用的函数，通
过测试你发现错误出现点，往往你就能很快到达错误起点（因为你把错误可能出现的地方限定在了有限的范围）。而如果你代码结构混沌不堪，函数/类之间关系错
综复杂，哪怕你用测试找到了错误出现点，开着调试器进去看，你也会很快转晕。所以提高代码质量，合理应用适合的调试工具和手段，正确使用调试的方法才是正
道。在这里，不得不提一下TDD。最初的时候我总觉得TDD最核心的是T，Test。后来才开始明白，它最核心的其实是D，Drive。你可以把测试写的
很弱，但你一定要在此影响下把代码重构的很好。由此得到一个蛮歪的理：如果你或你团队的代码素质很高，可以尝试不用TDD的一些开发手段；但如果你或你团
队代码素质不够高，请把自己套在TDD里面磨练一下。之所以说歪，是因为我其实只想说后半句，前半句纯属为了对仗工整而用。<br />
最后我发现我忘提一个很好玩的东西，断言。我一直觉得这个东西很有意思。是一种游离在单元测试与调试器之外的手段，是一个隐藏在事后分析中的事前推测派来
的间谍。assert的意义在于猜测并提醒一些最有可能的错误，它不精确但也不死板。我一直觉得，全面合理的铺下断言这张网（三个部分，输入输出不变
式），可以很有效的提高调试速度。<br />
<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1108091.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41936/" target="_blank">[新闻]微软正在构思将Wi-Fi带入汽车</a>]]></description></item><item><title>coding的路。。。</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/03/15/1106680.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Fri, 14 Mar 2008 16:39:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/03/15/1106680.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1106680.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/03/15/1106680.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1106680.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1106680.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">刚在<a href="http://groups.google.com/group/pongba">TopLanguage</a>上发的一帖，回顾自己的编程之路。所有人的贴在<a href="http://groups.google.com/group/pongba/browse_thread/thread/cf2a57d6456ee20e">这里</a>，推荐大家看看。<br />
<br />
我学程序的路也走得比较诡异，不是那种扎扎实实一步一步往上走的。高中毕业到大一，开始淘腾程序，基本觉得好玩的都去学学，主要是VB，混着还有Html，ASP，ActionScript等等之类。总之是杂七杂八，每样沾点皮毛。这算是第一个开头阶段。<br />
由于本科学的是飞行器动力（研究导弹发动机...），只能自己选一些计算机方面的选修课满足欲望。于是碰到了对我影响极大的金旭亮老师。金老师是那种超负
责超有激情的人，从他身上你可以看到那种对技术的渴望和对学生的负责。我想无论他的学生资质如何，大部分都可以成为一个合格的软件工程师的。我上了他一年
的课，从VB学到了VB.net。这时候就基本进入第二个阶段，属于蒙头猛做期，这个阶段最大的特点就是实践脱离理论，快乐高于一切。那时候做东西没什么
目标、技术方向、设计之类的，也无所谓什么技术含量，只是想到做什么软件好玩，就写代码实现。那时候自己一个人写了很多的小软件玩，印象最深的有两个。一
个是GDI/GDI+做的游戏（这东西做游戏还真是够烂...），将三国无双的必杀技系统和俄罗斯方块做在了一起，算起来也是火拼俄罗斯的前辈了，只是个
人感觉比火拼要有意思些^_^（一共写过两版，VB版和VB.Net版，本来想做成一个传统小游戏+三国人物+人物必杀系统+故事模式的系列，只是代码写
太烂带最后完全无法维护...）；还一个就比较猥琐了，大学我考分最低的课是那该死的物理实验，在上完那学期课后，我做了一个工具，不仅能帮你快速计算出
实验结果，甚至可以自动生成所有实验数据，对错误的实验数据进行校正，保证每一份报告都正确且独一无二，免去copy被发现之苦，用此来发泄我心中的不满
（我承认，我渎职了，我利用我物理课代表的职务之便黑下来大量的正确的实验报告，在它们帮助下我成功的助纣为虐...）。那时候写代码真是很开心，没有所
谓的项目，完全是为了自己的乐趣。<br />
但蒙头写多了，人总是会疲惫的，特别是在那种代码质量下。那时候我很少看编程方面的书，看起来也就是示例比较多的入门级书，导致的结果就是代码Bug狂
多，到最后维护至吐血。仔细回想一下，什么垃圾代码我都生产过，总结一下，绝对可以拼成一本《代码大全（错误版）》了。于是痛定思痛，开始提高阅读质量，
狂啃书。系统自学了一下计算机系的大部分课程，读了一些设计模式方面的书。空闲之余，随手写些小东东练手。那时候的coding乐趣明显有所下降，很多代
码都是为了学习而演练的。coding的效率也明显降低，很多时候写了就得不够优雅，就不停的推倒重写，到最后也没有写出一个我觉得有意思的东西来。这时
候就来到了第三个阶段，蒙头苦读期，其特点是理论没学到精髓，引导了错误的实践...。<br />
再接着，就是考研。由于本科不是学计算机，考得又是THU，惨烈程度可见一斑。那时候除了啃书就是啃书，偶尔从书堆里爬出来敲两行代码也都是书中的示例，
混得和刚学程序的小孩似的。这勉强算是第四阶段吧。在这个阶段，我获得的东西都不是技术上的，而是心理和学习能力上的，虽然整个考研过程搞得跌宕起伏，但
我想这份付出也算是有所回报的。<br />
再后来，就是实习和毕设。我同学的大四下都过得悠然自得，只有我自己把自己忙得很鬼似的。起早坐一小时车摸到公司coding外包项目一天，晚上摸黑爬回
宿舍继续coding毕设项目。好不容易做完了毕设，又被老师抓着去做别的项目，顺带着还帮兄弟姐妹做了几个毕设。导致的结果就是我出色的不睡觉能力在那
个阶段有了进一步提升...。算一下，这是第五个阶段了。在这阶段最重要的有两点，一个是我扒开门缝窥看了一眼中国外包行业和大学做软件的现状，帮助我找
到了我的发展方向；还有一个是我总与开始正二八经做C++了，并从此觉得喜欢上了这家伙，纯正的.net血统开始分崩离析，我的coding生涯终于开始
从空中楼阁回归地面...。<br />
再再后来，就是现在，算第六个阶段。开始一边读书一边做项目，感觉在经过理论脱离实际，实际脱离理论后，总算开始找到节奏，对技术的理解也开始有所提高。
科研项目是C++/MFC的，虽然建立在一片狼藉的千年老妖精项目基础上，但是相对还是比较独立，我也可以尝试一些自己的想法，找到了久违的乐趣。业余做
Android，蛮好玩的一个东西。看书基本是跟着当下需求走，有时间就看自己储备的东西。现在再让我说什么叫做技术，我会觉得做技术就是要做好两头，再
来做中间。一个是基础的模块，包括纯数学知识和计算机相关的算法，数据结构之类的，这是构架大厦的砖块，不搞扎实了，大厦摇摇欲坠；另一头是程序设计的理
念，架构抉择的思想，设计能力，对程序理解力之类的抽象的东西，只有具备这些素质，才不会一叶障目，不说做大师级的东西，至少不会一看自己明明想做住宅怎
么做成了猪圈。做好了这些，再往中间走，这就包括语言细节的理解，工具的使用，调试测试等实际工程能力的培养之类的，想成为扎扎实实的实干者，这些硬条件
时必须努力提升的，而且这些东西都是可以融汇贯通的，不同平台不同语言之间都有着相似的分析方法，不能说是一通百通，至少也是可以举一反三的。<br />
回顾那么多年（其实和很多前辈比，着实算不上什么长...），我觉得，无论你起点如何，经过什么样的曲折，只要多学，多想，多练，总归会殊途同归（一个收敛的函数^_^...）。<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1106680.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41935/" target="_blank">[新闻]对比测试：IE8 Beta 2 VS Firefox 3.0.1</a>]]></description></item><item><title>Android大变脸。。。</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/02/16/1070558.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Sat, 16 Feb 2008 04:30:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/02/16/1070558.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1070558.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/02/16/1070558.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1070558.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1070558.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">2月14日情人节，一向善于挑日子的Google在其Android官方Blog上公布了新版Android
SDK发布的消息（根据网站上的日期，SDK应该是2月12日就更新了，看来Google的公关做得确实很不勤劳...）。这次发布的SDK版本号为
M5，理论上这应该会是第一轮比赛初赛前最后一个版本了，在此前，为了大家更好适应新的SDK，Google将第一轮比赛初赛的结束日期顺延了将近一个半
月，这意味着此版SDK会有巨大的变化。但当我迫不及待跑起新的模拟器的时候，还是着实吓了我一大跳，心里只会叨念三个字，大变脸。<br />
所
谓&#8220;大变脸&#8221;有两个层面的意思，一个是使用了全新风格的界面上。随手截了几个比较有特点的界面图，从中可略见一斑。一直做Android的同志们都可能会
有感觉，早先的Android的界面，还是比较中规中矩的，风格颇为&#8220;传统&#8221;，与Symbian等操作系统都会有很多相似的界面和操作方式。而这一次，算
是真的做出了一些特色。
<div>
<table class="zeroBorder" classname="zeroBorder" id="vsig" border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr align="center" valign="middle">
            <td width="25%">
            <div id="ufmz" style="padding: 1em 0pt; text-align: left;"><img style="width: 320px; height: 480px;" src="http://docs.google.com/File?id=ddwgxw9r_418cc4sx9cg"  alt="" /></div>
            </td>
            <td width="25%">
            <div id="etf:" style="padding: 1em 0pt; text-align: left;"><img style="width: 320px; height: 480px;" src="http://docs.google.com/File?id=ddwgxw9r_419dh2x4t2r"  alt="" /></div>
            </td>
            <td width="25%">
            <div id="c92." style="padding: 1em 0pt; text-align: left;"><img style="width: 320px; height: 480px;" src="http://docs.google.com/File?id=ddwgxw9r_420gdps6vgp"  alt="" /></div>
            </td>
            <td width="25%">
            <div id="er86" style="padding: 1em 0pt; text-align: left;"><img style="width: 320px; height: 480px;" src="http://docs.google.com/File?id=ddwgxw9r_421dv32w5nr"  alt="" /></div>
            </td>
        </tr>
        <tr align="center">
            <td width="25%">图1：全新的初始界面<br />
            </td>
            <td width="25%">图2：全新的Contacts以及弹出菜单<br />
            </td>
            <td width="25%">图3：全新的Notification系统<br />
            </td>
            <td width="25%">图4：全新的Expanded菜单</td>
        </tr>
    </tbody>
</table>
</div>
套
用奥林匹克精神的经典台词，新的Android界面算是更大，更Q，更花哨了。更大是最显而易见的，现在所使用的图标和字体比老的起码大了一两倍，一屏能
显示的内容少了一大半，但格外的清晰耀眼。我个人分析这和Android的定位密切相关，Android定位在有一定硬件基础的手机平台上，它不再考虑对
低配置手机的支持。一定的硬件基础毫无疑问包括足够大的屏幕，特别是越来越流行的大触摸屏。更大的图标和文字可以让用户更充分享受大屏幕带来的更美好的视
觉效果，同时也可以更方便进行触摸操作。<br />
当然这种新界面和iphone的革命性UI不是同一个概念。iphone的一些酷酷的UI特性（双触点，
自动关闭触摸屏等等...）都依赖于XX感应器等硬件基础。而Android毕竟是一个开放的软件系统，它再需要高的硬件基础，也不可能高到iphone
的层度。但在新的SDK中，可以看到Android开始以另外一种方式兼容不同的硬件。在Activity中，新增了Touch
Mode的接口，用以兼容在有触摸屏的条件下提供更好的用户体验（主要是焦点上...）。我想这样的根据不同硬件条件提供的可选API会越来越多，当然这
样的API需要足够简单好用，不然会给开发人员增加很大的负担。<br />
另外很有趣的是Google在Android中采用了很Q的风格，图标都是可爱的圆弧角，字体也是圆圆的感觉。这估计是Android开发工程师们好这口，这一点可以从早先<a title="Google的展示视频" href="http://www.youtube.com/watch?v=I6ObTqIiYfE&amp;feature=PlayList&amp;p=5CE8623916B0E2FF&amp;index=0" id="m1s4">Google的展示视频</a>可略见一斑。<br />
伴随着Q而来的，是更为花哨的界面风格，大大的图标随处可见，颜色也是颇为的艳丽，更有趣的是其ViewGroup的动画效果比原来更为的夸张和好用。<br />
当然所有这一切界面风格的变化都不是无源之水。为了更好支持新的界面，所有的View的解析方式都有了全新的变化，并且Android的
CursorAdapter，Notification，ViewGroup，Menu等等类都做出了很多的改变，
SimpleCursorAdapter可以直接支持图片的显示，避免了更多的人重复造这个轮子；Notifaction变成了图3这样，有图标，有更丰
富的内容；ViewGroup支持了更好的动画显示，可以从Demo中看到其效果；Menu更是变化巨大（如图2，图4所示），带图标的Menu可以很容
易的搞定。<br />
当然，这一切也不只是花花架子，为了更好的显示图标、动画等等，View引入了Drawing Cache（其实就是双缓冲策略...）等新的机制，通过延迟、晚绑定等等底层方式，提高加载的效率。<br />
新界面的变化，使得用户的使用上也需要一些的改变。新的起始界面，如图1所示，采用了侧边栏的方式。最上面的图标（比如APIDemos，
Chamberlain）是根据你上次使用状况动态更新的。虽然很酷，但我个人觉得蛮乱蛮不好用的。新的Notification不再是通过上下键弹出，
而是需要下拉出现，虽然还是很酷，但同样还是不够好用。新的菜单进行了分离，分成了Icon menu, Expanded menu和Context
menu。最一般的菜单采用Icon方式，大于6个可以通过more按钮转换成为Expanded方式，而Context
menu需要长按2秒Center button才能够弹出，所有一切都违背了一般的操作方式，还是那句，很酷，但需要时间的考验。<br />
<br />
新的SDK另一个巨大的变脸就是大量API的变化。这种变化是老的项目的移植非常痛苦，但从长远来看绝对是一个好事。<br />
API最多的变化就是命名的变化，很多不合理的命名被更改。一些不清晰的API指定的更为明确，比如一些与SQLite相关的API都被附上了
SQLite前缀；一些原来在文档中标明过期的方法，在这一次彻底被废除了，比如ContentProvider的query方法；一些不统一的API也
进行了调整，比如ListView中的position和index统一成为position，解决了这一我原来颇为头疼的问题；一些命名风格进行了统
一，比如URI采用统一的Uri，ID采用了统一的Id；其他方面，AndroidManifest.xml中的一些项也做出了统一，能够能容易的被理
解。总之这样的变化还有很多，大量的API更为的清晰，易理解。这也是天下所有被重金诱惑的程序员帮助Google测试的结果。<br />
还有一些类进行了重构，进行了功能的分离和扩充。最典型的是ContentURI，被拆成了ContentUris这个功能类和Uri这个实体类，对程序
员的使用做出了更好的引导作用；而另一个典型的变化是Cursor，添加了一个extras接口，可以传出附加的数据，这简直是一场及时的一塌糊涂的雨，
使得原来很多很难做的是变得简单；还有一个是Notification进行了拆分，Notification现在只是指首页顶上的那个图标，那些临时的弹
出文字或视图被分离为Toasts，这对强扭的瓜终于得以各奔东西，单飞各自发展。<br />
一个比较特别的变化是Alerts，采用了新的Builder链式构建方式，而不是通过构造方法进行构造，其构造的灵活性更大了。与此相反，Notification则拥有了一个更长的构造函数，用起来及其的不爽，个人觉得这不是一个良好的变化。<br />
此
外，Android也添加了一些实用的类。新增的ExpandableListView，是一个二级树状AdapterListView，这是一个非常非
常实用的视图控件。我想这是大量开发人员提出需求的结果。我个人原先想自定义这个轮子的，后来采用一级模拟二级的方式实现。这一下好了，省心了。另外一个
革命性的东西就是Search
Manager接口，这是一个hooker接口，Android为你的Activity做了一个很酷的Search界面和接口（可以参看Sample），
通过实现改Hooker可以实现统一的Search，这个对很多和我一样做Search的人影响极大，从短期看，移植非常痛苦，从长线看这是一个颇有
Google味的变化，对Search有很大的推动作用。另一个比较Google味的变化，是将XXMP更名为GTalk，Google野心彰显无遗。<br />
<br />
除了这些变脸，SDK这次对插件进行了不小的改变，支持了多设备，将设备视图和Process视图合并；并添加了新的traceview工具，这是一个可视化的日志分析工具，这个工具使得Android的日志系统更为的强大，调试时间有望进一步降低。<br />
<br />
所有这些只是根据我这两天的一些观察得出来的，只是盲人摸象而已。更全面的内容可以参考<a title="这里" href="http://code.google.com/android/migrating/m3-to-m5/m5-api-changes.html" id="wn:5">这里</a>，<a title="这里" href="http://code.google.com/android/RELEASENOTES.html" id="htyt">这里</a>，<a title="这里" href="http://code.google.com/android/migrating/m3-to-m5/changes.html" id="zx4p">这里</a>。很遗憾的是，大部分SDK的文档都没有跟上，所以如果想学习的话，希望大家直接看SDK Sample，而不要阅读文档中的示例。<br />
进行了这一些改变后，Android越来越完善，Google的投在大奖赛的钱看来不会白花。对于所有做Android的人，这也是一个更好的机会，谁能适应新的SDK，谁就能占领到更好的位置。<br />
<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1070558.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41934/" target="_blank">[新闻]iPhone存在严重密码安全漏洞</a>]]></description></item><item><title>Study on Android【六】--消息机制，异步和多线程</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/01/24/1050813.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Wed, 23 Jan 2008 17:12:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/01/24/1050813.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1050813.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/01/24/1050813.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1050813.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1050813.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">有了framework后，我们不用面对赤裸裸的OS API，做一些重复而繁杂的事情。但天下没有免费的午餐，我们还是需要学会高效正确的使用不同的framework，很多处理某一特定问题的手法在不同的framework中，用起来都会有所不同的。<br />
在Android中，下层是Linux的核，但上层的java做的framework把这一切封装的密不透风。以消息处理为例，在MFC中，我们可以用PreTranslateMessage等东东自由处理消息，在C#中，<a title="Anders Hejlsberg" href="http://en.wikipedia.org/wiki/Anders_Hejlsberg" id="jnfi">Anders Hejlsberg</a>老大说了，他为我们通向底层开了一扇&#8220;救生窗&#8221;，但很遗憾，在Android中，这扇窗户也被关闭了（至少我现在没发现...）。<br />
在Android中，你想处理一些消息（比如：Keydown之类的...），你必须寻找Activity为你提供的一些重载函数（比如
onKeyDown之类的...）或者是各式各样的listener（比如OnKeyDownListner之类的...）。这样做的好处是显而易见的，
越多的自由就会有越多的危险和越多的晦涩，条条框框画好了，用起来省心看起来省脑，这是一个设计良好的framework应该提供的享受。对于我目前的工
程而言，我没有什么BT的需求在当前API下做不到的，google的设计ms还是很nice的。<br />
但世界是残酷的，有的时候我们还是必须有机制提供消息的分发和处理的，因为有的工作是不能通过直接调用来同步处理的，同时也不能通过Activity中内
嵌的消息分发和接口设定来做到，比如说事件的定时触法，异步的循环事件的处理，高耗时的工作等等。在Android中，它提供了一些蛮有意思的方式来做这
件事情（不好意思，我见不多识不广，我没见过类似玩法，有见过的提个醒 &amp;&amp;
嘴下超生^_^），它有一个android.os.Handler的类，这个类接受一个Looper参数，顾名思义，这是一个封装过的，表征消息循环的
类。默认情况下，Handler接受的是当前线程下的消息循环实例，也就是说一个<font color="#ff9966"><span style="font-weight: bold;">消息循环可以被当前线程中的多个对象来分发</span></font>，
来处理（在UI线程中，系统已经有一个Activity来处理了，你可以再起若干个Handler来处理...）。在实例化一个
handlerInstance之后，你可以通过sendMessage等消息发送机制来发送消息，通过重载handleMessage等函数来分发消
息。但是！该handlerInstance能够接受到的消息，只有通过handlerInstance.obtainMessage构造出来的消息（这
种说法是不确切的，你也可以手动new一个Message，然后配置成该handlerInstance可以处理的，我没有跟进去分析其识别机制，有兴趣
的自己玩吧^_^）。也就是说A, B, C, D都可以来处理同一线程内的消息分发，但<font color="#ff9966"><span style="font-weight: bold;">各自都只能处理属于自己的那一份消息</span></font>，
这抹杀了B想偷偷进入A领地，越俎代庖做一些非份之事的可能（从理论上看，B还是有可能把消息伪装的和A他们家的一样，我没有尝试挑战一下google的
智商，有BT需求的自行研究^_^）。这样做，不但兼顾了灵活性，也确保了安全性，用起来也会简单，我的地盘我做主，不用当心伤及无辜，左拥右抱是一件很
开心的事情。。。<br />
很显然，消息发送者不局限于自己线程，否者只能做一些定时，延时之类的事情，岂不十分无趣。在实例化Handler的时候，Looper可以是任意线程
的，只要有Handler的指针，任何线程也都可以sendMessage（这种构造方式也很有意思，你可以在A线程里面传B线程的Looper来构造
Handler，也可以在B线程里构造，这给内存管理的方法带来很大的变数...）。但有条规则肯定是不能破坏的，就是非UI线程，是不能触碰UI类的。
在不同平台上有很多解决方式（如果你有多的不能再多的兴趣，可以看一下很久很久以前<a title="我写的一个" href="../archive/2006/07/28/462365.html" id="jp83">我写的一个</a>，不SB不要钱）。我特意好好跟了一下android中的<font color="#ff9966"><span style="font-weight: bold;">AsyncQueryHandler</span></font>类，来了解google官方的解决方案。<br />
AsyncQueryHandler是Handler的子类，文档上说，如果处理ContentProvider相关的内容，不用需要自行定义一套东西，
而可以简单的使用async方式。我想指代的就应该是AsyncQueryHandler类。该类是一个典型的模板类，为ContentProvider
的增删改查提供了很好的接口，提供了一个解决架构，final了一些方法，置空了一些方法。通过派生，实例化一些方法（不是每个对
ContentProvider的处理多需要全部做增删改查，我想这也是该类默认置空一些方法而不是抽象一些方法的原因），来达到这个目的。在内部，该类
隐藏了多线程处理的细节，当你使用时，你会感觉异常便利。以query为例，你可以这么来用：<br />
<br />
<blockquote>// 定义一个handler，采用的是匿名类的方式，只处理query，因此只重写了onQueryComplete函数：<br />
queryHandler = new AsyncQueryHandler(this.getContentResolver()){ // 传入的是一个ContentResolver实例，所以必须在OnCreate后实例化该Handler类<br />
@Override<br />
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 在这里你可以获得一个cursor和你传入的附加的token和cookie。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 该方法在当前线程下（如果传入的是默认的Looper话），可以自由设定UI信息<br />
&nbsp;&nbsp;&nbsp; }<br />
};<br />
<br />
// 调用时只需要调用startQuery(int token, Object cookie, ContentURI uri,
String[] projection, String selection, String[] selectionArgs, String
sortOrder)函数即可：<br />
queryHandler.startQuery(token, cookie, uri, projection, selection, selectionArgs, sortBy);<br />
</blockquote>
可见，该类的使用是多么简单（其实现可不会很容易，因为我尝试做了一次造车轮的工作*_*），比直接用Handler简单无数倍。但让我倍感孤独的是，不
知道是没人做异步的ContentProvider访问，还是这个类使用太过于弱智（这个使用方法可是我摸索了半天的啊，难道我真的如此的弱@_@），抑
或是大家都各有高招，从SDK到网上，没有任何关于该类的有点用的说明。而我又恰巧悲伤的发现，这个类其实有很多的问题，比如他吃掉异常，有错误时只是简
单的返回null指针（这个其实不能怪他，你可以看看<a title="这里" href="../archive/2007/12/31/1021386.html" id="rp8v">这里</a>...）；当你传一个null的ContentResolver进去的时候，没有任何异常，只是莫名其妙的丢弃所有消息，使你陷入苦苦的等待而不知其因；更愤慨的是，他的<font color="#ff9966"><span style="font-weight: bold;">token传递竟然有Bug</span></font>（难
道还是我使用不对&amp;_&amp;），从startXX传入的token，到了onXXComplete里面一律变成1，而文档上明明写着两个是一
个东西（我的解决方法是用cookie做token，这个不会丢*_*）。不过我暂时还没有遗弃它的打算，虽然没人理睬，虽然有一堆问题，虽然我按图索骥
造了个新轮子，但为了节省剩下的一些无聊的工作，我决定苟且偷生了。。。<br />
还是习惯性跑题了，其实，我是想通过我对这个类的无数次Debugger跟进，说说它的多线程异步处理的解决策略的。他的基本策略如下：<br />
<blockquote>1. 当你实例化一个AsyncQueryHandler类时（包括其子类...），它会单件构造一个线程（后面会详述...），这个线程里面会构建一个消息循环。<br />
2. 获得该消息循环的指针，用它做参数实例化另一个Handler类，该类为内部类。至此，就有了两个线程，各自有一个Handler来处理消息。<br />
3. 当调用onXXX的时候，在XXX函数内部会将请求封装成一个内部的参数类，将其作为消息的参数，将此消息发送至另一个线程。<br />
4. 在该线程的Handler中，接受该消息，并分析传入的参数，用初始化时传入的ContentResolver进行XXX操作，并返回Cursor或其他返回值。<br />
5. 构造一个消息，将上述返回值以及其他相关内容绑定在该消息上，发送回主线程。<br />
6. 主线程默认的AsyncQueryHandler类的handleMessage方法（可自定义，但由于都是内部类，基本没有意义...）会分析该消息，并转发给对应的onXXXComplete方法。<br />
7. 用户重写的onXXXComplete方法开始工作。<br />
</blockquote>
这就是它偷偷摸摸做过的事情，基本还是很好理解的。我唯一好奇的是它的线程管理方式，我猜测他是用的<font color="#ff9966"><span style="font-weight: bold;">单件模式</span></font>。
第一个AsyncQueryHandler的实例化会导致创建一个线程，从此该线程成为不死老处男，所有的ContentResolver相关的工作，都
由该线程统一完成。个人觉得这种解决方式很赞。本来这个线程的生命周期就很难估量，并且，当你有一个ContentProvider的请求的时候，判断你
会做更多的类似操作并不过分。就算错了，花费的也只是一个不死的线程（与进程同生死共存亡...），换来的却是简单的生命周期管理和无数次线程生死开销的
节约。同时另外一个很重要的问题，他并会涉及到单件中数据同步的问题，每个类都有各自的Handler类，彼此互不干扰，分发可以分别进行。当多个数据请
求的时候，在同一个ContentResolver上进行的可能微乎其微，这就避免了堵塞。总而言之，这套解决办法和Android的整体设计算是天作之
合了。<br />
所以建议，如果你有什么非ContentProvider操作，却需要异步多线程执行的话，模拟一套，是个不错的策略，当然，具体情况具体分析，生搬硬套是学不好马列主义的。。。<br />
<br />
<br />
<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1050813.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41931/" target="_blank">[新闻]GC2008：星际争霸2进程报告 微调进程延续</a>]]></description></item><item><title>天使还是魔鬼？</title><link>http://www.cnblogs.com/duguguiyu/archive/2008/01/23/1049372.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Tue, 22 Jan 2008 16:47:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2008/01/23/1049372.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1049372.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2008/01/23/1049372.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1049372.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1049372.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">从1月22日起，微软通过Update推送SliverLight。<br />
从2月12日起，微软通过Update把所有的IE浏览器都强制升级为IE7。<br />
IE8快速前行在标准话的路上，并将超越ff，成为更&#8220;标准&#8221;的象征。<br />
这意味着什么呢？<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1049372.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41930/" target="_blank">[新闻]科学家在世界最大对撞机中观察到首批粒子</a>]]></description></item><item><title>Study on Android【五】--自定义ContentProvider的语义</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/12/31/1021386.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Sun, 30 Dec 2007 17:10:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/12/31/1021386.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1021386.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/12/31/1021386.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1021386.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1021386.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">
Android做到现在。开始感觉到Android确实还是太年轻。系统本身好不够成熟，相关文档更是少的可怜。在Android的旅途中到处是暗坑陷阱，掉进去摔得半死，还只能靠自己琢磨着爬出来。<br />
想
在大部分工作集中在了定义一套ContentProvider以及上层的显示控件上。一个ContentProvider向外提供的接口十分有限，但就是
这几个东西你要表征出正确（标准就是和系统ContentProvider一致的行为）的语义，还是很费功夫的。至少我就摔了好几个跟头。为了降低后续部
队的伤亡，我努力搬走几个绊脚石、填掉几个坑，希望能有一些作用。<br />
ContentProvider中，最重要的就是query操作。query根
据输入返回一个符合条件的Cursor。这就可能出现以下几种情况：1. 查询成功，包含几个正确的结果；2. 查询失败，没有符合的结果；3.
输入错误， 触发了某个异常；4.
没能查询到结果，但无法确定是输入错误还是查询失败。第一种情况是我们最需要的，当然是需要正确维系的，而最后一种情况在大部分应用中应该不会出现（但在
我的应用中会的*_#），而第二种第三种是比较常见的。<br />
经过我的测试，系统的ContentProvider维持这样的语义：如果是情况2，返回
正常的Cursor，并且，其count为0，相当于empty
cursor；如果是情况3，不抛出任何异常，返回null的Cursor。这样的话明明白白写出来是很好理解的，但由于没有官方的文档说明，在自定义的
时候经常会误用。比如在某些情况下，用null表征查询失败，用抛出异常来描述错误的输入。<br />
返回empty
cursor，如果是通过databasecursor自然会有db帮你维护，但是如果返回ArrayListCursor，MergeCursor或其
他自定义的Cursor，就需要自己维系了。ArrayListCursor可以通过new ArrayListCursor(Columns,
new ArrayList(){})来提供。其中Columns一定不为null。MergeCursor不能以new
MergeCursor(new Cursor[]{})来创建，而需要通过new MergeCursor(new
Cursor[]{aEmptyCursor, ...}来维系（其实很好理解，我呆了...）。自定义的Cursor也一定要提供生成empty
cursor的方式。<br />
如果将ContentProvider作为一个单独的module来理解，不通过异常而是通过null来返回MS是有好处
的。在module的出口吃掉所有异常，虽然不能提供足够的信息（异常信息全部写入日志），但可能会使上层使用更简单。但在Android中，我并没有感
觉到这一点。作为ContentProvider的上层函数，ListActivity.managedQuery、
ListView.setListAdapter等，根本不能处理一个null的Cursor，在ListView中这会触发一个异常。更无语的是，当你
把一个null Cursor设置为manage的后。它不会立即抛异常，而是在OnFreeze等生命周期函数的时候，因无法处理null
Cursor而抛出一个异常。这使得你根本无法在当地catch该异常，换句话，<font color="#ff0000">ListActivity的manageCursor根本是个无法使用的函数</font>。你必须用getContext().query()获得Cursor，然后判定该Cursor是否null，在进行startManagingCursor进行绑定。这远不如直接用异常进行错误路径的处理来的统一和方便。<br />
当然，有些东西我们是不能改变的，只能去适应。对于自定义的cursor,
ContentProvider，最重要的，是在无人造错误输入的情况下返回empty
cursor，而不是null。至于使用null响应还是异常响应上，我个人觉得还是和系统同步为好，虽然别扭，但至少统一不容易有歧义。<br />
此外，ContentProvider还有很多细致的语义。比如返回的Cursor需要绑定一个URI，以便自动响应更新。自定义的更新需要支持deleteRow等操作语义等等。总之，我们需要更好的文档或更多经验文档，以便我们更好的爬上巨人的肩膀。<br />
<br />
PS：而上层的ListView，更是陷阱重重。首先绑定到ListView的Cursor必须有_id项，否则会有异常抛出。如果做过.net的开发，
这一点是可以想到的，但是，这种问题应该在文档中写明。另外，在ListView中，如果你不绑定一个数据源，你一定不能在layout中添加涉及内容的
属性。比如android:height="wrap_content"，这会在onMeasure的时候抛出异常。<br />
<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1021386.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41929/" target="_blank">[新闻]阿里巴巴利润增1.36倍</a>]]></description></item><item><title>道简</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/12/18/1003843.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Mon, 17 Dec 2007 17:12:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/12/18/1003843.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/1003843.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/12/18/1003843.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/1003843.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/1003843.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">
最近读了TopLanguage上关于<a title="编程风格的一些讨论" href="http://groups.google.com/group/pongba/browse_thread/thread/2c7a279e615bfa06#bdd498391acf770e" id="cnh-">编程风格的一些讨论</a>，拜读了下云风老大的<a title="两篇佳作" href="http://blog.codingnow.com/2007/12/continue_random_thinking.html" id="i1ts">两篇佳作</a>。
感触良多。
做为一个&#8220;码头工人&#8221;，每天都在coding，不由会想，我们的脑细胞和陪mm的时间都耗在了哪行代码上。诚然，在C++这样的语言中，我们大把的时间花
在了等待编译以及做一些繁杂而和coding无直接关联的事情。Toplanguage上有老大说，他的C++生涯25%在等待编译，5%在各种字符串中
转换，狂赞。只是对我而言，起码还有5%的时间耗费在了在.h和.cpp文件中添加和维护相同的代码上。对此，我们能做的除了等待各位委员会老大高抬贵手
外，只能选择放本书在电脑旁，编译和看书并发进行。<br />
恩。抛开这种问题不提。个人觉得，做一个程序，主要的复杂度和耗时都来自于两个方面。一是算法逻辑，另一个是有平台和语言带来的细节性问题。关于算法逻
辑，我们学各式各样的算法，数据结构，我们偶尔灵光乍现把算法复杂度提上一个档次，这样的工作，本应该是程序最核心的内容，但往往在只占用我们花在工程上
的一小部分时间。对于很多项目而言，我们关心的是时刻在变化的算法逻辑。见佛杀佛，遇鬼杀鬼，只可惜，很多时候连我们自己都不知道我们面对的是什么。这世
界上，最复杂易变的东西就是人本身，最恐怖的是变化的需求。于是，我们又有了模式，它使得我们程序更容易适应某种类型的需求变化。我们抓住它，作为解决问
题的套路，方案，捷径。就像<a title="影响力" href="http://www.douban.com/subject/1786387/" id="nq71">影响力</a>里
面所描述的一样，我们找到了一个思维的高速公路，当我们提到xx模式的时候，就像&#8220;哔&#8221;的一下按了快门，&#8220;它适应于xx变化，可以解决xx类型的问题&#8221;之
类的内容，汹涌而出。但是，走多了夜路总会遇到鬼，走多了捷径，恩，我们需要重构。模式和重构，就像xx套和xx药（BS自己一下...越来越WS...
==！），事前事后帮助我们写出更符合需求的算法逻辑，或说算法的结构。这样的算法，解决的不只是当下的问题，还有未来可能的问题。<br />
无论算法设计的难度有多大，变化的可能性有多高，对于程序员，我觉得，这是我们份内的事情。我们没有借口去拒绝或埋怨它。程序员的定义，理想上，应该是设
计算法和结构解决某个问题的人。当然我明白，在当前满足这个定义的人，已经不会再叫程序员了，而是xx师、xx家。对于大部分的程序员而言，我们的工作是
另一个方面，就是利用自己对语言和平台的熟悉度，去实现某个已设计好的方案。这个需求本身并不过分，就像你空有奇想却不会使用画笔的人，不能称为画家一
样。过分的是，很多时候，它让我们离一些创造性的内容越来越远，深深陷入了细节的泥沼，并沉醉其中。百万程序员堕落沦为码工的旷世惨案就这样发生了。<br />
Sorry，又习惯性跑题了。言归正传。说另一个耗费我们头发的方面，语言和平台的复杂性。现实总是很残酷。我们想到了一个完美的算法解决方案，和遗憾，
这还远远不够。方案到实现，绝对不是汇编到机器码的复杂度。我们还需要关心大量的与算法本身无关的细节。比如，这个指针的对象何时归还，有人传了错误的参
数移走了我们需要的文件需要如何报错，平台的API和我们需要的不一样该如何使用。诸如此类。就是它，成为我们高效写程序的阻碍和绊脚石。在实验室中，每
周都有老大讲述老百姓自己的C++，倾诉着绕来绕去的语义，纷繁复杂的注意事项。我们能不听吗？不能，因为老大们有大把的例子说明，在我们的项目中，由于
对细节理解的不够BT，我们正在犯着各种各样的错误。对个人而言，了解更多的细节，机理是非常有益的，就像武侠小说中常出现的，服下xx大补丸内功暴涨
（只是请注意不要向东方不败一样走了火入了魔...）。但对于项目而言，从程序员的角度出发，来解决这个实现细节问题，过于的不现实。就像云风老大说的一
样，这是比window比unix更安全一样的笑话（转述的MS有点偏差...）。我们不能奢望程序员都是蝙蝠侠，在没有睡眠只有可乐的日子里像赵子龙一
样，在海量的细节面前屹立不倒（不要以为只有C++才有海量的细节，想handle任何一门语言的所有细节都绝对不是大众活）。我知道在大量的开源类库
中，大量的实践类书籍中，人们都是这么做的，用各种奇技淫巧解决细节问题。但是，那只是通用的方式，适合于任何情况任何场合。而对于特定的工程特定的场合
而言，我们需要做的是在架构和规范（此规范与101那样的通用规范不是一个概念...指的是在某个局部范围内简单的几条需要遵循的原则，比如在这些模块内
不能用引用，在这些模块内不能用指着之类的...）的层面上，事先将实现的复杂性控制在一定范围之内，扼杀在摇篮中。而不是放任各中各样复杂的实现细节蔓
延到程序的各个角落之后，在启用飞机大炮原子弹开始处理。云风老大在网易游戏引擎中的设计，从架构开始把所需要各个模块需要了解的实现细节规划的清清楚
楚。底层传值用POD、容器中用GC管理指针之类的。在一定范围内，你需要注意的实现细节只有一点点，完全处于人脑可控的范围内。同理，
Toplanguage中各位老大对引用say
no，也是这个道理。这里举这些例子，不是提供另一个捷径，触发流水般思维的快门。而只是一个单纯的例子，告诉你这样的方式是更好的解决之道。对于特定的
项目而言，我想，还是要具体问题具体分析，绝对不存在一成不变的规矩。在C++中提供了很多高阶的手段（相比存C...），它们能更容易在一定实现细节内
解决一些特定的问题。当你的工程中触及大量的这样的问题，而你却恰恰限制这样的使用的话，简约反而不简单了。多的自由，意味着多的麻烦。从根本上限制自
由，大大减少了麻烦。反之，限制如果加的不对，那反而是画蛇添足没事找事了。说的就是这个理。<br />
但现实的残酷性有再次提上了议程。我的地盘我可以做主，但出了这一亩三分地，谁是老大就不一定了。在我的程序世界，总是充斥着大量的遗留代码，或者是必须
面对的接口需求。在这样的地方，你不再能为所欲为了，很多看似美好的方案都会化成一卷废纸。面对遗留代码，我们可以选择一起堕落，或<a title="力挽狂澜" href="http://www.douban.com/subject/2248759/" id="vobj">力挽狂澜</a>，
更多时候是划清楚界限（模块化，服务化，就是这个理...）。在接口受限的情况下也是一样。对外的接口已经确定，但我想提供更多的内容出去，所能做的就是
将该接口的表征能力挖到极限。在这种情况下，我想将细节复杂性确定在一个有限的范围内是比较可行的方案。一面是花花世界，一面是清静的世外桃源。中间，是
混沌的地域。带着你们最NB的老大，和所有的奇技淫巧，去往这个地狱，搞定它，这个世界就清净了。。。<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/1003843.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41928/" target="_blank">[新闻]Google Gears覆盖四大浏览器 Safari版推出</a>]]></description></item><item><title>Imagine Cup 2008 Match 2 总结</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/12/07/986018.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Thu, 06 Dec 2007 16:03:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/12/07/986018.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/986018.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/12/07/986018.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/986018.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/986018.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">本来没想这么快就继续参加一个Match的。但一试水发现有戏，就一直做了下去。最高做到35，稍微懒散了几天，倒数第二天掉到了50。最后一天发挥各种猥琐手段，在unsolve的题上扒下来一些分数，以43名进入第二轮。<br />
虽然晋级，同样不开心，因为很多题没有搞定。看了别人的solutions，从技巧和模式上又发现许多值得一说的地方。但，也许是晋级了，也许是做的我郁闷不已，没觉着再有必要去总结那些技巧了。也许技巧之外的一些东西，更值得我去仔细想一想。<br />
这个比赛到了今天，想到Top
5的级别，经验和技巧的积累也许是必不可少的了。但这个积累的过程我觉得过程大不相同。人说举一反三，同样举一反三之间其实差别很大。这个三指的是与一相
近的三还是完全有质变的三。看到一个技巧，以后用相似的技巧解决更多的类似的问题，这是最基础的举一反三。更深一步，是你看到这个技巧，会想，这个是怎么
思考来的，这个能解决什么类别的问题，在此基础上可以有什么变化，这就需要勤于思考和善于思考。勤是起点，善是行为。<br />
在Imagine
Cup中，有些问题你会很容易找到解（或者接近找到解）。这时候你就需要考虑了，这是最优的么？我该如何改进。改进一般有两种，一种是纯技巧的，另一种是
换一种新的路线去做。在我的经验里，第一种我有时做到，但改进的方法缺少足够的创造力，基本属于前述一的范畴。而第二种，更是梦魇。有时候明明知道，这条
路就只能这样了，却依然垂死挣扎，不愿思考新的路线。从心理的角度看，人都是有思维惰性的，被自己肯定的东西总是会不断的继续肯定，明知有问题也不知悔
改。我现在还是不知道该如何摆脱，但我想下次我会多多尝试的。这件事又说明两个问题，一个是勇于思考，永远觉得自己能做到更好，另一个是敢于思考，不被自
己觉得思维禁锢。<br />
感觉自己开始给自己做报告，说的很空泛了。总之，希望以后能好的做一些事情。<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/986018.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41927/" target="_blank">[新闻]Internet Explorer 8 Beta 2 发布</a>]]></description></item><item><title>Imagine Cup 2008 Match 1 Summary</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/12/07/986017.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Thu, 06 Dec 2007 16:01:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/12/07/986017.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/986017.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/12/07/986017.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/986017.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/986017.html</trackback:ping><description><![CDATA[摘要: LeaderBoard 1 Rac 47687 Poland Politechnika Krakowska 2 Jedi_Knight 47326 Russia Moscow State University 3 XarN 46798 Poland AGH University of Science and Technology 4 chokudai 46085 Japan Senior High&nbsp;&nbsp;<a href='http://www.cnblogs.com/duguguiyu/archive/2007/12/07/986017.html'>阅读全文</a><img src ="http://www.cnblogs.com/duguguiyu/aggbug/986017.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41927/" target="_blank">[新闻]Internet Explorer 8 Beta 2 发布</a>]]></description></item><item><title>Imagine Cup 2008 Match 2 Summary</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/12/06/986015.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Thu, 06 Dec 2007 15:57:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/12/06/986015.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/986015.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/12/06/986015.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/986015.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/986015.html</trackback:ping><description><![CDATA[摘要: Leader Broad rank match 1 match 2 1 PL Rac RU Jedi_Knight 2 RU Jedi_Knight JP TaiTai 3 PL XarN JP Yendor 4 JP chokudai CN mstlq 5 NO Eirik Reksten RU Fly 6 HU szsz SI umnik 7 LT FloppyCat UA P@VeL 8 P&nbsp;&nbsp;<a href='http://www.cnblogs.com/duguguiyu/archive/2007/12/06/986015.html'>阅读全文</a><img src ="http://www.cnblogs.com/duguguiyu/aggbug/986015.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41924/" target="_blank">[新闻]中国软件协会：SAP羞辱国产软件是不正当竞争</a>]]></description></item><item><title>Study on Android【四】--显示控件使用</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/12/03/981680.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Mon, 03 Dec 2007 15:43:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/12/03/981680.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/981680.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/12/03/981680.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/981680.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/981680.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">Android的界面显示同样也是基于控件的。通常是用View（包括ViewGroup）控件配上XML的样式来做的。具体细节不想说了，可以参考
Samples里的ApiDemos/View，和View的Doc，以及Implementing a
UI这篇Doc。其他还有很多，感觉算是SDK讲述的最多的内容。<br />
从控件的使用上，和网页的设计类似，尽量用parent_width之类的抽象长度，用Theme来做风格，抽取所有的字串等信息做本地化设计。相关内容参看Implementing a UI就好。<br />
一
类比较重要的是数据绑定控件。如果做过ASP.Net会从中看到很多类似的地方。一个支持数据绑定的控件，比如ListView。可以通过一个
ListAdapter绑定到一个数据源上。ListAdapter是一个抽象类，主要的实现类包括SimpleAdapter和
SimpleCursorAdapter。前者是绑定一个静态的Array，后者是绑定一个动态的Cursor。Cursor前面说过，是一个指向数据源
的随机迭代器，将View绑定到Cursor通常要设置这样几个参数。一个是每一行的样式，称作Row
Layout，其实就是一个普通的Layout的XML文件。还有就是一个列和现实控件的对应关系。那个控件显示哪个列的值，这是需要配置的。为了定制一
个良好的数据显示控件，最简单你可以定制很PP的Row
Layout，复杂一点就是可以重载绑定控件View，或者是适配器ListAdapter。如果是一个数据显示密集的应用，且你对UI有些追求，这个工
作估计是必不可少的。<br />
一个主要用于显示数据内容的Activity，可以选择派生自ListActivity。它提供了一个具有ListView
的Layout，还有simple_list_item_1, simple_list_item_2,
two_line_list_item等默认的Row
Layout，还有一些比较不错的API，和可供响应选择Item的事件。可以满足你比较基础的需求。如果你觉得只有一个ListView的界面太突兀，
你可以为这个ListActivity指定一个Layout，需要注意的是，你需要提供一个id为@android:id/list的ListView控
件，避免Activity在内部偷偷寻找该控件的时候失败。<br />
除了这些要求，做好UI还有注意易用性和效率。快捷键是一个比较不错的选择，在
Activity中调用setDefaultkeyMode(SHORTCUT_DEFAULT_KEYS)，可以开启快捷键模式，然后你可以将菜单绑定
到指定快捷键上就OK了。个人觉得Tip也是一个比较重要的东西，但目前观察看来，这个东西只能够自己提供了。界面的动态性有时候是不可避免的，比如说菜
单就是一个需要经常根据光标位置提供不同的选项。这个东西Android很人道的考虑到了，你可以参看NodeList这个Sample。它采取的应该是
一个静态模拟动态的方式，这样有助于提高速度。你也可以利用ViewInflate，动态从一个XML创建一个控件。成本据Doc说很大，不到万不得已不
要使用。<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/981680.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41923/" target="_blank">[新闻]福布斯：Facebook网站十大最火爆游戏</a>]]></description></item><item><title>关于Android这个名字。。。</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/11/30/978103.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Fri, 30 Nov 2007 04:04:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/11/30/978103.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/978103.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/11/30/978103.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/978103.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/978103.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">今天爬到wikipedia上看了下Android这个词相关的故事。呵呵。很有意思。基本就是一个常出现在科幻小说中的具有人的能力的小机器人。Google取这个名字应该是希望安装了Android的手机像一个活生生的人一样成为你必不可少的一个帮手。<br />
不过这个名MS不是Google取得。而是2005收购Android平台前身的时候直接带来的。So。。有钱还是真无敌。。。。<br />
<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/978103.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41922/" target="_blank">[新闻]谷歌允许用户评论搜索结果调整顺序</a>]]></description></item><item><title>Study on Android【三】--Intent消息传递</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/11/30/977665.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Thu, 29 Nov 2007 17:42:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/11/30/977665.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/977665.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/11/30/977665.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/977665.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/977665.html</trackback:ping><description><![CDATA[<p goog_docs_charindex="1"><span style="font-size: 10pt">在前面写Android的ContentProvider时候，可以看到那是基于观察者模式的一个消息传递方法。每一个Cursor、ContentResolver做为一个小的注册中心，相关观察者可以在这个中心注册，更新消息由注册中心分发给各个观察者。而在MFC或Winform中，都会形成一个消息网，让消息在网中流动，被各节点使用、吃掉或者在出口死掉。<br goog_docs_charindex="175" />
相比之下，我个人觉得基于Intent的Android核心消息传递机制是有所不同的。它应该会有一个全局性的注册中心，这个注册中心是隐性的，整个Android系统中就那么一个。所有的消息接收者，都被隐形的注册到这个中心。包括Activity，Service和IntentReceiver。其实说隐形注册是不确切的，所有注册都还是我们手动告诉注册中心的，只是与传统的方式不一样，我们通常不是通过代码，而是通过配置文件来做。在应用的Manifest中，我们会为一些Activity或Service添加上Intent-filter，或在配置文件中添加&lt;receiver&gt;&lt;/receiver&gt;项。这其实就相当于向系统的注册中心，注册了相关的Intent-filter和receiver（这个事情完全可以通过代码来做，只是这样就失去了修改的灵活性）。<br goog_docs_charindex="545" />
当程序有一个消息希望发出去的时候，它需要将消息封装成一个Intent，并发送。这时候，应该是有一个统一的中心（恩，有可能Android底层实现的时候不是，但简单这样看是没问题的...）接受到这个消息，并对它进行解析、判定消息类型（这个步骤降低了耦合...），然后检查注册了相匹配的filter或receiver，并创建或唤醒接收者，将消息分发给它。这样做有很多好处。虽然这种传递有的时候不如点对点的传递快（这有些需要速度的地方，我们看到Android会通过直接通信来做），但有时候又因为它只经过一跳（姑且这么叫吧...），比复杂的流动又要更快。更重要的是，它耦合性低，在手机平台这种程序组件多变的条件下使用十分适合。并且它可以很容易实现消息的精确或模糊匹配，弹性很大。（我个人曾想在开发一个C++二次平台的时候引入这样的机制，但在C++中，建立一套完整的数据marshal机制不容易，相比之下，用java来做会简单很多...）<br goog_docs_charindex="959" />
恩，废话说了很多，具体讲讲Android中Intent的使用。当你有一个消息需要传递，如果你明确知道你需要哪个Activity或者其他Class来响应的话，你可以指定这个类来接受该消息，这被称为显性发送。你需要将Intent的class属性设置成目标。这种情况很常见，比如startActivity的时候，会清楚当前Activity完了应该是哪个Activity，那就明确的发送这个消息。</span></p>
<p goog_docs_charindex="1155"><span style="font-size: 10pt">但是，有的时候你并不确定你的消息是需要具体哪个类来执行，而只是知道接收者该符合哪些条件。比如你只需要有一个接收者能显示用户所选的数据，而不想制定某个具体的方法，这时候你就需要用到隐形发送（传统上，我们可能会考虑用多态，但显然这种方式更为灵活...）。在Android中，你可以为Intent指定一个action，表示你这个指令需要处理的事情。系统为我们定义了很多Action类型，这些类型使系统与我们通信的语言（比如在Activity里面加一个Main的filter，该activity就会做成该应用的入口点），当然你也可以用于你自己的应用之间的通信（同样当然，也可以自定义...）。强烈建议，在自己程序接收或发出一个系统action的时候，要名副其实。比如你响应一个view动作，做的确实edit的勾当，你发送一个pick消息，其实你想让别人做edit的事，这样都会造成混乱。当然只有Action有时候是不够的，在Android中我们还可以指定catalog信息和type/data信息，比如所有的显示数据的Activity，可能都会响应View action。但很多与我们需要显示的数据类型不一样，可以加一个type信息，明确的指出我们需要显示的数据类型，甚至还可以加上一个catalog信息，指明只有你只有按的是&#8220;中键&#8221;并发出这样的消息才响应。<br goog_docs_charindex="1731" />
从上面可以看出，Android的Intent可以添加上class, action, data/type, catalog等消息，注册中心会根据这些信息帮你找到符合的接收者。其中class是点对点的指示，一旦指明，其他信息都被忽略。Intent中还可以添加key/value的数据，发送方和接收方需要保持统一的key信息和value类型信息，这种数据的marshal在java里做，是不费什么力气的。<br goog_docs_charindex="1931" />
Android的Intent发送，可以分成单播和广播两种。广播的接收者是所有注册了的符合条件的IntentReceiver。在单播的情况下，即使有很多符合条件的接收者，也只要有一个出来处理这个消息就好（恩，个人看法，没找到确切条款或抉择的算法，本来想实验一下，没来得及...），这样的情况很容易理解，当你需要修改某个数据的时候，你肯定不会希望有十个编辑器轮流让你来处理。当广播不是这样，一个receiver没有办法阻止其他receiver进行对广播事件的处理。这种情况也很容易理解，比如时钟改变了，闹钟、备忘录等很多程序都需要分别进行处理。在自己的程序的使用中，应该分清楚区别，合理的使用。</span></p>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/977665.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41922/" target="_blank">[新闻]谷歌允许用户评论搜索结果调整顺序</a>]]></description></item><item><title>Study on Android【二】--ContentProvider数据模型概述</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/11/25/972060.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Sun, 25 Nov 2007 14:44:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/11/25/972060.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/972060.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/11/25/972060.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/972060.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/972060.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">Android的数据（包括files,
database等...）都是属于应用程序自身，其他程序无法直接进行操作。因此，为了使其他程序能够操作数据，在Android中，可以通过做成
ContentProvider提供数据操作的接口。其实对本应用而言，也可以将底层数据封装成ContentProvider，这样可以有效的屏蔽底层
操作的细节，并且是程序保持良好的扩展性和开放性。<br />
ContentProvider，顾名思义，就是数据内容的供应者。在Android中它是一
个数据源，屏蔽了具体底层数据源的细节，在ContentProvider内部你可以用Android支持的任何手段进行数据的存储和操作，可能比较常用
的方式是基于Android的SQLite数据库（恩，文档中和示例代码都是以此为例）。无论如何，ContentProvider是一个重要的数据源，
可以预见无论是使用和定制ContentProvider都会很多。于是花了点时间仔细看了看。<br />
<br />
<font size="4"><span style="font-weight: bold;">数据库操作</span></font><br />
从
我目前掌握的知识来看，SQLite比较轻量（没有存储过程之类的繁杂手段），用起来也比较简单。实例化一个SQLiteDatabase类对象，通过它
的APIs可以搞定大部分的操作。从sample中看，Android中对db的使用有一种比较简单的模式，即派生一个
ContentProviderDatabaseHelper类来进行SQLiteDatabase对象实例的获取工作。基本上，
ContentProviderDatabaseHelper类扮演了一个singleton的角色，提供单一的实例化入口点，并屏蔽了数据库创建、打开
升级等细节。在ContentProvider中只需要调用ContentProviderDatabaseHelper的openDatabase方法
获取SQLiteDatabase的实例就好，而不需要进行数据库状态的判断。<br />
<br />
<font size="4"><span style="font-weight: bold;">URI</span></font><br />
像
进行数据库操作需要用SQL一样，对ContentProivder进行增删改查等操作都是通过一种特定模式的URI来进行的（ig：content:
//provider/item/id），URI的能力与URL类似，具体细节可以查看SDK。建立自己的ContentProvider，只需要派生
ContentProivder类并实现insert, delete,
update等抽象函数即可。在这些接口中比较特殊的是getType(uri)。根据传入的uri，该方法按照MIME格式返回一个字符串（==!没听
过的诡异格式...）唯一标识该uri的类型。所谓uri的类型，就是描述这个uri所进行的操作的种类，比如content://xx/a与
content://xx/a/1不是一个类型（前者是多值操作，后者是单值），但content://xx/a/1和content://xx/a/2
就会是一个类型（只是id号不同而已）。<br />
在ContentProvider通常都会实例化一个ContentURIPraser来辅助解析和操作
传入的URI。你需要事先（在static域内）为该ContentURIPraser建立一个uri的语法树，之后就可以简单调用
ContentURIPraser类的相关方法进行uri类型判断（match方法），获取加载在uri中的参数等操作。但我看来，这只是在使用上简化了
相关操作（不然就需要自己做人肉解析了...），但并没有改变类型判定的模式。你依然需要用switch...case...对uri的类型进行判断，并
进行相关后续的操作。从模式来看，这样无疑是具有强烈的坏味道，类似的switch...case...代码要出现N此，每次一个
ContentProvider做uri类型的增减都会需要遍历修改每一个switch...case...，当然，如果你使用模式（策略模式...）进
行改造对手机程序来说无疑是崩溃似的（类型膨胀，效率降低...），所以，只能是忍一忍了（恩，还好不会扩散到别的类中，维护性上不会有杀人性的麻
烦...）。<br />
<br />
<font size="4"><span style="font-weight: bold;">增删改查</span></font><br />
ContentProvider
和所有数据源一样，向外提供增删改查操作接口，这些都是基于uri的指令。进行insert操作的时候，你需要传入一个uri和
ContentValues。uri的作用基本就限于指明增减条目的类型（从数据库层面来看就是table名），ContentValues是一个
key/value表的封装，提供方便的API进行插入数据类型和数据值的设置和获取。在数据库层面上来看，这应该是column
name与value的对应。但为了屏蔽ContentProvider用户涉及到具体数据库的细节，在Android的示例中，用了一个小小的模式。它
为每一个表建一个基于BaseColumn类的派生类（其实完全可以不派生自BaseColumn，特别当你的表不基于默认的自动id做主键的时候），这
个类通常包括一个描述该表的ContentURI对象和形如 public static final TITLE =
"title"这样的column到类数据的对应。从改变上角度来看，你可以修改column的名字而不需要更改用户上层代码，增加了灵活性。
insert方法如果成功会返回一个uri，该uri会在原有的uri基础上增加有一个row id。对于为什么使用row id而不是key
id我想破了脑袋。到最后，我发现我傻了，因为ContentProvider不一定需要使用数据库，使用数据库对应的表也可以没有主键，只有row
id，才能在任何底层介质下做索引标识。<br />
但，基于row
id在删除和修改操作是会造成一定的混乱。删除和修改操作类似。删除操作需要传入一个uri，一个where字串，一组where的参数（做条件判
定...），而修改操作会多一个ContentValues做更新值。着两个操作的uri都支持在末尾添加一个row
id。于是混乱就出现了。当在where参数中指明了key id，而在uri中提供了row id，并且row id和key
id所指函数不一致的时候，你听谁的？示例代码中的做法是完全无视row
id（无语...），如此野蛮的方式我估计也只能在示例中出现，在实际中该如何用，恩，我也不知道。幸运的是，我看了下上层对
ContentProvider的删除操作，其实都不会直接进行，而是通过调用Cursor的delete方法进行，在这前提下，我想Cursor会处理
好这些东西吧。<br />
最后一个操作是查询操作，可以想见，查询的参数是最多的，包括uri和一组条件参数。条件参数类型和标准的sql类似，包括
sort, projection
之类的。从这些参数到sql语句的生成，可以寻求QueryBuilder类的帮助，它提供了一组操作接口，简化了参数到sql的生成工作，哪怕你不懂
sql都完全没有问题（这话说的我自己都觉得有点悬...）。查询返回一个Cursor。Cursor是一个支持随机读写的指针，不仅如此，它还提供了方
便的删除和修改的API，是上层对ContentProvider进行操作一个重要对象，需要仔细掌握（Cursor还可以绑定到view上，直接送显，
并与用户进行交互，真是程序越往上，封装越好，工作越机械没有复杂性了...）。<br />
<br />
<font size="4"><span style="font-weight: bold;">数据模型</span></font><br />
在
与界面打交道的Cursor、ContentResolver等数据操作层中，大量采用观察者模式建立数据层与显示层的联系。一个显示层的视图，可以做成
某一种观察者注册到Cursor或ContentResolver等数据中间层中，在实现底层ContentProvider中，我们需要特别注意在对数
据进行修改操作（包括增删改...）后，调用相应类型的notify函数，帮助表层对象进行刷新（还有一种刷新方式是从一个view发起的）。可以看到
Android的整体数据显示框架有点像MVC的方式（贫瘠了...叫不出名）。Cursor、ContentResolver相当于控制层，数据层和显
示层的交互通过控制层来掌管，而且控制层很稳定不需要特别定制，通常工作只在定制数据层和显示层空间，还是比较方便和清晰的。<br />
<br />
<font size="4"><span style="font-weight: bold;">一个设计问题</span></font><br />
现
在有个设计问题，比如我要扩充一个已有的ContentProvider（第三方提供），我是建立一个ContentProvider，只保留第三方
ContentProvider的key信息，并为其添加更多的信息，在表层维护这两个ContentProvider的联系好；还是建议一个
ContentProvider，以第三方的ContentProvider做一部分底层数据源，像表层提供一个ContentProvider好。<br />
前者无疑在实现上简单一些，如果第三方改变，灵活性也更好，只是需要仔细维护表层的相关代码。后者实现上需要付出大量的苦力劳动，当表层使用会简单多了。我举棋不定，期待你的意见。。。<br />
</span>
<img src ="http://www.cnblogs.com/duguguiyu/aggbug/972060.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41921/" target="_blank">[新闻]Internet 另一超级漏洞被公布</a>]]></description></item><item><title>Study on Android【一】--概述</title><link>http://www.cnblogs.com/duguguiyu/archive/2007/11/17/962325.html</link><dc:creator>duguguiyu</dc:creator><author>duguguiyu</author><pubDate>Sat, 17 Nov 2007 02:36:00 GMT</pubDate><guid>http://www.cnblogs.com/duguguiyu/archive/2007/11/17/962325.html</guid><wfw:comment>http://www.cnblogs.com/duguguiyu/comments/962325.html</wfw:comment><comments>http://www.cnblogs.com/duguguiyu/archive/2007/11/17/962325.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cnblogs.com/duguguiyu/comments/commentRss/962325.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/duguguiyu/services/trackbacks/962325.html</trackback:ping><description><![CDATA[<p goog_docs_charindex="1"><span style="font-size: 10pt">如果你还不知道google的重磅炸弹Android（中文意思是机器人...感觉google取名字的天赋全部花在google这个词上了...）是什么，你可以看一下</span><a id="q89_" title="这里" href="http://code.google.com/android/" goog_docs_charindex="82"><span style="font-size: 10pt">这里</span></a><span style="font-size: 10pt">。如果你觉得挺没有意思，再看一下</span><a id="b0no" title="这里" href="http://code.google.com/android/adc.html" goog_docs_charindex="102"><span style="font-size: 10pt">这里</span></a><span style="font-size: 10pt">。如果还觉得不好玩，那下面的东西就不需要看了。。。</span></p>
<p goog_docs_charindex="132"><span style="font-size: 10pt">对我来说，Android还是很有吸引力的，不然一个MS技术的忠实走狗也不至于一下就投入java的怀抱。至于为什么？恩，等我有八卦精神的时候再使劲的侃。</span></p>
<p goog_docs_charindex="209"><span style="font-size: 10pt">在这里还是谈正事的要紧。这几天看了下Android SDK，编了几个练习，获得了一点点经验。简单的罗列一下，比较重要的内容都添上链接，也是方便我和所有需要的人查看。</span></p>
<p goog_docs_charindex="293"><span style="font-size: 10pt">&nbsp;</span></p>
<p goog_docs_charindex="294"><span style="font-size: 10pt">按google的说法Android包括一个操作系统，一些中间件和核心应用程序。操作系统是基于Linux的，上面的东西用了些开源的、google也花了不少精力开发了其他一些东东。底层用的是C++，但所有供应用程序开发的API都是java的（伪托管操作系统？^_^）。具体内容可以看一下</span><a id="m6pg" title="这里" href="http://code.google.com/android/what-is-android.html" goog_docs_charindex="436"><span style="font-size: 10pt">这里</span></a><span style="font-size: 10pt"> 。基本上不会与你闭着眼睛幻想的有太大区别。