<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>OneEyeWolf</title>
    <description>心如止水，宁静致远。</description>
    <link>http://oneeyewolf.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>电子商务网站的可持续发展</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/152136" style="color:red;">http://oneeyewolf.javaeye.com/blog/152136</a>&nbsp;
          发表时间: 2008年01月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p goog_docs_charindex="1">电子商务网站的可持续发展&nbsp;</p>
<p goog_docs_charindex="16">&nbsp;&nbsp;&nbsp;&nbsp; 2007年终于过去了，从焦油坑里爬出来幸存的人们，互相握手庆幸，喜极而泣，纷纷在博客上写工作总结与来年展望，而我终于厌倦了期权的精神鸦片，难得的坐下来，远离自己负责的网站，想一想来年的布局。</p>
<p goog_docs_charindex="16">&nbsp;&nbsp;&nbsp;&nbsp; 在国家大力宣扬环保，可持续发展的时候，从企业，从网站，就我个人，都要讲一个可持续发展，一夜暴富的思想只会浪费精力，没有方向，而只有平时注重积累，厚积薄发，终会有从量变到质变，扭转局面的时候。&nbsp;</p>
<p goog_docs_charindex="16">&nbsp;&nbsp;&nbsp; 我们发力在向前奔跑的时候，也要适时的停下来，倒掉鞋子里的沙子，让自己的步伐更轻快。&nbsp;</p>
<p goog_docs_charindex="104">&nbsp;&nbsp; 我所经历过电子商务网站都面临的下面的问题，如何让自己步子慢下来，解决这些问题，持续发展，是一个从管理和技术层面上，都比较有挑战、让人兴奋的问题：</p>
<p goog_docs_charindex="104">1.膨胀</p>
<p goog_docs_charindex="104">&nbsp;&nbsp;&nbsp; 公司业务向好，代码越加越多，原来一个人写一个类时，只是完成一两个单一的功能，随着需求的变化，一个核心类的代码，不知不觉膨胀到一两千行，有的Action代码，也会超过1000行。接手的人，一般不敢动，也不愿意动接手的代码，也就是说，他不会去重构以前的代码，一般就是线性的随着需求的增加，代码也不断的增加，同时在开发时，总是八股文开发，很机械、迂腐的套用一些重型的、所谓的J2EE设计模式，如Factory, DTO, Proxy等等，代码量和代码复杂度最终是线性增加。</p>
<p goog_docs_charindex="104">&nbsp;&nbsp;&nbsp; 则代码复杂度和行数的膨胀，会是负面循环，反过来影响你面对需求变化时态度。</p>
<p goog_docs_charindex="104">&nbsp;&nbsp;&nbsp; 举一个例子，从用户角度来讲，订单上增加一个字段的小需求，应当是很简单的一件事，但是对开发人员来说，增加一个字段，则要确认所有与订单相关的页面（相关的界面可能有十几个）都要修改、重新布局，这个工作量可不小，而且容易漏改。这不是一个容易避免的事情，不仅是页面，类也要修改。很多人写的关联查询，结果放在DTO类而不是Map,扔到页面上的话，则DTO类也要修改。</p>
<p goog_docs_charindex="104">&nbsp;&nbsp;&nbsp; 一般的性能问题，总是由开发人员的代码造成的，而不是由架构的Scalability瓶颈所造成的，累积的代码，就像电器上日积日厚的灰尘一样危险，随时会短路。以前的僵尸代码，会在数据量和访问量慢慢增长到某一个临界值的时候，突然复活，搞得你灰头土脸。&nbsp;如果你只会批评开发人员不小心，那种永远也解决不了问题，让谁写，都不能保证不会踩上地雷。领导不出BUG，只是因为他们不写程序。</p>
<p goog_docs_charindex="928"><br goog_docs_charindex="929" />
3.&nbsp;铁打的营盘，流水的兵<br goog_docs_charindex="113" />
&nbsp;&nbsp;&nbsp; &nbsp;第一个人下棋，下到中途，离开了，第二人接手，接着下，以后可能会有第三个人，接手的人，怎么下怎么不顺，这时总想重新下一盘，但没有选择，只能一边问候着前人的老妈，一边继续走。最后，我们再把这盘棋复盘来看，做成一个棋谱，会有什么的感觉？</p>
<p goog_docs_charindex="928">&nbsp;&nbsp;&nbsp; 这一般不是两个人能力差异的问题，是一个心理的问题，每个人都不愿意看别人的代码，都觉得别人的代码写的烂，不愿意花点时间，来review同事或者前人代码，他们认为这是考古学家的事情。这样的结果，如果不了解别人的代码，就无从重构，在此基础上增加功能或修改，只能说是乱上加乱。&nbsp;&nbsp;</p>
<p goog_docs_charindex="928">&nbsp;&nbsp; 要包容别人的代码，现在不是找出是谁造成的，而是要从自己接手这一刻，开始改进。</p>
<p goog_docs_charindex="928">&nbsp; 打江山的人，所基于的环境，是非常恶劣的，是非常不容易的，从无到有的创建一个网站的老员工，一个人做三个人的活，是非常值得尊敬的，接手别人，再怎么说，也是站在别人的肩膀上考虑问题。其实让你先下，让第二人再接手，他也会这么有同样的思维，我们需要的是宽容，宽容与谅解应当是自上而下的，而不是自下而上，不然就变成，项目经理说：我体谅你们，可领导不体谅我啊。</p>
<p goog_docs_charindex="928"><br goog_docs_charindex="428" />
4.新来的员工不是考古学家&nbsp;&nbsp;&nbsp; </p>
<p goog_docs_charindex="446">&nbsp;&nbsp;&nbsp; 新来的员工抱怨个不停，确实是很讨厌人，另一方面，从他的角度上来讲，没有选择的权力，必须在别人代码的基础上增加新的功能或修正一些BUG，你不能用你最擅长的东西，当别人的代码是JSP+Servlet，你就用这个，你必须要遵守这个规则，同时也要遵守别人的开发习惯。&nbsp;</p>
<p goog_docs_charindex="446">&nbsp;&nbsp; 新员工就像一个考古者，站在一段象形文字的文物面前，来想出前人的意图，确实非常的艰难。&nbsp;&nbsp; </p>
<p goog_docs_charindex="446">&nbsp;&nbsp;&nbsp; 所以每个公司的每个项目组，都应当向HR部门学习，制订一个良好的新员工入门索引，这个索引有什么内容，每个人根据自己的项目，自己来考虑。这样的索引目录可以重用，不用来一个要讲一遍，占用项目经理的时间。&nbsp;</p>
<p goog_docs_charindex="446">&nbsp;&nbsp; 一般的人，都是被动的，8个小时，怎么过，都是过，平时不会去看别人的代码，只是在自己承担一个任务时，才会去看那些相关的代码，这样就会时间太紧了，手忙脚乱的，容易出错。所以在平时，就要强制性的review代码，是必须要的，你不能信赖别人的主动性，否则的话就是自食苦果。&nbsp;</p>
<p goog_docs_charindex="587">5.脆弱的测试体系&nbsp;</p>
<p goog_docs_charindex="708">&nbsp;&nbsp; 长期膨胀，得不到改进、重构的代码，每有新功能开发，测试的代价非常、非常的高，因为非常容易犯错。</p>
<p goog_docs_charindex="1169">&nbsp; 很多的公司并没有一个良好的自动化回归测试体系，所带来的人工成本就是非常高，测试人员所做的工作，就是民工扛水泥包，又脏又累，测试覆盖的效率又差。&nbsp;</p>
<p goog_docs_charindex="1245">&nbsp;&nbsp; 频繁ReOpen的BUG，会牵累process当中每个环节的人，配置管理员，测试人员，开发人员，TeamLeader，也会影响到考核。带来的众多的参与其中的人，随着运转，打标签，提交测试，打回，修改、再打标签、再提交测试（此时所有开发人员的BUG都要改完才能提交），测试人员重新测试（原来已经测试通过的功能，还要再测试一遍），重复N次。&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p goog_docs_charindex="1245">&nbsp;&nbsp; 其实我们自己从开发，到测试部门，都可以不要对立，坐下面交流，来去考虑如何改进。测试部门可以指导开发树立测试的意识、思想、技巧，开发人员必须要承担测试，不仅要写单元测试，也要做功能测试，也要会自动化测试，这些除了可回归的单元测试，很艰难，不容易做，但可以一步步的改进，其它的比如自动化的界面测试，其实是很容易的，花个两天时间，把成员关在会议室里，搞Win runner界面测试，编写可重用的测试脚本，定制有效的、覆盖关键路径的、可重用的数据源，还是能收到成效的，这样当需求变化时，那些没有变化的功能，其脚本也不变，都可以在短时间内回归的测试一遍，而不要把成本直接转嫁到测试部门。&nbsp;</p>
<p goog_docs_charindex="1245">&nbsp; 关键是要不要走出第一步。&nbsp;不知道为什么领导总是愿意相信冶百病的偏方，相信永动机，相信不会犯错，项目不会延期、百战百胜的神人。&nbsp;不要再花钱找一些天桥说书、卖大力丸的QA了。其实没有一个人可以驱动一个庞大的团队，还是要靠团队中的核心都行动起来。</p>
<p goog_docs_charindex="1412">5.缺乏从宏观层面技术标准的概念统一和定义</p>
<p goog_docs_charindex="1412">&nbsp;&nbsp;&nbsp;&nbsp; 随着业务的发展，有很多的合作型的项目，子系统越来越多，同时要外接的系统越来越多， 做为一个分销的平台，可能要和外接的B2B系统对接，即要给别人在公网上发布接口，又要从第三方的系统获取产品数据源，这种系统与系统之间的数据交换，缺乏统一的标准，各种各样的技术都可能有，又有不同的项目组负责，各自为政，这不是他们的问题，他们不是CTO，不是架构师。&nbsp;&nbsp;&nbsp; </p>
<p goog_docs_charindex="1412">&nbsp;&nbsp;&nbsp;&nbsp; 从全局的基础上，对系统的服务基础设施建立一套共同的抽象规范，从架构师的层面，进行控制。</p>
<p goog_docs_charindex="1412">&nbsp;&nbsp;&nbsp;&nbsp; 主要有：</p>
<p goog_docs_charindex="1412">&nbsp;&nbsp;&nbsp;&nbsp; 1.服务的分类（支付网关、消息网关、中央工作流引擎、中心缓存服务、外部数据源对接服务、B2B订单预订接口服务等），以及各类服务的设计原则和建议 </p>
<p goog_docs_charindex="1412">&nbsp;&nbsp;&nbsp;&nbsp; 2.服务的技术标准定义与约束，耦合关系和原则的设计规范等</p>
<p goog_docs_charindex="1412">&nbsp;&nbsp;&nbsp;&nbsp; 3.服务调用的接口详细定义与约束，如此服务所支持的并发数的限制、超时调用的限制等。&nbsp;&nbsp;&nbsp;</p>
<p goog_docs_charindex="1412">&nbsp;&nbsp;&nbsp;&nbsp; 4.统一技术标准和约束（如统一使用spring, ibatis, struts2, jquery等），不滥用，注重有效积累，&nbsp;减小对后来的人增加维护难度，但确定下来的技术，新来的人都要强制先学习，从心理上接受这些技术，先期消化这些技术曲线，避免临阵磨枪，好事变成坏事。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p goog_docs_charindex="1544">5.被动的迎接变化,缺乏主动</p>
<p goog_docs_charindex="1544">&nbsp;&nbsp; 规划是很重要，但总有跟不上变化的时候，不可能有一劳永逸的架构和平台，初期业务和业务系统都是不成熟的，你在做一个系统时，可能只有两三个人的团队，所做的也只是一个初期的业务，你不可能想到，未来我的系统可能要与114合做，要与某某网站合做，当这个变化来时，你才能去做这个设计。</p>
<p goog_docs_charindex="1544">&nbsp;&nbsp; 例如你只知道大陆酒店的业务，当你的业务要扩展到香港、海外的时候，他们的业务规范与国内的差别非常大，新的业务有可能在推翻你前期的设计。&nbsp;</p>
<p goog_docs_charindex="1689">&nbsp;&nbsp;&nbsp;你的系统要和某某网站一个合作业务，要个某某银行合做一个信用卡联名卡业务，这些合做型的项目，对方都是强势的，你不是规则的制订方，你是接受规则的一方，你在欣喜公司的业务蒸蒸日上的同时，恭喜你！你的系统的复杂度，也在蒸蒸日上。&nbsp;</p>
<p goog_docs_charindex="1802">&nbsp;&nbsp; 唯一的办法，就是要去主动的重构，对系统和代码的复杂度降维，轻装上阵，在一个更有利的位置，拥抱变化。当然重构不是阳春白雪，不慎会带来新的不稳定因素，只要是对代码进行变动，都会引入风险，特别是遗留代码, 你在擦拭灰尘的时候，却不小心把桌上的瓷器给打破了，这时候主人肯定不会表扬你的勤劳。不管怎么样，这是你负责的项目，你跑不了，主动一点，总比束手待毙强。&nbsp;</p>
<p goog_docs_charindex="1833">&nbsp;6.人力的焦油坑</p>
<p goog_docs_charindex="1848">&nbsp;&nbsp;&nbsp; 人月神话这本书，只是给出版业带来了繁荣，平时的我们总是一遍又一遍的从一个焦油坑出来，又掉到另一个焦油坑里去，可见看书是没有用的。&nbsp;</p>
<p goog_docs_charindex="1848">&nbsp;&nbsp;&nbsp; 由于难以维护的系统，总是拖累正常配置的人力，使你感觉到人手总是他妈的紧，连正常的需求开发、BUG修正都满足不了，那有时间重构。所谓人力恶性循环，就是好不容易一个熟悉代码的人，培养起来，他也厌倦了，拍屁股走人了，再招人，就得招两个人，因为系统的复杂度又增加了，需求又增加了。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p goog_docs_charindex="1848">&nbsp;&nbsp;&nbsp; 这样的结果很可怕，没有时间来与时俱进，没有时间做提高用户体验、有价值的、增强用户粘性的功能了，没有创造性的工作，那些有创造力的人最终会含狠而去。&nbsp;</p>
<p goog_docs_charindex="1848">&nbsp;&nbsp;&nbsp; 增强人力资源的储备和技术储备，是一个有效的措施，在平时做，而不是到关口了才想起，手忙脚乱的。&nbsp; </p>
<p goog_docs_charindex="1848">&nbsp;&nbsp;&nbsp;&nbsp;招聘人，要招self-proactive的人，能够带来变化，能够解决问题，而不是抱怨的人，等着妈妈把饭嚼完送到嘴里的小鸟，否则就是效果相反，就造成了，加人，越加越累，因为你所加的，都不是解决问题的人，而且加人的时机也不对，平时，都没有储备，关键时候，才想起要人，太晚了。&nbsp;&nbsp; </p>
<p goog_docs_charindex="1848">&nbsp;&nbsp;&nbsp; 考虑一下，随便招一个普通的程序员，对于周围关联人的影响和所带来的成本：<br />
&nbsp;&nbsp;&nbsp; 增加一个测试人员的工作量（可能他的BUG增多），增加美工的工作量（他不会写页面，不懂JS,不懂CSS），增加项目经理的工作量，增加TeamLeader的工作量（做培训计划,讲需求，讲技术)，增加DBA的工作量（因为他不懂数据库，老写一些让服务器心脏博起的SQL 代码）。&nbsp;&nbsp;</p>
<p goog_docs_charindex="2239">7. 松散的组织架构</p>
<p goog_docs_charindex="2239">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;一个网站，大的网站，几十个频道，一般的也有十几人项目组，他们在维护同一个网站，彼此之间的联系很多，共同点也很多，看起来应当统一，都是自己人，也不难统一，但是现实却是非常的艰难，却如此的松散。&nbsp;&nbsp; </p>
<p goog_docs_charindex="2239">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 任何东西，自下而上，所带来的必然是混乱和无序，考虑一下从组织架构上来改变，建立CTO team，从全局的范围内，自上而下的推动、控制，加强全局控制力，改变各个频道或项目组各自为政的情况。将复杂的东西控制在上层，而不是程序员中间，任由其蔓延。</p>
<p goog_docs_charindex="2239">&nbsp;&nbsp;&nbsp;&nbsp; 改变架构师缺位，吃白饭的现状，公司不是养着架构师，学习新技术的，满口之呼者也，酸腐的人，谁都要学习，但要去一线解决问题。</p>
<p goog_docs_charindex="2239">&nbsp;&nbsp; 架构师要有责任，要有技术领导能力，要去Push别人，当开发人员在造轮子的时候，首当其首，责任就是架构师，如果开发人员在重复，还要你架构师做什么？很多开发人员自己写，是因为没有办法，他也不想写，但是现有的代码库当中，没有，或者没有他适合用的东东。</p>
<p goog_docs_charindex="2239">&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/152136#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 01 Jan 2008 11:26:54 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/152136</link>
        <guid>http://oneeyewolf.javaeye.com/blog/152136</guid>
      </item>
      <item>
        <title>好事要做到底，我们需要full stack的设计</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/150673" style="color:red;">http://oneeyewolf.javaeye.com/blog/150673</a>&nbsp;
          发表时间: 2007年12月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>full-stack 的设计，意味着各层能够无缝的集成在一起，遵循的DRY原则（don't repeat yourself)，将各层共用的东西，抽取出来，并通过自顶向下的设计，无缝的集成在一起，粘合在一起，达到更高层次、更粗粒度的重用，同时为了保证灵活的可扩展性，在更高、更粗的粒度上遵守开放-封闭的原则，在各层的各个关键点，要提供诸多的钩子，回调的接口，供使用者扩展。full-stack的设计，在层与层之间，并不一味的追求松散的机制，而是相反，在层与层之间增强一定的内聚性，粘合力，以此来达到粗粒度的封装与重用。</p><p>&nbsp; 可以说full-stack 的设计，其爆发出的威力是巨大的，相对普通的单一层面的设计，在开发效率上不是一个层次上的，基于28原理的设计，可以满足80的调用者直接开发，19%的调用者，通过扩展点进行扩展来满足需求，对于1%钻角尖的需求，自己去造轮子。 </p><p>&nbsp; spring, ruby on rails, Zend都是这样的工业级强度的full-stack的设计，我们的设计如果以他们为中心，生产力得到了极大的提高。</p><p>&nbsp; 但是我现在厌倦了，屁大的事，就要装模做样的写一个DAO，写一个Service，写一个Action，再写一个JSP，八股文式的开发模式，味同嚼蜡。我们的代码仍然在急速的膨胀了，我们仍然感觉很累，我们的千行代码出错率仍然没有减小，这不是个好事情。</p><p>&nbsp; 有人说，这就是设计吗，这连头猪都会。</p><p>&nbsp; 我做了电子商务网站多年了，无论是管理还是技术，都非常的有挑战性。</p><p>&nbsp; 从用户角度，前有看不见摸不着、挑剔的、脾气暴躁的互联网用户，后有工作量巨大、业务繁忙的后台业务部门用户，他们狠不得，用魔法棒，一指，网站上就会有这个功能，时间不等人。</p><p>&nbsp; 可是电子商务网站角度来讲，不同于一般的内容门户网站，出个错没有什么大不了的，当用户在我们的网站上看到的一切东西都是有法律效力的，当用户下单成功交易的一瞬间，这种关系已经实施，出个错，谁也担当不起，大家不记得DELL门事件，网上直销价格报错了，引出了多大麻烦，在外面，有公司担当着，在公司内部，估计当事人，也是痛苦的不得了。&nbsp; </p><p>&nbsp; 我们即要追求快速开发，以用户为中心，拥包变化，又要保证工业级的强度的稳定。</p><p>&nbsp; 一般的发包，从需求收集，明确，整理，发布release计划，拉分支，开发，内部测试，提交功能测试，压力测试，on stage, on production，上线跟踪测试, 合并分支, 这样的流程，一个环节都不能少，不能出漏子（当然只是从理论上保证）。<br />&nbsp;&nbsp; 这样即使一个月发一个包，开发时间不过10多天左右，这样的发包速度，还是满足不了要求。当我们对他们说，这个功能，下个月才能上线，用户会无辜的睁大双眼，看着你。<br />&nbsp;&nbsp; 所以在设计这个层面上，我们需要更多的重用，更多的粗粒度的，工业强度更强的重用，可以更高层次的在大大提高我们的开发生产力同时，减小我们出错的概率，当你的程序出错的时候，你一般不会就认为是springe的BUG造成的吧，是自己的代码出错。&nbsp;</p><p>&nbsp;&nbsp;&nbsp;我们不需要供养着一批只是评审工具的、满嘴术语、动不动就用可用性、可扩展性之类的Matrix表格让我们看他们的评估结果的架构师。</p><p>&nbsp;&nbsp; 我们也不需要满口hign-performance、large-scale、群集、ajax，光说不练的家伙，对于一个成熟的电子商务网站来说，基于Scalability的架构已经趋于稳定，并有专有团队来维护，用不着你来天天搞群集。</p><p>&nbsp;&nbsp; 我们也不需要只会写个JAVA类的所谓的设计师。&nbsp; </p><p>&nbsp;&nbsp; 我们需要的是full-stack的设计，我们需要的设计师，对于互联网应用来说，三层都应当相对精通，就像习武之人，任督二脉都打通那种高手，才是NB的高手，从front到database，都有要丰富的经验。</p><p>&nbsp;&nbsp; 我们需要的是基础扎实的，有热忱的设计师，能够真正的帮助开发人员解决问题，提高生产力，而不是那种只提供约束、规范，不提供方法，不解决问题的人。&nbsp;</p><p>&nbsp;&nbsp; full-stack设计体现的是一种设计思想，是要在不管是微观还是宏观层面上，去应用这种思想，并不是要一定要设计出像spring那样大的东东来，也不可能。&nbsp;</p><p>&nbsp;&nbsp; 我以一个电子商务系统当中的业务基础数据字典子模块的设计（很多人都做过，可以做一个对照），在一个三层切面，论述一下full-stack的设计的具体应用：&nbsp;&nbsp; </p><p>1.抽象描述层需求</p><p>(1)表现形式：下拉框、单选框，多选框，列表框，表格，文字<br />&nbsp;&nbsp;&nbsp; 不同的数据有不同的展现形式,&nbsp; 同一数据在不同的页面，也有不同的表现形式<br />&nbsp;&nbsp;&nbsp; 例如：我们在旅游网站上看到的，有的网站在选择城市时，是下拉框选择的，有的是弹出窗口，并将所有的城市按表格的形式列出来的， 还有的就是列表框显示的</p><p>&nbsp;&nbsp;&nbsp; 对于多选框，一般都需要自动添加一个全选的checkbox，并生成全选事件，不要调用者自己再写。<br />&nbsp;&nbsp;&nbsp; 如果是下拉框，要能够自动添加一个&ldquo;请选择&rdquo;的option或者从传参数中指定一个header.&nbsp; </p><p>&nbsp;&nbsp;&nbsp; 默认选中值，当传入默认值时，能够设置默认选中。</p><p><img src="../../../../topics/download/6236c704-e536-4dbb-bf89-2f82776bba74?disposition=attachment" alt="" /></p><p>(2) 控件事件模式<br />&nbsp; 要能够提供Callback，如Listener、Observerable模式的事件注入。&nbsp;</p><p>(3)基础数据在页面上的布局方案，<br />&nbsp;&nbsp; 基础数据是放在Table的TD单元当中，还是DIV当中<br />&nbsp;&nbsp; 对于多选框的展现与布局，当多选框多的时候，使用表格来布局，来保证换行时，自动对齐。</p><p>(4) 数据转换与渲染</p><p>&nbsp;&nbsp; 在页面上，能够将ID值，转换成用户可读的文字值，如订单状态1转换成已成交，2已配送，3，已取消的形式。&nbsp;</p><p>(5) 前后台数据交换机制：</p><p>&nbsp;&nbsp;&nbsp; 你可以使用异步应用，如ajax来解决问题，也可以使用同步的如JSP标签来解决问题。</p><p>&nbsp;&nbsp;&nbsp; 基于ajax的前后端数据交换格式：XML, JSON, DWR, 自定义等等。<br />&nbsp;&nbsp; 作为你自己的单独的应用，没有必要这么花哨，无论那一种，都可以。但如果是作为开源的、或者是商业产品，给未知的应用调用，就要考虑可扩展性，让调用者可以扩展，使用自己熟悉的方式，如EXT提供了XML,JSON都多种reader，你也可以扩展与DWR集成。&nbsp;</p><p>2.抽像后台需求</p><p>(1)多数据源的屏蔽：XML文件配置、properties配置、本地数据库表、远程Webservice接口。</p><p>&nbsp;&nbsp;&nbsp;&nbsp;如果是基于页面指定的查询条件，动态查询的接口，如类似于ibatis的查询接口</p><p>&nbsp;&nbsp;&nbsp; List ds.queryForList(queryID, paramMap)&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; </p><p>(2)排序</p><p>&nbsp;&nbsp; a、不同的基础数据在页面显示时，有不同的排序需求</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如城市是按拼音排序的，<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 订单操作步骤数据是按序列号来排序的<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 没有要求的，默认是按录入顺序来排序的&nbsp;&nbsp; </p><p>&nbsp;&nbsp;&nbsp;b、排序即可能在后台排序，也可能在页面上基于javascript排序<br />&nbsp;&nbsp; 所以无论是在前端，还是在后台，都要提供一个倒钩接口，让调用者可以按自己的要求对数据进行排序。&nbsp;</p><p>(3）分布式环境的要求<br />&nbsp;&nbsp;&nbsp; 分布式在中大型的电子商务当中，几乎是必须的，作为底层的支持，为其它分布在不同服务机器上的应用都要提供共用的的基础数据，同时要缓存，当数据修改后，要刷新缓存，并要通知第三方的应用。如机票、酒店、自由行、呼叫中心、配送、结算中心等等十几个子系统应用都要调用城市、支付网关列表等数据。</p><p>(4) 数据管理<br />&nbsp; 添加、修改、删除基础数据的权限.<br />&nbsp; 数据排序处理。</p><p>(5) 缓存<br />&nbsp; 缓存是一定要有的，一个是数据中心的缓存，当远程调用者又在本地做缓存时，数据变化时就要提供远程通知的接口，否则调用者客户羰的数据就不会自动刷新。</p><p>&nbsp; 缓存，可以基于spring+EHCache，配置缓存方案和策略。也可以通过适配器外接到其它的缓存配置方案上。</p><p>设计实施:</p><p>BasicData.config:{</p><p>&nbsp;&nbsp;&nbsp; type:'select',//*下拉框、单选框，多选框，列表框,&nbsp; 文字, tbody</p><p>&nbsp;&nbsp;&nbsp; id: 'select_id', //*指定绑定的控件ID，如果ID不存在，则系统会创建指定类型的控件，否则就绑定</p><p>&nbsp;&nbsp;&nbsp; name:'city',//控件名称，不是必须的</p><p>&nbsp;&nbsp;&nbsp; parentID:'div_city', //*父类容器ID，如果容器ID是tbody，则数据会自动填充到表格当中</p><p>&nbsp;&nbsp;&nbsp; defaultValue:'1,2,3', //默认值，对于多选框，多个默认值时有逗号隔开</p><p>&nbsp;&nbsp;&nbsp; resourceId:'', //*传给后台的基础数据标识，根据此代码，可以获取到指定的基础数据，如送票城市、转账银行等。</p><p>&nbsp;&nbsp;&nbsp; autoCreaeSelectAll:'y', //是否自动生成全选&nbsp;</p><p>&nbsp;&nbsp;&nbsp; header:'请选择',//如果是下拉框或列表框，要生成一个header</p><p>&nbsp;&nbsp;&nbsp; event:{name:'onchange', event:'changeChild'}, //事件监听</p><p>&nbsp;&nbsp;&nbsp; comparator:'compare',//排序比较函数，</p><p>&nbsp;&nbsp;&nbsp; cssStyle:'', //CSS风格</p><p>&nbsp;&nbsp;&nbsp; paramMap:{} //用于后台动态查询的查询参数</p><p>&nbsp;&nbsp;&nbsp; datasource:ds//设置数据源，可以为空，系统自动使用默认</p><p>}</p><p>&nbsp;</p><p>调用者：</p><p>&nbsp;/**</p><p>&nbsp;*获取信用卡列表，进行复选框排列</p><p>&nbsp;<a href="mailto:*@divID">*@divID</a> 你设置的DIV的ID号或其它父控件ID</p><p>&nbsp;<a href="mailto:*@paramName">*@paramName</a> 控件名称</p><p>&nbsp;*/<br />function setCreditCardList(divID_, paramName_, defaultValue_) {</p><p>&nbsp;&nbsp;&nbsp; xBaseData.draw({type:'select', id:paramName_, name:paramName_, parentID:divID_, dfaultValue:defaultValue_});<br />}</p><p>&nbsp;</p><p>整个方案实施的效果<br />&nbsp; 1.几乎是一劳永逸的解决了基础数据的需求问题<br />&nbsp; 2.开放者只需要在页面，一行JS代码或一行标签，就解决了问题，不用关心其它的东西了。<br />&nbsp; 3.使用者已经忘却以往的诸多不便，对一个局部的编码者而言，变化是小的，对于设计者，从全局几十个子系统，上百名开发者而言，效率的提升是显著的。所以设计者的格局要大。</p><p>&nbsp; 4.关于基础数据出错的概率，当然减小了。</p><p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/150673#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 25 Dec 2007 11:54:31 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/150673</link>
        <guid>http://oneeyewolf.javaeye.com/blog/150673</guid>
      </item>
      <item>
        <title>业务平台的真的存在吗</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/149545" style="color:red;">http://oneeyewolf.javaeye.com/blog/149545</a>&nbsp;
          发表时间: 2007年12月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          相信凡是开发者对用户纷繁复杂的需求，都趋之如虎，从制度上，我们建立了严格的需求变更的process, 从技术上，我们寻求一种所谓的业务平台，寻找一个冶百病的良药，在市场上，有商业软件来推销自己的平台，更在平台上加一个业务两字，真有这种平台吗。<br /><br />关键是我们要对“业务平台”这个词语都没有一个定义，这是个伪明题。<br /><br />像那些平台软件，反复所说的，UI组件之类，这些是业务吗，是与业务无关的东西剥离出来的一种框架解决方案而已，更不能说是平台中的特色吧。<br /><br />就是工作流引擎，也是为了将流程定制、跳转与业务逻辑剥离出来的一种设计思想的实施。<br /><br />表单定制更不是业务，也是与业务剥离的一种方式。<br /><br />而在现实开发当中，做为一个有成熟技术积累的行业软件公司，这些都是个屁，根本不值得一提，早就有了，技术含量也高不到那去。在Delphi时代，他们就有了各种VCL组件、框架，功能比这强大多了，现在WEB软件的MVC框架，甚至spring容器，都只是基础，我们真正关心、头疼的不是这个。<br /><br />在现实当中，真正影响我们，耗费我们大量时间的，对我们进度有很大影响的，就是在现实中复杂的需求，业务逻辑，这些复杂的需求，难以封装，造成复杂的设计、复杂的库表关系，这些复杂的设计，我们都知道越复杂的东西，越不稳定，更容易遭受到需求业务逻辑变化时的冲击。（希望那些做增删改查的人不要跳出来扯淡）<br /><br />比如我们在分销系统时，所基于一种价格、库存模型，如果算法本身发了变化，有的时候，设计不慎，就会造成很大的影响，如果要过早的考虑未来的变化，妄图要封装未来、不可预测的逻辑变化，就变成过度设计，库表结构、程序结构都会复杂的很。<br /><br />做为开发者，我们不可能去避免这些事情，只有依赖自己，我们只有不断的去积累，让自己对用户的业务理解的越来越成熟、深刻起来，不仅能剥离出非业务的技术，实现重用，更能将业务做成可扩展的框架。 <br />比如我们做一个电业局时，我们的设计是一种的设计，我们的可扩展性，特别是针对业务的可扩展性，考虑是有限的，但等我们做到5个电业局的单时，我们遇到了更新的东西，我们对用户的业务，理解更深刻了，我们的设计就越来越成熟，我们再做下一个电业局时我们的变动越来越小。设计也是不断进化的，平台也应当是可进化的，你对用户的需求、业务把握的越深刻，你就越主动，不会背动跟着业务走，很多行业软件公司的constant，都是来帮助用户来规划业务、流程的，这就扯到信息化了，扯远了。<br /><br />希望做业务平台的，可以去了解一下金蝶的BOS平台，用友的U8所基于的平台，这是他们做财务、ERP的长期的业务积累，是他们在有中国特色的MIS，ERP的开发实施的经验积累，是吃了很多的亏，走了很多的弯路，所积累起来的，是给他们自己用的，不是给外人用的。<br /><br />分层，Plug-in, component, framework, platform都只是一种分离粒度不同的技术手段，一种解决问题复杂度、降维的方式，而没有对业务的深刻理解，都是虚假的，而对业务最理解的，当然是你自己了，因为只有你奋站在用户的第一线上了，而不是那些厂商、Constant，他们只想拿到钱就走了，并且不要单心需求变化，因为他们所谓的平台，是和需求、业务没有关系的，而且他们吹嘘的就在此，那就是通用，只需要配置就可以完成一切，其实这是他们降低自己运营成本是一种方式，而不是真正的来解决你的问题。<br /><br />所以我觉得，真正的业务平台，要有生命力，要依赖自己，在技术的基础上，要加强自己对用户业务理解的深刻度，从一开始就打造自己的业务平台内核，在一开始是不成熟的，但要去积累，用孵化的思想，去建设、壮大适合自己用的业务平台。只有自己的平台，才有生命力。
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/149545#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 19 Dec 2007 22:09:05 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/149545</link>
        <guid>http://oneeyewolf.javaeye.com/blog/149545</guid>
      </item>
      <item>
        <title>敏捷-意淫者的天堂</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/145405" style="color:red;">http://oneeyewolf.javaeye.com/blog/145405</a>&nbsp;
          发表时间: 2007年12月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          看了infoq中文站的那篇敏捷之文，又顺藤摸瓜，找到了太极掌门人的网站，作为一个旁观者，仿佛看到两个下盲棋的高人，飘在空中，一个说“炮五平六”，一个说“马8进7”，杀的好不激烈，另有一群评棋之人，或指点，或赞同，或反对，好不热闹。<br /><br />回到JavaEye,却更觉得这是块净地，务实求进，Pragmatic, 是我看到的JavaEye的风格之一。更觉可贵，也更希望保持下去。看到很多追求卓越的人努力的改进自己所在项目的软件过程，虽处在强大的官僚机器之下，力量弱小，却又像一群拓疆之士，在大雪迷漫当中，互相扶拥，奋力前进，自己身处于其中，似乎更加亲切。<br /><br />软件开发本来就是一种抽象的过程，将现实世界的连续的东东，转化成离散的数字，这不可避免的要运用人的思维意识去做这个复杂的事情。那就不可避免的存在了意识膨胀，意识膨胀是管理者、经营者经常容易犯下的错误，不仅仅是IT，在IT当中，更盛行。人们越来越多的所求实际，人们也在努力的改善，避免出现，如“IT三大忽悠”，“皇帝的新衣”，“灯下黑”之类的错误。<br /><br /><br />意识膨胀，常常是我们长时间脱离实际，官僚，形式主义，再加上所决策、控制、工作之事物，本来就是抽象的东西，更加容易犯下错误，在决策时，容易产生错觉，以为所有的资源都在我的控制之下，对于资源的生产力，又过度放大，期望过高，对自己本身，又无限完美，是万物之神。<br /><br />再加上每个人的能力都是有限的，所以要有分工，要有依赖，管理者不熟悉技术就要依赖于技术者，对于不熟悉的事物，思考过于简单，用自己的思维一刀切，来解决自己不熟悉、不了解也不打算去了解的事物、背景, 这种产生了意识膨胀。<br /><br />一些体现如：<br />1.过于激进的进度计划，对于资源的规划，分配，都头脑发热，过于简单。<br />2.自己也做不好的事情，却以为别人能够做好。<br />3.自己能做好的事情，以为别人也能够做好<br />4.以为所有的问题，都是软件过程不好所造成的。<br />5.以为所有的问题，都是由于没有敏捷。<br />6.自己是锤子，其他人都是钉子，砸你没商量，用自己擅长的东西解决不熟悉的事情，如技术者，喜欢对管理说三倒四，却不愿意首先改善自己，管理者一有问题出现，就认为是沟通的问题，是软件过程出现问题。<br /><br />7.过度抽象，喜欢用一些八股文之类的语言，或者火星语，去教训别人，去和别人去沟通毫不相关的问题，这是经常从事抽象工作的人（如consultant, architecture designer)所容易做的事情，所谓的架构、分布式、SOA、构架、敏捷、UP、RUP之类的，脱口而去，倒背如流，看了太极掌门人的文章，又长见识了，经常看到这样的形容词：“科学”。实际上人们的日常工作，和这些都八杆子都打不着。<br /><br /><br />上面的几点，不在于去针对谁，只是对自己的一个警醒。deliver result，result-oriented是老外的企业文化，我在GE公司的墙上，随处可以看到，这也是IT人必须要做的，却又最容易迷失的本质。<br /><br />我也是在努力的少去这些之类的网站，埋头，多写些软件，少谈些主义，我看的文章多了，我就会产生幻觉，以为自己也可以做到，实事上不是。<br /><br />有很多的好的东西，失去了它所必须的条件和环境，又没有足够的资源支持，不过是一坨屎而已。成熟的管理者在公司文化政治当中生存，总是避免激进，追求稳妥，作事先看看有没有足够的资源、背景，所谓天时、地利、人和，如果没有，那就闭嘴，而不是去大叫大嚷，搬石头砸自己的脚。
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/145405#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 02 Dec 2007 12:54:03 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/145405</link>
        <guid>http://oneeyewolf.javaeye.com/blog/145405</guid>
      </item>
      <item>
        <title>SOA穿着华丽外衣的苦力</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/98413" style="color:red;">http://oneeyewolf.javaeye.com/blog/98413</a>&nbsp;
          发表时间: 2007年07月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          　　长期以来，由于IBM等大的厂商，声嘶力竭、不遗余力的宣传，SOA开始在江湖盛传，但掌握着是否实施SOA的权力，掌握在高层的领导手中，而IBM的Sales，则将天花乱坠的Solution，很容易的输入到领导的大脑当中，SOA成为无所不能的利器，而领导对于实施SOA，来改变当前混乱的局面，寄于很高的期望。<br />　　而无论是在IBM、BEA、Oracle等大牌厂商，还是Mule等开源方案，都没有真正的案例，来提供很好的异构系统通信的解决方案，而这正是很多大公司长期以来，所希望解决问题。<br />　　最近在做一个公司的一个信息集成的工作，由于客户在长期信息化的过程当中，积累了多个IT遗留系统，在工作开始，客户便指定SOA作为一个基础架构的方案。<br />　　但实际上，客户当中的多个遗留系统当中，一部分是基于ASP＋SQLSERVE的系统，一部分是Jsp + Oracle系统，同时这些系统，物理位置也是分散在各地的。<br />　　而客户由于预算的原因，原则上在原有系统上不做较的大改造。<br />　　我研究了这些产品，没有这方面很好的支持，对于基于Java的集成当然是比较容易，但对于异构的支持，仍然要做大量的工作，例如让ASP系统来提供Webservice无异行不通，只能通过Http等通信方式来进行XML数据交换。仍然要写很多丑陋的代码，一些技术人员希望在内网通过异构数据库之间的数据交换方式或通过将存储过程发布服务的方式来解决问题，这无异又将服务直接依赖于底层数据格式上，背离了SOA的原则。<br />　　这也就算了，但领导受Sales的影响，固执的认为可以很容易的进行集成，给开发造的预算很少，都放在购买产品和服务上了。<br />　　
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/98413#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 06 Jul 2007 11:38:52 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/98413</link>
        <guid>http://oneeyewolf.javaeye.com/blog/98413</guid>
      </item>
      <item>
        <title>精心打造Team的组织架构</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/86333" style="color:red;">http://oneeyewolf.javaeye.com/blog/86333</a>&nbsp;
          发表时间: 2007年06月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial">精心打造Team的组织架构</font></p>
<p><font face="Arial">　　长期以来，很多Team的组合都是随意的，从创建到稳定,　不经意之间，一个Team就出世了，在项目进行当中，弊端尽现的时候，也没有人注意到是团队的组织架构，人员搭配是否出现了问题，Team成长过程，就好像一个树籽落在地下，然后自生自灭，有的长成了歪脖子，有的则树倒猢狲散，有一部分，运气好，成为能经风雨的大树。　　<br />
　　<br />
　　几年来，虽然敏捷管理与开发，深入一些经验丰富的PM和开发人员之心，但是在推广时，却南桔北枳，没有了味道，</font></p>
<p><font face="Arial">　　一些优秀的开发与设计思想或技术，如TDD、MDD，大部分只流转于个别经验丰富的开发人员之间，在团队项目开发中，不见了踪影。</font></p>
<p><font face="Arial">　　这些都非常不利于个人和团队开发经验的积累，更不利于推广。</font></p>
<p><font face="Arial">　　虽然这方面的缘由甚多，例如，在大公司，更倾向于按部就班的，流水化作业的形式，大多的领导，希望以文档驱动的方式，来进行作业。例如在Microsoft，也是个别的团队首先偷偷摸摸的搞起敏捷，然后才得以向其它团队推广，但推广的方式是思想沟通、培训多于实际运作。（见CSDN程序员２００６年杂志）。</font></p>
<p><font face="Arial">　　连Adobe这样有名的技术主导型的公司，，也不过是在2006年开发CS３的时候，才改变以往，吃尽苦头的，BUG成堆的，瀑布式运作方式，开始转向迭代增量开发。（虽然虽然迭代，在９０年代，就已经开始了）</font></p>
<p><font face="Arial">　　参见：Adobe edits the development cycle　http://www.regdeveloper.co.uk/2007/03/08/adobe_cs3_development/<br />
　　当时采访Adobe photoshop团队时，一个很直接问话：<br />
　　If it's such a good idea, why did it take so long &ndash; and how did you manage to change this time?　（如果这是一个非常不错的方法，为什么你们到现在才开始使用？你们是如何在这次项目当中，转变自己的？）<br />
　　<br />
　　但是更多的方面，还取决于团队中的每一个member.首当起冲的是Leader，是否有丰富的开发经验，是否有执行力，是否有Open的精神，能否坚持不懈的把敏捷这种思想，通过不同的形式，一点一点的展现或灌输给团队。<br />
　　一个自适应的团队，首先要来自于一个自我调节的Leader，能够通过沟通、持续改进等方式，来不断的调整自己的管理方法，不断的改进开发的过程，并且能不断的改进团队的思想，使团队的成员，不断的成长。<br />
　　Leader也需要学习，需要成长，在敏捷的团队当中，大家都是互补的，不存在junior, senior之分。</font></p>
<p><font face="Arial">　　所以团队的精心打造，就在于互补，很多领导寄希望于万能的Leader,　这往往是失败的开始，Team Leader往往成为进度的瓶颈，delay的主要因素，为什么？因为他只是扮演了一个救火队员的角色，到处都是失火，如何能救的过来。</font></p>
<p><font face="Arial">　　自适应的团队，就在于人人都是主动的、自发的。问题出现的时候，不在于是你的问题，还是他的问题，而是立即解决，不是积累到失控的时候，才去解决。</font></p>
<p><font face="Arial">　　所以打造这样的团队，不仅仅是对Leader要求高，对于团队中的每一个人要求都高。例如对于迭代中的一个best practice，就是要求，在每一个周期的，Time-box控制的都是相当严格的，要求Leader每天，都要跟紧成员的开发状态，以求每天都有结果。如果不是一个自适应的团队，如果一个团队有几十个人，那Leader都要累死了，每个人的座位走一遍，都快要下班了。</font></p>
<p><font face="Arial">　　有人会说，这是太理想化的东西，我想，这是一个思想层面的认识问题，一个推动力，一个唱黑脸，敢于在组织架构上动刀子的问题。</font></p>
<p><font face="Arial">　　这几年，我经历的团队当中，往往都是开始的，两三人，不断膨胀到十人左右，但真正起作用的，不过１／３，砍掉一半，团队照样跑的转。</font></p>
<p><font face="Arial">　　一个技术经验丰富的、Open的开发人员，胜过一堆猪脑子的程序员。领导们算账，算过了头，只愿意雇佣大批量的，低成本的开发人员，不愿意在团队结构上，精心考虑。</font></p>
<p><font face="Arial">　　我想一个３、４人的敏捷小分队，要胜过１０人的团队，很多PM总是在后期抱怨缺人，领导也一味的满足他们的要求，不断的在中后期加人，却不愿意在团队成立之初，去好好的考虑团队的建设问题！<br />
　　</font></p>
<p><font face="Arial">　　考虑一个团队的架构，很多人，自然会想到首先从技术方面想，如高级程序员，中级程序员，普通程序员，系统分析员等，一些大的公司，也会设这样的岗位，不同的岗位，Money不一样，职责不一样。这不过是一厢情愿的典型的人事设计方式，非常粗粒度的切割方式。</font></p>
<p><font face="Arial">　　其实从技术方面，来考虑，是打造Team的一种主要的方式，但也并是说用这种无知的、分级的方式打造，这样只会损害团队的合作！</font></p>
<p><font face="Arial">　　对于技术方面，要结合项目的特性，进行精细化的考虑，如果不知道怎么做，可以看看Microsoft的用户体验团队的组织架构：</font></p>
<p><font face="Arial">　　<img src="file:\\d:\team.jpg" height="607" alt="微软用户体验团队组织架构" style="WIDTH: 596px; HEIGHT: 441px" width="787" /><br />
　　另外，也可以看看我最欣赏和羡慕的Google的开发小分队的组织架构，就像三角洲的小分队，精悍无比。<br />
　　一个Team　leader, 一个用户体验工程师（不仅技术好，人机交互的理念也要到位）,一个teser.</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 目前的开发人员，很多都不满足不了这样的要求，很多程序员，除了会写个Java代码，其它一无所知，甚至不知道怎么去写HTML代码了，怎么可能去做一个解决问题的开发人员？我现在的项目，采用的是原型迭代的方式，项目中的几百页的静态原型，都是我一个人做的，我想交出去，没有一个人会！<br />
&nbsp;&nbsp;&nbsp; 现在的三层开发，误导了技术走向，很多人以为只会一层就够了，不会SQL，不会javascript，页面也不会写，要汝何用！</font></p>
<p><font face="Arial">　　其实从管理、自制和思想层面，也是另一种渠道。团队中人员要考量他的交流、沟通能力，他的思想层面，是否有团队精神，是否能够接受新技术，热爱技术。对于恶劣的磁、破坏性巨大的程序员，要敢于清除出队伍，避免毒性扩散。</font></p>
<p><font face="Arial">　　这是不是，还是非常的理想化，也许你们还是接受不了，宁愿十几人的干活的热闹场面，不愿意５个人以内的敏捷团队？</font></p>
<p><font face="Arial">　　也许可以学习一下国外公司的做法，如Microsoft、Google，招聪明的，不招呆滞的，遇到问题，连GOOGLE都不会去查一下的人。</font></p>
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/86333#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 03 Jun 2007 15:20:57 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/86333</link>
        <guid>http://oneeyewolf.javaeye.com/blog/86333</guid>
      </item>
      <item>
        <title>应用层缓存　VS　ORM缓存</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/85940" style="color:red;">http://oneeyewolf.javaeye.com/blog/85940</a>&nbsp;
          发表时间: 2007年06月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial"></font>&nbsp;<font face="Arial">　　最近做一个比较大的电子商务项目，预计每天订单量将在５万多单，客服人员需要频繁的下单、查询订单、操作订单，客人预订完订单后，会立即进入处理流程，为了提高服务质量，要求流水化作业，平均要在４０分钟－８０分钟内处理完订单，对于疑难订单要到第二天，才能处理完。所以订单在创建后，会在短时间内，被频繁的修改和查看。<br />
　　由于在项目中ORM层主要是基于Hibernate框架，所以在调优时，很自然的就想到打开Hibernate的二级缓存，以次来减小由于Load　订单大对象时N+1次查询给数据造成的压力，自己做的测试效果也非常好，也顺利通过压力测试。<br />
　　但在上线时，性能却并不佳，经过分析业务的操作特点，查找原因有以下几占：，</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 1.但由于中台每天在工作当中，频繁的批量分配工单，<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 因为要批量将订单分配给某一个工作人员处理，在代码当中执行了一个bulkUpdate的操作：<br />
　　template.bulkUpdate(&quot;update order set owner = ? where id in (?, ?,?)&quot;);<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 这时Hibernate会直接将Order对象的二级缓存清楚掉。<br />
&nbsp;&nbsp;&nbsp; 由于二级缓存，总是被刷掉，再查询时，需要重新从数据库Load，所以二级缓存变相直接起的作用很少。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 2.由于工作人员在处理订单时，每一次查看之后，都有更新操作，在更新之后，订单被清除缓存，下一组人在处理订单时，又得重新LOAD，所以效果并不好。<br />
&nbsp;&nbsp;&nbsp; 3.无论是白盒测试，还是压力测试时，所基于的案例太过于简单，没有更深入的模仿业务操作，对于压力测试的脚本，也很难精确的模拟出真实的流程化的业务操作过程。</font></p>
<font face="Arial">
<p><br />
&nbsp;&nbsp;&nbsp; 开始想到，直接获得Session，直接使用JDBC来编写更新代码，并在更新后，使用sessionFactory.evict(Order.class, id);来有目标的逐个清除特定的对象，以避免全部清楚缓存。<br />
&nbsp;&nbsp;&nbsp; 但样做，会对DAO层，修改过大。</p>
<p>&nbsp;&nbsp;&nbsp; 由于整个模块最核心的商业对象就是订单，最后决定在Service层对订单开小灶，对订单缓存的单独的定制处理。</p>
<p>&nbsp;&nbsp;&nbsp; 我觉得应用缓存存在以下优点：<br />
&nbsp;&nbsp;&nbsp; 　　１。速度要快于ORM缓存，<br />
&nbsp;&nbsp;&nbsp; 　　２。对于缓存的控制权更大，可以直接控制缓存工具的API进行操作，可以避免一些盲目清除的操作。<br />
&nbsp;&nbsp;&nbsp; 　　３。更灵活的控制缓存中对象的失效，如根据事件来清除缓存，如订单的处理流程结束时，将该订单从缓存中清除掉，<br />
&nbsp;&nbsp;&nbsp; 　　４。在更新数据库时，不是直接清除缓存，而是更新缓存（尽管这有风险），当业务层抛出异常时，才去清空缓存，避免由于频繁更新，而清空缓存。</p>
<p>&nbsp;&nbsp; 　缺点：<br />
&nbsp;&nbsp; 　　１。订单的更新操作，必须是单点的，只能通过IOrderService提供的接口，进行更新操作，否则数据不一致的风险较大。<br />
&nbsp;&nbsp; 　　２。想要透明化，需要有一定的代码工作量,不容易达到ORM缓存最强大的那种透明化和灵活可配置，你可以使用Ehcache, 也可以选Jboss，有钱的话，可以用Tangosol。<br />
<br />
&nbsp;&nbsp; 　　３。如果不对第三方缓存包，进行一定的封装的话，会直接耦合于第三方的缓存包，不能像Hibernate那样，灵活选择和配置缓存工具。<br />
&nbsp;&nbsp; 　　４。对业务层代码有一定的侵入</p>
<p>&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; 目前的方案是采用应用层的现代化，同时使用如Proxy模式来提供透明化的设计，</p>
<p>&nbsp;&nbsp;&nbsp; 　　IOrderService －》&nbsp; OrderService －》 CacheableOrderService </p>
<p>&nbsp;&nbsp; 　通过Spring的Bean配置，一样可以实现透明化的操作。</p>
<p><br />
&nbsp;&nbsp; 　结论：<br />
&nbsp;&nbsp; 　１。缓存的清空与更新，要尽量精确的去操作受到更新影响的对象，而不是全部搞掉。<br />
&nbsp;&nbsp; 　　　在Hibernate当中，也提供了sessionFactory.evict(class, id)这样细粒度的清空缓存对象的方法。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sessionFactory.evice(class)的操作，要看这样的操作是否频繁，如果频繁，对于缓存的作用就会大大的折扣。<br />
　　　２。如果缓存对象过多，对于失效的算法与处理，要与业务对象的特性紧密的联合起来，通过事件来驱动对象的失效。<br />
　　　３。对于商业对象的缓存，必须要深刻分析对象的生命周期，业务特性。<br />
　　　４。对于数据不一致的风险，要有足够的认识与预防手段。<br />
　　　５。合理的估计订单对象的大小，分配足够的内存<br />
　　　６。如果只使用中心缓存，只能减小数据库的压力，对于网络带宽的压力，还是有的，速度上也远远逊于本地缓存的效果，所以要结合本地缓存＋中心缓存的策略方案，即提高速度，避免群集复制时的瓶颈。</p>
<p><br />
&nbsp;&nbsp; 　</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>　　</p>
</font>
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/85940#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 02 Jun 2007 19:34:10 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/85940</link>
        <guid>http://oneeyewolf.javaeye.com/blog/85940</guid>
      </item>
      <item>
        <title>不做技术的奴隶</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/77195" style="color:red;">http://oneeyewolf.javaeye.com/blog/77195</a>&nbsp;
          发表时间: 2007年05月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial"></font>&nbsp;</p>
<p><br />
<font face="Arial">&nbsp;&nbsp;&nbsp; 近日，上论坛中，看了Ibatis和Hibernate的帖子，看后，心里觉得的憋闷，不说不快, 其实Robbin之前有一个帖子，都说过了，但在这里，我想更细化一下：</font>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 1. 库表关系的复杂度，首先取决于需求，不取决于设计，设计能力强的人，也要遵守库表设计的规范，从巴克斯三个范式上，原则上也要遵守。不能说用了Hibernate,自己的库表设计能力就强了。不能为了用Hibernate，就去一味批判复杂的关系不对。复杂的关系设计对不对，首先取决于是否有复杂的需求，其次才取决于设计者的能力。</p>
<p>&nbsp;&nbsp;&nbsp; 2. 只要你用的是关系数据库，就必须要明白，为什么叫关系数据库，而不叫面向对象数据库，把面向对象的那些观点，拿到库表设计上，后期维护和调优上，你要担起责任，不能让开发人员替早期决策人员擦屁股。我见过有的人，打着OO和扩展性的旗号，硬生生的把一个表，拆成了三个表，而这三个表，本来，只需要增加一个类型字段，再做一些冗余，就可以是一个表。现在查询时，还要把这三个表Union到一块来查。当需求变更时，增加一个字段，不仅要改变三个类，还要改变三个表，简直是乱伦。</p>
<p>&nbsp;&nbsp;&nbsp; 3.One-One的库表设计，对于DBA来讲，并不是一个best practice的设计。不能为了Hibernate，刻意把大表拆成小表，再用几个小类，做成One-One的映射关系。整体性，是不能随便的分割，毕竟开发人在调试、测试和维护的时候，更喜欢看数据库里的数据，本来一个SQL，就查出来，现在要到多个表中去查。</p>
<p>&nbsp;&nbsp;&nbsp; 4. 增删改存的实体维护<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ibatis比不上Hibernate，说实在话，现在让我写SQL来维护一个多对多关系的实体维护，我都要考虑上半天，别说写代码了。</p>
<p>&nbsp;&nbsp;&nbsp; 5. 你需要写原生SQL吗<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先你要确认，你项目的要求不需要写原生SQL，再来讲Ibatis和Hibernate的好坏，在写原生SQL上，特别是动态生成的SQL，ibatis比Hiberante有得一拼，ibatis就像一个模板一样，将SQL写在配置文件当中，集中配置，特别方便技术领导者监控项目成员写的SQL好坏，而且没有什么学习曲线，就写SQL就完事了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有人会说，Hibernate也支持写SQL，但是写代码当中，就失去了原来基于Hibernate的DAO的简洁性。那个DAO一点也不简洁，如果你将动态拼SQL的代码也放在DAO当中，那个DAO就会充斥大量的If 。。Else。。之类的语句，一坨一坨的，非常的壮观。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还有人会说，Hibernate也支持命名查询，将SQL写在映射文件当中，但是命名查询，只支持占位符固定的情况，也就是说，where a = ? and b = ? and c=?，是三个问号，就是三个问号，传参时，少一个都不行。但是很多项目的查询，都是动态的，也就是说用户选了这个查询条件，才会生成这个占位符的。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hibernate办不到。</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还有人会说，我自己用Hibernate写一个框架，也可以做到，那你写的绝对可能比Ibatis好，也可能差，你要造轮子，谁来拦不着。<br />
&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; 5. 调优<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 早期调优，有些Bad SQL，其实在code review阶段，只要看看Ibatis的SQL配置文件，就可以扼杀掉的，如果使用HSQL，可能不会被发现，因为它不仅隐藏在代码当中，有的时候，还需要程序跑起来，通过日志打印出SQL或者通过其它工具如P6Spy来看的出来。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 后期调优，既然是后期调优，我想就一定是遇到了瓶颈，可能要在库表上做冗余，可能要检查那些Bad SQL，可能要修改代码，可能要动用DBA层次上的一些调优手段，那么调优越深入，Ibatis的优势就越能体现出来，比如说增加临时表，中间表，增加冗余字段等。</p>
<p>&nbsp;&nbsp;&nbsp; 6. 开发速度<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果项目当中，没有一个Hibernate高手，你的项目又相对的复杂，不仅有复杂的库表关系，还有大量的报表查询，那么使用Hibernate，速度上逊于Ibatis.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 问题在于，怎么样算是一个Hibernate高手，别看论坛上，那么多人，群情激奋的在说Hibernate的好，有谁真的是高手？</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7. 平台移植性<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你的项目要做产品，而且打算基于多个数据库平台的发布，使用Hiberante是没有说了。</p>
<p>&nbsp;&nbsp;&nbsp; 8. 维护性<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果不考虑移植性，Ibatis的可维护不差于Hibernate，库表变动引起实体类变动时，HSQL也会有改动，有人说不用改，说这话的那个人可能整天只会有select * ，如果ibatis也是这样写，也不用动了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HSQL好阅读吗，From order，确实很简单，但实际当中，这跟拿HelloWord做例子，有什么区别？</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 9. 我在实际项目当中的运用<br />
&nbsp;&nbsp;&nbsp; 项目背景：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我自己从Hibernate2开始使用，我现在也不认为我是Hibernate高手，我也没有时间去钻研Hibernate，更深的东西，我也不喜欢坐在开发人员旁边老半天，去帮他们解决Hibernate遇到的问题，因为我自己还有很多事要做。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我的项目当中，在Hibernate方面，还有一个比我更强的人，他也很烦去看Hibernate打印出来的sql，看上老半天，再调上老半天，项目进度，嗖嗖的过去了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 水平越高的人，任务越重，很少有时间和耐心去解决一般性的问题。</p>
<p>&nbsp;&nbsp;&nbsp; 最终的运用：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在基于Spring的容器事务管理之下，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 增、删、改、存及在事务中的查询，使用Hibernate。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 非事务性的查询及报表，都用Ibatis，维护非常的直观方便，开发速度上也快很多。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我觉得现在技术换代很快，使用一项技术，首先是要快速的解决问题，然后要学习他的思想，那些整天死抱着Hibernate，自认为学习到ORM的设计技巧的人，就去继续的学吧。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我已经会用Hibernate的一些方面，我觉得够用就行了，犯不上，天天钻研HSQL，如果有时间，我觉得躺在草坪上看看Unix的编程艺术，看看代码大全，看看Oracle的编程艺术，比看Hibernate的SB书要惬意多了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 简单能够带来快乐，用过EJB，再用Spring的人，都有体会，那简直是一种思想上的重生。</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ibatis的设计者认为，在新的项目当中，可以使用Hibernate，在旧的遗留项目当中，可以使用Ibatis，不明白，他为什么说这样的话，这与新旧项目有什么区别？ 用不用Ibatis，我觉得对我上面说的几点有关。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp; </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />
</p>
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/77195#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 05 May 2007 18:02:00 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/77195</link>
        <guid>http://oneeyewolf.javaeye.com/blog/77195</guid>
      </item>
      <item>
        <title>重视代码</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/77186" style="color:red;">http://oneeyewolf.javaeye.com/blog/77186</a>&nbsp;
          发表时间: 2007年05月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial"></font>&nbsp;</p>
<p><font face="Arial"><br />
&nbsp;&nbsp; 计算机专业毕业的学生在学校当中，都读过软件工程这本书，而软件工程的书，都无一例外的，强行规定了一个编码阶段，并且十分严肃的告诉学生，代码在整个软件过程的生命周期阶段当中，只占了1/5左右。需求分析和设计、项目管理，更强于代码。我想对这于刚毕业的学生，是一种思想上的毒害，很多人刚毕业一两年，都耐不住性子，哭着喊着，要做architect，要做PM。</font></p>
<p><font face="Arial">&nbsp;&nbsp; 我认为回避代码是可耻的，只要编码显的有意义，我们在任何阶段，都应当投入到编码当中。</font></p>
<p><font face="Arial">&nbsp;&nbsp; 最近一个项目，我下面有两个设计人员（GM派过来的），协助我做设计，我做了一个设计的骨架，然后交给他们去迭代细代。下班前，我去看看他们的工作只有一些空洞的UML图和一个还没有写内容的概要设计模板，我对他们说，不要求你们去写文档，我也没有时间去看，我不知道你们以前，是怎么做这设计的，但在我这个组，这样做，不行。做为设计者，首先是自己要理解要做的东西，并且真正知道怎么去设计它才能满足涉众需求，第二步，才是让别人能够理解你的设计。怎么样让别人理解你的设计，文档并不是唯一的途径，对于普通程度员来讲，白板上的讲解和直白的代码注释甚至比UML图更容易理解和平易近人，我们很多的设计者，总是喜欢用大量的4＋1 UML图和文档中生硬、冰冷的词汇来吓唬程序员，恰恰反映出了设计者内心的空虚与胆怯。</font></p>
<font face="Arial">
<p><br />
&nbsp;&nbsp; 以往自身的设计经历，谈一下：<br />
&nbsp;&nbsp; 我第一次给另一个组做一个子模块的设计时，心里很紧张，因为我不在它们那个组中，也不参与他们的开发，这个设计对于他们的项目进度来说，又是一个关键路径，我生怕我自己设计的不好，考虑问题考虑的不周到，在项目后期，如果出现问题，自己责任重大。</p>
<p>&nbsp;&nbsp; 其实我给他们说，这个设计需要两个星期，其实我只化了三天，就把接口文档写好了，我对着接口考虑来考虑去，还是觉得没有底，我忍不住想写代码，来验证这样做对不对，又怕别人说我的设计能力不强。我就偷偷摸摸的写代码，又和他们的组的主要使用者反复沟通了几次，根据需求，设计了几种不同的案例，来验证我的设计是否有漏洞。</p>
<p>&nbsp;&nbsp; 最后，又对接口修复了几次，觉得接口相对稳定和健壮了，就让他们过来看看，提出问题，结果也没有提出什么问题。于是我就交工了。</p>
<p>&nbsp;&nbsp; 实事上，这个接口，在开发后期，还是有一点修改，但并没有给他们的项目造成很大的影响，他们本身也认为能考虑的这么全面，已经不易。</p>
<p><br />
&nbsp;&nbsp; 做开发这么多年，越来越觉得设计是一个很复杂的东东，他不像建筑工程中的设计一样，可以用工程化的方法去中规中矩的验证，并交给工人进行构造。</p>
<p>&nbsp;&nbsp; 这几年，我经历的每个项目，几乎都有评审，需求评审，设计评审等等，但我现在回想过来，我想不出对我的项目有太多的意义，很多人痴迷于通过文档和评审来试图证明设计是正确的，而通过评审，对于PM和Architect，似乎也被当做是一个项目当中非常重大的milestone，直到现在，我的上级和我的同事，似乎从未改变。而我的自己观点的表白在OP会上，迎来的是批判。</p>
<p>&nbsp;&nbsp; 文档必须要有，总体的架构设计和模块的详细设计，都是需要的，但是设计者，往往忘记了，文档只是设计者自己对已经构思好的设计的一种反映，这种反映只是让别人去分析、理解、修正、接受并按照它来进行开发的一个工具，它绝对不是一个证明自己完成一个良好设计的方法。</p>
<p>&nbsp;&nbsp; 编码、测试、调试、交付用户UAT，都应当视为是设计的过程，也应当是验证设计是否正确的最好的办法。</p>
<p>&nbsp;&nbsp; 尽早的进入代码开发，是敏捷开发中一个很重要的标志，所谓的标志，我认为如果在项目前期的前一两个月，你仍然徘徊在需求分析、文档编写的工作当中，而没有代码产生，你绝对不是敏捷。这个观点是我自己加的，我很难容忍，我的设计、分析人员天天在写文档，开发人员在心猿意马的看长遍大论的需求和设计文档，一句话，越早进入开发，我就越主动。</p>
<p>&nbsp;&nbsp; 我验证设计的一些方法：<br />
&nbsp;&nbsp; 1.根据以往的设计经验，做一些check list.<br />
&nbsp;&nbsp; 2.写代码，做demo。做Demo是我非常喜欢的一个方法，一个可以运行的Demo，远胜过文档了。开发人员一看，直接copy、paste就完了。做汽车、计算机等新产品，都会有样机，对样机做大量的试验后，才能上线，大批量的生产，在软件当中，怎么一做完设计，就大规模的进行开发了呢。<br />
&nbsp;&nbsp; 3.做测试案例，TDD是一种方法，有长期开发经验的人很容易吸收的思想，并且愿意在重要的地方使用，来理顺和验证自己思路。<br />
&nbsp;&nbsp; 4.对于设计的涉众人员，能够尽早的看到，并充分的沟通，不要把文档写完了，才交给他们，那是一种思想上的强暴。很多时候，在领导的安排下，设计人员与开发人员，在能力上，并差不了多少。所以设计人员要虚心，并且要有责任心。</p>
<p>&nbsp;&nbsp; 好的设计应当交付什么：<br />
&nbsp;&nbsp; 1. 有简洁注释的代码<br />
&nbsp;&nbsp; 2. TestCase<br />
&nbsp;&nbsp; 3. Demo<br />
&nbsp;&nbsp; 4. 模型<br />
&nbsp;&nbsp; 5. 文档</p>
<p>&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</font>&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/77186#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 05 May 2007 16:34:23 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/77186</link>
        <guid>http://oneeyewolf.javaeye.com/blog/77186</guid>
      </item>
      <item>
        <title>群集的存在意义</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/40795" style="color:red;">http://oneeyewolf.javaeye.com/blog/40795</a>&nbsp;
          发表时间: 2006年12月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          近来为客户新做一个电子商务网站，部门经理天天给我说要把群集做进方案里，听的都吐了，在没有对于用户服务需求真正在进行好认真的分析的前提下，就将群集做进方案里，真的觉得很厌烦。<br />    <br />    我觉得即使对于中型的电子商务网站，也不一定需要群集，群集只会增加复杂度，甚至有可能延长用户请求的响应时间。同时限制Web应用的开发方案，如对于重型的基于SessionWeb-Flow方案，你就要考虑不能使用了。但对于电子商务网站，web-flow的应用很多，想像一个网站下单的过程，-查询－预订－登陆－填写需求-填写配送单－信用卡担保（或网上支付)-生成订单。使用wegbflow框架很方便，但在群集环境下，却有性能负担。<br />    我觉得基于apache的前导load-balancer方案，已经足够了，它可以持续将同一个Session的请求，分发给同一个worker进行处理。没有必要再使用群集来进行Session复制。
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/40795#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 26 Dec 2006 11:17:31 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/40795</link>
        <guid>http://oneeyewolf.javaeye.com/blog/40795</guid>
      </item>
      <item>
        <title>SQL优化是重点</title>
        <author>OneEyeWolf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://oneeyewolf.javaeye.com">OneEyeWolf</a>&nbsp;
          链接：<a href="http://oneeyewolf.javaeye.com/blog/19464" style="color:red;">http://oneeyewolf.javaeye.com/blog/19464</a>&nbsp;
          发表时间: 2006年03月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          信息系统访问量又不大，瓶颈一般不会出现在应用层，极有可能在数据库这一层，不用急着看程序。先找出逻辑读取次数最多的SQL，硬盘读取次数最多的SQL，找到SQL，对于SQL进行优化。看看有没有发生全表扫描的地方。<br />一般发生全表扫描，极有可能是没有建立合理的索引，或者索引由于左边引用函数或其它原因造成索引失效。<br />对于运行一年多的系统，最好要自己写一个自动重建索引的程序，定时重建索引。<br />或者使用TOAD工具帮你重建索引。<br /><br />另外在看一下数据库的CPU占用率，如果占用率在经常在80%－100%，那一定要是SQL或存储过程及trigger中写的不好。<br /><br />不需要从应用层找SQL，方向性错误，太累，也看不出效果。<br />而应当使用pl/SQL, toad等工具，分析出最bad的SQL语句，一看到这些语句后，再修改应用层的查询就是了。又快又方便。<br /><br /><br /><br />-- 逻辑读多的SQL<br />select * from (select buffer_gets, sql_text<br />from v$sqlarea<br />where buffer_gets > 500000<br />order by buffer_gets desc) where rownum&lt;=30;<br /><br />-- 执行次数多的SQL    <br />  select sql_text,executions from <br />  (select sql_text,executions from v$sqlarea order by executions desc) <br />   where rownum&lt;81;<br /><br />-- 读硬盘多的SQL  <br />  select sql_text,disk_reads from <br />  (select sql_text,disk_reads from v$sqlarea order by disk_reads desc) <br />   where rownum&lt;21;     <br /><br />-- 排序多的SQL    <br />  select sql_text,sorts from<br />   (select sql_text,sorts from v$sqlarea order by sorts desc) <br />    where rownum&lt;21;            <br />  <br />--分析的次数太多，执行的次数太少，要用绑变量的方法来写sql<br />set pagesize 600;<br />set linesize 120;<br />select substr(sql_text,1,80) "sql", count(*), sum(executions) "totexecs"<br />   from v$sqlarea<br />   where executions &lt; 5<br />   group by substr(sql_text,1,80)<br />   having count(*) > 30<br />   order by 2;
          <br/>
          <span style="color:red;">
            <a href="http://oneeyewolf.javaeye.com/blog/19464#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 29 Mar 2006 08:44:07 +0800</pubDate>
        <link>http://oneeyewolf.javaeye.com/blog/19464</link>
        <guid>http://oneeyewolf.javaeye.com/blog/19464</guid>
      </item>
  </channel>
</rss>