Two words... Serious Poundage.
20061025
20061022
NMock2... Rhino.Mocks' Nemesis
I am a "Traditional" mocking guy... I write all my mocks, and got to the point that it has became very fast to implement. But sometimes I just wish that there is a good mocking tool out there.
I have tried Rhino, and I may be stupid (which I am) but I can't figure the damn thing out... I wish there was something that was very straight forward.
NMock2 to the rescue!
I have coded a quick Model View Presenter sample that uses NMock2. Enjoy.
The Test
[TestFixture]public class DJInventoryPresenterTest
{private Mockery mocks;
private DJInventoryPresenter presenter;
private IDJInventoryTask task;
private IDJInventoryView view;
[SetUp]public void SetUp()
{mocks = new Mockery();
task = mocks.NewMock<IDJInventoryTask>(); view = mocks.NewMock<IDJInventoryView>();presenter = new DJInventoryPresenter(view, task);
}
[TearDown]public void TearDown()
{mocks.VerifyAllExpectationsHaveBeenMet();
}
[Test]public void ShouldAdd()
{Expect.Once.On(view).GetProperty("Name");
Expect.Once.On(view).GetProperty("Description");
Expect.Once.On(view).SetProperty("Id");
Expect.Once.On(task).Method("Add").Will(Return.Value(1));
presenter.Add();
}
[Test]public void ShouldDelete()
{Expect.Once.On(view).GetProperty("Name");
Expect.Once.On(view).GetProperty("Description");
Expect.Once.On(view).GetProperty("Id").Will(Return.Value(1));
Expect.Once.On(task).Method("Delete");
presenter.Delete();
}
[Test]public void ShouldUpdate()
{Expect.Once.On(view).GetProperty("Name");
Expect.Once.On(view).GetProperty("Description");
Expect.Once.On(view).GetProperty("Id").Will(Return.Value(1));
Expect.Once.On(view).SetProperty("IsUpdated");
Expect.Once.On(task).Method("Edit").Will(Return.Value(true));
presenter.Update();
}
[Test]public void ShouldGetById()
{Expect.Once.On(view).SetProperty("Name");
Expect.Once.On(view).SetProperty("Description");
Expect.Once.On(view).GetProperty("Id").Will(Return.Value(1));
Expect.Once.On(task).Method("GetDJInventoryById").Will(Return.Value(CreateDJInventory()));
presenter.GetDJInventoryById();
}
[Test]public void ShouldGetAll()
{Expect.Once.On(view).SetProperty("AllInventories");
Expect.Once.On(task).Method("GetAllDJInventories").Will(
Return.Value(new DJInventory[] {CreateDJInventory()}));
presenter.GetAllInventories();
}
private DJInventory CreateDJInventory()
{DJInventory inventory = new DJInventory();
inventory.Name = "Test"; inventory.Description = "Test Description"; return inventory;}
}
The Presenter
public class DJInventoryPresenter
{private readonly IDJInventoryView view;
private readonly IDJInventoryTask task;
public DJInventoryPresenter(IDJInventoryView view, IDJInventoryTask task)
{ this.view = view; this.task = task;}
public void Add()
{DJInventory inventory = CreateDJInventoryFromView(view, true);
view.Id = task.Add(inventory);
}
public void Delete()
{ task.Delete(CreateDJInventoryFromView(view, false));}
public void Update()
{ view.IsUpdated = task.Edit(CreateDJInventoryFromView(view, false));}
public void GetDJInventoryById()
{ DJInventory result = task.GetDJInventoryById(view.Id);view.Name = result.Name;
view.Description = result.Description;
}
private DJInventory CreateDJInventoryFromView(IDJInventoryView view, bool ignoreId)
{DJInventory inventory = new DJInventory();
inventory.Name = view.Name;
inventory.Description = view.Description;
if (!ignoreId)inventory.Id = view.Id;
return inventory;}
public void GetAllInventories()
{view.AllInventories = CreateDataTable(task.GetAllDJInventories());
}
private DataTable CreateDataTable(DJInventory[] inventories)
{DataTable dt = new DataTable();
CreateColumns(dt);
CreateRows(dt, inventories);
return dt;}
private void CreateColumns(DataTable dt)
{ dt.Columns.Add("ID"); dt.Columns.Add("Name"); dt.Columns.Add("Description");}
private void CreateRows(DataTable dt, DJInventory[] inventories)
{foreach (DJInventory inventory in inventories)
{dt.Rows.Add(CreateRow(dt, inventory));
}
}
private DataRow CreateRow(DataTable dt, DJInventory inventory)
{ DataRow row = dt.NewRow(); row["ID"] = inventory.Id; row["Name"] = inventory.Name; row["Description"] = inventory.Description; return row;}
}
Switch Statement = Ghetto... Enum = Ghetto
U like the title? Aww yeaa foo!
I like bustin' some OOP nyahh all the time, and some of the developers I have paired with notice two things: (1) I don't do switch statements, (2) I rarely (never) use enums...
Why you ask?
Switch / Case: It's gay.
Switch / Case: Too much code in the containing class.
Switch / Case: Can become complex.
Switch / Case: Containing class needs to be changed when a condition is added/changed.
Switch / Case: A 'case' is hard coded "case IsUgly:"
Enum: It's just a frigging int...
Enum: It's gay.
I will show you some cool tricks how to get rid of the nastyness...
Okay... here is a test.
[Test]public void ShouldDJ()
{Person jonas = new Person("Jonas");
jonas.Do(DoSomething.DJ);Assert.AreEqual("DJ", jonas.IsDoing);
}
Okay, nothing fancy... we are verifying that Person is DJing. But now here comes the ugly.
public enum DoSomething
{DJ = 1,
BMX = 2,
GetDrunk = 3
}
What the F**k is that!?!? That's the enum! we are just replacing numbers with something readable... So nasty!
Here's the Person object:
public class Person
{private readonly string name;
private string isDoing;
public Person(string name)
{ this.name = name;}
public string Name
{get { return name; }
}
public void Do(DoSomething doStuff)
{ switch(doStuff) {case DoSomething.DJ:
isDoing = "DJ"; break;case DoSomething.BMX:
isDoing = "BMX"; break;case DoSomething.GetDrunk:
isDoing = "Aww yeaa foo!"; break;}
}
public string IsDoing
{get { return isDoing; }
}
}
I know I coded a switch for this sample (almost made me throw up).
So what is the big deal with using enums or switch?
Three words: Object Oriented Programming. You basically make objects to build your application. Yes, they make take longer to develop, but they are waaaay more maintainable. And if you programmed it so it can be readable, you can read your code like a story.
How can we fix the code that you showed above?
First off, you will notice the Person() object has a method called "Do". What do you see very similar to what it's doing?... Yess they all set "IsDoing" property with a value which is a string.
What we need to implement is a strategy pattern:
public abstract class WhatToDoStrategy
{public static WhatToDoStrategy DJ = new DJStrategy();
public static WhatToDoStrategy BMX = new BMXStrategy();
public static WhatToDoStrategy GET_DRUNK = new GetDrunkStrategy();
public abstract string Do { get; }
private class DJStrategy : WhatToDoStrategy
{public override string Do
{get { return "DJ"; }
}
}
private class BMXStrategy : WhatToDoStrategy
{public override string Do
{get { return "BMX"; }
}
}
private class GetDrunkStrategy : WhatToDoStrategy
{public override string Do
{get { return "Aww yea foo!"; }
}
}
With the WhatToDoStrategy() strategy, our Person() object is now "naked" to all the logic when it comes to what it needs to do... it will simply just call an object.
Sometimes, you may not want to call your strategy directly. As for this example, I created an interface called IStuffToDo that is taken in by Person() object.
public interface IStuffToDo
{ WhatToDoStrategy Doing();}
public class DJing : IStuffToDo
{public WhatToDoStrategy Doing()
{return WhatToDoStrategy.DJ;
}
}
public class BMXing : IStuffToDo
{public WhatToDoStrategy Doing()
{return WhatToDoStrategy.BMX;
}
}
public class GettingDrunk : IStuffToDo
{public WhatToDoStrategy Doing()
{return WhatToDoStrategy.GET_DRUNK;
}
}
The code above replaces the enum we had. This is wayyyyyy better. now when you look at the code for DJing(), you know it is calling the DJ strategy, not a fu*king number 1 which doesnt make any sense.
Here is the modification to the Person() object:
public class Person
{ //...public void Do(IStuffToDo stuffToDo)
{isDoing = stuffToDo.Doing().Do;
}
//...}
Notice how it is taking in an IStuffToDo object, which in turn calls our strategy...
Lastly, how do we verify if this code works? Tests!!!!
[TestFixture]public class PersonTest
{ [Test]public void ShouldDJ()
{Person jonas = new Person("Jonas");
jonas.Do(new DJing());
Assert.AreEqual("DJ", jonas.IsDoing);
}
[Test]public void ShouldBMX()
{Person jonas = new Person("Jonas");
jonas.Do(new BMXing());
Assert.AreEqual("BMX", jonas.IsDoing);
}
[Test]public void ShouldGetDrunk()
{Person jonas = new Person("Jonas");
jonas.Do(new GettingDrunk());
Assert.AreEqual("Aww yea foo!", jonas.IsDoing);
}
}
Nyahhh!!!
20061016
A Conversation While Contemplating Buying Skis using a Mediator Pattern
using System.Collections.Generic;using NUnit.Framework;namespace jonas.patterns.behavioral.mediator{ [TestFixture]public class MediatorTest
{ [Test]public void ShouldBuySkis()
{Store pacesetterSkiShop = new Store();
Person suzie = new SalesPerson("Suzie");
Person jonas = new Customer("Jonas");
pacesetterSkiShop.Add(suzie);
pacesetterSkiShop.Add(jonas);
suzie.Message = "Finding what you are looking for?";suzie.Talk(jonas);
Assert.AreEqual("Sales Person Suzie says: Finding what you are looking for?", jonas.Recieve(suzie));
jonas.Message = "I'm looking for skis. Can you help me out?";jonas.Talk(suzie);
Assert.AreEqual("Customer Jonas says: I'm looking for skis. Can you help me out?", suzie.Recieve(jonas));
suzie.Message = "Sure what kind are you looking at?";suzie.Talk(jonas);
Assert.AreEqual("Sales Person Suzie says: Sure what kind are you looking at?", jonas.Recieve(suzie));
jonas.Message = "Actually, I just want your number...";jonas.Talk(suzie);
Assert.AreEqual("Customer Jonas says: Actually, I just want your number...", suzie.Recieve(jonas));
suzie.Message = "Get the hell out of this store!";suzie.Talk(jonas);
Assert.AreEqual("Sales Person Suzie says: Get the hell out of this store!", jonas.Recieve(suzie));
}
}
internal class Customer : Person
{public Customer(string name) : base(name)
{}
public override string Recieve(Person otherPerson)
{return string.Format("Sales Person {0}", base.Recieve(otherPerson));
}
}
internal class SalesPerson : Person
{public SalesPerson(string name) : base(name)
{}
public override string Recieve(Person otherPerson)
{return string.Format("Customer {0}", base.Recieve(otherPerson));
}
}
internal class Person
{private string name;
private string message;
private Store store;
public Person(string name)
{ this.name = name;}
public string Name
{get { return name; }
}
public string Message
{get { return message; }
set { message = value; }
}
public Store Store
{set { store = value; }
}
public void Talk(Person otherPerson)
{ store.Talk(otherPerson, this);}
public virtual string Recieve(Person otherPerson)
{return string.Format("{0} says: {1}", otherPerson.Name, otherPerson.Message);
}
}
internal class Store
{private Dictionary<string, Person> people;
public Store() {people = new Dictionary<string, Person>();
}
public void Add(Person person)
{ if (!people.ContainsKey(person.Name)) {people.Add(person.Name, person);
person.Store = this;}
}
public void Talk(Person from, Person to)
{ if (people.ContainsKey(to.Name))to.Recieve(from);
}
}
}
20061012
Unit of Work Pattern
What do you do after watching 12 episodes of The Office seasons 1 & 2?
- Some people may have smoke up
- have a brew or two... okay fine... get gunned!
- Some people may DJ (I usually do that)
As for me, this particular night was to post some sample code, some nyahhh and some tests for the Unit of Work pattern (UoW). I can't believe there is no sample code out there for this pattern. I'm just under the assumption that a lot of people that know about this pattern are not willing to share the love. So I ended up whipping up the pattern with unit tests! This may be some uber nyahhh for some... Ah well.
What is Unit of Work?
From kinda looking at the Fowler P of EAA book, it is more like an item that keeps track of objects (Domain Objects) for any changes whether it is a new object (an insert to the db), changes/modifications to any properties (update), or removing an item (delete). It does all of these changes as one big dump to the db.
UoW seems to be pretty efficient when it comes to database calls. Instead of doing the usual the service layer calls some mapper to do an insert for one item (which is slow, depending on how you have set up your db transactions), UoW keeps track of all the business transaction that affects the db. A programmer does not have to explicitly call any data mappers for any database changes- UoW does it all for ya'll!
Lets see some code!!!
Before we begin, I will warn all of you reading this, that there are no comments what so ever. I tried to make the Tests (busted some TDD stylez) speak for the pattern it self. If you can't read the test... learn TDD or even Unit Tests foo!
The Test
Note: I instanciated "ExtendedUnitOfWork" (inherit from UnitOfWork class) in order to override my DatabaseConnection object to use a Mock.
using NUnit.Framework;using unitofworkspike;namespace UnitOfWorkTest{ [TestFixture]public class UnitOfWorkTest
{private MockMapper mapper;
[TestFixtureSetUp]public void TestFixtureSetUp()
{mapper = new MockMapper();
MapperFactory.Instance.AddMapper(typeof (SimpleObject), mapper);
}
[TearDown]public void TearDown()
{mapper.Reset();
}
[Test]public void ShouldInsertSimpleObject()
{ExtendedUnitOfWork work = new ExtendedUnitOfWork();
CreateNewSimpleObject(work);
work.Commit();
Assert.IsTrue(mapper.HasCalledInsert); Assert.IsFalse(mapper.HasCalledUpdate); Assert.IsFalse(mapper.HasCalledDelete); Assert.AreEqual(1, mapper.InsertCount); Assert.AreEqual(0, mapper.UpdateCount); Assert.AreEqual(0, mapper.DeleteCount);}
[Test]public void ShouldInsertMultipleSimpleObjects()
{ExtendedUnitOfWork work = new ExtendedUnitOfWork();
CreateNewSimpleObjects(work, 5);
work.Commit();
Assert.IsTrue(mapper.HasCalledInsert); Assert.IsFalse(mapper.HasCalledUpdate); Assert.IsFalse(mapper.HasCalledDelete); Assert.AreEqual(5, mapper.InsertCount); Assert.AreEqual(0, mapper.UpdateCount); Assert.AreEqual(0, mapper.DeleteCount);}
[Test]public void ShouldUpdateOneSimpleObjectWithOneInsert()
{ExtendedUnitOfWork work = new ExtendedUnitOfWork();
CreateNewSimpleObject(work);
CreateToEditSimpleObject(work, 1);
work.Commit();
Assert.IsTrue(mapper.HasCalledInsert); Assert.IsTrue(mapper.HasCalledUpdate); Assert.IsFalse(mapper.HasCalledDelete); Assert.AreEqual(1, mapper.InsertCount); Assert.AreEqual(1, mapper.UpdateCount); Assert.AreEqual(0, mapper.DeleteCount);}
[Test]public void ShouldUpdateMultipleSimpleObjects()
{ExtendedUnitOfWork work = new ExtendedUnitOfWork();
CreateEditSimpleObjects(work, 4);
work.Commit();
Assert.IsFalse(mapper.HasCalledInsert); Assert.IsTrue(mapper.HasCalledUpdate); Assert.IsFalse(mapper.HasCalledDelete); Assert.AreEqual(0, mapper.InsertCount); Assert.AreEqual(4, mapper.UpdateCount); Assert.AreEqual(0, mapper.DeleteCount);}
[Test]public void ShouldRemoveSimpleObject()
{ExtendedUnitOfWork work = new ExtendedUnitOfWork();
CreateToDeleteSimpleObject(work, 1);
work.Commit();
Assert.IsFalse(mapper.HasCalledInsert); Assert.IsFalse(mapper.HasCalledUpdate); Assert.IsTrue(mapper.HasCalledDelete); Assert.AreEqual(0, mapper.InsertCount); Assert.AreEqual(0, mapper.UpdateCount); Assert.AreEqual(1, mapper.DeleteCount);}
[Test]public void ShouldRemoveMultipleSimpleObjects()
{ExtendedUnitOfWork work = new ExtendedUnitOfWork();
CreateToDeleteSimpleObjects(work, 7);
work.Commit();
Assert.IsFalse(mapper.HasCalledInsert); Assert.IsFalse(mapper.HasCalledUpdate); Assert.IsTrue(mapper.HasCalledDelete); Assert.AreEqual(0, mapper.InsertCount); Assert.AreEqual(0, mapper.UpdateCount); Assert.AreEqual(7, mapper.DeleteCount);}
[Test]public void ShouldDoMultipleJobsForUnit()
{ExtendedUnitOfWork work = new ExtendedUnitOfWork();
CreateNewSimpleObjects(work, 9);
CreateEditSimpleObjects(work, 8);
CreateToDeleteSimpleObjects(work, 3);
work.Commit();
Assert.IsTrue(mapper.HasCalledInsert); Assert.IsTrue(mapper.HasCalledUpdate); Assert.IsTrue(mapper.HasCalledDelete); Assert.AreEqual(9, mapper.InsertCount); Assert.AreEqual(8, mapper.UpdateCount); Assert.AreEqual(3, mapper.DeleteCount);}
private void CreateNewSimpleObjects(ExtendedUnitOfWork work, int count)
{for (int i = 0; i < count; i++)
{CreateNewSimpleObject(work);
}
}
private void CreateEditSimpleObjects(ExtendedUnitOfWork work, int count)
{for (int i = 0; i < count; i++)
{CreateToEditSimpleObject(work, i);
}
}
private void CreateToDeleteSimpleObjects(ExtendedUnitOfWork work, int count)
{for (int i = 0; i < count; i++)
{CreateToDeleteSimpleObject(work, i);
}
}
private void CreateToEditSimpleObject(ExtendedUnitOfWork work, int id)
{SimpleObject simple = new SimpleObject(work);
simple.Id = id;
simple.IsTrue = true; simple.Text = "ExistingItem";}
private void CreateToDeleteSimpleObject(ExtendedUnitOfWork work, int id)
{SimpleObject simple = SimpleObject.Remove(work);
simple.Id = id;
simple.IsTrue = true; simple.Text = "DeleteItem";}
private static void CreateNewSimpleObject(ExtendedUnitOfWork work)
{SimpleObject simple = SimpleObject.Create(work);
simple.IsTrue = false; simple.Text = "Test";}
private class ExtendedUnitOfWork : UnitOfWork
{protected override IDatabaseConnection GetDatabaseConnection()
{return new MockDatabaseConnection();
}
}
private class MockDatabaseConnection : IDatabaseConnection
{public void Dispose()
{}
}
private class MockMapper : IMapper
{public bool HasCalledInsert;
public int InsertCount = 0;
public bool HasCalledUpdate;
public int UpdateCount = 0;
public bool HasCalledDelete;
public int DeleteCount = 0;
public void Insert(IDatabaseConnection connection, DomainObject domainObject)
{ HasCalledInsert = true;InsertCount++;
}
public void Update(IDatabaseConnection connection, DomainObject domainObject)
{ HasCalledUpdate = true;UpdateCount++;
}
public void Delete(IDatabaseConnection connection, DomainObject domainObject)
{ HasCalledDelete = true;DeleteCount++;
}
public void Reset()
{ HasCalledInsert = false;InsertCount = 0;
HasCalledUpdate = false;UpdateCount = 0;
HasCalledDelete = false;DeleteCount = 0;
}
}
private class SimpleObject : DomainObject
{private int id;
private string text;
private bool isTrue;
public SimpleObject(UnitOfWork unitofwork) : base(unitofwork)
{}
public SimpleObject() : base(null)
{}
public static SimpleObject Create(UnitOfWork unitofwork)
{SimpleObject simple = new SimpleObject(unitofwork);
simple.MarkNew();
return simple;}
public static SimpleObject Remove(UnitOfWork unitofwork)
{SimpleObject simple = new SimpleObject(unitofwork);
simple.MarkRemove();
return simple;}
public int Id
{get { return id; }
set { id = value;MarkDirty();
}
}
public string Text
{get { return text; }
set { text = value;MarkDirty();
}
}
public bool IsTrue
{get { return isTrue; }
set { isTrue = value;MarkDirty();
}
}
}
}
}
The base Domain Object
namespace unitofworkspike{public class DomainObject : IDomainObject
{private UnitOfWork unitofwork;
private bool isMarkedNew;
private bool isMarkedRemove;
private bool isMarkedDirty;
public DomainObject(UnitOfWork unitofwork)
{ this.unitofwork = unitofwork;}
public void MarkNew()
{if(unitofwork == null) return;
unitofwork.RegisterNew(this); isMarkedNew = true;}
public void MarkDirty()
{if (unitofwork == null) return;
if (isMarkedDirty) return;
if (!isMarkedNew && !isMarkedRemove) { unitofwork.RegisterDirty(this); isMarkedDirty = true;}
}
public void MarkRemove()
{if (unitofwork == null) return;
unitofwork.RegisterRemoved(this); isMarkedRemove = true;}
}
}
namespace unitofworkspike{public interface IDomainObject
{ void MarkNew(); void MarkDirty(); void MarkRemove();}
}
Unit of Work
using System.Collections.Generic;using unitofworkspike;namespace unitofworkspike{public class UnitOfWork : IUnitOfWork
{private IList<DomainObject> newObjects = new List<DomainObject>();
private IList<DomainObject> dirtyObjects = new List<DomainObject>();
private IList<DomainObject> removedObjects = new List<DomainObject>();
public void RegisterNew(DomainObject domainObject)
{newObjects.Add(domainObject);
}
public void RegisterDirty(DomainObject domainObject)
{dirtyObjects.Add(domainObject);
}
public void RegisterRemoved(DomainObject domainObject)
{removedObjects.Add(domainObject);
}
public void Commit()
{using (IDatabaseConnection connection = GetDatabaseConnection())
{InsertNew(connection);
UpdateDirty(connection);
DeleteRemoved(connection);
}
}
private void InsertNew(IDatabaseConnection connection)
{foreach (DomainObject newObject in newObjects)
{ MapperFactory.Instance.GetMapper(newObject.GetType()).Insert(connection, newObject);}
}
private void UpdateDirty(IDatabaseConnection connection)
{foreach (DomainObject dirtyObject in dirtyObjects)
{ MapperFactory.Instance.GetMapper(dirtyObject.GetType()).Update(connection, dirtyObject);}
}
private void DeleteRemoved(IDatabaseConnection connection)
{foreach (DomainObject removedObject in removedObjects)
{ MapperFactory.Instance.GetMapper(removedObject.GetType()).Delete(connection, removedObject);}
}
protected virtual IDatabaseConnection GetDatabaseConnection()
{return new DatabaseConnection();
}
}
}
Note: Some of you people that knows UoW may notice I did not implement RegisterClean(DomainObject domainObject) and RollBack(). I just wanted to see the CrUD done... I'm too lazy to do the other ones.
namespace unitofworkspike{public interface IUnitOfWork
{void RegisterNew(DomainObject domainObject);
void RegisterDirty(DomainObject domainObject);
void RegisterRemoved(DomainObject domainObject);
void Commit();}
}
