Saturday, July 18, 2009

Just fix it!

It’s Saturday.  I just spent an hour and a half outside a Starbucks killing off open project items for an old client.  It was hot outside and the friendly folks enjoying their Saturday were starting to distract me… so now I’m at the library.

I like developing software – even on Saturday.  There are other things I like doing more (especially on Saturday, especially if it involves my wife and kids.)  Developing software isn’t the worst thing I could be doing, but this particular software is trying my patience.

This software is a giant beast of business critical software that people are counting on.  It needs to be functional soon so the legacy system can rest in peace.  This software project put me out of business (I guess that’s not totally fair… my 5-year-ago self’s lack of project management skills did me in – but this software is the blob in front of me that points that out.)

Why am I writing about this instead of “Just fixing it”?  Good question.  Answer: I don’t know how to fix a lot of the open items that are left.  The original requirements analyst did not give me a good set of requirements explaining how the system should work (btw, I was the original analyst.  And developer.  And accountant.  And salesman…)

Now there, I got that off my chest and onto the internet – I feel much better.  Now, back to work… This is not an intractable problem, but I can’t program my way out of this one without some help.

Some software problems are easy to solve.  For example: “The feature rate isn’t getting populated when I add a feature to the rental agreement.”  I can fix that.

Some problems are harder, even impossible, without a better story behind them.  For example: “The rental agreements are billing 10 days”.  I can’t just fix that.  I get the implication here… rental agreements should not always “bill 10 days”.  How should they bill?  Are there some cases where 10 days is appropriate?  The questions go on and on…

This is not at all meant to belittle the user who reported this issue.  He saw something wrong and reported it, nothing wrong with that.  My point is that I have a lot of non-programming work to do before I can begin to solve such a problem.  I need to expand this user’s ~10 word problem report into a series of stories that look like this:

“When a user does X, the software should respond with Y.”

A more specific, contrived example: “When a rental agreement is created with Usage type D, it should use the Daily Rate and should not be included in the ready to Invoice List until the next Friday after it was created.”

Once I have a complete set of those, then I can fix it.  Since I’m a proactive kind of guy, I’ll spend this Saturday expanding this one issue into lots and lots of short phrases (user stories) like the one above.  It isn’t the most satisfying work… especially since it will probably take a while for my client to confirm, deny or expand my list of stories.  But c'est la vie…

Thursday, June 11, 2009

Side by side code: Classic ADO.Net and the NHibernate ORM

This post continues my “NCharlie” post series, in which I take Agile methods/technologies I picked up at a .Net Bootcamp in Austin back to work. My intended audience is my future self (reference) and my coworkers – we write custom business apps using .Net 2.0 webforms backed by SQL Server.

Currently our team maintains lots of SQL stored procedures per application. As our lead developer I would like to lead the team in a new direction that doesn’t include all these sprocs. The benefits of such a move are numerous and well-stated (edited, updated incorrect link) by people much smarter and more experienced than me. But for us, the immediate value would be:

1) Less code to maintain (yes, Transact-SQL is code).

2) Persistence ignorance, resulting in code that is more testable and easier to create, understand later, and fix if needed. An SQL stored procedure is a terrible place for business logic to reside (hard to test, hard to find)… removing the temptation to put it there is a hidden benefit.

3) Faster development cycles. We’ve built this CRUD over and over again so many times. Let’s be pragmatic and stop repeating ourselves. Even with code generators the CRUD procedures and data access layers are a painful part of our projects we shouldn’t be worrying about.

I could probably go on… instead I’ll jump into an example. You can find this type of example code in many other places, I’m not reinventing anything here. Hopefully this side by side format will help someone else out there move on from writing the type of data access code I’ve been writing for too many years now.

First up let’s knock the “C” off the classic ADO.Net CRUD. “C” is for create, and I want to create a record in my database that corresponds to an entity class in my application I’ve populated with data. The entity may have been populated by taking a user’s inputs on a web form and mapping them to the entity’s properties… it doesn’t matter where I got the data – I’m concentrating now on persisting it to the datastore. Here are the steps involved in such a task:

1) Write a stored procedure that takes input parameters corresponding to the entity properties I want to save, executes an INSERT statement against the proper table, and returns an identifier for the new record. (note: we use a code generator against a database table to create this procedure)

CREATE PROCEDURE [dbo].[InsertTask]
@Description varchar(500),
@Submitted datetime,
@SubmittedBy varchar(50),
@Closed datetime,
@ClosedBy varchar(50),
@Priority int,
@AssignedTo varchar(50)
AS

INSERT INTO
[dbo].[wdtasks_Tasks] (
[Description],
[Submitted],
[SubmittedBy],
[Closed],
[ClosedBy],
[Priority],
[AssignedTo]
) VALUES (
@Description,
@Submitted,
@SubmittedBy,
@Closed,
@ClosedBy,
@Priority,
@AssignedTo
)

SELECT SCOPE_IDENTITY()



2) We use a data helper class (cleverly named DataHelper) to instantiate a connection object and an ADO.Net command object. Then we build up the input parameters and execute a stored procedure.



string cn = ConfigurationManager.AppSettings.Get("dbConnection_Tasks");


SqlParameter[] aParams = new SqlParameter[7];
aParams[0] = new SqlParameter("@Description", SqlDbType.VarChar);
aParams[0].Value = Null.GetNull(oEntity.Description);
aParams[1] = new SqlParameter("@Submitted", SqlDbType.DateTime);
aParams[1].Value = Null.GetNull(oEntity.Submitted);
aParams[2] = new SqlParameter("@SubmittedBy", SqlDbType.VarChar);
aParams[2].Value = Null.GetNull(oEntity.SubmittedBy);
aParams[3] = new SqlParameter("@Closed", SqlDbType.DateTime);
aParams[3].Value = Null.GetNull(oEntity.Closed);
aParams[4] = new SqlParameter("@ClosedBy", SqlDbType.VarChar);
aParams[4].Value = Null.GetNull(oEntity.ClosedBy);
aParams[5] = new SqlParameter("@Priority", SqlDbType.Int);
aParams[5].Value = Null.GetNull(oEntity.Priority);
aParams[6] = new SqlParameter("@AssignedTo", SqlDbType.VarChar);
aParams[6].Value = Null.GetNull(oEntity.AssignedTo);




return int.Parse(DataHelper.ExecuteProcedureScalar(cn, "InsertTask", aParams).ToString());



After executing the command, we receive a scalar value (the new record identifier) in return. Then we dispose of the command object and close the connection. (note: our DataHelper class handles the repetitive code here too.)



Wow, that wasn’t so bad huh? Code generation and that DataHelper really helps! It is a good thing it does too, because those 5 steps have to be repeated over, and over, ad nauseam, for ALL the entities that need to be persisted to the database.



Object Relational Mapping to the rescue… let’s perform that same task (saving our entity to the database) using NHibernate:



1) Create an XML mapping file for the entity.



<?xml version="1.0" encoding="utf-8" ?>
<
hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NCharlie.Core"
namespace="NCharlie.Core.Domain.Model">

<
class name="Task">

<
id name="ID" column="ID" type="Guid">
<
generator class="guid.comb"/>
</
id>

<
property name="Description" />

<
bag name="Tags" access="field.camelcase-underscore" cascade="all-delete-orphan" >
<
key column="Task_ID" />
<
one-to-many class="Tag" />
</
bag>

</
class>

</
hibernate-mapping>



2) Call the “SaveOrUpdate” method.



using (ISession session = GetSession())
using (ITransaction tx = session.BeginTransaction())
{
session.SaveOrUpdate(entity);
tx.Commit();
}


Some of you may be looking at that mapping file and thinking I bumped my head… kind of seems like I’m introducing more complexity if you are used to plain old SQL. And I am. But it is a good tradeoff… because once you get that mapping file done, you also get the RUD parts of CRUD for free, as well as a ton of other NHibernate features (including custom queries, paging…) The other methods (to round out the CRUD feature) are “List”, “Get” and “Delete”.



The code in step 2 above, the code using the NHibernate ORM, is actually really nice and simple to use once you get used to it. You can see it in action in the NCharlie example project… and if you work with me, you’ll see it in the near future in the prototype stage of one of our next projects :)

Geo Tracks – 2009 May 30

(published this a bit after the fact… big deadline at work was cramping my style!)

Elegant Code Cast 23 – Jeremy Miller on the StructureMap IOC tool for .Net, FubuMVC, JQuery, etc.  I’m not a big IOC user (or understander, for that matter)… but I’ll file this away for the future – Jeremy states that an IOC tool helps us construct applications using composition of objects vs. inheritance.

Hanselminutes 162 – Powershell 2.0.  I love my command shell in Windows XP… and it sounds like Powershell, which is built in to Windows 7, is definitely something to learn at some point.

StackOverflow Podcast #54 – Bespoke software development (a.k.a. bidding for jobs vs. creating a new product), the “God” algorithm (the one that just knows the correct answer in one operation), URL routing (and the snafus available when URLs conflict with data… eg. a user with username “username”).

God is Strong, Am I? – Francis Chan from May 10, 2009.  Let’s live by the Spirit people… why do we go through life afraid or weak or ambivalent when the One who made everything dwells in us?

Saturday, May 23, 2009

Revving up the TDD engine

tach

I’m still in the early stages of writing unit tests at work… but I did commit 26 passing tests to source control this afternoon!  The pain is fading, I’m gaining confidence and speed and I’m getting excited about the number of tests I’ve written.  We’re no mature TDD shop yet, but it is an enjoyable stage when the shiny new unit tests still make us go “ah”.

In this post I’ll finish out the TDD section of my NCharlie project series by walking through some code that tests the interaction between a controller and view.  It includes using Rhino Mocks to raise an event and verify that the controller calls the correct method on the view in response.  I know in my last post I practically gave up on Rhino Mocks in favor of writing my own mock classes and methods… well, I changed my mind.  RM is a great tool, and I’m getting used to the syntax required for .Net 2.0 projects.  So here goes…

search-results

I want to test the behavior when a user clicks one of the “[show]” links in the Task Search results list.  The application should show the Task Detail view when this happens:

task-detail

So I’ll name my test accordingly:

[Test]
public void Should_call_show_task_when_task_selected_event_is_raised()
{
}


Before I start into the body of this test method, there is some setup code that I need to get in place:



[TestFixture]
public class TaskManagerControllerTests
{
MockRepository mocks;
ITaskManagerView viewMock;
ITaskRepository repository;

[SetUp]
public void SetUp()
{
mocks = new MockRepository();
viewMock = mocks.DynamicMock<ITaskManagerView>();
repository = mocks.CreateMock<ITaskRepository>();
}



The mock view will allow me to test my controller code without needing to have a view implementation (ASPX page) wired up and working first.  First I arrange the needed elements for the test by creating the event arguments object that will be passed with the event and an event raiser named “clickEvent”:



[Test]
public void Should_call_show_task_when_task_selected_event_is_raised()
{
string taskID = "12345678-1234-1234-1234-123456789012";
TaskSelectedEventArgs e = new TaskSelectedEventArgs(taskID);

IEventRaiser clickEvent = Expect
.Call(delegate { viewMock.TaskSelected += null; })
.IgnoreArguments()
.GetEventRaiser();



Next I use the Rhino mocks “Expect.Call” method to state that I expect the view’s “ShowTask” method to be called with with my test task ID as the parameter.  The expectations are finished with a call to the R.M. “ReplayAll” method:



[Test]
public void Should_call_show_task_when_task_selected_event_is_raised()
{
string taskID = "12345678-1234-1234-1234-123456789012";
TaskSelectedEventArgs e = new TaskSelectedEventArgs(taskID);

IEventRaiser clickEvent = Expect
.Call(delegate { viewMock.TaskSelected += null; })
.IgnoreArguments()
.GetEventRaiser();

Expect.Call(delegate { viewMock.ShowTask(e.TaskID); })
.Repeat.Once();
mocks.ReplayAll();
}



Finally, I execute the code that will test this behavior… I instantiate a new TaskManagerController (this happens when the view is created) and raise the click event.  The R.M. “VerifyAll” method verifies that all my expectations are met when the code executed:



[Test]
public void Should_call_show_task_when_task_selected_event_is_raised()
{
string taskID = "12345678-1234-1234-1234-123456789012";
TaskSelectedEventArgs e = new TaskSelectedEventArgs(taskID);

IEventRaiser clickEvent = Expect
.Call(delegate { viewMock.TaskSelected += null; })
.IgnoreArguments()
.GetEventRaiser();

Expect.Call(delegate { viewMock.ShowTask(e.TaskID); })
.Repeat.Once();
mocks.ReplayAll();

new TaskManagerController(viewMock, repository);
clickEvent.Raise(null, e);
mocks.VerifyAll();
}


That’s it.  The code to make it pass is painfully simple (painful because the code to test it is so much longer… I’m getting less and less offended by this state of affairs though, since the tests look like this for complicated code under test as well.  Besides, these tests copy and paste very easily!)  Here is the code from the controller under test:



private void OnTaskSelected(object sender, TaskSelectedEventArgs e)
{
view.ShowTask(e.TaskID);
}


And that makes it pass:



tests-passed



 



 

Thursday, May 14, 2009

Do we have time to write tests on our projects?

This is a question I would like to answer in the context of my day job.  It came up again today as I was talking with the other developers about some of the “new methods” I would like to integrate into our development process.  The title of this post is how the question sounds now in my head.  This afternoon it went more like this: “We don’t have time to write tests on our projects!”

Granted the developer who made this statement is a big believer in the “speak first, reason it out later” method of communicating… this is his knee-jerk reaction to someone telling him we would write more code for the same functionality.  I can sympathize with him… we have deadlines on our projects to meet.  But I don’t agree with him.  I’ve already written some tests at work to solve a problem in the business logic of software we released 2 months ago.  The exercise helped me find other problems in that code and refactor it to a state that will be much easier to maintain.  Do we have time to maintain legacy code that is hard to understand and has no tests written against it?  I don’t.

But… even though I am convinced we need to write tests, I want to be practical.  Will my team benefit from this?  Are there certain types of developers or certain types of projects that will never see the benefit of writing tests against code?  Maybe so – but I hope that isn’t a description of the team I work with.  And I think the best way to find out is to do the best I can to set us up for success.  That is a big reason I am writing about my experience building up the NCharlie project.  I have some work to do before we are there though.  As I mentioned before, TDD still feels like a pain point for me because of the way my tests look using Rhino Mocks to mock objects like the database access code.  When I mentioned this pain point to my boot-camp instructor his advice was to “abandon ship”… not on TDD, but on the Rhino Mocks Expect-Replay-Verify model and use the easier to understand Arrange-Act-Assert model of testing (I know AAA is possible with Rhino Mocks… but not with nice syntax in .Net 2.0).

So, I am going to follow my instructor’s advice and abandon ship.  I’m going to start writing tests without a mocking framework.  I can create a class quickly that mocks a database access class without using Rhino Mocks.  Sure it will be a bit more code to write, but I think the clarity it will bring to the tests will be worth it.  I also think it will be a good exercise even if I do end up coming back to a mocking framework like Rhino Mocks… I will appreciate it more after manually building mock objects.

This means I am going to stay on the topic of writing tests for at least one more post.  Earlier in this series I wrote some tests to verify that the controller class for the Task Search page in the NCharlie project was correctly responding to events raised in the view.  I didn’t show the code for the test in the post (it was available in the code repository) because I did not want to distract from the intent of that post.  Now it is time to show that code… almost (actually, in the next post).  First, let me answer the question I posed in the title of this post:

Yes, we do have time.  It will make us go faster because our code will end up being easier to work in now, and easier to extend or fix later.

Tuesday, May 5, 2009

TDD Pain Points, A Retrospective

This is the fourth weekend into writing about test driven development… taking agile methods I learned in boot-camp back to work.  Time for a retrospective…

First I will say that writing about this process has been a tremendous help in making these concepts gel.  Try teaching someone about something you are trying to learn.  I don’t care if no one ever reads these posts – the process of writing them has been invaluable to me.

Now, for the pain points:

Supervising controller:

I chose this pattern (a flavor of Model-View-Presenter) for two reasons.  1) We use .Net 2.0 at work and our developers have a lot invested in webforms.  2) It helps me separate functionality away from code-behind files and adhere to the Single Responsibility Principle, which is especially important if the code will be tested.

I like most of the Supervising Controller pattern in the context of webforms.  What I don’t like (pain point) is the "loop" of event handling: view fires event, then raises another event that the controller is subscribed to, then the controller responds by executing some logic and then calling a function back in the view to render results.  This is convoluted... I like the separation of concerns, but I don't like having to subscribe to events more than once.  Can I just call controller methods directly from the view?  Maybe what I'm describing is called the "Passive Controller"... I need to look into it.  This is really, probably, a pain point that should be attributed to webform development.  But hey, webforms pay the bills!

TDD:

Yes, as of now I’m listing Test Driven Development as a pain point.  I really like testing my code.  I don't really like the syntax I'm using to mock functionality.  Mocking my dependencies is necessary to write unit tests, but the Record, Replay, Verify syntax in Rhino Mocks is not natural for me to set up and harder to explain to my team.  I am still trying to shove the Rhino Mocks 3.3 RRV syntax into the Arrange, Act, Assert (AAA) method I learned in boot-camp.  I need to change the way I'm using Rhino Mocks, or I need to start using a different mocking framework (Rhino Mocks supports the AAA syntax and is explained really well... Using .net 3.x lamba expressions.  AAA is possible with Rhino Mocks, but the 2.0 syntax is painful.

That’s it for pain points for now.  These by no means mean I am giving up on TDD or Supervising Controller.  Although painful right now, I think these are birth-pangs… I am hopeful that in 2 or 3 months they will be big giant assets in my toolbox.  I’ll end now on a (what is the opposite of a pain point?) happy point: Resharper 4.5 is incredible.  It makes me go faster… I intend to dedicate a future post to my top X favorite features.

<< NCharlie: TDD – Part 3 (a UI test)

Geo Tracks – 2009 May Cinco

I’m a little late this week because we moved last weekend.  Now I am closer to work (cut 2 hours per day off the commute!)… which means less time with the podcasts and more time with the family – a nice trade I think.  I’m still listening to book one in the Wheel of Time series, and will be for while.