Month: May 2014

如果你的系统既有web界面,又要暴露remote api,应该怎么分层?

如果你的系统既有web界面,又要暴露remote api,应该怎么分层? 我的回答是: 1. 如果web操作为主,remote api是少数,那就用最常见的web-biz模式;web层不必那么薄,可以通过组装biz services实现use cases 2. 如果remote api为主,web操作为辅,则应该用web-app-biz模式,并且web层不准直调biz层。 ============================================== 这张图好理解,也比较容易接受:app层组装biz service并实现校验逻辑,对外暴露服务;web层本身很薄,主要职能是把请求转给app层,校验都不用做。 可能存在的争论是:为什么要禁止web层直调biz层? 两层在同一个系统里(比如同一个JVM里),直调无障碍; 禁止直调的话,如果一个操作不作为remote api对外暴露,仍要在app层中加一层封装的代码供web层调用,岂不是很蛋疼? 这些坏处确实是存在的。但是经验表明,禁止直调带来的好处更多: 1. 系统做大后,出于分工或性能考虑,可能需要把web层剥离为一个独立系统。 如果你禁止直调,分分钟可以完成剥离; 否则,几乎不可能,除非你直接把biz service暴露成remote api(非常不好的做法)。 2. web层直调省不了多少工作量。问自己这样一个问题:校验及报错在哪里做? 非直调的话,校验做在app层,并使用标准的errorCode/errorMessage API返回错误,web层自己不必再校验; 直调的话,web层需要自己做一堆校验,工作量还是有的。 3. 直调时,web层要自己实现校验逻辑和biz service组装逻辑,直接使用domain objects, 这要求web层的开发者也要非常非常清楚业务逻辑;如果不允许直调,web层开发者只须组装request对象和渲染response对象,他可以把精力更多地放在javascript/css上,对业务逻辑只需有所了解即可;也就是说,web层的开发可以轻松外包(对于资源紧张的团队,这一点很有意义) 4. 最严重的问题在于,如果允许直调,对于某些use case,web层和app层可能会实现重复的校验逻辑和biz service组装逻辑。不要小看这些逻辑,可轻可重; 如果没有实现在单一的地方,系统很容易腐化 (违反DRY原则) ========================================== 禁止直调除了要作为开发规范让大家遵守,也应该在技术上作好防卫性设计。如果你用的是maven,可以这样: <!–web工程的pom.xml–> <dependency> <groupId>some.group</groupId> <artifactId>app</artifactId> </dependency> <dependency> <groupId>some.group</groupId> <artifactId>app-impl</artifactId> <exclusions> <exclusion> <groupId>some.group</groupId> <artifactId>biz</artifactId> …

如果你的系统既有web界面,又要暴露remote api,应该怎么分层? Read More »

小技巧:从多个数据源中取出前10条记录

考虑这样的场景:论坛里有个页面,混合展示所有的精华贴和热门贴; 帖子按ID逆序排列,并且要有分页。 怎么写出一个符合这种要求的SQL? 受限于你的数据库设计和性能约束,这样的SQL可能很难写。 有种办法是:先取出10条精华贴,再取出10条热门贴,然后再在内存里按ID逆序排列并去重,最后返回前10条。 这样做不需要做复杂的SQL查询,性能也能接受。不过,这种模式只适于 比较式分页(ID小于某个值的前10个帖子),不适应于普通的页码式分页(第N页)。  考虑一下取第二页的场景,你就明白我的意思了。