Replace Development with Design

by Kofi Sarfo 27. May 2010 17:21

About seven years after everyone else got it I think I may have finally gotten it too. That final letter in TDD may be about Design as anything else!

I've never written anything in Java so the offer to deconstruct/reconstruct and deploy a Java EE website based on Struts sounded a death march. We brought in a dedicated contractor who struggled some with Tomcat instances and lock down. Difficulties correctly called.

We needed to work out which code (including SQL) was being called for each page on a public facing website. I didn't fancy clicking through the website and scribbling down the execution path, which someone suggested and I'd no idea whether there existed anything that allows bytecode instrumentation without modifying the Java source. A quick look at Spring and AspectJ indicated that neither are particularly lightweight. 

This looked promising though: Javassist is a load-time reflective system for Java. IBM developerworks has a handy guide to aspect-oriented changes with Javassist. Still not sure, however, how to tie method calls to database calls.

In the end I wrote some code generation utility to add logging for both method calls and database calls (via OJDBC), using Regex to identify each. The key thing here was that no single method in the C# tool was written without first writing a test. Not only is this the first thing I've ever written with 100% code coverage but I managed also to maintain the discipline needed to avoid squeezing in some code without first having a failing test. Each initial test was followed with a passing test using the very simplest solution, writing a second failing test by varying parameters, before completing the implementation.

Once applied to production code I then realised that I'd made no design decisions. Absolutely none! This is something I'd never previously considered. I expect this very same light bulb went on too for many folks almost a decade ago. If you only ever write the next method required the design just emerges. Also, the simplest possible solution in this case meant there were no redundant lines to delete at the end. Just very satisfying indeed.

Tags: , ,

Obviously

Have hammer, recognise screw, can't find screwdriver

by Kofi Sarfo 1. February 2010 06:14

For all it's usefulness XQuery never really took off the way it seems it should have done. We have a query language from the W3C for XML and since XML use is pervasive... it's very much like SQL which is wildly popular and since querying data is a fairly natural thing to want to do... and there are some excellent tools from Altova, Stylus Studio and Saxonica... However, there the story appears to end without the expected outcome. Going forward (sorry) we'll certainly be making greater use of XQuery because so many of the terabytes we process are wrapped in angle brackets and it's XML all the way down to even input & output parameters on stored procedures.

To demonstrate its value by example. Here's one way to generate XML using LINQ and hash table to validate against a given schema:

using System.Collections.Generic; using System.Linq; using System.Xml.Linq; namespace Wimiro.Data.Examples { public static class TransformXmlImperatively { public static string GenerateCdsSpreadOutput(this string xml, string requestXml) { var rootNode = xml.GetXmlDocument().FirstChild; var xmlWithNewDocumentRoot = rootNode.GetProcessingInstruction(); xmlWithNewDocumentRoot += "<" + requestXml.GetResponseRootElementName() + " xsi:noNamespaceSchemaLocation=\"curves.xsd\" " + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"; xmlWithNewDocumentRoot += xml.GetCurvesPointsFromXml(); xmlWithNewDocumentRoot += "</" + requestXml.GetResponseRootElementName() + ">"; return xmlWithNewDocumentRoot; } public static string GetCurvesPointsFromXml(this string xml) { var curveDictionary = new Dictionary<string, XElement>(); var rawDoc = XDocument.Parse(xml); var rawElements = from elements in rawDoc.Elements("root").Elements("row") select elements; var curveRoot = new XDocument(new XElement("root")); foreach (var rawElement in rawElements) { if (!ContainsCurve(curveDictionary, rawElement)) { AddCurve(curveDictionary, rawElement, curveRoot); } FindCurve(curveDictionary, rawElement).Add(GetCurvePoint(rawElement)); } return curveRoot.ToXml().StripRoot(); } private static XElement FindCurve(IDictionary<string, XElement> curveDictionary, XElement rawElement) { return curveDictionary[rawElement.GetKey()]; } private static XElement GetCurvePoint(XElement rawElement) { XElement curvePoint; curvePoint = new XElement("Point"); curvePoint.SetAttributeValue("Spread", rawElement.Attribute("Spread").Value); curvePoint.SetAttributeValue("Maturity", rawElement.Attribute("Maturity").Value); return curvePoint; } private static void AddCurve(Dictionary<string, XElement> curveDictionary, XElement rawElement, XDocument curveRoot) { XElement curveElement; curveElement = new XElement("Curve"); curveRoot.Element("root").Add(curveElement); curveDictionary.Add(rawElement.GetKey(), curveElement); foreach (var curveAttribute in rawElement.Attributes()) curveElement.SetAttributeValue(curveAttribute.Name, curveAttribute.Value); curveElement.SetAttributeValue("Spread", null); curveElement.SetAttributeValue("Maturity", null); } private static bool ContainsCurve(IDictionary<string, XElement> curveDictionary, XElement rawElement) { return curveDictionary.ContainsKey(rawElement.GetKey()); } } }

And here's the way it should have been done using XQuery:

select @xml_out.query (' for $Ticker in distinct-values(/root/row/@Ticker) let $Tickers := /root/row[@Ticker=$Ticker] for $Currency in distinct-values($Tickers/@Currency) let $Currencies := $Tickers[@Currency=$Currency] for $Date in distinct-values($Currencies/@Date) let $Dates := $Currencies[@Date=$Date] return <Curve Ticker="{$Ticker}" Currency="{$Currency}" Date="{$Date}">{ for $node in $Dates return <Point Maturity="{data($node/@Maturity)}" Spread="{data($node/@Spread)}" /> } </Curve>')

StackOverflow! For all your hardware needs.

Typical 2356% APR On a Payday Loan Does Seem Quite An Incredible Offer!

by Kofi Sarfo 1. January 2010 14:37

The Vanilla BlogEngine.NET allows comments to be posted via an HTTP post which is great in terms of enabling an AJAX implementation for blog post comments. However, it's great too for spam bots, almost exclusively, offering pay day loans throughout the comment sections of this site. One new year's resolution was to implement a solution using ReCaptcha. In this case the solution may require writing no code.

StackOverflow: How would one integrate ReCaptcha in to BlogEngine.net (ASP.net C#)?

I can't think why anybody would think a pay day loan a good idea when there's Zopa, for example.

I have a need, a need for a quote from an iconic 80's film

by Kofi Sarfo 7. October 2009 00:52

It's been almost one week since we started doing this daily code Kata: Roy Osherove's TDD Kata 1 - String Calculator. Thirty minutes every day in October so far. Six days. Three hours. Writing the same functionality over and over. What happens is that, naturally, each time we get a little closer to the end (we've not yet completed it in thirty minutes) and we optimise by anticipating functional requirements and code to allow for simple changes ahead. We'll decide how much of this is cheating once we're actually done a few times within thirty minutes before moving onto the next Kata.

We're using just the one code snippet, TDDtestmethod, which generates a test method. We abandoned the calculator variable name, opting for c.Add instead.

Is there a prize for the longest [Test] case method name?

Calculator_ MultipleDelimeterVaryingLengthSpecifiedDelimitedMultipleStringDecimalValues_ ShouldReturnSummedValues()

Using underscores would only make matters worse. And when we looked at some of our tests recently we discovered that we were unit testing parts of the framework (guess we're still not sure about Entity Framework) and using unit tests for spikes too. The words "Gone Too Far" appeared suddenly.

Tags: ,

Dojo

A member of the BrainBench Appreciation Society

by Kofi Sarfo 24. August 2009 08:26
C# 2.0
 
  Score 4.28
  Percentile Scored higher than 95% of previous examinees
  Account Percentile Scored higher than 95% of 21 examinees within this account
  Proficiency Level: Advanced (Master)
Demonstrates a clear understanding of many advanced concepts within this topic. Appears capable of mentoring others on most projects in this area.
  Strong Areas
  • Object Oriented Design
  • Unmanaged Interoperability
  • Grammar and Logic
  • Assembly Loading and Reflection
  • Arrays and Collections
  Weak Areas
  • None noted

It's tempting to do a few more for a perfect score. When I did a BrainBench test online last it included questions I thought were less relevant such as those about compiler options, for example, but this one was much better. It still requires a fair amount of thought and for those questions where compiling the code or executing the example will give the correct answer they use images rather than text so cut & paste isn't an option.

Tags:

Resources

Nuff chat. Now code.

by Kofi Sarfo 10. June 2009 01:33

We've spent the last few weeks reading, trying to get up to speed with .NET 3.5 and looking at some code. Meanwhile we've not been writing anything besides snippets for learning generics, LINQ and WCF. No ASP.NET MVC. No WPF. No Silverlight. No worries. It's time to build something.

So the concept is reviews for the Twitterati. Reviews of 120 Characters or less. Tweeviews if you like. Key characteristics should be that it's simple, clean and intuitive.

Key technical features:

  • REST-based architecture
    • API versioning
    • Caching
  • ASP.NET Webforms (initially with AJAX)
  • SQL Server 

Functional areas:

  • Category
  • Review
  • Thumb up or down (as opposed to 4/5 stars)
  • Reviewer
  • Reviewed object (restaurant, etc)

Not sure whether we call those things above entities.

Old school Microsoft approach is database design first. Data-centric rather than domain driven. I think we're still stuck in that world. Will be worth reconsidering this application and how it might have been done differently using NHibernate, Rhino Mocks, etc. Ayendeified. It ought to be an adjective.

What's interesting (for me) about this is that we've never written a publicly accessible API. We've done Web Services for both inter and intra application domain hookups (not in the .NET sense but rather as an interface between disparate applications on the same platform as well as between different platforms). We used Web Services, for example, in the Advert Framework* for FireText. No problems with SOAP. It didn't really need to be WS-* as it never made use of transactions as originally intended. Still, it was fun playing with the PHP SOAP implementation :)

Extra bits:

  • URL shortening API
  • Twitter API
  • Some reporting & filtering type UI

First pass, writing this as quickly as I can using tried/tested approach. Second attempt, a rewrite using shiny newish technology. The idea being then able to compare the old versus new, discern what real advantages the new offers and get some refactoring practice. This should be interesting...

Notes:

* It was subsequently rewritten in PHP because the engineer I handed the code to didn't fancy learning C# but a story for another time...

Full Circle on Action<T>

by Kofi Sarfo 6. June 2009 00:02

Reminded recently of a method for determining Prime Numbers (Sieve of Eratosthenes) and saw some Generic Collection Class action (p. 97 C# In Depth)

            List<int> candidates = new List<int>();

            for (int i = 2; i <= 100; i++)
            {
                candidates.Add(i);
            }
 
            for (int factor = 2; factor <= 10; factor++)
            {
                candidates.RemoveAll(delegate(int x)
                    { return x > factor && x % factor == 0; }
                );
            }
 
            candidates.ForEach(delegate(int prime)
                { Console.WriteLine(prime); }
            );

Bouncing around looking for code samples to see what we're missing in terms of Generics... we spot something. Switch on the Code: The Built-In Generic Delegate Declarations.

Difference between Func<T> and Action<T> is the latter doesn't have a return type. Too obvious to miss? Maybe. Quick search shows difference between new Action() and Lambda at Stack Overflow. Response from author of code sample above. Jon Skeet. 3900 answers on Stack Overflow in 8 months. Or 16 answers a day, every day.

Notes:

MSDN: Lambda Expressions

CodeBetter: Back to Basics - Delegates, Anonymous Methods and Lambda Expressions

Online Hang Outs Part I

by Kofi Sarfo 5. June 2009 16:56

 

I can't remember where I read something about having to read a decent amount of well written code in order to be able to understand how to code well. I think a parallel with writers and books was drawn somewhere nearby... Anyhow, this is why we've been hanging round the The Code Project since 2001 sometime and there appear excellent articles / code samples every so often; for example, the "Best C# article of April 2009" competition winner was Geoplaces. "A hybrid smart client, involving RESTful WCF/WPF and more." It's pretty.

 

It's a while since we wrote anything from scratch and those bits of code we've picked up in the last year don't look much like this. They don't look this good.

The Data Layer is all Entity Framework so happy to give that a miss but the Restful Service Layer is a nice intro into the System.ServiceModel namespace.

The Service Interface provides examples of ServiceContract and OperationContract. Backing up... MSDN: Introduction to Building Windows Communication Foundation Services. Note that this intro was written four years ago! Cut to mid 2009 and we still have indication of pain. Ayende: WCF Works in Mysterious Ways. IColloquialize: WCF Service References Generating Empty Root Proxy Classes. First takes suggest WCF might not be so straightforward.

Kofi Sarfo modified theme by Mads Kristensen



Content by WIMIRO Technology is licensed under a Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License.

Creative Commons License

Powered by BlogEngine.NET 1.5.0.7

About Me

Director, Wimiro Technology
London, United Kingdom

Writes in third person and first person plural; currently commutes to Moorgate.

Kiva Loans

  • Kamala Hasanova

    Kamala Hasanova

    Cattle

    Requested loan: $1250

    Amount raised: $0

    Imishli, Azerbaijan

    To purchase cattle and six sheep.

    Loan Now »

  • Nizami Shirinov

    Nizami Shirinov

    Cattle

    Requested loan: $1125

    Amount raised: $0

    Imishli, Azerbaijan

    To purchase one milking cow and one calf.

    Loan Now »

  • Lhagva Dulam

    Lhagva Dulam

    Sewing

    Requested loan: $1450

    Amount raised: $0

    Hentiy,, Mongolia

    To purchase fabrics and materials.

    Loan Now »

 To see more entrepreneurs »

Kiva Loans