概述: 使用过程来组织业务逻辑,每个过程处理来自表现层的单个请求
特点
(1) 以数据为中心(输入->查询->处理->输出),典型的面向过程思想)
(2) 代码简单,易懂
(3) 适合项目不大的开发
(4) 业务逻辑和领域逻辑夹杂在事物脚本中,容易产生冗余数据
组织方式
(1) 一个类处理一类事物脚本,我们非常熟悉的编程方式
1 public class Gateway{ 2 private static final String findRecognitionsStatement = "select amount from revenueRecognitions where contract = ? and recognizedOn <= ?" 3 private static final String findContractStatement = "select * from contracts c,product p where id = ? and c.product = p.id"; 4 private static final String insertRecognitionStatement = "insert into revenueRecognitions values(?,?,?)"; 5 private Connection _db; 6 public ResultSet findRecognitionsFor(long contractId,Date asof) throws SQLException{ 7 PreparedStatement stmt = db.preparedStatement(findRecognitionsStatement); 8 stmt.setLong(1,contractId); 9 stmt.setDate(2,asof); 10 return stmt.executeQuery(); 11 } 12 public ResultSet findContract(long contractId)throws SQLException{ 13 PreparedStatement stmt = db.preparedStatement(findContractStatement); 14 stmt.setLong(1,contractId); 15 return stmt.executeQuery(); 16 } 17 public void insertRecognition(long contractId,Money amount,Date asof) throws SQLException{ 18 PreparedStatement stmt = _db.preparedStatement(insertRecognitionStatement); 19 stmt.setLong(1,contractId); 20 stmt.setBigDecimal(2,amount.amount()); 21 stmt.setDate(3,asof); 22 stmt.executeUpdate(); 23 } 24 }
class RecognitionService{ private Gateway _db; public Money recognizedRevenue(long contractNumber,Date asof){ Money result = Money.dollar(0); try{ ResultSet rs = _db.findRecognitionsFor(contractNumber,asof); while(rs.next()){ result = result.add(Money.dollars(rs.getBigDecimal("amount"))); } return result; }catch(Exception ex){ throw new RuntimeException(ex); } } public void calculateRevenueRecognitions(long contractNumber){ try{ ResultSet contracts = _db.findContract(contractNumber); contracts.next(); Money totalRevenue = Money.dollars(contracts.getBigDecimal("revenue")); Date recognitionDate = new Date(contracts.getDate("dataSigned")); String type = contracts.getString("type"); if(type.equals("S")){ Money[] allocation = totalRevenue.allocate(3); _db.insertRecognition(contractNumber,allocation[0],recognitionDate); _db.insertRecognition(contractNumber,allocation[1],recognitionDate.addDays(60)); _db.insertRecognition(contract,allocation[2],recognitionDate.addDays(90)); }else if(type.equals("W")){ _db.insertRecognition(contractNumber,totalRevenue,recognitionDate); }else if(type.equals("D")){ Money[] allocation = totalRevenue.allocate(3); _db.insertRecognition(contractNumber,allocation[0],recognitionDate); _db.insertRecognition(contractNumber,allocation[1],recognitionDate.addDays(30)); _db.insertRecognition(contract,allocation[2],recognitionDate.addDays(60)); } }catch(Exception ex){ throw new RuntimeException(ex); } } }
(2) 一个类处理一个事物脚本,这种方式可以以命令模式方式组织. Command pattern
1 interface transactionScript{ Object run() }
1 class recognizedRevenueTransationScript implements TransationScript{ 2 private long _contractNumber; 3 private Date _asof; 4 public recognizedRevenueTransationScript(long contractNumber,Date asof){ 5 _contractNumber = contractNumber; 6 _asof = asof; 7 } 8 public Object run(){ 9 Money result = Money.dollar(0); 10 try{ 11 ResultSet rs = _db.findRecognitionsFor(_contractNumber,_asof); 12 while(rs.next()){ 13 result = result.add(Money.dollars(rs.getBigDecimal("amount"))); 14 } 15 return result; 16 }catch(Exception ex){ 17 throw new RuntimeException(ex); 18 } 19 } 20 21 }
1 class calculateRevenueRecognitionsTransationScript implements TransationScript{ 2 private long _contractNumber; 3 4 public calculateRevenueRecognitionsTransationScript(long contractNumber){ 5 _contractNumber = contractNumber; 6 _asof = asof; 7 } 8 public Object run(){ 9 try{ 10 ResultSet contracts = _db.findContract(contractNumber); 11 contracts.next(); 12 Money totalRevenue = Money.dollars(contracts.getBigDecimal("revenue")); 13 Date recognitionDate = new Date(contracts.getDate("dataSigned")); 14 String type = contracts.getString("type"); 15 if(type.equals("S")){ 16 Money[] allocation = totalRevenue.allocate(3); 17 _db.insertRecognition(contractNumber,allocation[0],recognitionDate); 18 _db.insertRecognition(contractNumber,allocation[1],recognitionDate.addDays(60)); 19 _db.insertRecognition(contract,allocation[2],recognitionDate.addDays(90)); 20 }else if(type.equals("W")){ 21 _db.insertRecognition(contractNumber,totalRevenue,recognitionDate); 22 }else if(type.equals("D")){ 23 Money[] allocation = totalRevenue.allocate(3); 24 _db.insertRecognition(contractNumber,allocation[0],recognitionDate); 25 _db.insertRecognition(contractNumber,allocation[1],recognitionDate.addDays(30)); 26 _db.insertRecognition(contract,allocation[2],recognitionDate.addDays(60)); 27 } 28 }catch(Exception ex){ 29 throw new RuntimeException(ex); 30 } 31 return null; 32 } 33 34 }
现在大多数公司都是用这种方式开发软件,原因有以下几点
(1) 本质业务并不复杂
(2) 学习成本低(以数据为中心的编程方式不用考虑抽象,多态等一些问题)
(3) 这种开发方式已经被大多数公司认定为开发标准
(4) 公司不看重开发过程,只看最终结果
总结 :
这种开发方式是典型的经典的面向过程开发方式,在业务不复杂的时候可以非常好的解决
业务问题。
由于一个功能执行一个脚本,随着业务不断复杂,必定会出现冗余代码.
比如转账业务和取钱业务,都会出现相同的查询账户和验证。
可以通过抽取方法,或提取公共类解决相应的问题,
可是增加了复杂度,违背了事物脚本简单的初衷。
时间: 2024-10-07 15:53:09