Skip to content

Instantly share code, notes, and snippets.

@rommsen
Last active February 26, 2020 18:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rommsen/8bd366d237197b32eec4b7f8c881ddef to your computer and use it in GitHub Desktop.
Save rommsen/8bd366d237197b32eec4b7f8c881ddef to your computer and use it in GitHub Desktop.
Practical DDD Step 4 - Value Objects
using System;
using System.Collections.Generic;
namespace ddd_patterns
{
public class Attendee
{
private readonly Guid _id;
private readonly string _firstname;
private readonly string _surname;
private readonly IEnumerable<string> _phoneNumbers;
private readonly string _email;
public Attendee(Guid id, string firstname, string surname, IEnumerable<string> phoneNumbers, string email)
{
_id = id;
_firstname = firstname;
_surname = surname;
_phoneNumbers = phoneNumbers;
_email = email;
}
// Behaviour here
}
}
using System;
namespace ddd_patterns
{
public class BirdConfiguration
{
public readonly DateTime EarlyBirdFrom;
public readonly DateTime EarlyBirdUntil;
public readonly DateTime BlindBirdFrom;
public readonly DateTime BlindBirdUntil;
public readonly decimal BlindBirdPrice;
public readonly decimal EarlyBirdPrice;
public readonly decimal NormalBirdPrice;
public BirdConfiguration(
DateTime earlyBirdFrom,
DateTime earlyBirdUntil,
DateTime blindBirdFrom,
DateTime blindBirdUntil,
decimal blindBirdPrice,
decimal earlyBirdPrice,
decimal normalBirdPrice)
{
EarlyBirdFrom = earlyBirdFrom;
EarlyBirdUntil = earlyBirdUntil;
BlindBirdFrom = blindBirdFrom;
BlindBirdUntil = blindBirdUntil;
BlindBirdPrice = blindBirdPrice;
EarlyBirdPrice = earlyBirdPrice;
NormalBirdPrice = normalBirdPrice;
}
}
}
using System;
namespace ddd_patterns
{
internal static class BirdPriceCalculator
{
public static decimal Apply(BirdConfiguration birdConfiguration, DateTime bookingDate)
{
var price = birdConfiguration.NormalBirdPrice;
if (bookingDate >= birdConfiguration.BlindBirdFrom && bookingDate <= birdConfiguration.BlindBirdUntil)
{
price = birdConfiguration.BlindBirdPrice;
}
else if (bookingDate >= birdConfiguration.EarlyBirdFrom && bookingDate <= birdConfiguration.EarlyBirdUntil)
{
price = birdConfiguration.EarlyBirdPrice;
}
return price;
}
}
}
using System;
namespace ddd_patterns
{
public class DiscountPriceCalculator
{
private readonly IVoucherService _vouchers;
public DiscountPriceCalculator(IVoucherService vouchers)
{
_vouchers = vouchers;
}
public decimal Apply(string voucher, decimal amount)
{
return amount - _vouchers.DiscountFor(voucher);
}
}
}
namespace ddd_patterns
{
public interface IPaymentService
{
public bool Pay(decimal amount, decimal vat);
}
}
using System;
namespace ddd_patterns
{
public interface ITicketRepository
{
public int HowManyAreAvailable();
public Guid Book(Guid attendee);
public void Cancel(Guid tId);
void Payed(Guid ticket);
DateTime BookingDateFor(Guid ticket);
}
}
namespace ddd_patterns
{
public interface IVoucherService
{
public int DiscountFor(string voucher);
}
}
using System;
namespace ddd_patterns
{
public class OnlineTickets
{
private readonly ITicketRepository _tickets;
private readonly IPaymentService _paymentService;
private readonly DiscountPriceCalculator _discountPriceCalculator;
private readonly BirdConfiguration _birdConfiguration;
public OnlineTickets(
ITicketRepository tickets,
IPaymentService paymentService,
DiscountPriceCalculator discountPriceCalculator,
BirdConfiguration birdConfiguration)
{
_tickets = tickets;
_paymentService = paymentService;
_discountPriceCalculator = discountPriceCalculator;
_birdConfiguration = birdConfiguration;;
}
public Guid BookFor(Guid attendee)
{
var availableTickets = _tickets.HowManyAreAvailable();
if (availableTickets <= 0)
{
throw new Exception("No Ticket available");
}
return _tickets.Book(attendee);
}
public void Cancel(Guid ticket)
{
_tickets.Cancel(ticket);
}
public bool PayFor(Guid ticket, string voucher)
{
var bookingDate = _tickets.BookingDateFor(ticket);
var amount = BirdPriceCalculator.Apply(_birdConfiguration, bookingDate);
amount = _discountPriceCalculator.Apply(voucher, amount);
var vat = VATCalculator.Apply(amount);
if (!_paymentService.Pay(amount, vat))
{
return false;
}
_tickets.Payed(ticket);
return true;
}
}
}
using System;
using System.Data.SqlClient;
namespace ddd_patterns
{
public class SqlTicketRepository : ITicketRepository
{
private readonly string _connectionString;
public SqlTicketRepository(string connectionString)
{
_connectionString = connectionString;
}
public int HowManyAreAvailable()
{
var availableTickets = 0;
const string sql1 = @"SELECT get number of available tickets from db";
using var connection = new SqlConnection(_connectionString);
var command = new SqlCommand(sql1, connection);
connection.Open();
var reader = command.ExecuteReader();
while (reader.Read())
{
availableTickets = reader.GetInt32(0);
}
reader.Close();
return availableTickets;
}
public Guid Book(Guid attendee)
{
using var connection = new SqlConnection(_connectionString);
var tId = Guid.NewGuid();
const string sql2 = @"Insert into tickets... tId = @tId, aId = @aId";
var command2 = new SqlCommand(sql2, connection);
command2.Parameters.AddWithValue("@tId", tId);
command2.Parameters.AddWithValue("@tad", attendee);
command2.ExecuteNonQuery();
return tId;
}
public void Cancel(Guid tId)
{
using var connection = new SqlConnection(_connectionString);
const string sql = @"Delete FROM tickets WHERE tId = @tId";
var command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@tId", tId);
command.ExecuteNonQuery();
}
public void Payed(Guid ticket)
{
throw new NotImplementedException();
}
public DateTime BookingDateFor(Guid ticket)
{
throw new NotImplementedException();
}
}
}
namespace ddd_patterns.Step7
{
internal static class VATCalculator
{
public static decimal Apply(decimal amount)
{
return amount * 0.19m;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment