Service Architecture patterns

65
Service Architecture Patterns Avinash Chugh Vivek Singh Rohith Rajagopal

Transcript of Service Architecture patterns

Page 1: Service Architecture patterns

Service Architecture Patterns

Avinash ChughVivek Singh

Rohith Rajagopal

Page 2: Service Architecture patterns

Designs are neither good nor bad. They are more or less useful.

Martin Fowler

Page 3: Service Architecture patterns

Service = SOA service

External InterfaceInterface contractsMaps service contracts to/from domain entitiesInteracts with DDD servicesCross functional responsibility

Page 4: Service Architecture patterns
Page 5: Service Architecture patterns

SOA Services

Services

Mappers

ServiceContract

PersistenceMappings

Repositories

get client requests as

request/response withdomain objects

Factories Entities

Value ObjectsAggregates

DomainModel

find domain objects

orchestrates business logic

read/writedata source

send request contract to

find/save domain objects

Page 6: Service Architecture patterns

Service = DDD Service

Core business logicOrchestrates domain layerReusable within a SOA service

Page 7: Service Architecture patterns

Simple Banking Application

Customer(1)----(*)Account(1)----(*)TransactionOpening an accountView transactions across accountsAccount SummaryCustomer ProfilePerform transaction

Page 8: Service Architecture patterns
Page 9: Service Architecture patterns

Service Responsibility Partition

Breaking system into different services

Page 10: Service Architecture patterns

Minimal Distributed System Architecture

Services

Database

User Interface

Application

Page 11: Service Architecture patterns

Grows to monolithic services

Single databaseEverything gets deployed every timeTest everything every time

Need for smaller sub-systems

Page 12: Service Architecture patterns

Database

Domain Model

Service A

Database

Domain Model

Service B

Database

Domain Model

Service C

Database

Domain Model

Service D

Data Ownership Driven Services

Page 13: Service Architecture patterns

Advantages

Development decouplingIndependent evolutionDeployment independenceLow testing cost

Page 14: Service Architecture patterns

Disadvantages

Page 15: Service Architecture patterns

Inner loop problem/N+1 problem

Database

Domain Model

Account Service

Database

Domain Model

Transaction Service

Customer

Acc 1

Acc2

Acc4

Acc3

Txn1

Txn2

Txn3

Txn1

Txn5

Txn1

Txn2

Txn1

Page 16: Service Architecture patterns

AccountService calling TxnService

GetTransactions(acc1)GetTransactions(acc2)GetTransactions(acc3)GetTransactions(acc4)

Page 17: Service Architecture patterns

Batch Request Interface

GetTransactions(acc1, acc2, acc3, acc4)

Use correlation ids instead of orderDoesn’t solve all problems

Page 18: Service Architecture patterns

Transaction Atomicity

Database

Domain Model

Service A

Database

Domain Model

Service CCustomer

New Acc

Txn1

Page 19: Service Architecture patterns

Transaction

No transaction between service operationsDistributed transaction has performance issues

Page 20: Service Architecture patterns

Database

Domain Model

Service A

Domain Model

Service C

Domain Model

Service B

Domain Model

Service D

Shared Data Services

Database Database

Page 21: Service Architecture patterns

Advantages

Easier resolution of performance issuesTransaction supportDevelopment still quite independent

Page 22: Service Architecture patterns

Disadvantages

Unclear domain boundariesFuzzy ownership of dataCode duplication across services

Page 23: Service Architecture patterns

Tradeoffs

Code duplicationModel duplicationTransactions

Service IndependencePerformanceData Ownershipvs

Page 24: Service Architecture patterns
Page 25: Service Architecture patterns

Service Contract Design

Page 26: Service Architecture patterns

By design & not by side-effect

Service is a productContract is user interface for serviceCan help in multi-version capability

Page 27: Service Architecture patterns

Banking application contract

class OpenAccountRequest { int CustomerId; DateTime StartingDate; AccountType AccountType; Name AccountHolderName; }

class Name { string FirstName; string LastName; }

enum AccountType { Savings, Current }

Page 28: Service Architecture patterns

class OpenAccountRequest { string CustomerId; string StartingDate; string AccountType; Name AccountHolderName; }

class Name { string FirstName; string LastName; }

class OpenAccountRequest { int CustomerId; DateTime StartingDate; AccountType AccountType; Name AccountHolderName; }

class Name { string FirstName; string LastName; }

enum AccountType { Savings, Current }

Page 29: Service Architecture patterns

Possible starting dates

03/11/201003/11/10

03-11-201003-11-10

03-Nov-20103-Nov-10

Page 30: Service Architecture patterns

Possible customer id

008675100004664100004664

8675100004664CC008675100004664

Page 31: Service Architecture patterns

Service

Serve as much as possible

Page 32: Service Architecture patterns

class OpenAccountRequest { string CustomerId; string StartingDate; string AccountType; string AccountHolderFirstName; string AccountHolderLastName; }

class OpenAccountRequest { string CustomerId; string StartingDate; string AccountType; Name AccountHolderName; }

class Name { string FirstName; string LastName; }

Business doesn’t understand objects

Page 33: Service Architecture patterns

….and definitely not class inheritance

class OpenJointAccountRequest : OpenAccountRequest { int AccountNumber; } class OpenAccountRequest { string CustomerId; string StartingDate; string AccountType; string AccountHolderFirstName; string AccountHolderLastName; }

class OpenAccountRequest { string CustomerId; string StartingDate; string AccountType; string AccountHolderFirstName; string AccountHolderLastName; string JointAccountNumber; }

Page 34: Service Architecture patterns

Use flat structure, no nested objectsNested objects only when using list

Business Readable Contract

Page 35: Service Architecture patterns

Service operations are not methods public interface PaymentGatewayService { bool Authorize(string cardNumber, string verifiedByVisaPassword); bool Validate(string cardNumber, string holderName, string cvv); bool PerformTransaction(string cardNumber, string holderName, string cvv, decimal amount); }

interface PaymentGatewayService { CreditCardPaymentResponse Process(CreditCardPaymentRequest request); }

Page 36: Service Architecture patterns

class CreditCardPaymentRequest { string CardNumber; string CVVNumber; string VBVPassword; string HolderName; string Amount; }

class CreditCardPaymentResponse { string ErrorCode; string ErrorDescription; string TransactionReferenceNumber; }

No parameters/return-value/exception

Page 37: Service Architecture patterns
Page 38: Service Architecture patterns

Late Binding over Fail fast

Service side validation over schema validationLoose types over strong typesError message over system exceptions

Also useful in versioning

Page 39: Service Architecture patterns
Page 40: Service Architecture patterns

Decouple Domain Entities and Service Contract

Page 41: Service Architecture patterns

Web Services

Database

User Interface

Application

Data Transfer Objects

UI Model

Domain Model

Extremely Common Architecture

ORMapping objects

Page 42: Service Architecture patterns

Writing different data definition and mapping them

Can be quite tedious and error prone

Page 43: Service Architecture patterns

What can we do?

Page 44: Service Architecture patterns

Web Services

Database

User Interface

Application

Data Transfer Objects

UI Model

Domain Model

ORMapping objects

Hibernate

Page 45: Service Architecture patterns

How about?

Page 46: Service Architecture patterns

Web Services

Database

User Interface

Application

Domain Model

Domain Model

Domain Model

Hibernate

Data Transfer Objects

UI Model

Shared Domain Model

Page 47: Service Architecture patterns

public class Customer { int id; Name name; int age; IList<Account> accounts; } public class Account { int id; string number; DateTime openingDate; DateTime closingDate; decimal balance; IList<Transaction> transactions; } public class Transaction { int id; DateTime date; decimal amount; TransactionType type; }

public enum TransactionType { Credit, Debit } public class Name { string first; string middle; string last; string title; }

Domain Model

Page 48: Service Architecture patterns

public class Customer { int id; string firstName; string middleName; string lastName; string title; int age; }

public class Customer { int id; Name name; int age; }

public class Name { string first; string middle; string last; string title; }

Domain ModelContract

Can tolerate this

Page 49: Service Architecture patterns

public class Customer { string id; string firstName; string middleName; string lastName; string title; string age; }

public class Customer { int id; Name name; int age; }

public class Name { string first; string middle; string last; string title; }

Contract

…even this

Domain Model

Page 50: Service Architecture patterns

public class Customer { int id; int customerId; string firstName; string middleName; string lastName; string title; int age; }

public class Customer { int id; int customerId; string firstName; string middleName; string lastName; string title; int age; }

Contract

Encapsulate service internals

Domain Model

Page 51: Service Architecture patterns

public class Customer { public string CustomerId { get; set; } public string FirstName { get; set; } public string MiddleName { get; set; } public string LastName { get; set; } public string Title { get; set; } public string Age { get; set; } }

public class Customer { int customerId; string firstName; string middleName; string lastName; string title; int age; }

Encapsulate Domain Model

Contract

Domain Model

Page 52: Service Architecture patterns

public class Customer { public string CustomerId { get; set; } public string FirstName { get; set; } public string MiddleName { get; set; } public string LastName { get; set; } public string Title { get; set; } public string Age { get; set; } }

public class Customer { int id; int customerId; Name name; int age; }

public class Name { string first; string middle; string last; string title; }

Too much mismatch

Contract DomainModel

Page 53: Service Architecture patterns

Bad contract and domain

Page 54: Service Architecture patterns

public class CustomerService { private readonly CustomerRepository customerRepository;

public CustomerService(CustomerRepository customerRepository) { this.customerRepository = customerRepository; }

public Customer Get (CustomerServiceRequest request) { try { return customerRepository.LoadCustomer(request. Identification); } finally { customerRepository.Dispose(); } } }

Simple Service Implementation

Page 55: Service Architecture patterns

public class Customer { Name name; int age; }

public class Customer { Name name; IList<Account> accounts; } public class Account { decimal balance; IList<Transaction> transactions; } public class Transaction { int id; DateTime date; decimal amount; TransactionType type; }

public class Customer { Name name; IList<Account> accounts; } public class Account { string number; decimal balance; }

Customer Profile

Accounts Summary

Transactions Since

Page 56: Service Architecture patterns

No control over data sent

Page 57: Service Architecture patterns

<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping > <class name="Customer" table="Customers" lazy="true"> <id name="Id"> <column name="Id" not-null="true" /> <generator class="identity" /> </id> <bag name="accounts" lazy="true" cascade="all-delete-orphan" access="field"> <key column="CustomerId" /> <one-to-many class="Account"/> </bag> </class>

<class name="Account" table="Accounts" lazy="true"> <id name="Id"> <column name="Id" not-null="true" /> <generator class="identity" /> </id> </class></hibernate-mapping>

Page 58: Service Architecture patterns

Serializing lazy domain object

Create Session Load

Customer

Return Customer

Close Session

Get Customer

Customer Response

Page 59: Service Architecture patterns

Lazy entities not loaded

Account 2

IdBalance

Account 1

IdBalance

Customer

IdNameAge

Page 60: Service Architecture patterns

hacks…<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping > <class name="Customer" table="Customers" lazy=“false"> <id name="Id"> <column name="Id" not-null="true" /> <generator class="identity" /> </id> <bag name="accounts" lazy=“false" cascade="all-delete-orphan" access="field"> <key column="CustomerId" /> <one-to-many class="Account"/> </bag> </class>

<class name="Account" table="Accounts" lazy=“false"> <id name="Id"> <column name="Id" not-null="true" /> <generator class="identity" /> </id> </class></hibernate-mapping>

Page 61: Service Architecture patterns

isn’t this smart public Customer Get(CustomerIdentification customerIdentification) { try { Customer customer = customerRepository.LoadCustomer(customerIdentification); ForceLoad(customer); return customer; } finally { customerRepository.Dispose(); } }

private void ForceLoad(Customer customer) { customer.ToString(); customer.Accounts.ForEach(account => account.ToString()); //.....so on }

Page 62: Service Architecture patterns

no…may be should have used reflection

Page 63: Service Architecture patterns

Tradeoffs

Code reuseLess codeMapping simplicity

Design compromiseDecouplingControl serialized dataPerformance

vs

Page 64: Service Architecture patterns
Page 65: Service Architecture patterns

Thank you!