作者swpoker (swpoker)
看板java
标题Re: [问题] MVC程式架构
时间Mon Sep 2 11:57:32 2013
MVC中的model并不只是资料而已
model可以代表该企业模型相关资料及行为
但是首先要先说明的是
资料库并不是开始
相反的则是第二步骤之後
以我自己开发为例
我会先描述规划该作业相关的属性跟行为
先写好XXXBean的属性类别跟初步的行为类别,例如你觉得很奇怪的Service Manager
还有相关DAO-->这时是空的或是骗人的函式
然後稍微写一下testcase来验证一下规划的架构有没有怪怪的
甚至这个时候我还会把画面跟流程先给使用者看看有没有什麽大问题
(例如需要输入或显示的资讯是否充足 ,其他例如美观通常就不在此)
然後我才开始开table 实做dao
-->存放资料的实作其实是之後才开始的,而非一开始就先开好table
其实这种开发模式我是照着书上写的来试看看,然後发觉还不错用
於是我就养成这种习惯了
然而我的同事跟配合厂商的开发模式几乎都是DFD( Data Flow Diagram)
先开好TABLE,然後一路照着资料流的方式来走
通常在DFD的思维下,整个mvc就很不漂亮了
以spring 2.5(3.0)+开始导入annotation为例
其对於model的定义就并非以资料为主
而是 将 view的资料转换成model的资料并交付model去执行运算,并将其结果传至view
PS.我当初看到自动转换model的时候,相当的激动,可是看到为了系统实际需要
例如session 或是...
其原本所规画的model必须要被spring或是httprequest(view)所侵入的时候
我就觉得这不是model阿 ◢▆▅▄▃-崩╰(〒皿〒)╯溃-▃▄▅▆◣
那麽什麽是企业行为
你所举的workflow就是一例
举例来说
1.某企业开始创建全新的资讯系统
2.一开始就来先弄个web ap吧
3.程式就照web的规范来写就好
XXXAPageAction:
run(){
readdata();
doaaa();
dobbb();
writeccc();
if(aa){
gotopage1();
}else{
gotopage2();
}
}
以上可以发现到
将企业逻辑-doaaa dobbb 跟企业资料-readdata writeccc 还有显示方式 page1 page2
通通都放在一起
PS.其实这里我个人是认为(这里有不同的说法)-Action是用来桥接view的controller
而非model或是workflow
通常如果只有开发没有异动,通常就到此为止了
而这也是学校老师常会犯的错误,以为table开好就没事了吗
通常开始测试的时候,才是专案真正的开始
4.发现某个作业page也需要差不多的流程,但是显示的页面是不同的
所以要怎麽做?
*.共用?
XXXAPageAction:
run(){
readdata();
doaaa();
dobbb();
writeccc();
if(aa){
if(来源==XXXXB){
gotopageB1();
}else{
gotopage1();
}
}else{
if(来源==XXXXB){
gotopageB2();
}else{
gotopage2();
}
}
}
或是
*.复制?
XXXBPageAction:
run(){
readdata();
doaaa();
dobbb();
writeccc();
if(aa){
gotopageB1();
}else{
gotopageB2();
}
}
上述的两个方式,对於需求异动的应变能力相当的低
看看php asp 纯jsp 就知道了
所以把上述只跟企业有关的程式码通通集合在一起,取个大家了解的名子
这样不但可以重覆使用企业流程,同样的也方便异动
所以你的症结就在於使用DFD的思维去看系统设计
而忽略了企业行为(逻辑 流程 等...)的重要性
(基本上看到"资料存放在资料库"就知道是DFD的思维了)
因为资料存放在那里并不是物件导向设计第一要考虑的事情
可是我也不能对这种思维有什麽评论,老实说我周遭的人都是这种思维
其实model不仅是资料或是行为也包括相关的操作
例如交易范围 系统纪录等等 但这些都不是view所关切的
可是老实说也不是百分百的跟企业逻辑有关的-->PROXY AOP无误
所以整个mvc会是
view -controller - model(含流程 资料及相关如交易) - controller-view
model:
service(manager) - componment....
透过service可以有效的整理及管理企业相关资料 逻辑 及相关操作如交易等
只是大多的状况都是利用service来作为交易的管理就是
其实我自己认为在model层还要视情况导入process/flow层来分离企业流程
service-(flow)-componment
题外话(赚P币用的):
spring 2.0 + spring web( view(jsp/json))
有个问题就是跟页面有关的参数资料影响了json多余的资料
这也是跟mvc有关
例如
ajsp.
----
需要某个参数资料的显示
<c:forEach begin="1" items="${cusbeanrs}" var="cusbeanList">
<OPTION value="<c:out value="${cusbeanList.attra}"/>" >
<c:out value="${cusbeanList.attra}" /></OPTION>
</c:forEach>
----
所以
controller就会被迫加入
mav.addObject("cusbeanrs", queryBeanrs());
以供ajsp使用
其实cusbeanrs跟企业逻辑无关 这只跟view-jsp有关
甚至有些view-jsp是不需要该cusbeanrs的,但还是会执行该函数,造成浪费
这就是mvc没有切的很乾净 (来人阿!拖出去在阉!!)
解决方法就是
1.提供custom tag来用
但也会有个问题tag会好多,开发会是个问题,而且客制化也是个问题
2.使用ajax来呼叫
容易造成server的request过多,也造成重复或不必要
所以我自己弄了springtag 供jsp直接呼叫spring注册的bean来呼叫
将controller有关的参数档通通赶到jsp去(controller的mvc)
然後也降低了custom tag的开发-因为只有一个
程式码就变成了
ajsp
<springtag:bean beanname="cusDao" method="queryBeanrs"
name="cusbeanrs" />
<c:forEach begin="1" items="${cusbeanrs}" var="cusbeanList">
<OPTION value="<c:out value="${cusbeanList.attra}"/>" >
<c:out value="${cusbeanList.attra}" /></OPTION>
</c:forEach>
PS.是个有危险的tag(要注意PG是否滥用,但我有加入交易或是名称的限制)
然後搭配ajax来做非同步的submit,避免页面reload
在连续操作该作业的情况下,达到好处
*.页面参数分别只会查询一次,降低sql,也不需要ajax,降低request
(该参数是固定的结果,如果非固定则不在此)
*.controller更为乾净,避免不必要的函数
*.配合动态view输出,直接将jsp改为json,立刻变成 类REST Web App
※ 引述《cyclone350 (老子我最神)》之铭言:
: 大家好,因为这几年遇过几个web专案,有几个问题想起教大家
: 当然,我知道什麽是MVC,我也会用spring,也可能是我只懂皮毛,所以才会有以下问题
: 我会先分析专案所使用的程式架构,并尝试说明使用每个元件(如Dao)的原因
: 最後问一些问题,当中如果有错请指正,谢谢
: 首先资料是存在Database或是档案里面,为了方便(或是抽象),我们将结构化
: 的资料一对一对称到Java Bean,通常被称为是Entity,例如
: 资料库栏位跟值如下
: id | name | age |
: ----------------------------
: 5566 | google | 10 |
: ----------------------------
: 会对应到以下Java Bean
: public class Tablex {
: public int id;
: public String google;
: public int age;
: }
: 为了简化资料存取的逻辑,通常一个Entity会对应一个Dao class
: 例如要select资料只需要下列语法大概就能使用
: tablexDao.selectByPK(5566);
: 再来是 MVC,优点不赘述
: 首先 view 一定是 JSP
: controller 是一般的 Java class
: model 是 view 跟 controller 来互传的 Java Bean
: 以 Struts2 来举例好了,Controller 是 Action class,
: 也就是说在Action 我们必须做一连串的动作来完成事情,
: 举一个例子,我要从tablex检查特定id资料有无资料
: Action 可以写成如下:
: public class testPageAction {
: TablexDao tablexDao;
: testPageFormBean formBean;
: ...
: ...
: ...
: //假设Dao跟FormBean都设定完传好值开始跑
: public void run() {
: int pk = formBean.getId();
: Collection resultSet = TablexDao.selectByPK(pk);
: if (resultSet.isEmpty()) {
: Page.forward("fail");
: } else {
: Page.forward("success");
: }
: }
: ...
: ...
: ...
: }
: 对我而言,Action class 只是一个 workflow,
: 一连串的行为都必须到对应的Action 完成,当然为了 clean code 我们可以
: 设定一些 private method 来避免程式码重复等问题
: 有人可能会多写一个Function,例如
: private boolean doSomething(int id) {
: ...
: ...
: return false;
: }
: 然後再 run 里面呼叫
: public void run() {
: ...
: ...
: x = doSomething(4);
: y = doSomething2(1,x);
: if(x || y) Page.forward("success");
: Page.forward("fail");
: }
: 以上,是我所认识的 MVC 架构
: 问题来了,我待过的每一个Web专案理,都会在Action 跟 Dao 中间夹带一层 Service
: 或是 manager...
: 而规定几乎是 "一个Action对应一个manager"
: 而 manager 所做的事,就像是把Action 的 private method 移到 manager 变成
: public method ...
: 我完全找不到理由可以说明为啥要特地开一个 manager, manager的工作事项模糊不清
: 一个写在 manager 的 public method 完全可以改到自身
: Action class 的 private method
: 而实际情况是,在写method时,有些程式设计师会写到 Action ,有些会写到 Manager
: 这完全没有意义,假设有 10 个 method,两位程式设计师可能写完全不一样
: 例如
: 程式设计师A: 1,2,4,5,6 写到 Action, 3,7,8,9,10写到 Manager
: 程式设计师B: 2,6,7,5,8,10 写到Action, 1,3,4,9写到 Manager
: 我所遇到的专案就是如此,有没有人能够解释 Service 或 Manager 的必要,以及它们
: 真正存在的意义在哪里?
: 苦恼很久了
: 谢谢大家看完
--
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 163.29.28.131
1F:推 cyclone350:感谢回复,我可能需要...一点点点点点的时间吸收... 09/02 12:52
2F:→ swpoker:我是在思考SOA中的何谓"服务"中想到的~提供参考 09/02 13:24
3F:→ flowwinds:请问不能塞empty object给mav.addObject()吗?不大懂.. 09/02 13:39
4F:→ swpoker:spring2.5+直接支援把jsp输出改成json~controller不变喔 09/02 13:43
5F:→ swpoker:重点在不变更现有程式下,却可扩增系统功能喔 09/02 13:46
其实这里的问题是
原本作业的流程是
a.jsp->
a.controller( ->xxService )->
b.jsp
後来有json+ajax这个好东西出现後
如果可以改成
ajax->a.conroller->json
但会有个问题就是
当输出(view)改变时,其controller是否要改变?
spring提供了不用改变的架构,透过uri的指定,可以改变要输出的view
但这就会有个问题
原本page的controller里面有提供给jsp使用的资料(跟业务逻辑无关)
也会一并输出成json,但是对於用ajax来呼叫的服务来说,里面有些资料是没有用的
换句话说,ModelAndView里面夹杂了非关业务逻辑的资料
如果无用就算了,但会多呼叫SQL,也是造成不必要的运算
那该怎麽办?
情境是
1.
a作业:
a.jsp->a.controller->a1.jsp
b作业:
b.jsp->ajax call a.controller with json->json get!!!
2.如何在异动最少及降低系统负担的情况下,达成上述的功能
因此我进一步的将controller理的modelAndView中的资料再次分离
原则为:
1.业务逻辑相关的资料及行为放在Model里
2.跟view相关的资料及行为放在各view里
达成了各元件的乾净,也可以降低系统不必要的操作
PS.其实也可以透过客制化的jsonview及model属性命名规则也可以达成同样的效果!
※ 编辑: swpoker 来自: 163.29.28.131 (09/02 14:27)
※ 编辑: swpoker 来自: 163.29.28.131 (09/02 14:33)
※ 编辑: swpoker 来自: 163.29.28.131 (09/02 14:34)
6F:→ flowwinds:大体上了解了, 感谢说明 09/02 20:05