diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea5ebf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,205 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# AWS +*.aws-sam/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +#packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +#!packages/build/ + +!src/packages/**/*.dll +!src/packages/**/*.pdb + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml +src/packages/EventStore.Client.3.3.1/lib/net40/EventStore.ClientAPI.xml + +# JetBrains Rider +.idea/ +*.sln.iml + +# Vagrant VM files +.vagrant +vagrant/dbv/data/meta/revision + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea5ebf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,205 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# AWS +*.aws-sam/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +#packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +#!packages/build/ + +!src/packages/**/*.dll +!src/packages/**/*.pdb + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml +src/packages/EventStore.Client.3.3.1/lib/net40/EventStore.ClientAPI.xml + +# JetBrains Rider +.idea/ +*.sln.iml + +# Vagrant VM files +.vagrant +vagrant/dbv/data/meta/revision + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/BloatedHandler.cs b/BloatedHandler.cs new file mode 100644 index 0000000..e558ee7 --- /dev/null +++ b/BloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.Bloated; + +public class DispatchShipmentHandler : ICommandHandler +{ + private readonly Db _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public DispatchShipmentHandler(Db db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + if (shipment.Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready for dispatch."); + } + + shipment.Status = ShipmentStatus.Dispatched; + shipment.DispatchedAt = DateTime.UtcNow; + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + +public class Shipment +{ + public Shipment(DateTime dispatchedAt, Guid id) + { + DispatchedAt = dispatchedAt; + Id = id; + } + + public ShipmentStatus Status { get; set; } + public DateTime DispatchedAt { get; set; } + public Guid Id { get; set; } +} + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface Db +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea5ebf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,205 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# AWS +*.aws-sam/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +#packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +#!packages/build/ + +!src/packages/**/*.dll +!src/packages/**/*.pdb + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml +src/packages/EventStore.Client.3.3.1/lib/net40/EventStore.ClientAPI.xml + +# JetBrains Rider +.idea/ +*.sln.iml + +# Vagrant VM files +.vagrant +vagrant/dbv/data/meta/revision + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/BloatedHandler.cs b/BloatedHandler.cs new file mode 100644 index 0000000..e558ee7 --- /dev/null +++ b/BloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.Bloated; + +public class DispatchShipmentHandler : ICommandHandler +{ + private readonly Db _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public DispatchShipmentHandler(Db db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + if (shipment.Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready for dispatch."); + } + + shipment.Status = ShipmentStatus.Dispatched; + shipment.DispatchedAt = DateTime.UtcNow; + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + +public class Shipment +{ + public Shipment(DateTime dispatchedAt, Guid id) + { + DispatchedAt = dispatchedAt; + Id = id; + } + + public ShipmentStatus Status { get; set; } + public DateTime DispatchedAt { get; set; } + public Guid Id { get; set; } +} + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface Db +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/BloatedHandler.csproj b/BloatedHandler.csproj new file mode 100644 index 0000000..fd4bd08 --- /dev/null +++ b/BloatedHandler.csproj @@ -0,0 +1,10 @@ + + + + Exe + net9.0 + enable + enable + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea5ebf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,205 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# AWS +*.aws-sam/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +#packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +#!packages/build/ + +!src/packages/**/*.dll +!src/packages/**/*.pdb + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml +src/packages/EventStore.Client.3.3.1/lib/net40/EventStore.ClientAPI.xml + +# JetBrains Rider +.idea/ +*.sln.iml + +# Vagrant VM files +.vagrant +vagrant/dbv/data/meta/revision + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/BloatedHandler.cs b/BloatedHandler.cs new file mode 100644 index 0000000..e558ee7 --- /dev/null +++ b/BloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.Bloated; + +public class DispatchShipmentHandler : ICommandHandler +{ + private readonly Db _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public DispatchShipmentHandler(Db db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + if (shipment.Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready for dispatch."); + } + + shipment.Status = ShipmentStatus.Dispatched; + shipment.DispatchedAt = DateTime.UtcNow; + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + +public class Shipment +{ + public Shipment(DateTime dispatchedAt, Guid id) + { + DispatchedAt = dispatchedAt; + Id = id; + } + + public ShipmentStatus Status { get; set; } + public DateTime DispatchedAt { get; set; } + public Guid Id { get; set; } +} + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface Db +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/BloatedHandler.csproj b/BloatedHandler.csproj new file mode 100644 index 0000000..fd4bd08 --- /dev/null +++ b/BloatedHandler.csproj @@ -0,0 +1,10 @@ + + + + Exe + net9.0 + enable + enable + + + diff --git a/Folder.DotSettings b/Folder.DotSettings new file mode 100644 index 0000000..691357c --- /dev/null +++ b/Folder.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea5ebf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,205 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# AWS +*.aws-sam/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +#packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +#!packages/build/ + +!src/packages/**/*.dll +!src/packages/**/*.pdb + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml +src/packages/EventStore.Client.3.3.1/lib/net40/EventStore.ClientAPI.xml + +# JetBrains Rider +.idea/ +*.sln.iml + +# Vagrant VM files +.vagrant +vagrant/dbv/data/meta/revision + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/BloatedHandler.cs b/BloatedHandler.cs new file mode 100644 index 0000000..e558ee7 --- /dev/null +++ b/BloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.Bloated; + +public class DispatchShipmentHandler : ICommandHandler +{ + private readonly Db _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public DispatchShipmentHandler(Db db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + if (shipment.Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready for dispatch."); + } + + shipment.Status = ShipmentStatus.Dispatched; + shipment.DispatchedAt = DateTime.UtcNow; + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + +public class Shipment +{ + public Shipment(DateTime dispatchedAt, Guid id) + { + DispatchedAt = dispatchedAt; + Id = id; + } + + public ShipmentStatus Status { get; set; } + public DateTime DispatchedAt { get; set; } + public Guid Id { get; set; } +} + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface Db +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/BloatedHandler.csproj b/BloatedHandler.csproj new file mode 100644 index 0000000..fd4bd08 --- /dev/null +++ b/BloatedHandler.csproj @@ -0,0 +1,10 @@ + + + + Exe + net9.0 + enable + enable + + + diff --git a/Folder.DotSettings b/Folder.DotSettings new file mode 100644 index 0000000..691357c --- /dev/null +++ b/Folder.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/LessBloatedHandler.cs b/LessBloatedHandler.cs new file mode 100644 index 0000000..0257f16 --- /dev/null +++ b/LessBloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.LessBloated; + +public class LessBloatedHandler +{ + private readonly DB _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public LessBloatedHandler(DB db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + shipment.Dispatch(); + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + +public class Shipment +{ + public Guid Id { get; private set; } + public ShipmentStatus Status { get; private set; } + public DateTime? DispatchedAt { get; private set; } + + public void Dispatch() + { + if (Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready."); + } + + Status = ShipmentStatus.Dispatched; + DispatchedAt = DateTime.UtcNow; + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface DB +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea5ebf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,205 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# AWS +*.aws-sam/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +#packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +#!packages/build/ + +!src/packages/**/*.dll +!src/packages/**/*.pdb + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml +src/packages/EventStore.Client.3.3.1/lib/net40/EventStore.ClientAPI.xml + +# JetBrains Rider +.idea/ +*.sln.iml + +# Vagrant VM files +.vagrant +vagrant/dbv/data/meta/revision + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/BloatedHandler.cs b/BloatedHandler.cs new file mode 100644 index 0000000..e558ee7 --- /dev/null +++ b/BloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.Bloated; + +public class DispatchShipmentHandler : ICommandHandler +{ + private readonly Db _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public DispatchShipmentHandler(Db db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + if (shipment.Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready for dispatch."); + } + + shipment.Status = ShipmentStatus.Dispatched; + shipment.DispatchedAt = DateTime.UtcNow; + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + +public class Shipment +{ + public Shipment(DateTime dispatchedAt, Guid id) + { + DispatchedAt = dispatchedAt; + Id = id; + } + + public ShipmentStatus Status { get; set; } + public DateTime DispatchedAt { get; set; } + public Guid Id { get; set; } +} + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface Db +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/BloatedHandler.csproj b/BloatedHandler.csproj new file mode 100644 index 0000000..fd4bd08 --- /dev/null +++ b/BloatedHandler.csproj @@ -0,0 +1,10 @@ + + + + Exe + net9.0 + enable + enable + + + diff --git a/Folder.DotSettings b/Folder.DotSettings new file mode 100644 index 0000000..691357c --- /dev/null +++ b/Folder.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/LessBloatedHandler.cs b/LessBloatedHandler.cs new file mode 100644 index 0000000..0257f16 --- /dev/null +++ b/LessBloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.LessBloated; + +public class LessBloatedHandler +{ + private readonly DB _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public LessBloatedHandler(DB db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + shipment.Dispatch(); + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + +public class Shipment +{ + public Guid Id { get; private set; } + public ShipmentStatus Status { get; private set; } + public DateTime? DispatchedAt { get; private set; } + + public void Dispatch() + { + if (Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready."); + } + + Status = ShipmentStatus.Dispatched; + DispatchedAt = DateTime.UtcNow; + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface DB +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/PipelineHandler.cs b/PipelineHandler.cs new file mode 100644 index 0000000..74f40fd --- /dev/null +++ b/PipelineHandler.cs @@ -0,0 +1,209 @@ +namespace BloatedHandler.Pipeline; + +public class Shipment +{ + public Guid Id { get; private set; } + public ShipmentStatus Status { get; private set; } + public DateTime? DispatchedAt { get; private set; } + + public void Dispatch() + { + if (Status != ShipmentStatus.Ready) + throw new InvalidOperationException("Shipment is not ready."); + + Status = ShipmentStatus.Dispatched; + DispatchedAt = DateTime.UtcNow; + } +} + +public interface IShipmentDispatchStep +{ + void Execute(DispatchShipmentContext context, NextStepDelegate next); +} +public delegate Task NextStepDelegate(DispatchShipmentContext context); + +public class ShipmentDispatchPipeline +{ + private readonly List _steps; + + public ShipmentDispatchPipeline(IEnumerable steps) + { + _steps = steps.ToList(); + } + + public async Task ExecuteAsync(Guid shipmentId) + { + + } +} + + +public class DispatchShipmentHandler : ICommandHandler +{ + private readonly ShipmentDispatchPipeline _pipeline; + + public DispatchShipmentHandler(ShipmentDispatchPipeline pipeline) + { + _pipeline = pipeline; + } + + public async Task Handle(DispatchShipment command) + { + await _pipeline.ExecuteAsync(command.ShipmentId); + } +} + +public class DispatchShipmentContext +{ + public Guid ShipmentId { get; set; } + public Shipment Shipment { get; set; } + public List Events { get; } = new(); +} + +public class LoadShipmentStep : IShipmentDispatchStep +{ + private readonly DB _db; + + public LoadShipmentStep(DB repository) + { + _db = repository; + } + + public void Execute(DispatchShipmentContext context, NextStepDelegate next) + { + var shipment = _db.GetById(context.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + context.Shipment = shipment; + + next(context); + + _db.Save(context.Shipment); + } +} + +public class DispatchShipmentLogicStep : IShipmentDispatchStep +{ + public void Execute(DispatchShipmentContext context, NextStepDelegate next) + { + context.Shipment.Dispatch(); + context.Events.Add(new ShipmentDispatched(context.Shipment.Id, context.Shipment.DispatchedAt!.Value)); + + next(context); + } +} + +public class PublishEventStep : IShipmentDispatchStep +{ + private readonly IEventPublisher _eventPublisher; + + public PublishEventStep(IEventPublisher eventPublisher) + { + _eventPublisher = eventPublisher; + } + + public void Execute(DispatchShipmentContext context, NextStepDelegate next) + { + foreach (var @event in context.Events) + { + _eventPublisher.Publish(@event); + } + + next(context); + } +} + +public class ShipmentDispatchedCustomerEmail +{ + private readonly IEmailer _emailer; + private readonly DB _repository; + + public ShipmentDispatchedCustomerEmail(IEmailer emailer, DB repository) + { + _emailer = emailer; + _repository = repository; + } + + public void Handle(ShipmentDispatched evnt) + { + var shipment = _repository.GetById(evnt.ShipmentId); + _emailer.NotifyCustomer(shipment); + } +} + + + + + + + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(Guid shipmentId) + { + ShipmentId = shipmentId; + } + + public Guid ShipmentId { get; set; } +} + + +public class ShipmentDispatched +{ + public Guid ShipmentId { get; } + public object DispatchedAt { get; } + + public ShipmentDispatched(Guid shipmentId, object dispatchedAt) + { + ShipmentId = shipmentId; + DispatchedAt = dispatchedAt; + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(object shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface DB +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea5ebf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,205 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# AWS +*.aws-sam/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +#packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +#!packages/build/ + +!src/packages/**/*.dll +!src/packages/**/*.pdb + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml +src/packages/EventStore.Client.3.3.1/lib/net40/EventStore.ClientAPI.xml + +# JetBrains Rider +.idea/ +*.sln.iml + +# Vagrant VM files +.vagrant +vagrant/dbv/data/meta/revision + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/BloatedHandler.cs b/BloatedHandler.cs new file mode 100644 index 0000000..e558ee7 --- /dev/null +++ b/BloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.Bloated; + +public class DispatchShipmentHandler : ICommandHandler +{ + private readonly Db _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public DispatchShipmentHandler(Db db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + if (shipment.Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready for dispatch."); + } + + shipment.Status = ShipmentStatus.Dispatched; + shipment.DispatchedAt = DateTime.UtcNow; + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + +public class Shipment +{ + public Shipment(DateTime dispatchedAt, Guid id) + { + DispatchedAt = dispatchedAt; + Id = id; + } + + public ShipmentStatus Status { get; set; } + public DateTime DispatchedAt { get; set; } + public Guid Id { get; set; } +} + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface Db +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/BloatedHandler.csproj b/BloatedHandler.csproj new file mode 100644 index 0000000..fd4bd08 --- /dev/null +++ b/BloatedHandler.csproj @@ -0,0 +1,10 @@ + + + + Exe + net9.0 + enable + enable + + + diff --git a/Folder.DotSettings b/Folder.DotSettings new file mode 100644 index 0000000..691357c --- /dev/null +++ b/Folder.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/LessBloatedHandler.cs b/LessBloatedHandler.cs new file mode 100644 index 0000000..0257f16 --- /dev/null +++ b/LessBloatedHandler.cs @@ -0,0 +1,118 @@ +namespace BloatedHandler.LessBloated; + +public class LessBloatedHandler +{ + private readonly DB _db; + private readonly IEmailer _emailer; + private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; + + public LessBloatedHandler(DB db, IEmailer emailer, IEventPublisher eventPublisher, ILogger logger) + { + _db = db; + _emailer = emailer; + _eventPublisher = eventPublisher; + _logger = logger; + } + + public void Handle(DispatchShipment command) + { + var shipment = _db.GetById(command.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + shipment.Dispatch(); + + _db.Save(shipment); + + _emailer.NotifyCustomer(shipment); + + _eventPublisher.Publish(new ShipmentDispatched(shipment.Id, shipment.DispatchedAt)); + + _logger.Log($"Shipment {shipment.Id} dispatched."); + } +} + +public class Shipment +{ + public Guid Id { get; private set; } + public ShipmentStatus Status { get; private set; } + public DateTime? DispatchedAt { get; private set; } + + public void Dispatch() + { + if (Status != ShipmentStatus.Ready) + { + throw new InvalidOperationException("Shipment is not ready."); + } + + Status = ShipmentStatus.Dispatched; + DispatchedAt = DateTime.UtcNow; + } +} + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(object shipmentId) + { + ShipmentId = shipmentId; + } + + public object ShipmentId { get; set; } +} + + +public class ShipmentDispatched +{ + public ShipmentDispatched(Guid id, object dispatchedAt) + { + throw new NotImplementedException(); + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(ShipmentDispatched shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface DB +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/PipelineHandler.cs b/PipelineHandler.cs new file mode 100644 index 0000000..74f40fd --- /dev/null +++ b/PipelineHandler.cs @@ -0,0 +1,209 @@ +namespace BloatedHandler.Pipeline; + +public class Shipment +{ + public Guid Id { get; private set; } + public ShipmentStatus Status { get; private set; } + public DateTime? DispatchedAt { get; private set; } + + public void Dispatch() + { + if (Status != ShipmentStatus.Ready) + throw new InvalidOperationException("Shipment is not ready."); + + Status = ShipmentStatus.Dispatched; + DispatchedAt = DateTime.UtcNow; + } +} + +public interface IShipmentDispatchStep +{ + void Execute(DispatchShipmentContext context, NextStepDelegate next); +} +public delegate Task NextStepDelegate(DispatchShipmentContext context); + +public class ShipmentDispatchPipeline +{ + private readonly List _steps; + + public ShipmentDispatchPipeline(IEnumerable steps) + { + _steps = steps.ToList(); + } + + public async Task ExecuteAsync(Guid shipmentId) + { + + } +} + + +public class DispatchShipmentHandler : ICommandHandler +{ + private readonly ShipmentDispatchPipeline _pipeline; + + public DispatchShipmentHandler(ShipmentDispatchPipeline pipeline) + { + _pipeline = pipeline; + } + + public async Task Handle(DispatchShipment command) + { + await _pipeline.ExecuteAsync(command.ShipmentId); + } +} + +public class DispatchShipmentContext +{ + public Guid ShipmentId { get; set; } + public Shipment Shipment { get; set; } + public List Events { get; } = new(); +} + +public class LoadShipmentStep : IShipmentDispatchStep +{ + private readonly DB _db; + + public LoadShipmentStep(DB repository) + { + _db = repository; + } + + public void Execute(DispatchShipmentContext context, NextStepDelegate next) + { + var shipment = _db.GetById(context.ShipmentId); + if (shipment == null) + { + throw new InvalidOperationException("Shipment not found."); + } + + context.Shipment = shipment; + + next(context); + + _db.Save(context.Shipment); + } +} + +public class DispatchShipmentLogicStep : IShipmentDispatchStep +{ + public void Execute(DispatchShipmentContext context, NextStepDelegate next) + { + context.Shipment.Dispatch(); + context.Events.Add(new ShipmentDispatched(context.Shipment.Id, context.Shipment.DispatchedAt!.Value)); + + next(context); + } +} + +public class PublishEventStep : IShipmentDispatchStep +{ + private readonly IEventPublisher _eventPublisher; + + public PublishEventStep(IEventPublisher eventPublisher) + { + _eventPublisher = eventPublisher; + } + + public void Execute(DispatchShipmentContext context, NextStepDelegate next) + { + foreach (var @event in context.Events) + { + _eventPublisher.Publish(@event); + } + + next(context); + } +} + +public class ShipmentDispatchedCustomerEmail +{ + private readonly IEmailer _emailer; + private readonly DB _repository; + + public ShipmentDispatchedCustomerEmail(IEmailer emailer, DB repository) + { + _emailer = emailer; + _repository = repository; + } + + public void Handle(ShipmentDispatched evnt) + { + var shipment = _repository.GetById(evnt.ShipmentId); + _emailer.NotifyCustomer(shipment); + } +} + + + + + + + + + + + + + + + + + + + + + +public class DispatchShipment +{ + public DispatchShipment(Guid shipmentId) + { + ShipmentId = shipmentId; + } + + public Guid ShipmentId { get; set; } +} + + +public class ShipmentDispatched +{ + public Guid ShipmentId { get; } + public object DispatchedAt { get; } + + public ShipmentDispatched(Guid shipmentId, object dispatchedAt) + { + ShipmentId = shipmentId; + DispatchedAt = dispatchedAt; + } +} + +public enum ShipmentStatus +{ + Ready, + Dispatched +} + +public interface ILogger +{ + void Log(string s); +} + +public interface IEventPublisher +{ + void Publish(object shipmentDispatched); +} + +public interface IEmailer +{ + void NotifyCustomer(object shipment); +} + +public interface DB +{ + void Save(object shipment); + Shipment GetById(object shipmentId); +} + +public interface ICommandHandler +{ +} \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..3751555 --- /dev/null +++ b/Program.cs @@ -0,0 +1,2 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!");