Sunday, March 13, 2011

Intense TDD Focus Not So Healthy?

I believe in the value a TDD/BDD approach yields. However, I have seen great software produced with no unit tests at all and really poor code produced with lots of tests.

TDD is one perspective of many that affect the outcome of the quality of your software, so for some time now, I have been a little bewildered by the somewhat over-the-top hype surrounding TDD.

Now I have finally figured out what it is that bugs me so much about the current trend of TDD/BDD hysteria.

During the design process, I think about the various alternatives - at varying levels of abstraction - weigh up their pros and cons, discuss with the team and consider the impact on the overall architecure.

Sometimes, working with pro-TDD people, I find that I am under pressure to make key design decisions as quick as a keystroke, because I cannot have a failing test for more than a few minutes - right? I am given very little think time. Which is what I feel great design is all about - thinking!

TDD provides a great perspective on micro level design, and provides us with a more solid API with the focus on test/specification as a client of the code under test. Even so, I still think there is a tendency to proceed a little too quickly at the cost of considering the alternatives, but sometimes at this level of abstraction, the building blocks are smaller and so there is less to keep in the brain at once.

At the macro level though, we often want consider the various responsibilities, whether things fit neatly within the existing architectural and design constraints and mechanisms and put more of a focus on the non-functionals as well.

Which is more important? This has been the focus of argument between the design/architecture and programmer/developer communities for some time. My feeling is that they are equally important. What's more, there is no artificial dividing line between architecure and code, there is a single continuum and great developers and architects constantly think and adapt along the continuum. There is effectively no difference between great developers and great software architects. Others remain stuck, constrained at the specific levels of abstraction about which they care.

Sunday, July 11, 2010

C# TDD with Visual Studio

I have been working with C# in the .NET world for a while now, but I can't help being puzzled by something. There are plenty of tools around that help the developer to work with Visual Studio, but in a test driven environment, the cycle seems far too slow and painful to be of value. Trying to drive development with tests is almost not worth it - by the time the test has run, its been such a long time, I've almost forgotten my ideas or train of thought. But then again - maybe its just my age!

Are there any tricks I am missing out on? Are there language or tool constraints? Working with Java on Eclipse is quick and relatively easy - working in Ruby it's a breeze - so in these environments, its really fun. However, I do believe that without certain support from the language and toolsets, blind adoption of certain (mostly useful and powerful) techniques is actually counterproductive.

Any thoughts or ideas welcome.

Sunday, December 6, 2009

Design By Contract

Wanted to post on this subject for some time. There is a general lack of awareness of this powerful concept which is one of most profound ideas the professional developer can embrace along with sound object oriented principles. Next time you see a really clean piece of code - look carefully and you will probably notice DbC in action.

To start off this post, I will attempt to briefly talk about defensive programming, the antithesis of professional software development. At college along with most other computer science folk, I was taught how important it was to program defensively. This means that if a parameter can be null, then it needs to be checked to ensure that condition otherwise the program could fail. In the case of the following example, if ToUpper message is invoked on the string object and the string is nil, then what happen to the code - typically it will crash but that depends on the language.

string Convert(String str) {
// This would crash if str is NULL
if (str.ToUpper() == "XYZ")
return;
...
}


So to counter this, developers typically do the following -
string Convert(String str) {
if (str == null)
throw Exception("bad string parameter");

if (str.ToUpper() == "XYZ")
return;
...
}


To the best of my knowledge, it was "Bertrand Meyer" who formally introduced the software development community to the idea of design by contract and published it in his book "Object-Oriented Software Construction". There is an entire lengthy chapter dedicated to the subject, so I will try my best to paraphrase.

Code written to perform run time checks on parameters is unnecessary and more dangerous than the very issues it attempts to prevent. It leads to duplication with the same values being checked multiple times in different methods, it adds to cyclomatic complexity to the program which in turn decreases reliability, readability and comprehension.

Meyer - In relations between people or companies, a contract is a written document that
serves to clarify the terms of a relationship. It is really surprising that in software, where
precision is so important and ambiguity so risky, this idea has taken so long to impose
itself.


To achieve reliability and hence quality, simplicity is crucial. If there are one or two of these 'null' checks across thousands of methods in a system, then the overall complexity of the system has been increased massively. with thousands of new potential failure points being introduced.

So, in essence, design by contract says, do not be concerned with performing validity checks at the beginning of a method (the most common example being to check an object reference for null), rather let the caller know that your method expects a valid object. If the caller sends the message to Convert with a null parameter, the client is at fault, not your program! Remember that this is a contract and the customer is involved just like any other type of contract. This may seem like a simple statement, but at the most basic level, it's pretty much all there is to know. Its implications though are huge.

Looking at the earlier example in a new light -
string Convert(String str) {
if (str.ToUpper() == "XYZ") // This will still crash if str is NULL
return; // - caller is the problem, our program
... // expects a valid string object.
}


Several points on this. Applying this style tends to push validation code as high up in the system as it can reach
- don't allow bad data into your system in the first place
- don't pass null values around
- don't allow users to select invalid values

If there is a case where processing can happen without that object being present, overload the method and write one that doesn't require that object.

Non-Redundancy Principle.


"Under no circumstances should the body of a routine ever test for the routine's precondition."

In the following example, the difficulty arises with the error handling step. What is it that needs to happen - only the client knows and typically the client would have to either handle an exception or check for an error result anyway. DbC says, why not just state the contract that 'p' is required to be valid and then the checking can be done one time, by the caller, before it even reaches our code.

if (p == NULL) then
Error handling, logging, exception ...
else
do something with p ...
end


Tolerant or Demanding Preconditions.


There are two ways to view preconditions, one way is tolerant of any customer calling on them, and will try to guess at the right way to behave when unexpected input occurs. The alternative demands that input criteria are met by the customer and therefore does not need to guess at what to do with incorrect input.
It is the client who knows what to do when there is not enough information to supply the correct inputs to us and what it really means. If we are trying to decide how to handle a null reference, do we log, raise an exception, ignore the issue or what?

Sidenote on complexity


In 1976 Thomas McCabe formalized a software metric called cyclomatic complexity. Basically, it counts the edges and nodes of a control flow graph through source code with any condition (if/then/else/switch) or iteration (for/do/while/iterate) counting as additional complexity. I don't want to go into the details of this so check out Wikipedia for a more complete explanation.

Unlike this post, Meyer's chapter on Design By Contract is very detailed and I recommend you read it with an open mind. Contrary to popular belief the DbC mindset makes complete sense if a little thought is applied. You have a choice - try to recover from bad things, or don't allow bad things to occur. Hope I have managed to invoke a little interest.

Friday, December 4, 2009

Getting Started with Cappuccino

Downloading


So you can get a prepackaged version of the code from the Cappuccino Download Page and grab the latest Cappuccino Tools zip file. Alternatively, you can use -

git clone git://github.com/280north/cappuccino.git

I recommend using github which will give you everything you'll need. While I appreciate all the hard work thus far on Cappuccino, it is a beta and as such a little patience is required.

Once you have the code there seems to be two ways to get going with a project.
1. Download the Cappuccino Starter zip (on the same download page) which contains a standard application that you can edit
2. Use 'capp' to generate a bolierplate application structure

Using CAPP


If you chose the Github route you will have the 'capp' utility available to you.
Type capp with no parameters to get some help on usage. To create a new application, type

capp gen MyTestApp

After running the command, capp should have generated a project directory structure like the following -

drwxr-xr-x@ 10 340 Dec 4 19:41 .
drwxr-xr-x@ 3 102 Dec 4 19:41 ..
-rw-r--r--@ 1 984 Dec 4 19:41 AppController.j
drwxr-xr-x@ 7 238 Dec 4 19:41 Frameworks
-rw-r--r--@ 1 373 Dec 4 19:41 Info.plist
-rw-r--r--@ 1 770 Dec 4 19:41 Rakefile
drwxr-xr-x@ 3 102 Dec 4 19:41 Resources
-rw-r--r--@ 1 3578 Dec 4 19:41 index-debug.html
-rw-r--r--@ 1 3481 Dec 4 19:41 index.html
-rwxr-xr-x@ 1 299 Dec 4 19:41 main.j


Open up 'index-debug.html' in a browser and you will see the text "Hello World!".

Thursday, November 26, 2009

Introduction to Cappuccino

For many years I have been waiting for real web application software toolsets to arrive. Widespread abuse of HTML, CSS and scripting has created a slew of messy web applications written in technologies that were never designed to be used for such a purpose. They are well suited to web content, but not to building rich applications.

In the 90's, I was building rich client applications for the desktop that were far more usable and responsive than many modern web applications, but the reach and simplicity of deployment for the web model was too great and (almost) everyone jumped on the bandwagon.

Well, the guys over at 280north have been working hard on Cappuccino - a web development framework with a difference. This one provides a rich, object-oriented way of developing applications for the web that run in the browser without the need for plug-ins.

It has its own language called Objective-J the syntax of which is similar to Objective-C. It adds the use of classes instead of relying on Javascripts pure prototype based approach to OO. Unlike Objective-C, it only runs in garbage collected mode, and loses the reference counting model. Other changes includes the dropping of the pointer syntax and moving source code to one .j file instead of requiring a separate header. Classes in Objective-J have a 'CP' prefix instead of 'NS' used by Objective-C. See this tutorial for a quick overview. Since the language is dynamically typed, unit testing and the discipline of keeping code clean are a must to retain one's sanity - but these are good things regardless IMHO.

Programs written in Objective-J are preprocessed into pure Javascript which can be executed in the browser or on the desktop - more on this in a later post.

If you're interested, go over to the cappuccino web site and look into it more detail.

Although there are some incomplete features at this time, it's a lot of fun to work with - I have never been this excited about writing applications for the web before.

Friday, September 4, 2009

Objects 101

I have heard some interesting stories recently and am beginning to comprehend where my assumptions are going awry. My time spent in academia included lecture theatre discussions about the object oriented paradigm any why many believed it was a major step forward. Yes I am going back in time a little here, but in my opinion, objects are still a very powerful way to understand both the problem and solution domains and I very much believe in them - until something better comes along. Having said all that - I am interested in functional languages as well - although I’m not sure that they have to be classified under a completely different paradigm.

It has only recently struck me how fortunate I have been to have worked with many talented people. My ‘apprenticeship’, under the wing some very experienced mentors, provided me with a solid grounding and a varied toolbox of techniques, approaches and strategies for delivering software – but the more experienced I become, the more I realize I have to learn.

Object technology is one of the most misunderstood concepts in computer science, while simultaneously one of the most simplistic. There are really very few key ideas behind them, but it is a subject that will only become apparent to open minded developers over time. I do not claim to be an object expert, just open minded enough to keep learning about them. Part of the problem is unlearning the procedural habits of the past, most modern languages apparently encourage that way of thinking.

1. Objects have the great property that they try to model things of interest in the real world. As such, they can be used to model the problem domain (forget about computers for a minute) as well as the solution domain. Use objects to understand the problem domain first. Get up to the white board and ask your customer about the key abstractions in the problem domain and their relationships to one another
2. Their key advantage lies in their ability to break down complexity and talk to one another to get the job done. When an object talks to another, it sends a message – if the receiving object understands the message, it selects an appropriate method to execute and sends the answer back to the caller. The caller does not need to understand what is going on though, only that the message it has sent gets a response.
3. You can speak to a number objects in the same way, e.g. if you have a number of sprite objects that all require drawing, you don’t have to know which is which, you can just send them all the ‘Draw’ message and if they respond to the same protocol, they will do as asked. This is usually achieved by inheritance or interfaces in most statically typed languages.
4. Objects should focus their efforts on doing on thing well – if you find an object doing a calculation, formatting some text and rendering some shapes on a screen, its doing too much.

A number of enlightening books on the subject have on the subject from the last 30 years contain more than enough information to make most developers’ lives far less complicated. In my experience, the majority of issues developers face are man-made and using objects sensibly can go a long way to minimizing this ‘accidental’ complexity. I have heard it said that the promise of object technology didn’t deliver – in reality, it never had a chance in a world where many didn’t seek to understand and influential organizations downplay it for financial advantage.

It seems as if the diligent use of the OO paradigm is regressing, perhaps to be viewed as a fad, while we slip further into a dark and distant procedural past.

Monday, August 24, 2009

Just Venting...

Its been a while, but tonight I feel the need to vent. What is it about the need to automate everything so much that the customer now has less say in what happens with their service or product than before the so called 'progress' that computerization has brought.

Tonight, I ordered something online. During the process of ordering, I was asked to sign up and create an account. After doing this, the system then had me go back to my inbox, click on the confirmation email and then sign in to the web site. On doing so, I noted that the system had dutifully remembered the state of my cart - so I proceeded to the payment stage. After I had completed the sale, I read the confirmation email and noted with dismay that I had ordered the Spanish version.

When I called the customer service line (at least a human answered) I was told that I have to let the system dispatch the package and ship it across America to my home address so that I can refuse to accept it - because she had no way to stop the transaction!

What ever happened to a quick call to hand over you card details - over and done with.

Is this really progress - I'm not so sure.