Permalink
Browse files

Add E006 Code and Questions Project

  • Loading branch information...
1 parent d10f610 commit 175e28c8f8e72602940ac9c050c4645cb2759075 Kerry Street committed Sep 10, 2012
@@ -0,0 +1,12 @@
+## Being the Worst - E006
+
+This folder contains additional materials for **Episode 6 – Community Code and Questions 1**:
+
+Original code and questions forked from: https://github.com/jtinbergen/bebung
+Thanks to Jaapjan Tinbergen for his code and questions for this episode.
+
+
+Subscribe to the podcast at [beingtheworst.com](http://beingtheworst.com)
+or via [iTunes](http://itunes.apple.com/us/podcast/being-the-worst/id554597082).
+
+Follow us on twitter: [@beingtheworst](https://twitter.com/beingtheworst)
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>E006_community_code_questions_1</RootNamespace>
+ <AssemblyName>E006-community-code-questions-1</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\ReadMe.md">
+ <Link>ReadMe.md</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
@@ -0,0 +1,179 @@
+// New BSD License
+// Author:
+// Jaapjan Tinbergen jaapjan@tinbergen.net
+//
+// Copyright (c) 2012, Jaapjan Tinbergen
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the distribution.
+// * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace eventquestions1
+{
+ class MainClass
+ {
+ public static void Main(string[] args)
+ {
+ License lic = new License();
+ lic.ChangeCustomerName("Erick Eberhart");
+ lic.ChangeNumberOfSeats(5);
+ foreach (var @event in lic.GetUncommitedEvents())
+ {
+ Console.WriteLine(@event.ToString());
+ }
+
+ Console.ReadKey();
+ }
+ }
+
+ class License
+ {
+ private Guid identity;
+ private string name;
+ private int seats;
+ private IList<IEvent> uncommitedevents;
+
+ public License()
+ {
+ this.uncommitedevents = new List<IEvent>();
+ this.identity = Guid.NewGuid();
+ this.name = "New license";
+ this.seats = 1;
+ // Question: Set initial state here ... or generate events to set state?
+ // Especially in the case of the identity which many events would need to identify the aggregate root?
+ // Generate the identity event first in that case?
+ }
+
+ public void ChangeCustomerName(string newName)
+ {
+ if (string.IsNullOrEmpty(newName))
+ {
+ throw new InvalidOperationException("A valid name must be specified.");
+ }
+
+ // Question: These events have changed in their name. Is this right?
+ ApplyNewEvent(new CustomerNameHasChanged(this.identity, newName));
+ }
+
+ // Question: These commands contain change in their name.
+ // What -do- you name a command when a customer wants less seats for a reason?
+ // (Maybe they have less seats required because they fired people .. or another reason outside the domain/one you do not know?)
+ public void ChangeNumberOfSeats(int newSeatCount)
+ {
+ if (newSeatCount < 0)
+ {
+ throw new InvalidOperationException("A license without seats is not allowed.");
+ }
+
+ ApplyNewEvent(new SeatCountForLicenseChanged(this.identity, newSeatCount));
+ }
+
+ public IEnumerable<IEvent> GetUncommitedEvents()
+ {
+ return this.uncommitedevents;
+ }
+
+ private void ApplyNewEvent(IEvent @event)
+ {
+ this.uncommitedevents.Add(@event);
+ this.Apply(@event);
+ }
+
+ private void Apply(IEvent @event)
+ {
+ ((dynamic)this).When((dynamic)@event);
+ }
+
+ private void When(SeatCountForLicenseChanged @event)
+ {
+ // Question: Should we guard against applying events with the wrong aggregate identity here?
+ this.seats = @event.Seats;
+ }
+
+ private void When(CustomerNameHasChanged @event)
+ {
+ this.name = @event.Name;
+ }
+ }
+
+ /// <summary>
+ /// Clearly defined role.
+ /// </summary>
+ interface IEvent
+ {
+ }
+
+ class SeatCountForLicenseChanged : IEvent
+ {
+ // Question: Should events have a constructor to make setting its properties mandatory and thus valid?
+ public SeatCountForLicenseChanged(Guid identity, int seats)
+ {
+ this.identity = identity;
+ this.Seats = seats;
+ }
+
+ public Guid identity
+ {
+ get;
+ private set;
+ }
+
+ public int Seats
+ {
+ get;
+ private set;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("[SeatCountForLicenseChanged: identity={0}, Seats={1}]", identity, Seats);
+ }
+ }
+
+ class CustomerNameHasChanged : IEvent
+ {
+ public CustomerNameHasChanged(Guid identity, string name)
+ {
+ this.identity = identity;
+ this.Name = name;
+ }
+
+ public Guid identity
+ {
+ get;
+ private set;
+ }
+
+ public string Name
+ {
+ get;
+ private set;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("[CustomerNameHasChanged: identity={0}, Name={1}]", identity, Name);
+ }
+ }
+}
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("E006-community-code-questions-1")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("E006-community-code-questions-1")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3612b100-4a03-498a-a04b-ae382ec4f247")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
View
@@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "E004-event-sourcing-basics"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "E005-testing-use-cases", "..\E005-testing-use-cases\sample-csharp\E005-testing-use-cases.csproj", "{63386748-DD98-4C84-87B9-EB85631653BC}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "E006-community-code-questions-1", "..\E006-community-code-questions-1\sample-csharp\E006-community-code-questions-1.csproj", "{71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -58,6 +60,16 @@ Global
{63386748-DD98-4C84-87B9-EB85631653BC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{63386748-DD98-4C84-87B9-EB85631653BC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{63386748-DD98-4C84-87B9-EB85631653BC}.Release|x86.ActiveCfg = Release|Any CPU
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Debug|x86.ActiveCfg = Debug|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Debug|x86.Build.0 = Debug|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Release|Any CPU.ActiveCfg = Release|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Release|Mixed Platforms.Build.0 = Release|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Release|x86.ActiveCfg = Release|x86
+ {71BEAF52-EC6E-469B-AD35-6E2E0ABF7731}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

0 comments on commit 175e28c

Please sign in to comment.