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:
- 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? - The business logic is implemented in the
ReconignitionService.CalculateRevenueRecognitions
function.
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
Jamie Dixon has been writing code for as long as he can remember and has been getting paid to do it since 1995. He was using C#and javascript almost exclusively until discovering F# and now combines all three languages for the problem at hand. He has a passion for discovering overlooked gems in data sets and merging software engineering techniques to scientific computing. When he codes for fun, he spends his time using Phidgets, Netduinos, and Raspberry Pis or spending time in Kaggle competitions using F# or R.
Jamie has a BSCS in Computer Science and a Masters in Public Health. He is the former Chair of his town's Information Services Advisory Board and is an outspoken advocate for Open Data. He also is involved with his local .NET User Group (TRINUG) with an emphasis on data analytics, machine learning, and the internet of things (IoT). He is the author of Mastering .NET Machine Learning,
Jamie lives in Cary, North Carolina with his wonderful wife Jill and their three awesome children: Sonoma, Sawyer, and Sloan. He blogs at jamessdixon.wordpress.com and can be found on Twitter @jamie_dixon