Thursday, December 24, 2009

Resisting the Urge To Refactor

I'm working on the main Controller (as in the C in MVC) of a GUI application and trying to design the Controller along the lines of "The Humble Dialog" [PDF] by Michael Feathers. Some of the Controller's methods make repeated calls to the View object. For example:

view.clearAuctionEvents();
view.enableUpdateDatabaseButton(false);
view.displayErrorMessage("Could not download email messages.");

My first instinct was to follow the Refactoring advice of Fowler and Beck and move these three calls into a new method on the View. Then it struck me that it's actually desirable for the Controller to be so pedantic with the View. After all, I'm trying to "humiliate" the view as "The Humble Dialog" article puts it by stripping it of any logic or behavior.

So sometimes it's okay not to refactor.

Saturday, December 5, 2009

Rapid Web Service Construction with Groovy

I'm reading Thomas Erl's book, "Principles of Service Design" and, when he discusses contracts, they're usually codified in WSDL and XSD. So I've been trying to find a way to quickly throw together Web Services that use WSDL and XSD so that I can play with some of the book's concepts.

Failed Attempts

I thought that Ruby would be the answer. I first tried SOAP4R but found that it could not generate WSDL from service methods and types. Since I don't want to generate WSDL files yet, this was a deal-breaker.

I then tried Ruby's ActionWebService but the generator script was not installed correctly so it wouldn't work.

Success

I then stumbled upon Groovy's WSServer library (installation instructions). Groovy is a dynamic language that runs on the JVM. I installed the Groovy support for Eclipse and had created a fully working web service in minutes. I fired up the Web Service from within Eclipse and then switched over to Microsoft Visual Studio and imported the Service Reference and called my service code from C#. It was so easy.

I then thought I'd try a web service call that would return a complex type (e.g. a Person object). This made the Web Service crash with a stack overflow.

It took me hours to find the solution. The following links helped a lot:

Basic Service - This page showed how to create a simple Web Service.

Using the Aegis Mapping - This showed me that I needed to create a mapping XML element for the Person class that ignored the 'metaClass' property of my Person object. My guess is that the stack overflow was caused by navigating a very deep or even cyclic object graph during the serialization process.

Aegis Binding - This link told me where to put the mapping XML element.

Now I can create Web Services very quickly just to try things out. And they run on any platform Groovy runs.

Have you found a better way to quickly develop Web Services? I'd love to hear about what you've found!

Tuesday, March 24, 2009

Exploring XML Using Haskell

I am trying to learn how to process XML using Haskell and I haven't found any "Hello World" tutorials on how to just access various nodes and attributes of an XML document using HaXml.

The following is a transcript of a ghci session I had tonight (minus a handful of bloopers).

I'm not a Haskell expert so expect less than stellar Haskell code. My main purpose for writing this is to give others a jumping off point into HaXml.

First I started ghci:
tim@laptop:~$ ghci
GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help
Then I declared a String that held my XML document text (formatted to fit your screen):
Prelude> let xmlText = "<?xml version=\"1.0\"?><order>
<part number="\">Hammer</part>
<part number="\">Nail</part>
</order>"
Before I can parse the XML, I'll need to import some of HaXml's libraries. The :m +
command will do that for us:
Prelude> :m +Text.XML.HaXml
Prelude Text.XML.HaXml> :m +Text.XML.HaXml.Parse
Now I can parse the XML and extract just the root of the document:
Prelude Text.XML.HaXml Text.XML.HaXml.Parse> let (Document _ _ root _) = xmlParse "(No Document)" xmlText
Actually, no parsing has taken place yet. xmlParse is lazy and will only parse the XML text when necessary.

The first argument to xmlParse is "(No Document)". That's just a dummy value that's used by HaXml for error reporting purposes. If I had parsed XML from a file, I would have substituted the file name for the dummy value.

Let's see what type the root has:
Prelude Text.XML.HaXml Text.XML.HaXml.Parse> :t root
root :: Element Text.XML.HaXml.Posn.Posn
The combinators I'll be using expect a Content value not an Element. So let's create a Content value from this Element. But first we need to load another module:
Prelude Text.XML.HaXml Text.XML.HaXml.Parse> :m +Text.XML.HaXml.Posn
Having all these modules in the prompt is getting annoying. Let's remove them:
Prelude Text.XML.HaXml Text.XML.HaXml.Parse Text.XML.HaXml.Posn> :set prompt "> "
Now our prompt will just be the > character followed by a space.

And now we can wrap the Element value in a Content value:
> let rootElem = CElem root noPos
> :t rootElem
rootElem :: Content Posn
To select nodes in the XML tree we can use the tag function:
> :t tag
tag :: String -> Content i -> [Content i]
It takes a String and a Content value (our document root) and returns potentially multiple Content values (each node whose tag name matched the supplied String).

Let's see the type of value we get when we supply tag with a String:
> :t tag "order"
tag "order" :: Content i -> [Content i]
No surprise there if you're familiar with currying.

And let's see the type of the value returned from tag when both a String and a Content value are supplied:
> :t tag "order" rootElem
tag "order" rootElem :: [Content Posn]
How many element names matched "order"?
> length $ tag "order" rootElem
1
You can search for tags within tags using the /> function. Notice that the chained functions below have the same type as the tag function:
> :t tag "order" /> tag "part"
tag "order" /> tag "part" :: Content i -> [Content i]
Let's search for "part" tags within the "order" tag and see how many nodes we get (it should be 2 because we have 2 orders in our XML text):
> length $ tag "order" /> tag "part" $ rootElem
2
Let's grab just the first "part" element and examine its type:
> let firstPart = (tag "order" /> tag "part" $ rootElem) !! 0
> :t firstPart
firstPart :: Content Posn
Great. We now have a single XML element in firstPart.

Let's poke around the internals of firstPart. To do that we'll pattern match on firstPart:
> let (CElem (Elem name attributes _) _) = firstPart
Now we can look at the part elements tag name:
> name
"part"
And see how the attributes are stored:
> :t attributes
attributes :: [Attribute]
That makes sense since an element can have multiple attributes.

We know that this node just has one attribute so let's grab it:
> let (attrName, _) = attributes !! 0
> attrName
"number"
The second part of an Attribute is an AttValue which is a list of "Either String Reference" values. I'm not sure why this is. I thought that a single attribute could only have one value. Perhaps not?

Let's grab the first attribute's AttValue:
> let (_, attrValue) = attributes !! 0
> :t attrValue
attrValue :: AttValue
And now we'll grab the list of Either values and store the first one in "firstAttrValue":
> let (AttValue (firstAttrValue:_)) = attrValue
> :t firstAttrValue
firstAttrValue :: Either String Reference
Now we'll try to access the attribute String:
> let (Left value) = firstAttrValue
> value
"101"
Sure enough, the first "part" has a part number of "101".

Wednesday, February 25, 2009

REST and Déjà vu

REST is getting a lot of attention. I'm still working my way through "RESTful Web Services" by Leonard Richardson and Sam Ruby.

As I understand REST, if I want to access a resource I can use the GET method and I will receive a representation of that resource that includes that resource's data. If I want to update the resource, I use the PUT method to "save" the resource's new data.

What does that remind me of? Think. Think.

Ah yes! My early days of coding in C. I would get a struct-full of data from somewhere, change one or more members, and then call some method that persisted those changes. The struct I was changing just contained data and had no behavior.

Object Orientation

Later on I learned how to encapsulate the struct's data and use functions to provide behavior for the struct. Then I learned about Object Orientation (OO). With OO, as a user of an object, I don't need to know anything about the object's data, what its members mean, valid combinations of data, etc. I let the object handle all that stuff.

I know OO isn't a panacea and that it isn't universally accepted and that those who do accept it rarely agree on what it means or how to do it right. But hasn't it taught us that encapsulation is good?

I do know that I don't want to go back to programming like I did in my early days of C programming.

Un-RESTful Web Services

I'm not saying that we need to start exposing all our objects via URIs. Objects typically have chatty interfaces (lots of fine-grained messages passed to the object) and chatty doesn't scale very well.

I do think that the Facade design pattern can be used to keep the interfaces more chunky (fewer, but coarser-grained messages passed to the facade) and our systems performing better.

This is the approach that many web services use today.

Hackable URLs

REST provides hackable URLs:

GET /book (returns all books)
GET /book/123 (returns the representation of book #123)

That's very cool. There's nothing preventing us from using hackable URLs in web services. In fact all you Smalltalkers and Objective-Cers might feel right at home with URLs like:

/book/123/delete (deletes book #123)
/book/124/loanToUser/432 (loans book #124 to user #432).
/books/addTitle/Object+Thinking/copies/4/branch/Central (adds 4 copies of a book to one branch's inventory)

Encapsulation

Another reason why we use objects is because our object's representation, the very thing that REST makes public, might change and we don't want the user of our object to be affected by a change to our object's internals.

Conclusion

I'll keep reading the RESTful Web Services book and hopefully I'll find out that I've misunderstood everything and that REST really is a step forward (or at least sideways) and not a step backwards.

Monday, December 29, 2008

Single Responsibility Principle

I really do like what Robert C. Martin has to say about OO but I just don't agree with his position on the Single Responsibility Principle. It sounds like a good principle but then when I try to apply it in my mind, problems arise.

Let's look at a few of the classes he ends up with in his paper on SRP. The Connection interface has two methods: dial (which takes a string) and hangup. Does this class really have only one reason to change? No, there are still a number of reasons why this class might need to change. There might be different ways of hanging up ("politely" for valid connections and abruptly for would-be hackers). There might be different ways of dialing (with or without the speaker, supplying credentials, selecting a protocol, specifying minimum modem speed, etc.). There might be modems that never hang up.

I would posit that most classes have more than one reason for change. Here are a few examples.

Rectangle - the data types for the coordinates may change (16-bit to 32-bit), we may want polar coordinates instead of Cartesian. We may even want non-euclidean rectangles.

String - The character set may need to change. The storage mechanism may change (e.g. list, array, linked blocks of memory). The allocation scheme may change.

Just as easily as someone can say there is only one reason for a class to change, someone can find out multiple reasons for that same class to change (with very few exceptions). It's quite subjective.

If you could split all your classes into single responsibility objects, you'd have a huge number of classes that each did very little. To do anything useful, you would need to enlist the help of many classes. This makes for poor comprehension of the system and poor usability.

I want there to be a one to one mapping between concepts and classes. If I have a concept of a file, and I want to read and write from a file, I will expect there to be a file object with read and write methods. If I have to create input streams and output streams and file-opener objects, I will not enjoy the experience. I want a file object. I don't care if, behind the scenes the file is using an input stream and a output stream and a file-opener. I just don't want to see them or need to know about them.

With this one concept per class approach, there is a greater chance of complexity if precautions aren't taken. To combat that complexity, I would consider breaking up the main concept into sub concepts (e.g. input, output, seeking, etc.) and then coding each sub concept as a separate class and then hide that class behind the facade of the main concept's class.

This approach also helps with testing. If each of the sub concept classes can be mocked and injected into the main concept's class, the class is easy to use and easy to test.

You still need to guard against combining incompatible concepts into one class (e.g. file management with searching directories) mostly to avoid confusing the user. Remember that class size and complexity can be managed by decomposing the main concept's class into other classes.

Monday, May 12, 2008

Measuring Talkativeness With Big O Notation

In addition to its commonly known uses, Big O Notation can also useful for describing a person's talkativeness. Given the number of words you say to a person, their Big O factor tells you how long their response will probably be.

The stereotypical male's Big O factor is O(1). Regardless of what you say to him, you get a constant response (which may or may not be a grunt).

A cooperative conversation would be some where in the neighborhood of O(n) meaning that both parties are contributing equal amounts.

Then we get to the chatterbox who has a Big O factor of O(n^3). I get a little nervous when I encounter a person with this kind of Big O factor. I know that even if I grunt, that will spawn a long and drawn out discussion on some topic.

I used to know a guy who was somewhere around O(n^n!). I really dreaded seeing him.

What gets dangerous is when you have two O(n^n) (or worse) folks talking with each other. Each one's response is amplified by the others until they're both talking over each other and they pass out from buffer overflows.

I've been too general up too this point. I know that based on the topic of conversation, I have different Big O factors. Here is a list of topics and my Big O factor for each topic.

  • Sports - O(1) (yes, I will grunt).
  • Politics - O(n/2)
  • Computers - O(n^2)
  • Clothing, Shoes or Purses - O(1)

Thursday, May 1, 2008

SharePoint : The Perfect Storm

Wikipedia defines a perfect storm as "the simultaneous occurrence of events which, taken individually, would be far less powerful than the result of their chance combination."

Rather than events, in the case of SharePoint, I see the elements of the perfect storm being conditions. Those conditions are:

  • SharePoint is widely accepted by CEOs, CTOs, architects, and users all around. SharePoint's user experience is very nice for the most part. I think that the product brings a lot of value to users. This is a good thing.
  • SharePoint does a lot just out of the box. It has all sorts of useful templates for sites and it has common workflows. However, beyond a certain point (as with most if not all software) SharePoint cannot do what you want without customizing it with managed code (C#, VB.NET, etc.). This too is a good thing.
  • SharePoint's developer experience is terrible. I won't go into details.
So on the one hand you have CEOs, CTOs, and architects pushing for the use of SharePoint in the company, and on the other hand you've got a terrible developer experience. The eventual result is a shortage of SharePoint developers and an increased demand for them.

Will enough SharePoint developers leave SharePoint that Microsoft will be pressured into improving the developer experience? Or will there always be enough SharePoint developers to squeak by?

CTOs and CEOs who select SharePoint and need to customize it might start feeling the effects of this perfect storm when they have a harder time hiring and retaining developers, and then have to pay them more.

If you are in the software development business for the money, SharePoint development could be a great cash cow. The only problem is that you have to develop in SharePoint.

The next time you hear a technology is hot, you may want to find out why the technology is hot.