Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Fowler's Domain Logic Examples From Patterns of Enterprise Applications

3.00/5 (4 votes)
3 Feb 2009CPOL3 min read 34.5K   33  
A C# project that implements Fowler's Transaction Script Pattern.

Introduction

I started reading Martin Fowler's Patterns of Enterprise Architecture recently. I became confused with his description of the Transaction Script Pattern, so I created a Visual Studio Solution that implements the examples he used in the chapter. Fowler does not provide code samples/solutions on his website, and I could not find anyone else who did a similar project on CodeProject, so I started from scratch. The attached Zip file includes a database script and a VS2008 solution to help any one who is working though the same text.

Background

This code is meant to accompany Fowler's Patterns of Enterprise Application Architecture (14th printing), pages 110-115.

Using the Code

The accompanying Zip file includes several files: DomainLogicPatternsDatabase.sql should be run to set up the database. You need to configure the App.config to connect to the database.

The FowlerTransactionScript solution includes two projects (the DomainLogic project and a Console project). Domain Logic is based on the Java code that Fowler uses in the project to demonstrate a business tier construction. I added the interfaces to make things easier to understand. The Console project represents the UI Layer.

There are a couple of things to note:

  1. The UI layer references System.Data as the DataTable is the data structure used to hold data across layers. This is very close to a Table Module Pattern. Perhaps, he should have used a generic data structure to really show the difference?
  2. The business logic is implemented in the ReconignitionService.CalculateRevenueRecognitions function.
C#
datatable = gateway.FindContract(contractId);
decimal totalRevenue = Decimal.Parse(datatable.Rows[0][1].ToString());
DateTime recognitionDate = DateTime.Parse(datatable.Rows[0][2].ToString());
string contractType = datatable.Rows[0][5].ToString();
decimal revenuePiece = 0;

switch (contractType)
{
    case "S":
        revenuePiece = totalRevenue / 3;
        gateway.InsertRecognition(contractId, revenuePiece, recognitionDate);
        gateway.InsertRecognition(contractId, revenuePiece, recognitionDate.AddDays(60));
        gateway.InsertRecognition(contractId, revenuePiece, recognitionDate.AddDays(90));
        break;

    case "W":
        gateway.InsertRecognition(contractId, totalRevenue, recognitionDate);
        break;

    case "D":
        revenuePiece = totalRevenue / 3;
        gateway.InsertRecognition(contractId, revenuePiece, recognitionDate);
        gateway.InsertRecognition(contractId, revenuePiece, recognitionDate.AddDays(30));
        gateway.InsertRecognition(contractId, revenuePiece, recognitionDate.AddDays(60));
        break;

    default:
        break;
}

If this code was replaced with TSQL and placed in the database, the ReconignitionService.CalculateRevenueRecognitions would only be calling a Stored Procedure. I wonder if it is still a TransactionScript Pattern? On one hand, the interface did not change. But on the other, DomainLogic is a smack dab in the the data layer.

Domain Logic

The accompanying Zip file includes two projects - the Domain Logic Layer Project and the User Interface (Console) project. I did not hook up a database to this project. If you want to see how to do that, use the project found here.

The key classes in the Domain Logic are Product and Contract. Unfortunately, Fowler's code snippets are not correct and he does not present an entire solution so I had to cobble together some things to get to his intent. In this example, you create a product, then associate that product to one (or more) contracts and then calculate the recognition via the product. This seems counter-intuitive to me - I would assume that contracts would be responsible for calculating their own recognitions, but that is not how he set it up.

One other area where I differed from the book is around Recognition Strategies. He used an abstract class, I used an interface. Both gets you to the same place but as a general rule, Interfaces > abstract classes and tie goes to the runner.

Points of Interest

None.

History

  • Version 1.0 - 1/21/2009.
  • Version 2.0 - 2/03/2009
    • Added Domain Logic section

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)