﻿<?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>BlogJava-nighty-随笔分类-软件架构</title><link>http://www.blogjava.net/nighty/category/31270.html</link><description>折腾的年华</description><language>zh-cn</language><lastBuildDate>Sat, 28 Apr 2012 04:07:04 GMT</lastBuildDate><pubDate>Sat, 28 Apr 2012 04:07:04 GMT</pubDate><ttl>60</ttl><item><title>Flex在企业应用中关于单元测试的一种设计思路</title><link>http://www.blogjava.net/nighty/archive/2012/04/28/376941.html</link><dc:creator>寒武纪</dc:creator><author>寒武纪</author><pubDate>Sat, 28 Apr 2012 04:03:00 GMT</pubDate><guid>http://www.blogjava.net/nighty/archive/2012/04/28/376941.html</guid><wfw:comment>http://www.blogjava.net/nighty/comments/376941.html</wfw:comment><comments>http://www.blogjava.net/nighty/archive/2012/04/28/376941.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighty/comments/commentRss/376941.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighty/services/trackbacks/376941.html</trackback:ping><description><![CDATA[<div><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用Flex做企业应用将近有一年时间了，这个过程很累，在国内这方面的积累不多，真正有参考意义的资料的确非常少。经过一段长时间的摸索后，多少也积累了一点经验，就最近的关于单元测试的想法做一点总结，由于涉及的知识较多，这里也只是给出个人的一种思路。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 众所周知，Flex的缺点是开发调试效率较低，而且它只是表现层的一种解决方案。在企业应用中最需要解决的是编译生成的swf体积问题，我想任何客户都很难接受一个企业应用全部打包在一个swf里，几MB甚至几十MB的初始化过程谁都无法接受，所以都必不可少地采用Module的加载方式，把不同的业务功能编译成独立的swf，需要用的时候再去加载。把核心功能、通信机制、公共组件设计成库项目，编译成swc做为RSL让业务模块共享调用，达到尽量减少业务模块编译体积的目的。在这方面如果用心优化的话，基本上可以控制到每个swf体积大概在200KB以内，这样就算是互联网方式部署，客户访问仍是可以接受的。</span><br />&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align="left">
<div align="center"><img style="border-bottom-color: #000000; border-top-color: #000000; border-right-color: #000000; border-left-color: #000000" border="1" alt="" src="http://www.blogjava.net/images/blogjava_net/nighty/frame.png" width="530" height="282" /></div><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 该结构图给出了一种整体的设计方案，Flex的启动肯定得有Application，这个是用户初登录后第一个加载的swf（登录就不要用flex了，用jsp或是模板实现吧）。所以它负责加载你设计的整个框架，包含模块加载机制、通信代理方式、基础库初始化等等，而和Java端的通信目前比较有效的仍然是blazeds，这个技术需要的介绍内容不在本文的范围之内。关于通信接口的实现有一种非常有用的方式就是借用Java的动态代理理念，Spring有一个flex的扩展子项目叫做springactionscript，而这个项目又引用了as3commons的库（类似于apache commons的一些公共组件）。为什么提及这个，因为flex本身的反射功能api非常难用，所以as3commons就做了扩展，它大大简化了反射的使用，而且提供了一个bytecode的工具用于操作字节码，它是实现动态代理的关键。至于为什么要动态代理？目的就是达到在写和Java对接的接口时，可以只声明接口，不需要实现类（得减少多少重复代码呀？），而和Java对接接口我们又可以开发一个工具让java code 自动转成 as code，如果懂得Eclipse插件开发的话还可以进一步做一个插件，达到Java只写一次就可以自动生成对应的flex接口，提高开发效率。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 转入正题，关于单元测试的概念，Flash Builder在4.5已经把flex unit作为内置库了，这点和Eclipse把junit内置类似，而flex unit的使用网上有大量的资料介绍，这里也不多说。flex unit在测试as代码还是不错的，和junit测试一样，提供了一些简单的Assert断言，但是你最痛苦的却不是as的测试。企业开发的特点就是数据量不大，但是需求坑爹，经常变来变去，而且结构复杂，往往一张表很多字段，关联子表，层级属性多。而你如果选择了Flex做了展示层的技术，那必定是看中它比HTML + CSS + JS更强的界面交互功能。的确，这点不容质疑，Flex Spark的皮肤机制的确提供了很多优秀的特点，不过如果你想纯熟掌握它的整个机制，恐怕得花很多时间阅读源代码才行，而皮肤的制作整对别想让美工独自实现，它同样是需要技术积累的，介绍它需要用几个篇幅才足够。任何技术方案都一样，BS、CS、AIR在实现复杂界面时，对于开发人员来说，最痛苦的莫过于界面的单元测试。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 痛苦在哪里？回看上面那幅架构图，业务功能界面实现在Flex，业务逻辑在后台Java，那么当二个团队同时进行工作的时候，沟通就是最大的成本。解决沟通的问题就必须在先前设计时约定好接口和数据结构，那是会影响双方团队协调的关键因素。当双方同时进行开发的时候，势必存在前台依赖后台的情况，因为它能到达界面的前提得在整个框架载入后（并且可以初始化一堆数据，发生了通信），Java后台还好说，依赖于spring和junit可以做到很好的单元测试。而flex就痛苦了，我没有通讯啥都做不了呀！</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 如何设计单元测试？最大的出发点就是如何切掉和后台通信连接，看下面的简单结构图 </span>
<div align="center"><img style="border-bottom-color: #000000; border-top-color: #000000; border-right-color: #000000; border-left-color: #000000" border="1" alt="" src="http://www.blogjava.net/images/blogjava_net/nighty/impl.png" width="506" height="223" /></div><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 实现思路介绍：</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 1.&nbsp; 简化Application加载过程&nbsp;&nbsp; --&nbsp;&nbsp; 可以套用你主程序中的加载过程，但是不需要你的主界面其它多余的元素，达到减少到达测试界面的多余步骤（尽可能少地减少鼠标和键盘操作）</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 2.&nbsp; 定义测试配置&nbsp;&nbsp; --&nbsp;&nbsp; 测试哪个模块？哪个工作流程？你得通过配置的方式来定义，而不是每次都手写代码，才能方便你的成员使用你这个工具</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 3.&nbsp; 模拟后台接口实现&nbsp; --&nbsp; 记得上面说的动态代理吗？其实是为接口动态生成一个实现类，然后注入真正通信的实现代码，例如WebService、HTTP，既然可以注入这些通信渠道，当然就可以注入本地实现类啦</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 4.&nbsp; 对象查看器&nbsp;&nbsp;&nbsp; --&nbsp;&nbsp; 这个是神马？因为你都不要Java后台了，每次操作一个界面后得提交数据吧？没有后台了，提交到哪里？你得必须把你的提交对象用界面展示出来吧？好吧，这个可是个难点！</span><br /><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 我想这四个方面的原则无非就是：减少单元测试需要进行的步骤（最快到达测试界面），脱离后台依赖（自己简单模拟后台实现，可惜flex没有类似java的mock库，悲剧！），如何查看提交到后台的结果。 单元测试的目标：界面能正常加载、提交数据正常，如果二者都没问题，那么联调的时候就可以非常容易定位到是Flex的问题还是Java的问题！达到介分责任的目标，当然，如果你所在团队是按模块分的，也就是说flex和java都是同一个人做，那么就不存在责任问题。</span><br /><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 怎么实现上面的四个步骤呢？简要地介绍一下吧。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 第1简化application加载，其实你可以把第一张图中的application加载机制拷贝过来，只是主界面可以做得非常简单，比如不需要多余的控件（比如过长的菜单、当前登录人、时间、一陀设置按钮等），只留下最核心的能到达你测试界面的入口，至于怎么设计这个简化版的application，那得发挥你本人的创造力，另外还得看具体的业务。<br /></span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp; 第2定义测试配置。模块如何加载？通信接口本地模拟实现类定义？通过配置显示在appliation做为触发控件，这些你都得自定义一套xml之类的文件来配置吧，这个就需要技巧了，不能设计得太复杂，因为你的开发人员需要沿用你定义的规范来定义它需要测试的模块，关于这方面的知识，可以参考spring加载配置文件方式、struts2加载定义文件等理念，有一个概念我比较推荐，就是struts2中的include配置文件，允许配置文件分散，让大家提供代码和文件时减少冲突，又可以套用你正常的加载机制。<br /></span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp; 第3模拟后台接口实现。这个是比较烦的，模拟机制本身通过动态代理倒是不难实现，恶心的是你得自己动手用flex简单实现一次后台生成数据、处理数据的逻辑。这里我有个实践的总结经验分享，在前期你调试完的后台接口证明是没有问题的，那么可以混合使用，一部分调试过的接口可以直接用后台，而新接口才本地模拟。一个原则就是后台有的，已经证明稳定的就用后台，没有的或是后台还没有完成的你就自己模拟。<br /></span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp; 第4对象查看器。想想flex不能操作数据库、由于安全限制不允许直接操作文件、无法读取本地文件目录。而你的测试数据也许会有关联（特别是在工作流方面），所以你得想一个方案来保存你的对象结果，而且得以一种人性化的方式查看对象内容。且抛开数据存储的问题，这个对象查看器如何设计就够你头疼的了，首先是对象得定义成一种格式，一种人可以看得懂的格式，比如xml，可以支持序列化和反序列化，你得去掉多余的无用属性和访问器。又得回到反射机制上了，序列化其实不难，难的是反序列化时如何正确地转成原来的对象。列一种本人设计的结构：</span><br /><span style="font-size: 14pt">&nbsp;</span><span style="color: #0000ff; font-size: 14pt">&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 14pt">&nbsp; &lt;xxx&nbsp;&nbsp; type="com.xx.oo.XXClass"&gt;</span><br /><span style="color: #0000ff; font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;aa type="String"&gt;aaa&lt;/aa&gt;</span><br /><span style="color: #0000ff; font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bb type="Boolean"&gt;true&lt;/bb&gt;</span><br /><span style="color: #0000ff; font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list type="mx.collection.ArrayCollenction"&gt;</span><br /><span style="color: #0000ff; font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....</span><br /><span style="color: #0000ff; font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;</span><br /><span style="color: #0000ff; font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; &lt;/</span><span style="color: #0000ff; font-size: 14pt">xx</span><span style="font-size: 14pt">x&gt;</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 对象分简单对象、复杂对象、动态对象等，如何表达这种结构和保证序列化时不丢失数据需要细心考虑。那么最后如何实现查看器呢？其实有一个参考的范例，就是Eclipse的&#8220;大纲&#8221;视图，经过实践的扩展，把树视图换成表格树（这种控件原生没有，有第三方的可以拿来修改），看个样图吧！</span><br />
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/nighty/result.png" width="701" height="500" /></div>&nbsp; <br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 因为你关注的对象内容无法就是这三个方面，属性名、值、和类型，又支持以树方式导航对象，已经足够你人眼分辩内容了。至于如何有效的保存测试数据，并且组织好结构，这个方面我目前也仍在思考中，未有较好的思路。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; 以上内容仅是出于本人的一种方案，也许有更好的实现方案，只是水平不足以超过这种认识，希望后续能进一步思考能实现更加完美的单元测试框架。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;&nbsp;&nbsp; ST测试更关注的界面的自动化测试，这方面涉及的知识更多，一般公司是很难有财力和技术去支持做自动化测试，属于比较高端的范围，实现是很多回归都靠测试团队人肉在实现。</span></div><img src ="http://www.blogjava.net/nighty/aggbug/376941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighty/" target="_blank">寒武纪</a> 2012-04-28 12:03 <a href="http://www.blogjava.net/nighty/archive/2012/04/28/376941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>B/S，C/S架构混合使用</title><link>http://www.blogjava.net/nighty/archive/2008/05/06/198669.html</link><dc:creator>寒武纪</dc:creator><author>寒武纪</author><pubDate>Tue, 06 May 2008 04:43:00 GMT</pubDate><guid>http://www.blogjava.net/nighty/archive/2008/05/06/198669.html</guid><wfw:comment>http://www.blogjava.net/nighty/comments/198669.html</wfw:comment><comments>http://www.blogjava.net/nighty/archive/2008/05/06/198669.html#Feedback</comments><slash:comments>21</slash:comments><wfw:commentRss>http://www.blogjava.net/nighty/comments/commentRss/198669.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighty/services/trackbacks/198669.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 一般而言，我们平常接触的大多数项目都应该是单纯使用B/S或是C/S，除非在特殊场合，否则比较少混合使用B/S，C/S架构。首先说一下对这二种架构特点的一些个人理解。B/S应该是目前很多项目都应用的架构，浏览器的方式使得用户的使用十分方便，用户可以何时何地通过Internet访问URL而进行相应的工作，升级维护也能比较集中，缺点就是浏览器的表现能力受限以及常常受非议的安全性问题，如果软件的应用范围区域不集中，而且用户经常变换地点进行访问，那么这种架构是非常适合的。C/S架构的C端有非常强的处理能力，所以在交互表现和安全方面可以做得比浏览器强，但是缺点也是非常明显的，安装部署、升级维护、版本兼容都是比较头大的事情，一般的适用场景是集中的办公室场所，用户使用范围相对稳定，以及一些对业务处理非常复杂的场合，为了降低服务器的负荷，同样需要C模式的支持。<br />
&nbsp;&nbsp;&nbsp; 以前接触过的电信领域，就有过混合架构的软件。但是都是非常宠大，一直都对其实现方案比较感兴趣，但是都没有机会进一步了解。最近搜索了一下相关的资料，总结一下混合应用的一些想法（只针对Java方向）。<br />
&nbsp;&nbsp;&nbsp; ①混合架构的问题集中点。服务端共享，客户端采用不同的表现方式，共享的应该是业务层接口，持久层应该是屏蔽的。应用层的消息传递就是整个应用的关键所在，虽然像Jakarta提供的httpClient这种模仿浏览器的组件，但是毕竟是模仿，在很多方面的功能还是缺失的。<br />
&nbsp;&nbsp;&nbsp; ②最传统的方式是采用EJB做为服务，这个宠然大物容易让人害怕，不过在分布式的系统中它还是有应用优势的，像电信和金融这种行业应用还是比较广的，而且现成的中间件和应用服务器商都比较多，像Oracel、BEA、IBM、Sun都有成熟的应用产品，当然开发的成本和人力投入也是恐龙级数据的。<br />
&nbsp;&nbsp;&nbsp; ③有网友说在C端直接访问数据库，B/S结构不变，也就是通过数据库进行共享。这种方式是不可取的，二个缺点：把服务器的业务逻辑搬到了C端上，严格上讲是不安全的，升级维护也非常麻烦；并发控制的压力都在数据库上。<br />
&nbsp;&nbsp;&nbsp; ④采用RMI，这个老古董相信应该很多人都不使用了，因为它的使用要一连串的手续，比如服务接口定义必须实现Remote接口，服务Server在实现时必须继承UnicastRemoteobject类，必须使用rmic指令产生stub和skeleton等，设置上繁杂。<br />
&nbsp;&nbsp;&nbsp; ⑤Spring 远程服务。这个应该说是比较可取的，大家都比较喜欢轻量级的东西。就如第一点所说的，通过远程服务，我们可以在客户直接调用服务端的服务接口，就像本地调用一样，Spring对远程服务提供了好几种实现方案。<br />
&nbsp;&nbsp;&nbsp; ⑥WebService。适合异构环境，但是WSDL的这种方式相对来说会比较耗费资料，因为标准定义除了业务内容外，还有许多另外的说明内容。<br />
&nbsp;&nbsp;&nbsp; Spring远程服务实现方案介绍：<br />
&nbsp;&nbsp;&nbsp; ⑴Spring + RMI。Spring把传统的RMI方式的繁杂设置去掉，只要配置Bean文件就和定义服务接口可以。RMI的服务启动和管理都交给Spring来处理。RMI访问的缺点就是对防火墙的穿透力比较差。<br />
&nbsp;&nbsp;&nbsp; ⑵Spring + Caucho的Hessian、Burlap。Hessian使用Http将对象以中性的二进制消息进行传送，而不像RMI使用Java的序列化格式（这种序列化是专制的，不是Sun提供的序列化机制），由于是二进制消息，所以不受限于某种实现语言，传输时所需要的带宽较小是其优点。Burlap是以XML文件格式传送对象，XML文件有较高可读性，应用程序只要能解释XML就能接收消息，当然也不限于某种语言，但是组装XML和解释XML都需要消耗资源，当传输大数据时性能应该存在问题。<br />
&nbsp;&nbsp;&nbsp; ⑶Spring + Http Invoker。由于Hessian的序列化机制不是正统的Java序列化机制，所以当遇到传输复杂的业务模型时，就会存在各种问题，为此，Spring又提供了Http Invoker，同样是使用Http传送对象，而且是使用Java的序列化机制。相比RMI，Http对防火墙的穿透力要强。<br />
&nbsp;&nbsp;&nbsp; 后来尝试了最后的这种Http Invoker方式，是在Spring2.0版本下尝试的，开发非常简单，网上也有大量的资料介绍。应该说从这里入口可以做一些尝试。目前遇到的一个项目就需要混合架构，B/S采用Spring2 + Struts2 + Hiberntae3，浏览器只提供一些查询功能和数据展现，C端采用Eclipse的RCP平台，共享服务器的业务接口，调用就采用Http Invoker远程服务，复杂的业务功能都集中在C端上。</p>
<img src ="http://www.blogjava.net/nighty/aggbug/198669.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighty/" target="_blank">寒武纪</a> 2008-05-06 12:43 <a href="http://www.blogjava.net/nighty/archive/2008/05/06/198669.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>