« Home | Expense Calculator - Session 4 » | Expense Calculator - Session 3 » | Expense Calculator - Session 2 » | Expense Calculator - Session 1 » | Expense Calculator Started » | Hibernate Mappings & Encapsulated Collections » | My Desk » | Using Agile Practices » | Automated Tests are Great » | Changing Mindset »

Expense Calculator - Session 5

Now having implemented 4 requirements I come on to the next one:

Requirement 5: Generate an expense statement for a payer for a date range.

Say for bhavdeep for 1 Apr to 30 Apr 2005 genrate an expense statement should look like this:

Bhavdeep
1 Apr 2005 to 30 Apr 2005

Bhavdeep receive from Surender 13 USD
Bhavdeep receive from Deepak 5 USD

2 Apr 2005 Albertsons Deepak 12 USD
7 Apr 2005CostCo Surender 5 USD
16 Apr 2005 Burger King Deepak -7USD
28 Apr 2005 Panda Express Surender 8 USD

Thus we see a header with name, date range for statement, summary, and details.

I write a unit test, it fails, then i go on to implement it and it passes. Same old style by now.
But while implementing I am not able to come up with the right interface. I maintain a party message : getExpenseSheet(list transactions) and on expense sheet i supply party and date range as attributes to genrate statement. Is this the right way?Somehow I think not. I would like a party interface to which i can ask..getStatemetn(DateRange range). But then for that Pary would need to somehow get to the db and get list of transactions. So pary now talks to DB interafaces (not that i have any by now). But it would right. I dont like this coupling.

I stop. I rethink.I see what the user of this domain package would be comfortable with. UI and domain intermediate layer would speak to domain layer. Now this layer would also access facades that can let it speak to db layer. So I think..Party or for that matter any domain object should just have responsibilities. It must not know about the external world of db, ui et al.

So I come up with facades package. Primarily TransactionFacade that accepts a TransactionDao and gets me the list of transactiosn for date range. in my junit test case which i now re-write i use stubtransctiondao (not mock) and it returns me some canned transaction data. Good enough.

Now my test flow looks like this:
facade gets me list of trasnactions.
i ask party to get expensestatmetn for this set of trasnactions.

Simple this is . way better than my ugly looking test. also Party doesnt know where it got thsi set from (and rightly so). Now i look at expense sheet which does the bulk of printing. and its go t ugly. I see all this printing business requires a set of summary lines. I rightly move this code into an Extraced ExpenseStatement class. Now code looks cleaner.

Now i move on to my next requirement : Expense statement for a transaction.

Hmm.simple it looks. But when i see the structure of transaction expense statement i see it would have no details. Just trx name, date, payer, receivers and summary lines.

Now i look at expense statemnt class. I see a herirachy. one for party and other for transaction. I first refactor expensestatement into expensestatemetna and its child partystatement class.
Then i add the transcationstatement functionality.

Also my party interface looks like this: getExpenseStatemetn(DateRange, List trasnactons). You may ask why both?

First it lets me keep Party independent of calls to another layer such as persistence layer. Next daterange is required when printing the statement. AS of now this is good enough. Aslo that way i dont expose classes such as ExpenseStatement, ExpesneLine to the world outside domain package because they must not know about it. Lesser you expose better for your neighbors !!!!

Finally my class diagram looks like this:

A few observations on this class diagram:

  1. Party Expense Statement and Transaction Expense Statement are bit more coupled. Time to look up the GoF catalog probably :-). But for now lets wait.
  2. I can also probably have expensesheet heirarchy but that may lead to parellel class heirarchies. I need to evaluate.
  3. I need to do check my test coverage and make it more solid. Thats surely my next task.
  4. Also as of now I have the facility to handle transactions where payer has a share in expenses and doesnt have a share. When I think about those situations where part of expesnes are shared and part are not I realize the same classes do the trick. Basically I need to come up with a stable transction definition:
Transaction : is where there is only payer and there is only one amt. So a trx where total amt is 60$ but 40$ are shared equally but remaining 20$ are not is actually made up of 2 transactions: (assuming one payer of course): 40$ trx and 20$ trx. That gives me relief. At times simple thoughts do the trick .

My domain vocab looks like this;

Party: participates in transaction as payer or receiver
Transaction: has one party (payer), one amt and one or more receivers.
Distribution: Transaction amt is shared equally including payer (Equitable with Payer) or shared equally without the payer (Equitable without Payer)

So the above and money, daterange classes are what my domain package exposes to the outer world and thats fine enough. Always give a great thought to what you must keep public, private, friendly et al. Its important. Start by being stingy and then become moderate if reqd. Because other way is almost impossible always especially when your clients start going out of your control boundaries.

Posted by Hello