Upload
edward-blackburn
View
37
Download
0
Embed Size (px)
Citation preview
Components• Identity Management
• Customer Services• Customer Portal
• Payment and Risk Services
• Canonical, versioned reference data
• Path finding fare generation for routes
• Journey Construction, apportionment, capping and fares
Philosophy• Object-Orientation; an object has both state
(data) and behaviour (logic)
• Domain model focused
• Tell don’t ask
• SOLID
“Tell Don’t Ask”https://pragprog.com/articles/tell-dont-ask
Tell Don’t Askpublic class Journey{
…public void AssociateRevenueInspectionTap(Tap tap) {..};public void CounterZeroRateDueToRevenueProtection()
{..};…
}
Tell Don’t Ask?public class Journey : Entity<Journey, JourneyKey>, IComparable<Journey>, IComparable<Tap>, ITapSequence, ICanProtectRevenue, IJourneyAffectedByRevenueInspection, IMayNotExist, IHaveTravelDayKey, IRateable, IDisruptable{
…public void AssociateRevenueInspectionTap(Tap tap) {..};public void CounterZeroRateDueToRevenueProtection() {..};public bool IsCounteredBy(Tap candidate) {..};public bool Exists { get; }public bool ContainsRevenueInspectionTap { get; }…
}
private IRule<Tap> CreateRule(TravelDay travelDay){
// Create rulesreturn Rule.Create(specification: new
IsRITWithinPreviousJourney(travelDay),ifSatisfied: ScenarioT01,ifNotSatisfied: Rule.Create(..));
}
private IRule<Tap> CreateRule(TravelDay travelDay){
// Create rulesreturn Rule.Create(specification: new
IsRITWithinPreviousJourney(travelDay),ifSatisfied: ScenarioT01,ifNotSatisfied: Rule.Create(
specification: new IsPreviousJourneyDisrupted(travelDay), ifSatisfied: ScenarioTDIS01, ifNotSatisfied: ScenarioT02 ));}
public sealed class IsTapTypeRailInspection : Specification<Tap>{
private static readonly ISpecification<Tap> _compositeSpecification = new IsTapModeRail().And(new IsTapTypeRevenueInspection());
protected override bool IsSatisfiedBy(Tap candidate) { return _compositeSpecification.IsSatisfiedBy(candidate);
}}
“Small Is Beautiful”• E. F. Schumacher
• To counter Bigger is Better
• Empowers developers to build complex features through small lego pieces
• Easy to read
Aggregate
“Nothing outside the Aggregate boundary can hold a reference to anything inside,
except to the root entity…”
- Eric Evans, Domain Driven Design, 2004
Aggregates & Continuations?
public class Card : Entity<Card, TravelTokenId> {
…
public void PerformCommand(IRuleCommand<Journey> command) { PerformCommand(command, () => _journeys.Select(item => … ) }
private void PerformCommand<TEntity>(IRuleCommand<TEntity> command,
Func<IEnumerable<TEntity>> getEntities) { Rule.Create(command).Process(getEntities()); }
…}
Pipelines and decorators
public interface ICardOperation{
Card Process(Card card);}
public interface IDecoratedCardOperation{
ICardOperation InnerCardOperation { get; private set; }}
public class RevenueProtection : ICardOperation, IDecoratedCardOperation{
public RevenueProtection (...){
...}
public Card Process (Card card){
card = InnerCardOperation.Process (card);...return card;
}
public ICardOperation InnerCardOperation { get;set;}}
Summary• Abstractions rot code
• Small interfaces
• If you have a DTO reconsider your approach
• Even anaemic models can be encapsulated
• Immutability is your friend