软件构建中的理想设计特征


1、最小复杂度。设计的手艺好目标就是要复杂度最小,避免作出“聪明的”设计,因为“聪明的”设计常常难以理解 2、易于维护。 易于维护意味着在设计时为做维护的程序员着想。 3、松散耦合。松散耦合意味着在设计时让程序各个组织称部分之间的管理关系最小。通过应用类接口中合理还凑向、封装及信息隐藏等原则设计出相互关联尽可能小的类。减少关联也就是减少了集成、测试和维护时的工作量。 3、可扩展性。可扩展性是只可以增强系统功能而无须改变底层结构,可以改变某一个方面功能而不影响其他部分。 4、可重用性。可重用意味着代码可以在其他系统的组成部分中重复使用,降低整体的成本和提高生产效率。 5、高扇入。高扇入就是说让大量的类是有那个某个给定的类。这就是意味着设计出的系统很好的利用较低层次上的工具类。 6、低扇出。低扇出就是让一个类里少量或者适中的使用其他的类。高扇出说明了一个类使用了大量其他的类,因此可能变得过于复杂。 7、可移植性。可移植性是说应该设计的系统很方便的移植到其他的环境中。 8、精简性。精简就意味着系统没有多余的部分。这样有利于后面的单元测试。 9、层次性。层次性就意味着尽量保持系统各个层次保持可分解,使你能在任何层面观察系统。 10、标准技术。一个系统所依赖的外来的,古怪的东西越多,别人在第一次想要理解它的时候就越头痛。尽量使用标准化,常用的方法,让整个系统给人一种熟悉的感觉。

会话状态模式


个人觉得会话状态模式其实算不得一种模式,因为无非就两种,而且必须是其中的一种,一种存放在客户端,一种存放在服务端。两者都有风险和优点。 通常将会话保存在客户端是为了获得服务端的高度无状态特性,即服务端可以做到完全的无状态。Java中通常使用传输对象来进行数据传输,因为传输对象可以在网上进行序列化,即使是很复杂的数据也可以进行传输。当然序列化是有风险和代价的,不是所有的序列化数据都能够被反序列化回来,虽然出现反序列化回来的出错的概率很小。 如果使用HTML的话,选择相对多一点,URL参数,隐藏表单域和Cookie,URL对于较小数据量还是比较容易使用的,现代浏览放开了对URL长度的限制,但我们不得不考虑一些古董用户的需求,毕竟IE6及以下版本的浏览器还主导着WEB世界,而且URL过长,也不符合REST原则,更不美观。 隐藏表单域适合于POST方式的请求,POST方式可以避免因浏览器限制URL长度而导致的被截断的问题。隐藏表单域在我曾经的代码中经常使用,主要是为了跟踪和referer的referer,也就是跳转到一个页面之前的原来页面。 Cookie方式是最优争议的一种方式,PHPWind采用了这一种方法,从开发者口中得知,是为了减少服务器的负载,因为服务器不用维护session状态。通过把数据序列化或者加密后以文本方式放到Cookie中,我没有测试过,PHPWind这样做是不是真的能降低服务器的负载,根据我以前的测试,session维护成本对于服务器的影响是微乎其微的,还不如优化一条SQL来得更痛快,更有效,而且放在Cookie中会导致用户请求的流量变大,在很多上下带宽不对称的机房中,这是个严重的问题,比如blogbus之前存放在上海的**机房就是这样。而且为了获得Cookie中的数据还需要进行一些列运算,未必比维护session的成本小,而且会导致严重的安全问题。只要算法是可逆的,就一定能被人破解,何况我等庸人搞的算法。 服务器会话状态最简单的一种就是把会话数据放到应用服务器的内存中,可以将会话数据以会话标识号作为键标识放到内存映射表中,现在很多工具可以做到,比如memcache等key-value 的内存存储工具。 另一种是持久化,持久化也可以分为两种,一种以二进制序列化形式存放,但这样做的缺点是不容易阅读,更新起来成本有点高,如果每个会话都一个文件的话,在高并发的时候还得解决文件系统的巨量小文件查找效率问题。还有一种就是持久化到数据库,这个存放会话的模式,可能会因为维护会话状态而带来巨大的数据库开销问题,而且为了及时清除过期的会话,往往配合触发器来进行。 总结起来每种会话管理都有天生的缺陷,如果能多种结合能够提升一些效率,比如内存缓存配合持久化数据库,就是眼下很多高负载网站正在使用的模式,也许还有其他的更多的模式和方法有待探寻~~

数据源架构模式笔记(一)


数据源架构模式笔记 一、表数据入口 表数据入口半酣了用于访问单个表的或视图的所有SQL,如CRUD操作,其他代码调用它的方法来实现所有与数据库的交互。 表数据入口很简单,一般包括几个从数据库中干活去数据的查找方法以及更新删除放放风每个方法都将输入参数映射为一个SQL调用并在数据库链接上执行改语句。由于表数据入口用于数据读写,所以通常是无状态的。 使用时机: 1、可以和表模块一起很好的使用,它称身隔一个记录集数据结构由表模块处理。 2、特别适用于事务脚本。 3、通常表数据入口和领域模型很少一起使用,因为数据映射器更好地分离了领域模型和数据库。 二、行数据入口 行数据入口充当数据源中单条记录入口的对象,每行一个实例。行数据入口和单条记录机器相似的对象,如数据库中的一行。在该对象中数据库中每一列变成了一个域。行数据入口一般能实现从数据源类型到内存中类型的任意转换,这种转换很简单。这个模式保持一行中的数据以便客户可以直接访问行数据入口,行数据入口是每一个数据行的良好接口。这种方法尤其适用于事务脚本。 使用行数据入口通常非为两步:第一步是否真的需要用入口;第二步,是使用行数据入口还是表数据入口。 行数据入口能和数据映射其一起配合使用,尽管这样看起来有点多此一举,当行数据入口从元数据自动生成,而数据映射器由手动实现时,这种方法会很有效。 如果把事务脚本和行数据入口一起使用,可能会发现业务逻辑在多处脚本中重复出现,这些逻辑可能在行数据入口中有族谱那个,不断移动这些逻辑会使行数据入口演变成活动记录,活动记录很好,因为他减少了业务逻辑中的重复。

《企业应用架构模式》笔记一


企业应用 定义:  企业应用一般都涉及到持久化数据。 企业应用一般都涉及大量数据 企业应用还涉及很多人同时访问 企业应用还涉及大量操作数据的用户界面屏幕。 企业应用很少独立存在,通常需要与散布在企业周围的其他企业应用集成。(技术多样化,协议多样化) 可伸缩性: 响应时间 响应性 等待时间 吞吐率 负载 负载敏度 效率 领域逻辑组织方式: 1.事务脚本 2.领域模型 3.表模块 服务层: 表现逻辑和领域逻辑之间的交互完全通过服务层,就像应用程序API一样。 如果确实需要,使用最小化的服务层 映射到关系数据库: 1. 为查询语句返回的每一行产生一个它的实例,种种行数据入口就行是面向对象方式来看待数据。 2.许多环境提供记录集,这种表和数据行的一种通用数据结构,用来模拟数据库的表格属性。 如果使用记录集,对于数据库的每个表只需要一个对象来管理。 并发: 解决方案有两个,一个是隔离,一个是不变性 隔离是学习操作系统分配内存的方式,让一个单元只允许一个进程访问 只有共享数据可以被修改的情况下并发问题才会出现。 事务属性: 1.原子性  在事务里面所有的动作要么全部完成,要么全部回滚 2.一致性  在事务开始和结束的时候,所有的资源要保持一致 3.隔离性  在事务完成之后,他的结果对于其他事务才是可见的 4.持久性  已提交的事务必须是可持久性的,即任何崩溃都是可以保存下来的 事务资源: 定义:用事务来控制并发的过程 长事务:跨越多个事务请求的事务 请求事务:在请求开始时启动,在请求结束时完成的事务 延迟事务:在外界事务读取或加载完成时,启动的事务,即在更新时才启动的事务 事务建议: 1.使用事务的时间应尽可能的短,尽量避免长事务,因为事务进行时间越长,锁定的东西越多, 在没有任何并发控制的情况下,事务时间越长越有机会导致数据的不一致,造成事务的无效回滚,使用延迟事务能够提供事务的性能。 2.使用事务时应该清楚的知道锁定的到底是什么,对于数据库来说,锁定的是被访问的行级数据。 3.如果一个事务要求锁定的行数超过数据库最大可支持事务锁定,那么会上升为表级锁,即锁升级。锁升级显然对并发造成很大的影响。 这也是为什么不能在领域层超类型级别上使用“对象”表的原因。 4.尽可能的减少事务隔离 事务隔离级别(由低到高): 1.读未提交 2.读已提交 [...]