从AWDWR中的depot思考软件设计
一般对购物车简单的描述会是这样的(其实就是AWDWR中的那个depot):
一个容器,可以放很多商品,可以随时查看购物车中的商品列表,这个列表能列出商品名称,单个商品购买的数量,商品单价,以及总价格。
我的思考过程是这样的,首先,它是个容器,可以放很多商品,那就是个数组吧,至于数量,查看的时候不是要遍历嘛,顺带计算一下就好。
想了一会,我觉得这种思考习惯,或者说设计过程是属于自底向上的,一开始就脱离上层的需求,去思考最底层的实现。我觉得这样会带来问题。需求是最高层的,而这时候的设计却是最底层的,中间全脱节了。什么?没有脱离需求?没错,这样的做法最终确实能实现一个购物车,没有脱离最终的用户需求,但在开发过程中会带来很多麻烦。就从我上面的例子来说,最后的购物清单页面不得不塞入大量计算数量、价格等等的业务逻辑代码。
如果一开始就设计页面的代码呢,写好像这样的
<%for item in @cart.items%> <tr> <td><%=item.title%></td> <td><%=item.quantity%></td> <td><%=item.price%></td> </tr> <%end%> <tr> <td><%[email protected]_price%></td> <tr>
那接下来下面需要些什么不是很清楚了?也许一开始想不出什么@cart.item,但至少知道是个容器,里面的东西取出来之后,不需要写其它逻辑,不需要经过一系列计算就可以直接访问它的title、quantity、price属性。这样就明确了session里存放的应该是个容器,这个容器不会是个赤裸裸的数组,因为它得有个total_price方法,数组应该是它内部的一个属性。并且这个数组里不应该是直接存放Book、CD啥的,或者存放一堆的抽象类Product,不应该直接是这些……怎么称呼来着……Entity吧——不应该直接放这些东西,而是上层(页面)直接需要的东西——页面需要的是一个包含了title、quantity、price属性的对象,最后差的只是给它起个名字了,嗯,就叫CartItem吧。
前面提到的"脱离需求",不是指脱离最高层的需求,不是指脱离最终的用户需求,而是指下层脱离上层的需求。合理而自然的做法应该是下层的实现依赖于上层的需求,一层一层往下走,不知道这样描述够不够清楚。
嗯,搜索到ajoo的一篇:http://ajoo.iteye.com/blog/23304
看了一遍,其中有一句:
看来我的想法没有错。“不能让下层脱离上层的需求“就是指应该逐层地”自顶向下的逐渐细化求精“。
写得有些混乱,只是当笔记记录一下今天的领悟。