From a42a8ffbaa211c7c035baf3a2e08c72b1916fa89 Mon Sep 17 00:00:00 2001 From: Daryl Haase Date: Thu, 2 Mar 2017 14:35:00 -0600 Subject: [PATCH] Design Pattern Training (dhaase) --- .../DesignPatternsSolution.sln | 16 +++- .../Enumerables/Enumerables.csproj | 53 ++++++++++++ .../Enumerables/Properties/AssemblyInfo.cs | 36 ++++++++ DesignPatternsSolution/Enumerables/Type.cs | 9 ++ .../Execise.Tests/Execise.Tests.csproj | 4 + .../Execise.Tests/UnitTests.cs | 83 +++++++++++++++++-- DesignPatternsSolution/Exercise/Book.cs | 15 ++++ .../Exercise/BookBorrowable.cs | 7 -- DesignPatternsSolution/Exercise/Borrowable.cs | 28 +++++++ .../Exercise/{Person.cs => Customer.cs} | 9 +- .../Exercise/Exercise.csproj | 22 +++-- DesignPatternsSolution/Exercise/Item.cs | 22 ----- DesignPatternsSolution/Exercise/LibObject.cs | 17 ---- DesignPatternsSolution/Exercise/Library.cs | 19 +++-- .../Exercise/LibraryItem.cs | 15 ++++ .../Exercise/LibraryObject.cs | 21 +++++ .../Exercise/Registration.cs | 15 ++-- DesignPatternsSolution/Exercise/Video.cs | 19 +++++ .../ExerciseInterfaces.csproj | 64 ++++++++++++++ .../ExerciseInterfaces/IBook.cs | 12 +++ .../ExerciseInterfaces/IBorrowable.cs | 13 +++ .../ExerciseInterfaces/ICustomer.cs | 12 +++ .../ExerciseInterfaces/ILibraryObject.cs | 13 +++ .../ExerciseInterfaces/IRegistarable.cs | 9 ++ .../ExerciseInterfaces/IRegisteredObject.cs | 11 +++ .../Properties/AssemblyInfo.cs | 36 ++++++++ 26 files changed, 501 insertions(+), 79 deletions(-) create mode 100644 DesignPatternsSolution/Enumerables/Enumerables.csproj create mode 100644 DesignPatternsSolution/Enumerables/Properties/AssemblyInfo.cs create mode 100644 DesignPatternsSolution/Enumerables/Type.cs create mode 100644 DesignPatternsSolution/Exercise/Book.cs delete mode 100644 DesignPatternsSolution/Exercise/BookBorrowable.cs create mode 100644 DesignPatternsSolution/Exercise/Borrowable.cs rename DesignPatternsSolution/Exercise/{Person.cs => Customer.cs} (54%) delete mode 100644 DesignPatternsSolution/Exercise/Item.cs delete mode 100644 DesignPatternsSolution/Exercise/LibObject.cs create mode 100644 DesignPatternsSolution/Exercise/LibraryItem.cs create mode 100644 DesignPatternsSolution/Exercise/LibraryObject.cs create mode 100644 DesignPatternsSolution/Exercise/Video.cs create mode 100644 DesignPatternsSolution/ExerciseInterfaces/ExerciseInterfaces.csproj create mode 100644 DesignPatternsSolution/ExerciseInterfaces/IBook.cs create mode 100644 DesignPatternsSolution/ExerciseInterfaces/IBorrowable.cs create mode 100644 DesignPatternsSolution/ExerciseInterfaces/ICustomer.cs create mode 100644 DesignPatternsSolution/ExerciseInterfaces/ILibraryObject.cs create mode 100644 DesignPatternsSolution/ExerciseInterfaces/IRegistarable.cs create mode 100644 DesignPatternsSolution/ExerciseInterfaces/IRegisteredObject.cs create mode 100644 DesignPatternsSolution/ExerciseInterfaces/Properties/AssemblyInfo.cs diff --git a/DesignPatternsSolution/DesignPatternsSolution.sln b/DesignPatternsSolution/DesignPatternsSolution.sln index e5b257d..23c388c 100644 --- a/DesignPatternsSolution/DesignPatternsSolution.sln +++ b/DesignPatternsSolution/DesignPatternsSolution.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Exercise", "Exercise\Exercise.csproj", "{EA98A53A-F8CD-4539-9E57-1FEF2D64F13A}" EndProject @@ -13,6 +13,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documents", "Documents", "{ ..\Documents\GitHubQuickStart.docx = ..\Documents\GitHubQuickStart.docx EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExerciseInterfaces", "ExerciseInterfaces\ExerciseInterfaces.csproj", "{B26A05D5-9CEC-4339-92DD-9B42DEE8C028}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Enumerables", "Enumerables\Enumerables.csproj", "{216AA6BC-F503-4172-8FD8-F1DDCC2788DD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +31,14 @@ Global {464FBD03-CA8B-4926-8F69-66726819DA02}.Debug|Any CPU.Build.0 = Debug|Any CPU {464FBD03-CA8B-4926-8F69-66726819DA02}.Release|Any CPU.ActiveCfg = Release|Any CPU {464FBD03-CA8B-4926-8F69-66726819DA02}.Release|Any CPU.Build.0 = Release|Any CPU + {B26A05D5-9CEC-4339-92DD-9B42DEE8C028}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B26A05D5-9CEC-4339-92DD-9B42DEE8C028}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B26A05D5-9CEC-4339-92DD-9B42DEE8C028}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B26A05D5-9CEC-4339-92DD-9B42DEE8C028}.Release|Any CPU.Build.0 = Release|Any CPU + {216AA6BC-F503-4172-8FD8-F1DDCC2788DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {216AA6BC-F503-4172-8FD8-F1DDCC2788DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {216AA6BC-F503-4172-8FD8-F1DDCC2788DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {216AA6BC-F503-4172-8FD8-F1DDCC2788DD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/DesignPatternsSolution/Enumerables/Enumerables.csproj b/DesignPatternsSolution/Enumerables/Enumerables.csproj new file mode 100644 index 0000000..b9b47d9 --- /dev/null +++ b/DesignPatternsSolution/Enumerables/Enumerables.csproj @@ -0,0 +1,53 @@ + + + + + Debug + AnyCPU + {216AA6BC-F503-4172-8FD8-F1DDCC2788DD} + Library + Properties + Enumerables + Enumerables + v3.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DesignPatternsSolution/Enumerables/Properties/AssemblyInfo.cs b/DesignPatternsSolution/Enumerables/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..809adac --- /dev/null +++ b/DesignPatternsSolution/Enumerables/Properties/AssemblyInfo.cs @@ -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("Enumerables")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("VMS")] +[assembly: AssemblyProduct("Enumerables")] +[assembly: AssemblyCopyright("Copyright © VMS 2017")] +[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("5d38fac3-f3ee-4942-8b8a-e460f8f53625")] + +// 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")] diff --git a/DesignPatternsSolution/Enumerables/Type.cs b/DesignPatternsSolution/Enumerables/Type.cs new file mode 100644 index 0000000..23fba9d --- /dev/null +++ b/DesignPatternsSolution/Enumerables/Type.cs @@ -0,0 +1,9 @@ +namespace ExerciseEnums +{ + // Re-namned from ObjectType -- "Object" is implied... + public enum Type + { + Person, + Item + } +} diff --git a/DesignPatternsSolution/Execise.Tests/Execise.Tests.csproj b/DesignPatternsSolution/Execise.Tests/Execise.Tests.csproj index 317ab1f..34e9903 100644 --- a/DesignPatternsSolution/Execise.Tests/Execise.Tests.csproj +++ b/DesignPatternsSolution/Execise.Tests/Execise.Tests.csproj @@ -55,6 +55,10 @@ + + {b26a05d5-9cec-4339-92dd-9b42dee8c028} + ExerciseInterfaces + {ea98a53a-f8cd-4539-9e57-1fef2d64f13a} Exercise diff --git a/DesignPatternsSolution/Execise.Tests/UnitTests.cs b/DesignPatternsSolution/Execise.Tests/UnitTests.cs index 0a3b80e..4ca6110 100644 --- a/DesignPatternsSolution/Execise.Tests/UnitTests.cs +++ b/DesignPatternsSolution/Execise.Tests/UnitTests.cs @@ -1,4 +1,6 @@ -using Exercise; +using System.Linq.Expressions; +using Exercise; +using ExerciseInterfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Execise.Tests @@ -12,27 +14,98 @@ public void LibraryShouldBeSingleton() { //check that when you create a Library instance second time, //you get exactly the same instance as for a very first time + Library lib1 = Library.Instance(); + Library lib2 = Library.Instance(); + + Assert.AreSame(lib1, lib2); } //test that an book was registered successfully by checking the returned Id value is not -1 [TestMethod] public void BookShouldRegister() { + int returnVal = Library.Instance().Register(new Book("Daryl Haase","Memoirs of Daryl", 2001, 4)); + + Assert.IsFalse(returnVal==-1); } //test that an customer was registered successfully by checking the returned Id value is not -1 [TestMethod] public void CustomerShouldRegister() { + int returnVal = Library.Instance().Register(new Customer("Daryl Haase","123 Street")); + + Assert.IsFalse(returnVal == -1); } //test that a book can be borrowed [TestMethod] - public void CanBorrowBook() + public void CanBorrowBook_OneOfThreeAvailable() { + int quantity = 3; + int numberToBorrow = 1; + int numberBorrowed = 0; + //create a borrowable book with available amount more than one. - //Run BorrowOne method of the BookBorrowable instance. Check that total amount was reduced by one. - - } + //Run BorrowOne method of the Borrowable instance. Check that total amount was reduced by one. + ILibraryObject chickenLittle = new Book("Dunno ThinkItsAFable", "Chicken Little", 1910, quantity); + Borrowable chickenLittleBorrowable = new Borrowable(chickenLittle); + + numberBorrowed = chickenLittleBorrowable.BorrowOne(); + + Assert.AreEqual(numberBorrowed, numberToBorrow); + Assert.AreEqual(chickenLittle.AvailableAmount, quantity - numberToBorrow); + } + + //test that a book can be borrowed + [TestMethod] + public void CanBorrowBook_TwoOfThreeAvailable() + { + int quantity = 3; + int numberToBorrow = 2; + int numberBorrowed = 0; + + ILibraryObject chickenLittle = new Book("Dunno ThinkItsAFable", "Chicken Little", 1910, quantity); + Borrowable chickenLittleBorrowable = new Borrowable(chickenLittle); + + numberBorrowed = chickenLittleBorrowable.Borrow(numberToBorrow); + + Assert.AreEqual(numberBorrowed, numberToBorrow); + Assert.AreEqual(chickenLittle.AvailableAmount, quantity - numberToBorrow); + } + + //test that a book can be borrowed + [TestMethod] + public void CanBorrowBook_ThreeOfThreeAvailable() + { + int quantity = 3; + int numberToBorrow = 3; + int numberBorrowed = 0; + + ILibraryObject chickenLittle = new Book("Dunno ThinkItsAFable", "Chicken Little", 1910, quantity); + Borrowable chickenLittleBorrowable = new Borrowable(chickenLittle); + + numberBorrowed = chickenLittleBorrowable.Borrow(numberToBorrow); + + Assert.AreEqual(numberBorrowed, numberToBorrow); + Assert.AreEqual(chickenLittle.AvailableAmount, quantity - numberToBorrow); + } + + //test that we cannot borrow more books than the library has copies + [TestMethod] + public void CanBorrowBook_FourOfThreeAvailable() + { + int quantity = 3; + int numberToBorrow = 4; + int numberBorrowed = 0; + + ILibraryObject chickenLittle = new Book("Dunno ThinkItsAFable", "Chicken Little", 1910, quantity); + Borrowable chickenLittleBorrowable = new Borrowable(chickenLittle); + + numberBorrowed = chickenLittleBorrowable.Borrow(numberToBorrow); + + Assert.AreEqual(numberBorrowed, 0); + Assert.AreEqual(chickenLittle.AvailableAmount, quantity); + } } } diff --git a/DesignPatternsSolution/Exercise/Book.cs b/DesignPatternsSolution/Exercise/Book.cs new file mode 100644 index 0000000..cdd7ae5 --- /dev/null +++ b/DesignPatternsSolution/Exercise/Book.cs @@ -0,0 +1,15 @@ +using ExerciseInterfaces; + +namespace Exercise +{ + // Relocated from LibraryItem.cs -- Poor practice to define a concrete class within the abstract class file + public class Book : LibraryItem, IBook + { + public Book(string author, string title, int year, int amount) : base(amount, year) + { + NameOrTitle = title; + Author = author; + } + public string Author { get; set; } + } +} diff --git a/DesignPatternsSolution/Exercise/BookBorrowable.cs b/DesignPatternsSolution/Exercise/BookBorrowable.cs deleted file mode 100644 index 21bd9cf..0000000 --- a/DesignPatternsSolution/Exercise/BookBorrowable.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Exercise -{ - public class BookBorrowable - { - - } -} diff --git a/DesignPatternsSolution/Exercise/Borrowable.cs b/DesignPatternsSolution/Exercise/Borrowable.cs new file mode 100644 index 0000000..3e31257 --- /dev/null +++ b/DesignPatternsSolution/Exercise/Borrowable.cs @@ -0,0 +1,28 @@ +using ExerciseInterfaces; + +namespace Exercise +{ + public class Borrowable : IBorrowable + { + private readonly ILibraryObject _decoratedLibraryObject; + + public Borrowable(ILibraryObject libraryObject) + { + _decoratedLibraryObject = libraryObject; + } + + public new int BorrowOne() + { + return this.Borrow(1); + } + + public new int Borrow(int numberOfCopiesToBorrow) + { + if (_decoratedLibraryObject.AvailableAmount < numberOfCopiesToBorrow) + return 0; + + _decoratedLibraryObject.AvailableAmount -= numberOfCopiesToBorrow; + return numberOfCopiesToBorrow; + } + } +} diff --git a/DesignPatternsSolution/Exercise/Person.cs b/DesignPatternsSolution/Exercise/Customer.cs similarity index 54% rename from DesignPatternsSolution/Exercise/Person.cs rename to DesignPatternsSolution/Exercise/Customer.cs index 2c2ed21..51f8f92 100644 --- a/DesignPatternsSolution/Exercise/Person.cs +++ b/DesignPatternsSolution/Exercise/Customer.cs @@ -1,23 +1,26 @@ using System; +using ExerciseInterfaces; +using Type = ExerciseEnums.Type; namespace Exercise { - public class Customer : LibObject + public class Customer : LibraryObject, ICustomer { public string Address { get; set; } public DateTime RegisteredAt { get; set; } + //Exercise states "Customer class - extending Person abstract class". There is no Person class -- it's just a property type of the LibraryObject public Customer(string name, string addr) { NameOrTitle = name; Address = addr; RegisteredAt = DateTime.Now; - ObjType = ObjectType.Person; + Type = Type.Person; } public void SetId(int id) { - ObjectId = id; + Id = id; } } } diff --git a/DesignPatternsSolution/Exercise/Exercise.csproj b/DesignPatternsSolution/Exercise/Exercise.csproj index 31e129e..5a47b42 100644 --- a/DesignPatternsSolution/Exercise/Exercise.csproj +++ b/DesignPatternsSolution/Exercise/Exercise.csproj @@ -41,19 +41,29 @@ - - - - - + + + + - + + + + + + {216aa6bc-f503-4172-8fd8-f1ddcc2788dd} + Enumerables + + + {b26a05d5-9cec-4339-92dd-9b42dee8c028} + ExerciseInterfaces + + \ No newline at end of file diff --git a/DesignPatternsSolution/ExerciseInterfaces/IBook.cs b/DesignPatternsSolution/ExerciseInterfaces/IBook.cs new file mode 100644 index 0000000..de15e57 --- /dev/null +++ b/DesignPatternsSolution/ExerciseInterfaces/IBook.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ExerciseInterfaces +{ + public interface IBook + { + string Author { get; set; } + } +} diff --git a/DesignPatternsSolution/ExerciseInterfaces/IBorrowable.cs b/DesignPatternsSolution/ExerciseInterfaces/IBorrowable.cs new file mode 100644 index 0000000..56de55b --- /dev/null +++ b/DesignPatternsSolution/ExerciseInterfaces/IBorrowable.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ExerciseInterfaces +{ + public interface IBorrowable + { + int BorrowOne(); + int Borrow(int numberOfCopiesToBorrow); + } +} diff --git a/DesignPatternsSolution/ExerciseInterfaces/ICustomer.cs b/DesignPatternsSolution/ExerciseInterfaces/ICustomer.cs new file mode 100644 index 0000000..6314865 --- /dev/null +++ b/DesignPatternsSolution/ExerciseInterfaces/ICustomer.cs @@ -0,0 +1,12 @@ +using System; + +namespace ExerciseInterfaces +{ + public interface ICustomer + { + string Address { get; set; } + DateTime RegisteredAt { get; set; } + + void SetId(int id); + } +} diff --git a/DesignPatternsSolution/ExerciseInterfaces/ILibraryObject.cs b/DesignPatternsSolution/ExerciseInterfaces/ILibraryObject.cs new file mode 100644 index 0000000..c5798d7 --- /dev/null +++ b/DesignPatternsSolution/ExerciseInterfaces/ILibraryObject.cs @@ -0,0 +1,13 @@ +using Type = ExerciseEnums.Type; + +namespace ExerciseInterfaces +{ + public interface ILibraryObject + { + int Id { get; set; } + int AvailableAmount { get; set; } + string NameOrTitle { get; set; } + Type Type { get; set; } + int YearCreated { get; set; } + } +} diff --git a/DesignPatternsSolution/ExerciseInterfaces/IRegistarable.cs b/DesignPatternsSolution/ExerciseInterfaces/IRegistarable.cs new file mode 100644 index 0000000..2f2afb7 --- /dev/null +++ b/DesignPatternsSolution/ExerciseInterfaces/IRegistarable.cs @@ -0,0 +1,9 @@ +namespace ExerciseInterfaces +{ + public interface IRegistarable + { + // Program to interfaces. Do not use concrete user defined types in an interface. Now we can split this class + // into a separate dll and consumers do not need rebuild every time our RegisteredObject implementation changes + IRegisteredObject GetRegistrationInfo(); + } +} diff --git a/DesignPatternsSolution/ExerciseInterfaces/IRegisteredObject.cs b/DesignPatternsSolution/ExerciseInterfaces/IRegisteredObject.cs new file mode 100644 index 0000000..5dd683b --- /dev/null +++ b/DesignPatternsSolution/ExerciseInterfaces/IRegisteredObject.cs @@ -0,0 +1,11 @@ +namespace ExerciseInterfaces +{ + public interface IRegisteredObject + { + string Info { get; set; } + int Id { get; set; } + int AvailableAmount { get; set; } + + string ToString(); + } +} diff --git a/DesignPatternsSolution/ExerciseInterfaces/Properties/AssemblyInfo.cs b/DesignPatternsSolution/ExerciseInterfaces/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0793935 --- /dev/null +++ b/DesignPatternsSolution/ExerciseInterfaces/Properties/AssemblyInfo.cs @@ -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("ExerciseInterfaces")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("VMS")] +[assembly: AssemblyProduct("ExerciseInterfaces")] +[assembly: AssemblyCopyright("Copyright © VMS 2017")] +[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("ae9bccbc-6e6b-4c75-bece-16db0a1f81ab")] + +// 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")]