paulwong

#

软件架构那点事儿(二)

什么才是软件架构呢?这是一个让人费神的事情,其实呢我觉得“软件架构”至少应该是一个动词,而不是一个专有名词。那么什么才是架构呢?按照我个人的理解,架构这玩意简约不简单。“架构”的过程是一个把抽象转化为具体,其中的美妙不会低于设计师创造艾菲尔铁塔那般的感受。架构的过程会让你变得偏执、疯狂。至少在短时期内会为之寝食难安。那时时候你的世界之后架构二字了。有点长,希望耐心看完~~~ 哈哈!

(PS:尽管架构是与编程语言无关的事情,目前采用Java语言作为例子)

好了,很多人读到这里会怀疑,难道J2EE业界流行的那些SSH、SSI 不是架构吗?我的回答是“NO”,如果硬要如架构沾边的话,那也充其量是一个架构最最低级的一种。在现在的我看来,那些只不过是一些开源框架的简单集成,毫无技术含量可言,对于架构者本人而言,那就是通过固化的配置把这些开源框架进行一定程度的粘合,使其能互相配合完成工作。当然不是否认这个配置的过程,但是这个过程是机械化的学习,丝毫看不到自己的想法,这时的想法都被固化的配置所代替。想当年 偶也是这样子走过来的,所以说呢,现在的我不敢谈论架构的内涵,仅仅是表达出我对架构的一些想法。文以记之。

好了,经过SSH简单的粘合之后,感觉自己很伟大,而且看是跃跃欲试的样子,拿来做项目,这是必经的一部,从程序员到架构是一个设想与实践相结合的一个过程。你自己架构的东西必须通过项目的实践,才能了解是否有改进的余地。我是比较幸运的,一直以来很多项目都是我架构之后在实践呢,在这里感谢那些曾经呆过的公司。是他们给的平台才让我有今天坐在这里写文章的冲动。很多人在使用简单粘合的SSH框架去架构你的项目,你会发现那玩意不适合做项目,太原始了,仿佛回到了石器时代,当然当时你的水平估计也就是才进化到铁器时代吧。

第二阶段了,开始尝试修改SSH搭建的框架,新在而言还是用“框架”来形容比较的贴切一点。通过一轮或者几轮的项目实施,你会发现其实SSH等这些也不是很完美,至少还有很多地方可以改进,这时你已经不再满足于SSH的简单那粘合了,开始尝试去修改加工SSH的粘合。增加一些与SSH直接交互的隔离层代码,这样一来自己项目的代码干净了很多,SSH从入侵式到非入侵式(不可能100%),这已经是一个了不起的飞跃了。你发挥了作为人主观能动性的权利,现在你收获了。那改造的SSH继续项目到项目中去实践,也许改造后的架构在当时的你看来已经很完美了。勇者无惧,Going,开始第二阶段的试水,感觉很好吧,现在的你也许长大一点了,不再从单一的技术去看待项目了,开始考虑项目的开发计划了,有了后则一层的考虑说明你是一位勤奋好学的好孩子,已经不再是单纯的Coder了,面对计划,在看看自己的架构的“框架”,时间紧迫啊。用这玩意尽管目前代码尤雅了很多,但是对于项目小组成员的开发进度还是帮助不大,大家需要学习的东西太多了,Spring、Struts、Hibernate ....... 这对于经验不是很丰富的程序员而言,简直就是噩梦。考虑到这一点,你就开始进入第三阶段的进化了

第三阶段,开始思考屏蔽各种框架集成带来的复杂性,让不懂SSH框架的人也可以快速上手使用,为了达到这一点,又开始废寝忘食的框架重构,增加更多隔离层的代码。这时的框架有点架构的味道了,重构之后的你会洋洋得意,认为这是很完美的了,又去屁颠的拿去项目实战了,这时发现你隔离之后的反而适得其反,百思不得其解啊?什么情况呢?因为你对粘合的框架内核机制不了解,这时的你要虚心学习那些开源框架了,必须是源码级别的阅读,了解他们的内核机制,才能写出更好的隔离层,面对大量的源码,必须有个入口吧,下面我简单吧Spring的入口告诉大家:首先是Spring的Ioc容器,这是核心,主要是看init bean以及loadbean的这点内容是精髓,Aop的话比较深入了,简单一点就是采用动态代理方式实现AOP,在高级的就是采用CgLib的动态代码切入实现。学好这两个之后。在学习Spring MVC 了,这是一个难点,你要吧Mvc的解析流程整理好了,在从每一个环节思考架构为和要多一个这样的环节。(Struts1 太简单了,Struts2太复杂了)。言归正传了,经历一轮源码的洗礼,你脱胎换骨了,SSH对你而言 使用起来游刃有余了。你再也不用为框架不熟悉费力了,这是的你充满了自信,短期内不再关注学习框架了,更多的时间分配给了架构。这时应该进入第四阶段了吧

第四阶段,开始用全新的眼光以及思维去粘合SSH,不错,很多以前的使用不当现在都让你轻易的化解,而且开始考虑使用SSH特有的一些优势去美化的你的架构。现在的你开始考虑的不是开始了,而是如何保证代码的质量问题了,如何保证呢?好吧,找领导申请资源测试吧,对不起,测试团队是很昂贵的,公司很少会配备测试团队的,自测?小弟们才不会如此上心呢?未雨绸缪吧。架构时候为何不架构一套基于SSH的单元测试框架进来呢,好处呢可以脱离容器去测试功能,基于框架的单元测试进入了你的思考范围。等从思考到完全融入架构的时候,你有进入一个新的阶段了。编写测试架构就是为了提高工作效率,目前面向Web的开发,很多测试都需要依赖容器,每次启动容器调试是何等的低效啊。好了集成了自己的测试框架,小弟们高兴了。也会对你刮目相看,至少编写单元测试是一个程序员的义务,保证自己的代码的稳定性,现在你轻松了,每天吧小弟的成果用写的单元测试运行一次。没问题了,不错。下班。

第五阶段,也许这一阶段你的架构开始稳定,很长一段时间都会固化不变,也许到达了一个瓶颈了。单位来了狠多项目,每次你都构建一个基础成,1次 2次 。。。N次,O-MyGod,你开始讨厌这种重复的的劳作了,得,这是你的责任,你是公司的技术一把手,这些肯定有你来做。这是你开始考虑吧基础层与业务层开始解耦。解耦出来的东东作为单独的一个项目存放,自己手动维护,以及版本控制。新建的项目都依赖你的基础项目在做业务开发,现在感觉好多了,不用在为项目每次都搭建了。看着别人在忙,你在一边抽烟偷着乐吧。新在的你体会到一丝分离的快感。这不是就是所谓的程序的解耦吗?这不过你解耦的比较彻底了,从功能和物理上都实现了解耦。恩体会到设计模式的优美了,这是你也会才会发自内心的去迷恋设计模式。这些设计模式是前辈们精华的抽象,不同的模式用于解决各种现实的业务建模。学会是一回事,灵活掌握是另外一回事。关于设计模式,是必经的过程。不仅仅是学会,关键是灵活使用。在合适的场景下选用合适的模式,才是正解。

第六阶段了,通过之前的积累,你已经开始迈出走向架构的第一步了,之前都是为这一步的积累。好比是砍柴,之前都是磨刀了,现在才开始踏上砍柴的路途,哼着儿歌、一路进发。现在刀不是问题了,估计之前的砍柴都是刀不好,注意力都在刀上了,现在刀是没问题了,开始转移到观察柴了,什么柴比较好,砍哪里可以一刀成功,这些多是经验。映射到软件项目就是,开始关于业务建模,不同行业的业务都有其自身的特性,如何针对这些特有的业务特性去架构框架呢,在之前的隔离层上在封装一层业务支撑体系,这个体系可以良好的为业务系统提供强大的动力。通信、政府、金融、医疗、企业、税务、电商。。。。等等,每种行业有有其自身的业务特色,干活去吧,都发现架构的不足了,那就继续完善吧。coding~~~~~好了,针对业务的支撑层也开发完毕了。通过实践运行不错。。。。。 这时你的框架成了公司的某一业务线的开发平台了 。。。。如果继续留在公司,你也许会不断完善其业务建模的支撑体系。可惜,你可能换工作,换工作就意味这换行业。之前积累的业务体系完全行不通啊~~~悲剧了,没办法,从小弟开始做起吧,虚心学习业务基础 。。。。

第七阶段,跳槽太多也不是坏事,经历了几个不同的业务线,你敏锐的嗅觉开始体验到一些独立与业务之外的程序处理规则。如何能搭建一套快速满足不同业务建模的基础模型出来,说到底业务到了底层还是各种流程,只是每个流程节点处理的内容不同(不是工作流,但有其思想)。这时候,你考虑的问题已经不是业务建模了,而是业务之外的东东,这个时候你会忘记SSH这些所谓的框架,这些都是具体的形式体现,现在你需要的是高度的抽象,抽象业务之外,流程图是你研究的核心,因为任何程序其实都可以用流程图去表述,如何开发一套流程配置解析引擎呢,神码业务都是流程上的一个节点而已。只要业务流程化,按照我的配置写入,那么他就可以运行。见山不是山的境界吧哈哈~~~ 到了这一步了,感觉架构才是正的开始了。当然框架是抛不开的,现在面临的问题就是如何利用既有成熟的框架是完成你的这些构想,现在的框架开始考虑自己的分层了,内核层、安全层、缓冲层、ORM层、异常处理机制、国际化机制等等,是不是一项伟大的工程呢,也许Spring就是这样子走过来的。完成了这一阶段的修炼。那么你还不满足吗?恩的确有点就是说不出来,总是有点不满足。现在开始讨论更深层次的话题

第八阶段,架构是有了,你的项目规模也越来越大了,用这个玩意的人也越来越多了,现在考虑的是如何把你的框架能快速推广,市场是检验产品最好的标尺。是否具有可用性。是否能量产程序员(入门级),是否能保证代码的质量、是否能保证出现问题的快速定位,是否能够满足业务扩张的需求、是否满足性能的要求………………….. 咳咳~~一口气说完 太累了!!这些问题是现在需要考虑的问题了。现在架构的推广不仅仅是你的团队在用,也许其他团队也在用,可惜他们无法得到你的亲授,肿么办?开始文档化、标准化、提供实例Demo,这些够了吗?对了 还不够,100个程序员有100中独立风格的编程方式,那就意味这有100个风险的存在,你的架构如何屏蔽或者降低这些风险呢?答案呢?就是要用你的架构去诱导他们尽量编码风格一致。其好处不言而喻啊,统一的编码风格意味这每个程序员都是平等的,从项目角度考虑,那就是把人的风险降低了(包括离职风险)。带来的另外一个好处就是Review代码的快捷,统一风格的编码无需讲解 ……. 自己体会吧。说再多也是没用这个要亲自体会的。到了这一阶段感觉自己是什么?在雕琢一个艺术品?哈哈~~ 这个时候更加需要实践,去完善你的架构。因为现在你的架构是真正的架构吧。这个需要天时地利人和多方面的支撑。能达到这一步的程序员需要的不仅仅是自己的努力了,也需要公司的大环境……………….. 这就是为何什么程序员需要找适合自己发挥的平台。公司成了员工技术发展的桎梏。其结果就是让其平庸,或者释放去更宽广的空间。哇塞。好长久的文章啊。读者看到这里,需要休息休息了,找几张美女图片看看吧~~~也许我的文章让你费力了。现在OK了吗?架构可以了吧。恩 还是有差距的。

第九阶段,见山是山,再次回归项目中来,项目的目的是什么,盈利。这是最本质的东西。偏执也好、狂热也罢。这是一条基准,违背这一原则的任何架构都是失败的架构。盈利不是结果,而是项目每一步风险规避的积累。架构这是需要考虑的就是如何让架构能在每一阶段都能起到规避风险的功能呢?这是一个比较空洞的概念。但是这是必须考虑的,涉及到架构任何一个细微之处的调整。从项目开始到投产到维护。。。。这个过程,架构如何能保证每一阶段的风险规避呢。或者提供解决风险的更好的方法 ………………………..

上述为架构师修炼的过程,架构是具有中国特色的架构。不同于国外,一些老外闲的蛋疼去研究,我们都是苦逼的项目中提炼自己,利用8小时睡觉,8小时工作之外的时间去完成这一修炼,上面的文字也是本人的程序开发的成长历史,抛砖引玉吧~~希望能对开始“架构”你提供一些参考。最后浓缩几个字,算是文章的目的!

盈利、重构、坚持 。

posted @ 2012-02-26 20:47 paulwong 阅读(269) | 评论 (0)编辑 收藏

软件架构那点事儿(一)

关于标题,我也开始附庸文雅了。哈哈!话说软件架构是本人这些年的一些积累,在此做一点分享,希望对即将做架构或者是正在架构的 ITer 一些参考,也许见解浅薄,还望大家多多包涵,如有异议,可私聊,禁止拍砖。


说起架构可不是一件简单的事情,他是一个很庞大的系统骨架,但是面对到手的软件需求,你是如何设计一个合理的架构呢?原来架构这玩意也是分第一步、第二步、第三步 ........ 以此类推,不能急于求成,这样容易扯着蛋。要做到手中无剑,心中有剑的境界,并非一朝一夕的努力,需要长期项目的实践,经历无数次的失败与重构之后再能叩开“软件架构”这个大门的一丝门缝,从来一窥汪洋。


拿到一个软件的合同或者是用户的最原始的需求,很多架构师的第一直觉就是关注软件本身的功能,有哪些功能,适合采用哪些技术选型。这对于大多数人而言,的确是没有错误。但是在这之前还一点需要去做的事情 ...... 不知道大家想到了吗?架构是基于什么环境呢?这一点在架构之前不知道读者现在是否思考过这个问题。所谓的架构首先要了解软件运行的软硬件以及网络环境。之后明确了这一点才能考虑下一步的事情,否则就有点闭门造车的感觉了。


好了,说到运行环境,这是就要从硬件环境与软件环境分别对待了,例如:

1、硬件是采用几层架构啊,是采用集群还是单机部署呢? 典型的网络架构是Http服务器 + Web服务器 + 数据库服务器 。比较厉害的就是这些都放在一个机器上 哈哈~~~

2、软件运行的网络环境如何,是基于局域网还是公网呢?是否存在隔离的情况

3、硬件是什么机器呢?IBM刀片 还是 AIX系列呢
4、系统的灾备设备是什么,如何运作

......... 等等诸如此类的硬件环境首先要了解。



硬件明确了,下来考虑软件环境

1、软件运行的环境是 Window 、Linux、Unix ,是32位 /还是 64位

2、软件运行的Web服务器神码 WebSphere?Weblogic、Jboss、Tomcat、GlashFish还是别的?版本号是多少,支持的J2EE规范是多少。

3、JVM是什么版本,是全新部署 还是复用甲方已经存在的软件环境呢?
4、软件是否与其他软件有数据交互,交互采用什么介质

5、采用什么数据库,版本是多少?

.......... 这些是作为软件环境需要考虑的一些基础性的问题


通过上述简单的文字,好像大家有点明白了吧,其实这种事情,很简单的,只要平时多注意点就OK了,否则等开发后去现场实施才发现什么都不配套啊。如果在架构开始之前,你已经关注这一点了,恭喜了 说明你已经具备作为架构师最起码的嗅觉了。

上述的那些问题或多或少影响架构本身,架构是基于单机还是基于集群,这是两种迥然不同的架构模式,很多天真的童鞋认为 单机与集群架构差不多,复制一套在部署一台机器就OK了。其实则不然。二者存在太多的不同了,我举一些简单的例子哈:

在Java行业,很多开源软件使用很频繁,这些开源软件本身集成了Cache,用于提高性能,单系统是单机运行的时候,一切都正常,做了集群出现问题了。Cache 惹得祸,因为你的集群并没有把框架内部自带的缓存集群化,还是保持各自独立的状态,一用户通过A服务器修改了内容,并且刷新了Cache,但是作为集群的B服务器感知不到A对Cache的变化,依旧从自身的缓存中获取“脏数据”,这时其他用访问B服务器读到的值,其实是A用户通过A服务器修改之前的值。很绕吧。希望能理解。瓦咔咔~~~这是架构如果采用cache 需要重写自己的Cache框架,必须屏蔽开源项目中自带的Cached,否则出了问题都让你莫名其妙?


数据库部署是单机还是双机,是热备还是冷备,数据访问需要读写分离吗?如果硬件不支持数据库热切换,如何采用程序实现数据库的热切换?这些都是架构层次的需要直接面对的问题? 架构师们 你们心里有底吗?



与甲方内部的其他系统是采用什么通信方式?Socket、WS、RMI,访问的系统之间是否有防火墙隔离,采用什么技术可以穿透防火墙阻拦呢?



以后的系统如何快速部署到对甲方的真实环境中,是手动部署还是Ant自动部署?如何做到持续集成?发送错误如何回退?



......................... 现在是不是觉得有点复杂呢?其实没关系,成长有两种,一种是汲取别人成功的经验转为为自己的能力,另外一种是尝试失败,从经历失败中成长,本人呢二者兼有,前几年都是从失败中成长,但是随着时间的推移,发现这样的代价真的是很大。开始虚心学习前人的经验,从而转化为自己的知识。


掌握软件运行的软硬件环境是作为架构的第一步,切记切记!



上述文字,仅仅是作为软件架构之前需要考虑的一些大概,还有很多细节其实我也不是很了解,如有补充请回帖瓦咔咔~~~~ 软件架构 是一件艺术品~~~ 这是我对架构的感性认识。



每次架构完我都会在一段时间把它当作是完美的艺术品去欣赏,过了新鲜期后,发现很多问题,直接重构 这样循环不已 ............. 每次的迭代 都让自己收获很多!

posted @ 2012-02-26 20:44 paulwong 阅读(310) | 评论 (0)编辑 收藏

OutOfMemoryError : PermGen space

tomcat 出现 OutOfMemoryError : PermGen space

最近在把在 tomcat 5.5 上开发的项目 deploy 到 JBoss 4.2 上时,在操作一段时间就会出现 java.lang.OutOfMemoryError: PermGen space,开始以为是代码中存在死循环的地方造成这样的问题,但是后来发现,出问题的地方都是随机的,并不是某一处造成这样的问题出现,怀疑是内存泄 露,通过增大 heap 内存的方法来尝试,依然不行,但是同样的问题却并没有在 tomcat 中出现过,难道是 JBoss 的问题?

在网上做了一番搜索得到一些相关的内容。

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决方法也一定是加大内存。说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。

改正方法,在 run.bat 中加入:-Xms256m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

因为项目中引用了很多的 jar 包,而这些 jar 包中的 class 信息会被 JBoss 的 class loader 加载到 PermGen space 区域,在 JVM 默认的情况下,该部分空间的大小只有 4M,在 jar 包非常多的情况下,显然是不够用的,所以通过 -XX:MaxPermSize=256m 指定最大值后即可解决问题。

另外,如果 heap 内存不足出现 java.lang.OutOfMemoryError: Java heap space 时,可以通过 -Xmx512m 指定最大 heap 内存来解决这样的问题。

posted @ 2012-02-21 17:14 paulwong 阅读(351) | 评论 (0)编辑 收藏

Spring MVC如何防止重复提交?类似Struts Token机制!

首先,需要将继承了SimpleFormController之类的sessionForm设为true。这样,在显示一个新表单时,Spring会将command存放在session中,而在提交表单时,Spring会从session中取出此command,随后立即从session中删除存放command的attribute。如果发现在session中没有command,Spring将其断定为重复提交,转而执行handleInvalidSubmit(request, response),可覆盖此方法负责防止重复提交的任务。

可以这么说,当setSessionForm(true)之后,如果没有先后经历显示表单、提交表单的过程,就会被认为是重复提交表单。

而有一些情况下却必须重复提交表单,如,修改数据库的数据后,试图写入数据库时因某些异常失败,如果此时异常被当前页面捕获并依旧返回当前页面,由于command已经被Spring在后台从session中移走,因此,就被认为是无效重复提交,从而导致第二次经修改后的记录无法正确提交到数据库中。handleInvalidSubmit()必须考虑到这种情况。

posted @ 2012-02-20 22:57 paulwong 阅读(3594) | 评论 (0)编辑 收藏

SPRING MVC

SPRING MVC就是和STRUTS等一样,是实现了MVC的框架,但性能比STRUTS要好,STRUTS对于每个请求都是新建一个ACTION处理,而SPRING MVC是对应到不同的方法。以下为一些核心概念:
  1. ACTION SERVLET:前端控制器,和所有的WEB框架一样,是所有的请求的中心入口
  2. MAPPING HANDLER: 比对URL,找出负责处理的控制器
  3. CONTROLLER:控制器,负责处理前端的请求,返回MODELVIEW
  4. VIEW RESOLVER:根据CONTROLLER返回的MODEL VIEW找出负责展现的VIEW
  5. VIEW:由于展现内容可以有不同方式,如JSP,FREEMARKER等,VIEW就负责展现,分两步,取得要展现的模版的路径,使用解释器解释并取得最终内容。一般一个SPRING就一个展现器,如JSTLVIEW,对于不同的URL,只是JSP页面路径不同,从CONTROLLER返回的MODEL VIEW中取得JSP路径,输出最终内容
  6. FORM HANDLER:页面如果有表单,就涉及到如何从表单中读取数据或将数据绑定到表单中,表单处理器已经和CONTROLLER结合在一起了,只须继承SIMPLE FORM HANDLER就可以,在JSP中配置COMMANDNAME值,就可以此为KEY,从MODELVIEW中取表单值或绑定值到表单中
在STRUTS中,会有一配置文件:STRUTS-COMFIG.XML,配置了所要用到的BEAN的内容,好处是直观,但项目大了,免不了配置文件数量庞大,为了减少配置文件的数量,引入注释,实际上可以理解为配置文件不用手写,由容器在启动时动态帮你生成,只须在相应代码,如类名,方法上加上注释,容器在解释这些类的时候就会动态生成一虚拟的配置文件,供后续使用。具体的注释有@CONTROLLER/@SERVICE/@REQUESTMAPPING等。



Spring MVC 3 深入总结
http://www.blogjava.net/qcyycom/archive/2013/07/11/401467.html

posted @ 2012-02-20 22:53 paulwong 阅读(406) | 评论 (0)编辑 收藏

APPLE开发指引

https://developer.apple.com/library/ios/#referencelibrary/GettingStarted/RoadMapiOS/Introduction/Introduction.html

posted @ 2012-02-20 21:27 paulwong 阅读(238) | 评论 (0)编辑 收藏

项目经理攻略

每个人都期待职位的提升和别人的认可

在国内,项目经理应该是大多数程序员比较想要的职位

这篇文章将会告诉你,要成为项目经理的一些技巧。或者说,从另外的一个角度来看项目经理这个职位。

项目经理要懂技术

这个问题,在iteye上被讨论了很久。各有各的观点,我在这边不做评论。

技术做为一个人可以掌握的技能,当然是越多越好,所以从技能方面说,懂点技术当然比啥都不懂要好

另外一方面,项目经理要和技术人员沟通,而技术人员的难以沟通是出了名的。如果脱离一些基本层面的术语,沟通到一些具体的解决方案的时候,往往和技术人员的沟通有更好的效果。而这里就会用到很多技术。

所以,从这方面说,项目经理掌握一些技术,可以说是必须的。。。

当然,类似外资公司的项目经理,完全只考虑项目进度的,那就另外说。。。

项目经理要有口才

项目经理需要在团队士气低迷的时候,鼓舞士气

项目经理需要在客户沟通的时候,保持不卑不亢的气势

项目经理需要说服客户和领导给予更多的资源

项目经理要有谋略

办公室政治我就不在这边罗嗦了

我想要说的是,作为项目经理,你经常面临很多办公室政治的挑战。

你至少要做到团结可以团结的力量。包括你的领导,你的下属,你的战友,销售,客户等等

你可以把你的泡妞经历和技术人员分享,来换取他们的支持

你也可以把你赚钱的股票和他们分享

你甚至什么都不用付出,只要时不时的体现一下你对他们的关心。

光说不练,这边整个练习题

做项目的人经常碰到的,客户要在10天之内,完成一个功能模块,在技术人员开看基本上是不可能完成的任务

那做为项目经理,需要怎么样处理这件事??

我们都知道处理结果,要么增加周期,把10天换成20天,要么删减功能。那我们采取什么样的手段来实现这个结果??一方面不能得罪甲方,另外一方面要实现我们的预期。

方法:把技术人员和客户负责人叫到一起沟通,名义上解决一些gap,实际上是让有冲突的双方直接面对。作为甲方,你是不能得罪的,做为技术人员,你可以站在甲方的立场和技术人员争吵。这个时候,你要把甲方的负责人凉在一边,让他看你们争吵,你们在争吵的过程中最好要用到解决方案的具体细节,让他听不懂。然后时不时的回过神来,用甲方的口气和技术人员说,这个时间已经决定了的。你和技术人员可以事先沟通好,要尽量顶,甚至发火。然后你们的争吵就会让负责人很尴尬,退也不是不退也不是。
结果:一般1-2个小时以后,负责人就会让步,一般是延长周期,如果周期他决定不了,那一般是删减功能。
思考:我们没有得罪甲方,但是甲方顺利让步。但是我们得罪了技术人员,所以在事后,一定要诚恳道歉,除非你们已经很娴熟

另外,这个方法是考虑到如下因素

很可能这边提出的10天,不是最终的时间点,而是那个负责人为了自己的performance提出的,如果技术人员反对很严重,这个防线肯定会崩溃

还有可能是负责人不清楚最终的实现,时间也不是他定的,他也需要和上级沟通。如果他看到技术人员如此抵制,考虑到这个功能计算在自己的performance下面,他会帮你争取更多的资源。这个时候,让负责人和他的领导去谈,会取得更好的效果。

上面都是一些基本素质,如果具备下面的几点,会事半功倍哦!!!

幽默感:团队粘合剂,也是化解尴尬的最好的东西

真诚:如果你做不到欺骗一辈子,那你就坦率点

尝试用对方的角度思考:让你发现自己的问题,发现别人的弱点。

最后,留下一个问题,如果一个团队成功的做完了一个项目,各方面评价都很好,你猜测一下,谁在这个成功的项目中,获利最大?

http://www.iteye.com/topic/1120697

posted @ 2012-02-20 16:45 paulwong 阅读(193) | 评论 (0)编辑 收藏

Spring基于注解的缓存配置--web应用实例

基于方法级别的缓存:通常如果一个带有参数的方法执行后会返回一个Object,那可以认为如果参数相同,则返回的结果一样,这样就可以为这个方法建立一个缓存Map,参数就是KEY,返回的结果就是VALUE,调用此方法前可以先判断参数是否和之前的一样,如果是则从Map中取出结果返回调用者,而无需再进入此方法内执行得到,从而节省了此方法执行时的时间。

http://hanqunfeng.iteye.com/blog/605123

经验证,如果要支持分布式的缓存,用spring-modules-cache不好使,必须转用com.googlecode.ehcache-spring-annotations

全套MAVEN的POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
<modelVersion>4.0.0</modelVersion>
    
<groupId>EhCache-Cluster-Tester</groupId>
    
<artifactId>EhCache-Cluster-Tester</artifactId>
    
<version>0.0.1-SNAPSHOT</version>
    
<packaging>war</packaging>
    
<dependencies>
        
<dependency>
            
<groupId>net.sf.ehcache</groupId>
            
<artifactId>ehcache-jgroupsreplication</artifactId>
            
<version>1.4</version>
        
</dependency>
        
<!-- Spring framework -->
        
<dependency>
            
<groupId>org.springframework</groupId>
            
<artifactId>spring</artifactId>
            
<version>${spring.version}</version>
        
</dependency>

        
<!-- Spring MVC framework -->
        
<dependency>
            
<groupId>org.springframework</groupId>
            
<artifactId>spring-webmvc</artifactId>
            
<version>${spring.version}</version>
        
</dependency>
        
<dependency>
            
<groupId>javax.servlet</groupId>
            
<artifactId>servlet-api</artifactId>
            
<version>2.4</version>
            
<scope>provided</scope>
        
</dependency>
        
<dependency>
            
<groupId>org.slf4j</groupId>
            
<artifactId>slf4j-jdk14</artifactId>
            
<version>1.5.6</version>
            
<type>jar</type>
            
<scope>compile</scope>
        
</dependency>
        
<dependency>
            
<groupId>log4j</groupId>
            
<artifactId>log4j</artifactId>
            
<version>1.2.13</version>
            
<type>jar</type>
            
<scope>compile</scope>
        
</dependency>
        
<dependency>
            
<groupId>cglib</groupId>
            
<artifactId>cglib-nodep</artifactId>
            
<version>2.2.2</version>
            
<type>jar</type>
            
<scope>compile</scope>
        
</dependency>
        
<!-- 
        <dependency>
            <groupId>org.springmodules</groupId>
            <artifactId>spring-modules-cache</artifactId>
            <version>0.9</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        
-->
        
<dependency>
            
<groupId>com.googlecode.ehcache-spring-annotations</groupId>
            
<artifactId>ehcache-spring-annotations</artifactId>
            
<version>1.2.0</version>
            
<type>jar</type>
            
<scope>compile</scope>
            
<exclusions>
                
<exclusion>
                    
<artifactId>spring-aop</artifactId>
                    
<groupId>org.springframework</groupId>
                
</exclusion>
                
<exclusion>
                    
<artifactId>spring-expression</artifactId>
                    
<groupId>org.springframework</groupId>
                
</exclusion>
            
</exclusions>
        
</dependency>
    
</dependencies>
    
<build>
        
<finalName>cluster-test</finalName>
        
<plugins>
            
<plugin>
                
<groupId>org.apache.maven.plugins</groupId>
                
<artifactId>maven-compiler-plugin</artifactId>
                
<configuration>
                    
<source>1.6</source>
                    
<target>1.6</target>
                    
<encoding>UTF-8</encoding>
                
</configuration>
            
</plugin>
            
<plugin>
                
<groupId>org.mortbay.jetty</groupId>
                
<artifactId>jetty-maven-plugin</artifactId>
                
<version>8.0.4.v20111024</version>
                
<!-- 
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.26</version>
                
-->
                
<configuration>
                    
<contextPath>/cluster-test</contextPath>
                    
<scanIntervalSeconds>3</scanIntervalSeconds>
                    
<scanTargetPatterns>
                        
<scanTargetPattern>
                            
<directory>src/main/webapp/WEB-INF</directory>
                            
<excludes>
                                
<exclude>**/*.jsp</exclude>
                            
</excludes>
                            
<includes>
                                
<include>**/*.properties</include>
                                
<include>**/*.xml</include>
                            
</includes>
                        
</scanTargetPattern>
                    
</scanTargetPatterns>
                
</configuration>
            
</plugin>
        
</plugins>
    
</build>
    
<properties>
        
<spring.version>2.5.2</spring.version>
    
</properties>
</project>

posted @ 2012-02-16 17:04 paulwong 阅读(2847) | 评论 (0)编辑 收藏

SPRINGMVC 2.5 例子

http://www.mkyong.com/spring-mvc/spring-mvc-hello-world-annotation-example/

posted @ 2012-02-16 02:14 paulwong 阅读(315) | 评论 (0)编辑 收藏

删除LINUX虚拟网卡

在LINUX安装分布式缓存时,发现了一个奇怪的IP:192.168.122.1,这个IP并无手动配置,怎么会出现呢?输入命令
ifconfig,发现多了个网卡:

virbr0    Link encap:Ethernet  HWaddr 00:00:00:00:00:00
          inet addr:
192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
          inet6 addr: fe80::
200:ff:fe00:0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:
1500  Metric:1
          RX packets:
0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:
116713 errors:0 dropped:0 overruns:0 carrier:0
          collisions:
0 txqueuelen:0
          RX bytes:
0 (0.0 b)  TX bytes:15780234 (15.0 MiB)

经查这是虚拟网卡,于是除之
yum erase libvirt

重启,搞定。

posted @ 2012-02-15 12:47 paulwong 阅读(2401) | 评论 (0)编辑 收藏

仅列出标题
共115页: First 上一页 87 88 89 90 91 92 93 94 95 下一页 Last