var blog = new ThoughtStream(me); RSS 2.0
 Monday, March 10, 2008

Have you ever:

  • had a problem that you were having a hard time solving?
  • been in need of a design idea for a particular situation, and you don't know where to start?
  • solved a problem that was nagging you for a while?
  • come up with a good design for a common situation?
  • written some code that you wanted to keep around, to remind yourself how you did something?
  • wanted to find some code examples on how to do something with a specific technology?
  • wanted to know how to do something for a specific project?
  • wanted to share your knowledge on how to use a specific technology a specific way?
  • wanted to learn how to use a specific feature of a project?
  • wanted the world to know your opinion of a piece of software or technology, be it good or bad?

If you can answer "yes" to any one of these questions - you should be blogging.

If you can answer "yes" to more than one of these questions and you are not blogging, then shame on you! Start blogging today!

Don't think your opinion matters, or that you have anything worth saying? Stop fooling yourself. If you write code, you have opinions and preferences. If you have opinions and preferences, they are worth sharing. It's not possible to write code without opinions. Software development is not a mechanical process like building a house or a car - you can't sick a robot on a keyboard and write a functional piece of software.

The worst case scenario: If you post code examples on issues that you have solved, you will have a history of code you have written and issues you have solved. You'll be able to go back to this history and re-use existing knowledge, rather than having to think through the problem again.

The best case scenario: If you post your code examples, your thoughts on software development, your opinions and preferences; chances are that someone else in this wide world of ours has the same opinion or has had the same issues and will find the information you provide useful.

Why should you blog? Because you're a person with ideas worth listening to.

...

Get started now. Register a domain name and buy some web hosting so you can have a blog that is accessible to the world. I use dasBlog and WebHost4Life. There are thousands of options out there - find the one that works for you.

Monday, March 10, 2008 10:37:30 AM (Central Standard Time, UTC-06:00)  #    Comments [0]. Trackback 
Tags: General

 Saturday, March 08, 2008

After many years of being a loyal RSSBandit user, I've jumped ships and started using Outlook 2007 to manage all of my RSS feeds. My only reason is that I'm already using Outlook for so many other functions, and now that we are implementing SharePoint, that list of reasons is growing.

One of the things I did not like about Outlooks' default RSS capabilities, was not being able to see a quick, concise list of the feeds / posts that I have not yet read. Fortunately, there is an easy solution to this: Search Folders.

To create a quick, easy way to view all of the unread posts in your feed list, follow these simple steps:

  1. Right click on "Search Folders" in the Outlook tree and select "New Search Folder..."
    image
  2. On the screen that pops up, choose "Create a custom Search Folder" at the bottom of the list:
    image
  3. Click the "Choose" button for specifying criteria and name your folder
    image
  4. Click "Browse" to select the folders that you want to search. Unsleect the root "Mailbox" folder, and select the "RSS Feeds" sub-folder. Ensure that "Search subfolders" is selected.
      image
  5. Click OK to close the "Select Folder(s)" screen. Now click the "Criteria" button, and under the "More Choises" tab, select "Only items that are: ", "unread".
    image
  6. Click OK to close the criteria screen, click OK to close the Custom Search Folder screen, and Click OK to close the New Search Folder screen. You now have an "Unread RSS" folder in your Search Folders. Drag this item into your "Favorite Folder" list and you are done! 
    image

Now your unread RSS feeds are only a button click away! And the great part about this simple solution is that you can create some very specific RSS searches, in additional custom Search Folders. Just follow this process again, only selecting the specific folders that you want.

Saturday, March 08, 2008 9:15:29 PM (Central Standard Time, UTC-06:00)  #    Comments [0]. Trackback 
Tags:

I just can't help myself... I had to flesh out the Account Transfer behavior from my previous post. I was interested in two things:

  1. Adding a second set of Acceptance Criteria for a valid transfer
  2. Implementing the crazy looking "account.Transfer(ammount).To(account)" syntax

Expanded Acceptance Criteria

Existing User Story:

As an account holder,
I want to transfer money between accounts
So that I can avoid overdraft fees

Acceptance Criteria:

  1. Given a transfer between accounts,
    When the requested transfer amount is greater than the originating account's balance
    Then the transfer should fail and the balance of the originating and receiving accounts should not change
  2.  

  3. Given a transfer between accounts,
    When the requested transfer amount is less than the originating account's balance
    Then the transfer is successful, the originating account is debited the transfer amount and the receiving amount is credited the transfer amount

Implementing The Transfer.To Syntax

This was the fun part, really - seeing if I could implement the API that I wanted to see. It turned out to be significantly easier than I had thought it would be.

I started with the Account object, and added the "Transfer" method. I knew that this method needed to return an object so that I could have the "To" method accept an Account object. A few moments of thinking this through and I decided to go with an object called TransferCriteria. This would let me collect all of the information that I need, about the transfer.

public TransferCriteria Transfer(double ammount)
{
    TransferCriteria criteria = new TransferCriteria(this, ammount);
    return criteria;
}

The end-goal of this syntax model is to return an AccountTransfer object, directly. So, the TransferCriteria.To method then creates an AccountTransfer object, using the TransferCriteria.

public AccountTransfer To(Account receivingAccount)
{
    ReceivingAccount = receivingAccount;
    return new AccountTransfer(this);
}


In the end, I have an AccountTransfer object that contains all of the information I need - the originating account, the receiving account, and the transfer amount. With that in place, the rest of the code is simple.

Behavior Specification

AccountTransferSpecifications.cs

using AccountSample.Domain;
using NUnit.Framework;
using SpecUnit;
 
namespace AccountSample.Specifications
{
 
    [TestFixture]
    [Concern("Account Transfers")]
    public class When_The_Requested_Transfer_Amount_Is_Greater_Than_The_Originating_Account_Balance : ContextSpecification
    {
 
        #region Context
 
        private const double originatingAccountBalance = 100;
        private const double receivingAccountBalance = 0;
        private const double requestedTransferAmmount = 125.95;
        private Account originatingAccount;
        private Account receivingAccount;
        private AccountTransfer accountTransfer;
 
        protected override void Context()
        {
            originatingAccount = new Account(originatingAccountBalance);
            receivingAccount = new Account(receivingAccountBalance);
 
            accountTransfer = originatingAccount.Transfer(requestedTransferAmmount).To(receivingAccount);
        }
 
        #endregion
 
        #region Observations
 
        [Test]
        [Observation]
        public void The_Transfer_Should_Fail()
        {
            accountTransfer.Status.ShouldEqual(TransferStatus.Failed);
        }
 
        [Test]
        [Observation]
        public void The_Originating_Account_Balance_Should_Not_Be_Changed()
        {
            originatingAccount.Balance.ShouldEqual(originatingAccountBalance);
        }
 
        [Test]
        [Observation]
        public void The_Receiving_Account_Balance_Should_Not_Be_Changed()
        {
            receivingAccount.Balance.ShouldEqual(receivingAccountBalance);
        }
 
        #endregion
 
    }
 
    [TestFixture]
    [Concern("Account Transfers")]
    public class When_The_Requested_Transfer_Amount_is_Less_Than_The_Originating_Account_Balance: ContextSpecification
    {
 
        #region Context
 
        private const double originatingAccountBalance = 100;
        private const double receivingAccountBalance = 0;
        private const double requestedTransferAmmount = 25;
        private Account originatingAccount;
        private Account receivingAccount;
        private AccountTransfer accountTransfer;
 
        protected override void Context()
        {
            originatingAccount = new Account(originatingAccountBalance);
            receivingAccount = new Account(receivingAccountBalance);
 
            accountTransfer = originatingAccount.Transfer(requestedTransferAmmount).To(receivingAccount);
        }
    
        #endregion
 
        #region Observations
 
        [Test]
        [Observation]
        public void The_Transfer_Is_Successful()
        {
            accountTransfer.Status.ShouldEqual(TransferStatus.Success);
        }
 
        [Test]
        [Observation]
        public void The_Originating_Account_Is_Debited_The_Transfer_Amount()
        {
            const double newBalance = originatingAccountBalance - requestedTransferAmmount;
            originatingAccount.Balance.ShouldEqual(newBalance);
        }
 
        [Test]
        [Observation]
        public void The_Receiving_Account_Is_Credited_The_Transfer_Amount()
        {
            const double newBalance = receivingAccountBalance + requestedTransferAmmount;
            receivingAccount.Balance.ShouldEqual(newBalance);
        }
 
        #endregion
 
    }
 
}

Behavior Implementation

Account.cs

namespace AccountSample.Domain
{
 
    public class Account
    {
 
        #region Properties
 
        public double Balance { get; private set; }
 
        #endregion
 
        #region Constructor
 
        public Account(double currentAccountBalance)
        {
            Balance = currentAccountBalance;
        }
 
        #endregion
 
        #region Methods
 
        public TransferCriteria Transfer(double ammount)
        {
            TransferCriteria criteria = new TransferCriteria(this, ammount);
            return criteria;
        }
 
        public void Debit(double ammount)
        {
            Balance -= ammount;
        }
 
        public void Credit(double ammount)
        {
            Balance += ammount;
        }
 
        #endregion
 
    }
 
}

 

AccountTransfer.cs

namespace AccountSample.Domain
{
 
    public class AccountTransfer
    {
 
        #region Vars
 
        private TransferStatus _status = TransferStatus.None;
 
        #endregion
 
        #region Properties
 
        public TransferStatus Status
        {
            get { return _status; }
            private set { _status = value; }
        }
 
        public double TransferAmmount { get; private set; }
 
        public Account OriginatingAccount { get; private set; }
 
        public Account ReceivingAccount { get; private set; }
 
        #endregion
 
        #region Constructor
 
        public AccountTransfer(TransferCriteria criteria)
        {
            OriginatingAccount = criteria.OriginatingAccount;
            ReceivingAccount = criteria.ReceivingAccount;
            TransferAmmount = criteria.TransferAmount; 
            Execute();
        }
 
        #endregion
 
        #region Methods
 
        private void Execute()
        {
            if (TransferAmmount > OriginatingAccount.Balance)
            {
                Status = TransferStatus.Failed;
            }
            else
            {
                OriginatingAccount.Debit(TransferAmmount);
                ReceivingAccount.Credit(TransferAmmount);
                Status = TransferStatus.Success;
            }
        }
 
        #endregion
 
    }
}

 

TransferCriteria.cs

namespace AccountSample.Domain
{
 
    public class TransferCriteria
    {
 
        #region Properties
 
        public double TransferAmount { get; private set; }
 
        public Account OriginatingAccount { get; private set; }
 
        public Account ReceivingAccount { get; private set; }
 
        #endregion