Freigeben über


2009 Advent Calendar December 5th

Even though the solution created yesterday ensures thread safety when ImportantMethod is used I'm still not satisfied. It might be that I'm paranoid but when ImportantObject is changed in the future we don't really have any guarantee that the future developer remembers to keep things thread safe. For example if we needed to add AnotherImportantMethod to the ImportantObject it is easy to forget to make that new method thread safe too. Also, the ImportantObject now can be considered to violate the single responsibility principle because it does important things and has a lock to do it thread safe.

So let's try to keep the ImportantObject focused on the important things to do. And instead create a separate object to tie the lock and important object together. I'll call this object a transaction and the first test can look something like this:

    1:      public class Given_a_Transaction
   2:      {
   3:          class FakeLock : Lock
   4:          {
   5:              public bool IsLocked { get; private set; }
   6:   
   7:              public FakeLock()
   8:              {
   9:                  IsLocked = false;
  10:              }
  11:   
  12:              public void Lock()
  13:              {
  14:                  IsLocked = true;
  15:              }
  16:   
  17:              public void Unlock()
  18:              {
  19:                  IsLocked = false;
  20:              }
  21:          }
  22:   
  23:          private Transaction _transaction;
  24:          private FakeLock _lock;
  25:   
  26:          public Given_a_Transaction()
  27:          {
  28:              _lock = new FakeLock();
  29:              _transaction = new Transaction(_lock);
  30:          }
  31:   
  32:          [Fact]
  33:          void It_should_take_lock_when_created()
  34:          {
  35:              Assert.True(_lock.IsLocked);
  36:          }
  37:      }

And then the implementation would look like this:

    1:      public class Transaction
   2:      {
   3:          private readonly Lock _lock;
   4:   
   5:          public Transaction() : this(new MutexLock())
   6:          {
   7:              
   8:          }
   9:   
  10:          public Transaction(Lock aLock)
  11:          {
  12:              _lock = aLock;
  13:              _lock.Lock();
  14:          }
  15:      }

Let's add another test tomorrow!