Fair Housing for Business Rules
I was talking with someone about the reasons javascript is viewed by so many as something to be avoided. He suggested that he didn't want business rules expressed in different places (i.e. the server side code and the client side code). Similarly, in a recent thread on the TDD list it was suggested that stored procedures feel like a code smell because they are black boxes to the application coder and make writing code in an agile way more challenging.
Neither of these were isolated. I hear complaints about both javascript and stored procedures all the time, and for similar reasons: they are hard to maintain and they spread business rules throughout different execution environments.
I think the maintenance issues are more about tools. JSUnit is a wonderful xUnit tool that lets you write unit tests for your javascript and then execute those tests from your ant scripts (if you happen to be using ant). But it has not reached wide acceptance yet probably because of javascript-phobia. Ironic that a potential solution to a problem isn't recognized as such because of the problem itself.
Stored procedures remain difficult to maintain, but that's because vendors haven't recognized the need for tools that can hook into the "units" of a stored procedure so we can unit test them. So we can only really system test them through the exposed entry and exit points. Maybe there are such tools and I just don't know about them. If so, please add a comment below so we can all check them out.
But all of this still leaves open the issue of where to express business rules. We don't want to express them in different execution environments because they become difficult to synchronize. If you're writing a webapp and you want to use client side validation, you probably want to back it up with server side validation. Maybe you're using a tool that does this for you, but you still want to verify that you've configured everything correctly and you still have to synchronize the implementations. Or do you?
In TDD, we talk about requirements being expressed in the tests. Well, aren't business rules requirements? And aren't they therefore expressed in the tests? So what if we could write one test that tested both our server side and client side validation. We do something similar with abstractions in junit already. We write an AbstractWidgetTest and derive ConcreteWidgetATest and ConcreteWidgetBTest to test our classes derived from AbstractWidget. Methods in AbstractWidget are tested in AbstractWidgetTest, and those tests get executed by both derived test classes against the derived application classes.
The problem we face is not that we want to implement solutions in a variety of execution environments. The problem is that we want to test them in the execution environments in which they are written! We test java using JUnit. We test C# using NUnit. We test javascript using JSUnit. Perhaps someone has alredy invented SPUnit ("spoon it"?) for testing stored procedures.
What might be needed here is a language/environment independent testing system in which we can express our business rules all in one place and execute those tests against whatever environments our solutions are being written in. FitNesse accomplishes this at some level, but it doesn't get us all the way there because we lose the beautiful feedback we get from code editors like those in IntelliJ[?], Eclipse and dare I say Visual Studio. If I write a statement in my junit test that calls a method that doesn't exist on another class, I get immediate feedback because code is getting compiled on the fly. Fitnesse isn't capable of this yet. And it would take some doing to write a tool that could give me the same feedback if I were writing a test in java, but testing something in javascript.
In some sense, test-infected code has moved us away from "the best tool for the job" because the definition of "the best tool" has grown from "the most efficient tool" to "the most testable, understandable, maintainable and efficient tool." Having tools that could give us the feedback we have grown accustomed to from xUnit tools while freeing us up to use whatever tools we wish for solutions would open all sorts of new doors for us. Well, maybe just reopening some of the old doors would be a good start.
!commentForm
Hi,
I did try some unit testing for stored procedures. It is mainly a matter of separating concerns in the code :
For instance, have a stored procedure call another to fill in inputs, one to perform the calculation, and a third one to save the data.
The point here is that using several stored proc to get the job done can bring on "the seams (Working Effectively With Legacy Code)". Ok, the targeted database still needs to be up and available to make those test but it's one way to database business rules testing.
I did try some unit testing for stored procedures. It is mainly a matter of separating concerns in the code :
For instance, have a stored procedure call another to fill in inputs, one to perform the calculation, and a third one to save the data.
The point here is that using several stored proc to get the job done can bring on "the seams (Working Effectively With Legacy Code)". Ok, the targeted database still needs to be up and available to make those test but it's one way to database business rules testing.
One package that I have used for unit testing stored procedures under Oracle is utPLSQL
(find it at utplsql.sourceforge.net). I've found that stored procedures tend to be more
'procedural' (hence the name) and options that you may have in an OO language (e.g. using
Mock Objects) are not available. Still, if you do have to write Oracle stored procedures, it's
pretty useful.
(find it at utplsql.sourceforge.net). I've found that stored procedures tend to be more
'procedural' (hence the name) and options that you may have in an OO language (e.g. using
Mock Objects) are not available. Still, if you do have to write Oracle stored procedures, it's
pretty useful.
How right you are! William Caputo (from ThoughtWorks[?]) started this project, which is for SQL Server Stored Procedures. I've never used SPUnit so I can't speak to its efficacy, but here it is: http://spunit.sourceforge.net/
It will be interesting to see how Microsoft reconciles this issue in Sql Server 2005 (which will most likely be delivered sometime in 2008) ;)
It will be interesting to see how Microsoft reconciles this issue in Sql Server 2005 (which will most likely be delivered sometime in 2008) ;)
Databases change. UI change. Sure, you can probably test javascript and stores procedures quite well. But what do you do a year later when you have to swtich from Oracle to MySQL? What do you do when you need to switch from a browser based to web serveice based user interface? You have to rewrite all the business rules that were expressed in javascript and stored procedures. If all the business rules were expressed in Java or C# then this wouldn't be a problem.
By expressing business rules in different technologies, you are vulnerable to change, which is inevitable.
By expressing business rules in different technologies, you are vulnerable to change, which is inevitable.
I agree that change is inevitable and that you have to rewrite the implementations when you switch technologies. But that reality also places a burden on us. If we live by that as a restriction, then we are stuck writing every aspect of every application in only one technology - or at least in only one platform.
The point I'm trying to make is about where we think of the business rules as being expressed. Are they in the code? Or are they in the tests? If we think of them as being expressed in the tests and we have a useful way of talking to any technology from our tests, then we've got a ready made test harness for our database switch.
We already do things like this. In the diagram above, I was talking about classes, but what if those were Data Access Objects?
If we want to add a SqlServerThingDao we just add a SqlServerThingDaoTest and off we go. All of the tests are expressed in the AbstractThingDaoTest. Now we just have to make them pass.
Same with UI. If we decide to go from JSP to ASP.NET to PHP to CFM to whatever presentation technology we want, the only thing that our HtmlFixture tests need to change is configuration.
I'm just talking about extending that to where the tests themselves are actually expressed in one place that is able to "talk" to multiple technologies. That frees us up to use the right tool for the job based on our newer, test-infected definition: testable, understandable, maintainable and efficient.
The point I'm trying to make is about where we think of the business rules as being expressed. Are they in the code? Or are they in the tests? If we think of them as being expressed in the tests and we have a useful way of talking to any technology from our tests, then we've got a ready made test harness for our database switch.
We already do things like this. In the diagram above, I was talking about classes, but what if those were Data Access Objects?
If we want to add a SqlServerThingDao we just add a SqlServerThingDaoTest and off we go. All of the tests are expressed in the AbstractThingDaoTest. Now we just have to make them pass.
Same with UI. If we decide to go from JSP to ASP.NET to PHP to CFM to whatever presentation technology we want, the only thing that our HtmlFixture tests need to change is configuration.
I'm just talking about extending that to where the tests themselves are actually expressed in one place that is able to "talk" to multiple technologies. That frees us up to use the right tool for the job based on our newer, test-infected definition: testable, understandable, maintainable and efficient.
I agree with you in principle, Micah. Certainly when starting a green-field project, endeavouring to seperate out business
rules into their own tier in Java / C# / your preferred language is a good thing.
But take the project I've currently ended up with (please) - a two tier legacy application, ASP front-end with Oracle stored
procedure back-end.
In order to start adding automated unit tests to this application, it has to be done with the technology specific unit
test framework (in this case utPLSQL). But long term - how could it be transitioned to non-legacy code? (in Michael
Feather's usage of the phrase). A complete rewrite would perhaps be rather drastic and impractical.
If there were some mechanism to maintain tests of business rules in one technology, this would help to enable a larger
scale refactoring across technologies that would possibly be needed on this code base.
rules into their own tier in Java / C# / your preferred language is a good thing.
But take the project I've currently ended up with (please) - a two tier legacy application, ASP front-end with Oracle stored
procedure back-end.
In order to start adding automated unit tests to this application, it has to be done with the technology specific unit
test framework (in this case utPLSQL). But long term - how could it be transitioned to non-legacy code? (in Michael
Feather's usage of the phrase). A complete rewrite would perhaps be rather drastic and impractical.
If there were some mechanism to maintain tests of business rules in one technology, this would help to enable a larger
scale refactoring across technologies that would possibly be needed on this code base.
Add Child Page to FairHousingForBusinessRules