Add BehavioralPatterns project back again in the solution (somehow it was gone)

Update Scrum example on State pattern
Add Scrum pattern using state role interfaces
This commit is contained in:
Petrutiu Mihai
2016-07-21 13:59:57 +03:00
parent 2bea7d280f
commit 1d04dafb70
5 changed files with 378 additions and 14 deletions

View File

@@ -31,6 +31,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TemplatePattern", "src\Temp
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "VisitorPattern", "src\VisitorPattern\VisitorPattern.xproj", "{CDDB889F-3038-4796-95B1-47E1834DA93D}" Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "VisitorPattern", "src\VisitorPattern\VisitorPattern.xproj", "{CDDB889F-3038-4796-95B1-47E1834DA93D}"
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "BehavioralPatterns", "src\BehavioralPatterns\BehavioralPatterns.xproj", "{E3092EE0-1282-4AB4-9FA2-0338348D8FD1}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -77,6 +79,10 @@ Global
{CDDB889F-3038-4796-95B1-47E1834DA93D}.Debug|Any CPU.Build.0 = Debug|Any CPU {CDDB889F-3038-4796-95B1-47E1834DA93D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CDDB889F-3038-4796-95B1-47E1834DA93D}.Release|Any CPU.ActiveCfg = Release|Any CPU {CDDB889F-3038-4796-95B1-47E1834DA93D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CDDB889F-3038-4796-95B1-47E1834DA93D}.Release|Any CPU.Build.0 = Release|Any CPU {CDDB889F-3038-4796-95B1-47E1834DA93D}.Release|Any CPU.Build.0 = Release|Any CPU
{E3092EE0-1282-4AB4-9FA2-0338348D8FD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E3092EE0-1282-4AB4-9FA2-0338348D8FD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E3092EE0-1282-4AB4-9FA2-0338348D8FD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E3092EE0-1282-4AB4-9FA2-0338348D8FD1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -92,5 +98,6 @@ Global
{01B9D869-AF89-4919-8445-79206848FB5F} = {3820200F-354C-41E6-8F34-B301F5D621C2} {01B9D869-AF89-4919-8445-79206848FB5F} = {3820200F-354C-41E6-8F34-B301F5D621C2}
{E657BF85-C23A-46DE-B837-6939D51C3321} = {3820200F-354C-41E6-8F34-B301F5D621C2} {E657BF85-C23A-46DE-B837-6939D51C3321} = {3820200F-354C-41E6-8F34-B301F5D621C2}
{CDDB889F-3038-4796-95B1-47E1834DA93D} = {3820200F-354C-41E6-8F34-B301F5D621C2} {CDDB889F-3038-4796-95B1-47E1834DA93D} = {3820200F-354C-41E6-8F34-B301F5D621C2}
{E3092EE0-1282-4AB4-9FA2-0338348D8FD1} = {3820200F-354C-41E6-8F34-B301F5D621C2}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -39,7 +39,7 @@ namespace StatePattern.ScrumExample
/// User story states: New, Active, Resolved, Closed, Removed /// User story states: New, Active, Resolved, Closed, Removed
/// Actions on user stories: /// Actions on user stories:
/// Create - creates a new user story in state New /// Create - creates a new user story in state New
/// RemoveFromBacklog - moves a user story from state New to State removed /// RemoveFromBacklog - moves a user story from state New to State Removed
/// StartImplementation - moves user story from state New to state Active /// StartImplementation - moves user story from state New to state Active
/// MoveToBacklog - moves user story from state Active/Removed to state New /// MoveToBacklog - moves user story from state Active/Removed to state New
/// CodeFinishedAnUnitTestsPassed - move user story from state Active to state Resolved /// CodeFinishedAnUnitTestsPassed - move user story from state Active to state Resolved

View File

@@ -25,10 +25,13 @@ namespace StatePattern.ScrumExample
//but leaving that asside, assuming we will have to add another transition availalable that can be executed only from one state //but leaving that asside, assuming we will have to add another transition availalable that can be executed only from one state
//we will have to modify all the existing states, just to throw the exception. //we will have to modify all the existing states, just to throw the exception.
//To view what are the allowed transitions, is very hard when using state pattern with roles
} }
} }
/// <summary>
/// State interface
/// </summary>
public interface IScrumState public interface IScrumState
{ {
void RemoveFromBacklog(); void RemoveFromBacklog();
@@ -41,11 +44,25 @@ namespace StatePattern.ScrumExample
void AcceptanceTestsPassed(); void AcceptanceTestsPassed();
void CodeFinishedAnUnitTestsPassed(); void CodeFinishedAndUnitTestsPassed();
} }
/// <summary>
/// Context
/// User story states: New, Active, Resolved, Closed, Removed
/// Actions on user stories:
/// Create - creates a new user story in state New
/// RemoveFromBacklog - moves a user story from state New to State removed
/// StartImplementation - moves user story from state New to state Active
/// MoveToBacklog - moves user story from state Active/Removed to state New
/// CodeFinishedAndUnitTestsPassed - move user story from state Active to state Resolved
/// AcceptanceTestsFail - move user story from state Resolved to state Active
/// AcceptanceTestsPassed - moves user story from state Resolved to state Closed
/// </summary>
public class UserStory public class UserStory
{ {
public IScrumState State { get; set; }
public IScrumState New { get; private set; } public IScrumState New { get; private set; }
public IScrumState Active { get; private set; } public IScrumState Active { get; private set; }
public IScrumState Resolved { get; private set; } public IScrumState Resolved { get; private set; }
@@ -62,7 +79,6 @@ namespace StatePattern.ScrumExample
State = New; State = New;
} }
public IScrumState State { get; set; }
public int Name { get; internal set; } public int Name { get; internal set; }
public void AcceptanceTestsFail() public void AcceptanceTestsFail()
@@ -89,12 +105,15 @@ namespace StatePattern.ScrumExample
State.StartImplementation(); State.StartImplementation();
} }
public void CodeFinishedAnUnitTestsPassed() public void CodeFinishedAndUnitTestsPassed()
{ {
State.CodeFinishedAnUnitTestsPassed(); State.CodeFinishedAndUnitTestsPassed();
} }
} }
/// <summary>
/// Concrete State
/// </summary>
internal class ScrumStateNew : IScrumState internal class ScrumStateNew : IScrumState
{ {
private UserStory userStory; private UserStory userStory;
@@ -116,7 +135,7 @@ namespace StatePattern.ScrumExample
Console.WriteLine("Development didn't even started, you should check your tests"); Console.WriteLine("Development didn't even started, you should check your tests");
} }
public void CodeFinishedAnUnitTestsPassed() public void CodeFinishedAndUnitTestsPassed()
{ {
//throw the exception //throw the exception
Console.WriteLine("Before you can finish the code, you should have started implementation"); Console.WriteLine("Before you can finish the code, you should have started implementation");
@@ -130,8 +149,8 @@ namespace StatePattern.ScrumExample
public void RemoveFromBacklog() public void RemoveFromBacklog()
{ {
//throw the exception
Console.WriteLine("User story removed"); Console.WriteLine("User story removed");
userStory.State = userStory.Removed;
} }
public void StartImplementation() public void StartImplementation()
@@ -141,6 +160,9 @@ namespace StatePattern.ScrumExample
} }
} }
/// <summary>
/// Concrete State
/// </summary>
internal class ScrumStateActive : IScrumState internal class ScrumStateActive : IScrumState
{ {
private UserStory userStory; private UserStory userStory;
@@ -162,7 +184,7 @@ namespace StatePattern.ScrumExample
Console.WriteLine("Development is not yet done"); Console.WriteLine("Development is not yet done");
} }
public void CodeFinishedAnUnitTestsPassed() public void CodeFinishedAndUnitTestsPassed()
{ {
Console.WriteLine("I'll notify the testers!"); Console.WriteLine("I'll notify the testers!");
userStory.State = userStory.Resolved; userStory.State = userStory.Resolved;
@@ -170,8 +192,8 @@ namespace StatePattern.ScrumExample
public void MoveToBacklog() public void MoveToBacklog()
{ {
//throw the exception
Console.WriteLine("Moved userstory to backlog"); Console.WriteLine("Moved userstory to backlog");
userStory.State = userStory.New;
} }
public void RemoveFromBacklog() public void RemoveFromBacklog()
@@ -187,6 +209,9 @@ namespace StatePattern.ScrumExample
} }
} }
/// <summary>
/// Concrete State
/// </summary>
internal class ScrumStateResolved : IScrumState internal class ScrumStateResolved : IScrumState
{ {
private UserStory userStory; private UserStory userStory;
@@ -208,7 +233,7 @@ namespace StatePattern.ScrumExample
userStory.State = userStory.Closed; userStory.State = userStory.Closed;
} }
public void CodeFinishedAnUnitTestsPassed() public void CodeFinishedAndUnitTestsPassed()
{ {
//throw the exception //throw the exception
Console.WriteLine("The item was already resolved"); Console.WriteLine("The item was already resolved");
@@ -233,6 +258,9 @@ namespace StatePattern.ScrumExample
} }
} }
/// <summary>
/// Concrete State
/// </summary>
internal class ScrumStateClosed : IScrumState internal class ScrumStateClosed : IScrumState
{ {
private UserStory userStory; private UserStory userStory;
@@ -254,7 +282,7 @@ namespace StatePattern.ScrumExample
Console.WriteLine("User story is already closed"); Console.WriteLine("User story is already closed");
} }
public void CodeFinishedAnUnitTestsPassed() public void CodeFinishedAndUnitTestsPassed()
{ {
//throw the exception //throw the exception
Console.WriteLine("Item was already closed"); Console.WriteLine("Item was already closed");
@@ -262,6 +290,7 @@ namespace StatePattern.ScrumExample
public void MoveToBacklog() public void MoveToBacklog()
{ {
//throw the exception
Console.WriteLine("Item was already closed, cannot move to new state"); Console.WriteLine("Item was already closed, cannot move to new state");
} }
@@ -278,6 +307,9 @@ namespace StatePattern.ScrumExample
} }
} }
/// <summary>
/// Concrete State
/// </summary>
internal class ScrumStateRemoved : IScrumState internal class ScrumStateRemoved : IScrumState
{ {
private UserStory userStory; private UserStory userStory;
@@ -299,9 +331,9 @@ namespace StatePattern.ScrumExample
Console.WriteLine("Item was removed, you can only move it to backlog again"); Console.WriteLine("Item was removed, you can only move it to backlog again");
} }
public void CodeFinishedAnUnitTestsPassed() public void CodeFinishedAndUnitTestsPassed()
{ {
//throw the exception
} }
public void MoveToBacklog() public void MoveToBacklog()

View File

@@ -0,0 +1,321 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Reflection;
namespace StatePattern.ScrumWithRoleStates
{
public class ScrumStateWithRoleInterfacesExample
{
public static void Run()
{
UserStory userStory = new UserStory();
userStory.RemoveFromBacklog();
userStory.MoveToBacklog();
userStory.StartImplementation();
userStory.AcceptanceTestsFail();
userStory.StartImplementation();
userStory.AcceptanceTestsPassed();
userStory.StartImplementation();
userStory.CodeFinishedAnUnitTestsPassed();
userStory.AcceptanceTestsPassed();
Console.WriteLine("User story state: {0}", userStory.State.Name);
}
/// <summary>
/// Context
/// User story states: New, Active, Resolved, Closed, Removed
/// Actions on user stories:
/// Create - creates a new user story in state New
/// RemoveFromBacklog - moves a user story from state New to State Removed
/// StartImplementation - moves user story from state New to state Active
/// MoveToBacklog - moves user story from state Active/Removed to state New
/// CodeFinishedAndUnitTestsPassed - move user story from state Active to state Resolved
/// AcceptanceTestsFail - move user story from state Resolved to state Active
/// AcceptanceTestsPassed - moves user story from state Resolved to state Closed
/// </summary>
public class UserStory
{
public IScrumState State { get; set; }
public UserStoryStates States { get; private set; }
public string Name { get; set; }
public UserStory()
{
States = new UserStoryStates(this);
State = States.New;
}
public void MoveToBacklog()
{
ICanMoveToBacklog state = GetState<ICanMoveToBacklog>();
if(state == null)
{
Console.WriteLine("Cannot move to backlog from state: {0}", State.Name);
return;
}
state.MoveToBacklog();
}
public void StartImplementation()
{
ICanStartImplementation state = GetState<ICanStartImplementation>();
if (state == null)
{
Console.WriteLine("Cannot start implementation from state: {0}", State.Name);
return;
}
state.StartImplementation();
}
public void CodeFinishedAnUnitTestsPassed()
{
ICanFinishCode state = GetState<ICanFinishCode>();
if (state == null)
{
Console.WriteLine("Cannot mark the code as done from state: {0}", State.Name);
return;
}
state.CodeFinishedAndUnitTestsPassed();
}
public void AcceptanceTestsFail()
{
ICanRunAcceptanceTests state = GetState<ICanRunAcceptanceTests>();
if (state == null)
{
Console.WriteLine("Cannot fail the acceptance tests from state: {0}", State.Name);
return;
}
state.AcceptanceTestsFail();
}
public void AcceptanceTestsPassed()
{
ICanRunAcceptanceTests state = GetState<ICanRunAcceptanceTests>();
if (state == null)
{
Console.WriteLine("Cannot mark the code as done from state: {0}", State.Name);
return;
}
state.AcceptanceTestsPassed();
}
public void RemoveFromBacklog()
{
ICanRemoveFromBacklog state = GetState<ICanRemoveFromBacklog>();
if (state == null)
{
Console.WriteLine("Cannot remove from backlog from state: {0}", State.Name);
return;
}
state.RemoveFromBacklog();
}
private TTransition GetState<TTransition>()
{
if(State is TTransition)
{
return (TTransition)State;
}
return default(TTransition);
}
}
/// <summary>
/// State interface
/// </summary>
public interface IScrumState
{
string Name { get; }
}
public class UserStoryStates
{
public UserStoryStates(UserStory userStory)
{
New = new ScrumStateNew(userStory);
Active = new ScrumStateActive(userStory);
Resolved = new ScrumStateResolved(userStory);
Closed = new ScrumStateClosed(userStory);
Removed = new ScrumStateRemoved(userStory);
//Defined but not used, we could use this array to get from what state we can do an operation, by just checking which implements the required interface
AllStates = new IScrumState[] { New, Active, Resolved, Closed, Removed };
}
public IScrumState[] AllStates { get; private set; }
public IScrumState New { get; private set; }
public IScrumState Active { get; private set; }
public IScrumState Resolved { get; private set; }
public IScrumState Closed { get; private set; }
public IScrumState Removed { get; private set; }
}
#region role interfaces
internal interface ICanMoveToBacklog
{
void MoveToBacklog();
}
internal interface ICanStartImplementation
{
void StartImplementation();
}
internal interface ICanFinishCode
{
void CodeFinishedAndUnitTestsPassed();
}
internal interface ICanRunAcceptanceTests
{
void AcceptanceTestsFail();
void AcceptanceTestsPassed();
}
internal interface ICanRemoveFromBacklog
{
void RemoveFromBacklog();
}
#endregion
#region concrete state implementations
public class ScrumStateNew : IScrumState, ICanRemoveFromBacklog, ICanStartImplementation
{
private UserStory userStory;
public ScrumStateNew(UserStory userStory)
{
this.userStory = userStory;
}
public string Name { get { return "New"; } }
public void RemoveFromBacklog()
{
Console.WriteLine("User story removed");
userStory.State = userStory.States.Removed;
}
public void StartImplementation()
{
Console.WriteLine("Started work on User story: {0}", userStory.Name);
userStory.State = userStory.States.Active;
}
}
public class ScrumStateRemoved : IScrumState, ICanMoveToBacklog
{
private UserStory userStory;
public ScrumStateRemoved(UserStory userStory)
{
this.userStory = userStory;
}
public string Name { get { return "Removed"; } }
public void MoveToBacklog()
{
Console.WriteLine("Moved userstory to backlog");
userStory.State = userStory.States.New;
}
}
public class ScrumStateActive : IScrumState, ICanMoveToBacklog, ICanFinishCode
{
private UserStory userStory;
public ScrumStateActive(UserStory userStory)
{
this.userStory = userStory;
}
public string Name { get { return "Active"; } }
public void CodeFinishedAndUnitTestsPassed()
{
Console.WriteLine("I'll notify the testers!");
userStory.State = userStory.States.Resolved;
}
public void MoveToBacklog()
{
Console.WriteLine("Moved userstory to backlog");
userStory.State = userStory.States.New;
}
}
public class ScrumStateResolved : IScrumState, ICanRunAcceptanceTests
{
private UserStory userStory;
public ScrumStateResolved(UserStory userStory)
{
this.userStory = userStory;
}
public string Name { get { return "Resolved"; } }
public void AcceptanceTestsFail()
{
Console.WriteLine("We'll notify the devs, that they did a bad job");
userStory.State = userStory.States.Active;
}
public void AcceptanceTestsPassed()
{
Console.WriteLine("Cool, we'll close the us");
userStory.State = userStory.States.Closed;
}
}
public class ScrumStateClosed : IScrumState
{
private UserStory userStory;
public ScrumStateClosed(UserStory userStory)
{
this.userStory = userStory;
}
public string Name { get { return "Closed"; } }
}
#endregion
}
}

View File

@@ -1,5 +1,6 @@
using StatePattern.FanExample; using StatePattern.FanExample;
using StatePattern.ScrumExample; using StatePattern.ScrumExample;
using StatePattern.ScrumWithRoleStates;
using StatePattern.TVExample; using StatePattern.TVExample;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -32,6 +33,9 @@ namespace StatePattern
GoToNextStep(); GoToNextStep();
ScrumStatePatternExample.Run(); ScrumStatePatternExample.Run();
GoToNextStep();
ScrumStateWithRoleInterfacesExample.Run();
} }
private static void GoToNextStep() private static void GoToNextStep()