Enterprise application architecture

Download Report

Transcript Enterprise application architecture

ENTERPRISE APPLICATION
ARCHITECTURE
Domain Logic Patterns
 Transaction Script
 Domain Model
 Table Module
 Service Layer
Transaction Script
 Organizes business logic by procedures
where each procedure handles a single
request form the presentation
TS: How It Works
 Each business transaction corresponds to one
transaction script
 Business transaction: Book a hotel room
 Tasks: check room availability, calculate rates, update
the database – all handled in one BookARoom script.
 Transaction scripts access the database directly
 Don’t call any logic in the presentation layer
 Organization
 Each script is a procedure
 Related scripts are enclosed in one class
 Each script is in one class.
TS: Architecture
TransactionScript
businessTransaction1()
businessTransaction2()
businessTransaction3()
Gateway
sql_query= “ SELECT * FROM table 1…”
sql_insert = “INSERT into tablei…”
sql_update = “ UPDATE tablei …”
sql_delete = “DELETE FROM …”
findDataForBusinessTransaction1(sql_query)
insertRecordsForBusinessTransaction1(sql_insert, items)
updateRecordsForBusinessTransaction2(sql_update, items)
…
DB
TS: When to use it
 When the domain logic is very simple
 When transactions do not have a lot of
overlap in functionality
Example Revenue Recognition
 A contract is signed for one product
 The revenue of a contract may not be recognized
right away.
 Different types of product may have different
revenue recognition schedule
 Three types of product
 Word Processor: revenue recognized right away
 Spreadsheet: 1/3 today, 1/3 in 60 days, 1/3 in 90 days.
 Database: 1/3 today, 1/3 in 30 days, 1/3 in 60 days.
Product
Name
type
1 *
Contract
date _signed
revenue
1 *
RevenueRecognition
Amount
date
TS: Example
RecognitionService
calcRecognitions(contract#)
recognizedRevenue(contract#, date)
createContract(id, revenue, prod_id, date)
…
DatabaseGateway
Sql_findContract = “ SELECT * FROM Contract WHERE id = ?”
Sql_findRecogns = “select* from recog Where cid=? and date<?”
Sql_insertContract = “INSERT into contract…”
findContract(contract#)
findRecognitionsFor(contract#, date)
insertRecognition(contract#, revenue, date)
…
DB
Sequence Diagram: test cases
:Tester
:RecognitionService
:DatabaseGateway
:Database
createContract()
insertContract()
INSERT into contract …
calcRecognitions()
insertRecognition()
insertRecognition()
insertRecognition()
INSERT iinto Recog…
INSERT iinto Recog…
INSERT iinto Recog…
recognizedRevenue()
findRecognitionsFor()
SELECT * FROM …
TS: Example
class Gateway {
static String findRecogns = “SELECT * FROM
revenueRecognition WHERE contract = ? And date <= ?”;
static String findContract = “SELECT * FROM
contract c, product p WHERE c.id = ? And c.pid = p.id”;
public ResultSet findRecognitionsFor(int contrno, Date d)
{
PreparedStatement s = db.prepareStatement(findRecongs);
s.setInt(1, contrno);
s.setDate(2, d);
ResultSet result = s.executeQuery();
return result;
}
public ResultSet findContract(int contrno) {
PreparedStatement s = db.prepareStatement(findContract);
s.setInt(1, contrno);
ResultSet result = s.executeQuery();
return result;
}
}
TS: Example
class RecognitionService {
private Gateway gw = new Gateway();
public Money recognizedRevenue(int contrno, Date d) {
Money Result = Money.dollar(0);
ResultSet rs = gw.findRecognitionsFor(contrno, d);
while (rs.next()) {
result = result.add(rs.getBigDecimal(“amount”));
}
return result;
}
public void calculateRevenueRecognitions(int contrno) {
ResultSet contrs = gw.findContract(contrno);
totalRevenue = contrs.getBigDecimal(“revenue”);
dates = contrs.getDate(“date_signed”);
type = contrs.getChar(“type”);
if (type == ‘S’) {
db.insertRecognition(contrno, totalRevenue/3, date);
db.insertRecognition(contrno, totalRevenue/3, date+60);
db.insertRecognition(contrno, totalRevenue/3, date+90);
} else if (type = ‘W’) {
db.insertRecognition(contrno, totalRevenue, date);
} else if (type == ‘D’ {
...
}
...
Domain Model
 An object model of the domain that
incorporates both behavior and data
DM: Revenue Recognition
Contract
date _signed
revenue
recognizedRevenue(date)
calculateRecognitions()
*
1
Product
Name
type
calcRecognitions(contrct)
*
1
RecognitionStrategy
calcRecognitions(contrct)
1
*
RevenueRecognition
Amount
date
isRecognizableBy(date)
DB
Three-way
RecognitionStrategy
Complete
RecognitionStrategy
DM: Example
class RevenueRecognition {
private Money amount;
private Date date;
public RevenueRecognition(Money amnt, Date d) {...}
public Money getAmount() {
return amount;
}
public boolean isRecognizableBy(Date date) {
return this.date.before(date) || this.date.equals(date);
}
...
}
class Contract {
private List revenueRecognitions = new ArrayList();
public Money recognizedRevenue(Date date) {
Money result = Money.dollar(0);
Iterator it = revenueRecognitions.iterator();
while (it.hasNext()} {
RevenueRecognition r = (RevenueRecognition)it.next();
if (r.isRecognizableBy(date))
result = result.add(r.getAmount());
}
return result;
}
...
DM: Example
class RevenueRecognition {
private Money amount;
private Date date;
public RevenueRecognition(Money amnt, Date d) {...}
public Money getAmount() {
return amount;
}
public boolean isRecognizableBy(Date date) {
return this.date.before(date) || this.date.equals(date);
}
...
}
class Contract {
private List revenueRecognitions = new ArrayList();
public Money recognizedRevenue(Date date) {
Money result = Money.dollar(0);
Iterator it = revenueRecognitions.iterator();
while (it.hasNext()} {
RevenueRecognition r = (RevenueRecognition)it.next();
if (r.isRecognizableBy(date))
result = result.add(r.getAmount());
}
return result;
}
...
DM: Example
class Contract {
private Product product;
private Money amount;
private Date dateSigned;
private long id;
public Contract(Product p, Money amnt, Date d) {...}
public void addRecognition(RevenueRecognition rr) {
revenueRecognitions.add(rr);
}
public Date getDateSigned() {
return dateSigned;
}
public void calcRecognitions() {
product.calcRecognitions(this);
}
...
}
interface RecognitionStrategy {
public void calcRevenueRecognitions(Contract c);
}
DM: Example
class CompleteRecognitionStrategy implements ... {
public void calcRevenueRecognitions(Contract c) {
c.addRecognition(new RevenueRecognition(
c.getAmount(), c.getDateSigned());
}
}
class ThreeWayRecognitionStrategy implements ... {
private int firstRecognitionOffset;
private int secondRecognitionOffset;
public ThreeWayRecognitionStrategy(int offset1, int offset2) {
this.firstRecognitionOffset = offset1;
this.secondRecognitionOffset = offset2;
}
public void calcRevenueRecognitions(Contract c) {
c.addRecognition(new RevenueRecognition(
c.getAmount()/3, c.getDateSigned());
c.addRecognition(new RevenueRecognition(
c.getAmount()/3, c.getDateSigned()+offset1);
c.addRecognition(new RevenueRecognition(
c.getAmount()/3, c.getDateSigned()+offset2);
}
... }
DM: Example
class Product {
private String name;
private RecognitionStrategy recogStrategy;
public Product(String name, RecognitionStrategy rs) {
this.name = name;
this.recogStrategy = rs;
}
public void calcRecognitions(Contract c) {
recogStrategy.calcRecognitions(c);
}
public static Product newWordProcessor(String name) {
return new Product(name,
new CompleteRecognitionStrategy());
}
public static Product newSpreadsheet(String name) {
return new Product(name,
new ThreeWayRecognitionStrategy(60, 90));
}
public static Product newDatabase(String name) {
return new Product(name,
new ThreeWayRecognitionStrategy(30, 60));
}
}
DM: Example
class Tester {
public static void main(String[] args) {
Product word = Product.newWordProcessor(“IntelWord”);
Product calc = Product.newSpreadsheet(“calc II”);
Product db = Product.newDatabse(“DB IV”);
Date today = System.today();
Contract c1 = new Contract(word, 300000, today);
c1.calcRecognitions();
Contract c2 = new Contract(calc, 24000, today);
c2.calcRecognitions(); // sequence diagram – next slide
Contract c3 = new Contract(db, 540000, today);
c3.calcRecognitions();
System.out.println(c1.recognizedRevenue(today + 10));
System.out.println(c2.recognizedRevenue(today + 70));
System.out.println(c3.recognizedRevenue(today + 80));
}
}
DM: Sequence Diagram: c2.calcRecognitions()
:Tester
c2.:Contract
recogStrategy:RecognitionStrategy
product:Product
calcRecognitions()
calcRecognitions(c2)
calcRecognitions(c2)
Mount = getAmount()
date = getDateSigned()
(amount/3, date)
addRecognition(rr1)
(amount/3, date + 60)
addRecognition(rr2)
(amount/3, date + 90)
addRecognition(rr3)
rr1:RevenueRecognition
rr2:RevenueRecognition
rr3:RevenueRecognition
DM: Sequence Diagram: c2.recognizedRevenue()
:Tester
c2.:Contract
rr[0]:RevenueRecognition
recognizedRevenue(date)
isRecognizableBy(date)
getAmount()
isRecognizableBy(date)
getAmount()
isRecognizableBy(date)
return result
rr[1]:RevenueRecognition
rr[2]:RevenueRecognition
Table Module
 A single instance that handles the business
logic for all rows in a database table or view
 Each module is responsible for all the CRUD
operations on the corresponding table.
 No other modules are supposed to CRUD directly
on the table
 Each module also includes business logic that is
tightly related to the table.
TM: Architecture
TableModule_1
CRUD operations on Table_1
Business Logic related to Table_1
TableModule_2
CRUD operations on Table_2
Business Logic related to Table_2
Table_1
Attributes
Table_2
Attributes
Database
TableModule_n
CRUD operations on Table_n
Business Logic related to Table_n
Table_n
Attributes
TM: Example - Tables
Contract
Id:
dateSigned:
revenue:
prod_id:
Number
Date
Number
Number (FK)
RevenueRecognition
Id:
amount:
date:
c_id:
Product
Id:
Number
name: String
type:
String
Number
Number
Date
Number (FK)
TM: Example - Modules
Contract
RevenueRecognition
Insert(cid, revenue, prod_id, date)
calculateRecognitions(c_id)
Insert(c_id, amount, date)
recognizedRevenue(c_id, date)
Product
getProductType(prod_id)
DB
TM: Sequence Diagram: calcRecognitions()
:Tester
:RevenueRecognition
:Contract
:Product
calcRecognitions(cid)
getContract(id)
contract:ResultSet
DB
SELECT
getProductID()
getProductType(pid)
SELECT
getRevenue()
getDateSigned()
return result
insert(cid, revenue/3, date)
INSERT
insert(cid, revenue/3, date+60)
INSERT
insert(cid, revenue/3 date+90)
INSERT
TM: Sequence Diagram: recognizedRevenue()
:Tester
:RevenueRecognition
:Contract
recognizedRevenue(c_id, date)
getRecognitions(c_id, date)
recognitions:ResultSet
getAmount()
getAmount()
getAmount()
return result
DB
SELECT
Service Layer
 Defines an application’s boundary with a
layer of services that establishes a set of
available operations and coordinates the
application’s response in each operation.
 Two type of business logic
 Domain logic: pure logic of the business domain
 E.g., calculating revenue recognitions of a contract
 Application logic: application responsibilities
 E.g., notifying administrators and integrated
applications, of revenue recognition calculations
TM: Example - Modules
Data Loader
Integration
Gateways
Service Layer
Domain Model
DB
User Interfaces
SL: Architecture
 Domain logic: Domain model layer
 Application logic: Service layer
 Service layer:
 Operation Scripts – A set of classes that
implement application logic but delegate to
domain model classes for domain logic.
 Clients interact with the operation scripts
 Operation scripts for a subject area are
encapsulated in a class named SubjectService.
SL: Services and Operations
 Determined by the needs of clients
 Derived from use case models
 Data validation
 CRUD operations on domain objects
 Notification of people or other integrated
applications
 All responses must be coordinated and transacted
automatically by the service layer
SL: When to Use It
 When there are many different kinds of
clients
 When the response may involve application
logic that needs to be transacted across
multiple transactional resources
SL: Example
 Revenue Recognition
 New requirements: once revenue recognitions are
calculated, it must
 Email a notification to contract administrators
 Publish a message to notify other integrated
applications
SL: Example
ApplicationService
getEmailGateway(): EmailGateway
getIntegrationGateway(): IntegrationGateway
EmailGateway
IntegrationGateway
sendEmail(toAddr, subj, body)
publishRevenueRecogs(contract)
RecognitionService
calcRevenueRecogs(contr#)
recognizedRevenue(contr#, date)
Domain Model
Contract
RevenueRecognition
Product
SL: Example
class RecognitionService extends ApplicationService {
public void calcRevenueRecogs(contractNo) {
Transaction trans = Transaction.getNewTransaction();
trans.begin();
// delegate to domain objects
Contract contract = Contract.getContract(contractNo);
contract.calcRecognitions();
Contract c2 = new Contract(calc, 24000, today);
// interact with transactional sources
getEmailGateway().sendEmail(contract.getAdminEmail(),
“RE: contract revenue recognitions”,
contract.getId()
+”Recognitions calculated”);
getIntegrationGateway().publishRevenueRecogs(contract);
trans.commit();
}
}
Domain Logic: Summary
 Transaction Script
 One script per user request/action
 Good for simple, no-overlapping business logic
 Domain Model
 A set of interrelated objects for business logic
 Good for application with complex business logic
 Table Module
 A module for the CRUD operations and business logic for a table
in DB
 Compromise between Transaction Script and Domain Model
 Service Layer
 Application logic is separated into a new layer from domain logic
 Good for applications that have complex application logic –
interacting with multiple transactional resources