Highway to hell? DevTweet: @mariannerd and @aahoogendoorn review code

The following conversation between Marianne and me will be published as our DevTweet column of SDN Magazine, issue 102.

clip_image001[52]

Listening to Black Sabbath’s Master of Reality.

clip_image002[42]

@aahoogendoorn Look at you… new avatar! Is that an AC/DC shirt?

clip_image001[53]

@mariannerd Howdy partner! It is AC/DC all right. Your avatar new too? Something wrong with the old one?

clip_image002[43]

@aahoogendoorn Nope, just a change in scenery! Like the project I’m doing. I’m asked to do a code review.

clip_image001[54]

@mariannerd Cool! Whenever I’m asked to do a code review, the client always knows, or at least suspects, something’s terribly wrong.

clip_image002[44]

@aahoogendoorn Oh yes… We have the suspect… Now it’s a case of getting the evidence … I feel like Columbo..

clip_image002[45]

@aahoogendoorn You know the suspects from the beginning, but you still have to look for the evidence for conviction!

clip_image002[46]

@aahoogendoorn So when you are asked to do a code review, what is the first thing you do?

clip_image001[55]

@mariannerd The first thing I do? Ask the client what they’re hoping to achieve: do they actually want to know how deep the rabbit hole goes?

clip_image001[56]

@mariannerd Next, I make a list of all things I should look at during the review. Architecture, domain, data access, layers, extensibility..

clip_image001[57]

@mariannerd Security, authorization, reuse, code copying (especially in VB), way of working, documentation, design, quality of coding.

clip_image002[47]

@aahoogendoorn So far so good!

clip_image001[58]

@mariannerd Rule #1 in code reviews: more time means more detail.

clip_image002[48]

@aahoogendoorn Code Reviews are fun! No deadlines. just looking at somebody else’s code.

clip_image002[49]

@aahoogendoorn … Oh and telling what’s wrong with it… I must say this is the first time I get such an assignment.

clip_image001[59]

@mariannerd. You know, there’s so much horrible code out there, we could do code reviews for the rest of our lives.

clip_image002[50]

@aahoogendoorn Well a lot of this stuff is subject to opinion… 100 developers, 100 different code for the same functionality…

clip_image001[60]

@mariannerd Yes true, but some code is definitely worse than other code. And believe me, I’ve seen some bad coding in my time.

clip_image002[51]

@aahoogendoorn Any examples?

clip_image001[61]

@mariannerd Examples of bad code? How many do you need. Check out this old blog post of mine (in Dutch). http://htxt.it/reVB

clip_image001[62]

@mariannerd. Think of SQL statement in web pages, or of a single class that handles 50% of all functionality.

clip_image001[63]

@mariannerd. Or think of the same business rule implemented multiple times on different locations, in different ways.

clip_image002[52]

@aahoogendoorn One of the things I came across: internal web application: authentication by doing a LDAP query to see if the user exists.

clip_image002[53]

@aahoogendoorn Haven’t they heard of Windows Authentication in IIS? They didn’t even check if the user was enabled or disabled… :-S

clip_image001[64]

@mariannerd Haha, nice one. I once audited the enterprise web portal for a very large international company where ALL communication …

clip_image001[65]

@mariannerd between front end and back end went through one single class. Imagine the effect of a single change..

clip_image001[66]

@mariannerd Sometimes, it gets really bad. Code a whole company depends on, which is so bad, that productivity will definitely be below zero soon

clip_image001[67]

@mariannerd Anyway, I love being asked for code reviews. It gives the opportunity to help improve the quality of applications.

clip_image001[68]

@mariannerd. That is, if they follow up on your advice from your code review. Unfortunately, that is not always the case.

clip_image002[54]

@aahoogendoorn Well maybe it’s not needed… Or they just want to know the risks and are happy to take them!

clip_image002[55]

@aahoogendoorn Which could be the outcome of a code review. It’s not good, but far from worse.. And it may be fixed with a couple of quick wins.

clip_image001[69]

@mariannerd. Well yes, that could be the outcome. Maybe I’m to idealistic about writing good code. If it ain’t broken, don’t fix it.

clip_image001[70]

@mariannerd. But I just love clean code…

clip_image002[56]

@aahoogendoorn …. But even bad code can function.

clip_image001[71]

@mariannerd My favorite example: an ASP.NET web site that was never compiled by the developers. They just ran it from the browser. Great stuff!

clip_image001[72]

@mariannerd. As a consequence, of the over 40 pages in the application, only 6 compiled (the ones they visited running it in the browser)…

clip_image002[57]

@aahoogendoorn LOL "we got a live one here!". This business application compiled at runtime? No test cases just put it in production!

clip_image001[73]

@mariannerd. And then things can get pretty messy. Especially when your poor company lives of this software.

clip_image002[58]

@aahoogendoorn That is the whole point isn’t it.. Developers just start coding without a plan, or knowing best practices.

clip_image001[74]

@mariannerd Yes, a lot of developers code without having a decent architecture, without patterns, without layers – but with best intentions.

clip_image002[59]

@aahoogendoorn Oh yes, best intentions… The road to hell is paved with good intentions…

clip_image001[75]

@mariannerd. No stop signs, speed limits. Nobody’s gonna slow me down. Highway to hell. AC/DC# ?

clip_image002[60]

@aahoogendoorn Nope… 4 minutes by Madonna LOL.

clip_image001[76]

@mariannerd. Madonna? Girl you need a music review instead of a code review!

clip_image002[61]

@aahoogendoorn ….I guess even bad music can function. ;-)

God Class

In Dutch. Appears in SDN Magazine, February 2008.

Ik weet het nog goed, hoewel het twee jaar geleden was en mijn geheugen niet meer alles is. Mijn collega Wouter belde. Geschrokken. “Zoiets heb ik nog nooit gezien,” begint Wouter, mij nieuwsgierig makend. “Ik dacht dat we in Nederland toch wel aardig konden programmeren. Maar wat ik hier nu bij mijn klant meemaak is ongehoord. Ik heb hier een class voor me met meer dan 3.000 regels code.” Mijn nieuwsgierigheid is gewekt.

Meer dan 3.000 regels code in een enkele klasse is ongehoord. Een typisch voorbeeld van een God Class. Een bekend anti-pattern. Kort samengevat zegt het bijna 10 jaar oude boek AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis: “The God Class is found in designs where one class monopolizes the processing … The key problem here is that the majority of the responsibilities are allocated to a single class.” En inderdaad, Wouter’s klasse is een web part in een Sharepoint-applicatie die alles zelf regelt. De klasse stelt de te tonen controls vast, navigeert door de applicatie, voert validaties uit, maakt verbinding met de database, stelt queries samen en voert deze uit.

Nooit gedacht dat het nog erger kon. Totdat ik eerder deze week door een goede vriend werd gevraagd of ik hem even kan helpen met de deployment van een kleine webapplicatie. Natuurlijk wil ik dat wel. Eerst ruimen we de bekende problemen uit de weg. Zo is de database op zijn laptop ingesteld op Windows-authenticatie en de applicatie niet. En ook heeft de ASP.NET user onvoldoende rechten omdat eerst het .Net Framework was geïnstalleerd, en daarna pas IIS. Ook een bekende.

Op dat moment besluit ik de code eens te bekijken van de webpagina’s van de applicatie. Ik open de code behind page van de hoofdpagina zelfs . Dat had ik beter niet kunnen doen. Er rollen 4.912 regels Visual Basic .Net voorbij aan mijn ogen. Afschuwelijk. En dan heb ik het nog niet eens over die 4.912 regels. De eerste code in het nieuwe jaar, en dan dit. Een valse start. Ik haal er een paar hoogtepunten voor u uit.

If = true
Een makkelijke om er in te komen. Deze constructie mag natuurlijk niet ontbreken.

If Page.Session("ShowRemoved") = "1" Then
   ShowRemoved.Checked = True
Else
   ShowRemoved.Checked = False
End If

Hoewel deze code in principe niet fout is, doet deze mij toch meestal de wenkbrauwen fronsen. Waarom? Het is een symptoom – a smell of bad code – dat je overigens maar al te vaak tegenkomt. Dit kan ook in een enkele regel code.

Constant
En dan heb ik het nog niet eens over het feit dat vergelijken met een string "1" toch wat risicovol is. Was het nou "1", toch "True", of wel misschien "true"? Een eenvodige constante introduceren zou al een verbetering zijn. Laat staan het ophalen van de variabele Page.Session("ShowRemoved"). Zou er bijvoorbeeld verschil zijn met Page.Session("ShowRemoved") of met Session("ShowRemoved"), wat ik verderop in de code tegenkom?

Overal en nergens wordt trouwens gevalideerd aan variabelen die in de sessie worden opgeslagen. En op talrijke plekken worden ze ook van een waarde voorzien. Het zijn globale variabelen geworden. Zo is onmogelijk te garanderen dat bij het uitgevoeren van een stuk code de waarden in de sessie correct zijn. Een van de fraaiste voorbeelden hiervan is het opbouwen van queries zoals hieronder.

strQuery = ""
strQuery = strQuery + "WHERE" + vbCrLf
strQuery = strQuery + IIf(Page.Session("Screen") = "Info",
   " S. Info = 1", "").ToString + IIf(Page.Session("Screen")
   = "Report", " S.ReportScreen = 1", "").ToString + vbCrLf

Prachtig. Prachtig. Ik kan het niet anders zeggen. Waarom worden variabelen als Page.Session("Screen") niet gewoon als argument meegegeven aan de methode waarin de query wordt opgebouwd? Nog een klein voorbeeldje dan maar?

If myValues(1) = "Question" Then
   myQuestionID = CType(myValues(3), Integer)
   …
End If

Zo foutgevoelig. Één typefout en je bent de sigaar.

92
Dat brengt me op de meer hinderlijke eigenschappen van deze code behind. Kort door de bocht: de pagina doet alles. Er wordt een treeview opgebouwd. Er worden heel veel queries (hand)geschreven en uitgevoerd. Het zijn er 92 om precies te zijn. De code behind telt overigens 115 methoden.

Is dat nu zo erg? Denk eens aan onderhoudbaarheid. Veronderstel dat er een kleine wijziging komt in het domeinmodel van de applicatie. En veldje erbij, een veldje er af, misschien een nieuw domeinobjectje, of een relatie die wijzigt tussen twee domeinobjecten. Niet ongewoon hoor, zo’n kleine wijziging. Gemiddeld wijzigen de requirements gedurende een project ongeveer 20%. Het is voor de ontwikkelaars niet te hopen dat dit ooit gebeurt. Hoe vindt je nu terug welke methoden en queries door zo’n wijziging worden aangetast? Je zult deze applicatie maar in onderhoud hebben. Yoga, vroeg naar bed en veel water drinken!

Globaal
Globale variablen! Altijd goed. Ze zijn er vast.

Dim strQuery As String

Maar die variable strQuery heb ik toch al eerder gezien? Inderdaad. Het is de string waarmee alle tweeennegentig queries in de code behind page worden opgebouwd. Pardon? Inderdaad, vrijwel alle queries die worden opgebouwd in de code starten als volgt.

strQuery = ""
strQuery = strQuery + "SELECT " + vbCrLf

Ik heb het niet durven controleren, maar wat gebeurt er als een van de ontwikkelaars per ongeluk het bovenste van de deze statements vergeet? Je moet er niet aan denken. Zijn de ontwikkelaars misschien niet bekend met lokale variabelen?

Absent
Toch eens kijken naar de oorzaken van deze brei. Wat zegt Anti-Patterns? “Lack of (any) architecture. The absence of definition of the system components, their interactions, and the specific use of the selected programming languages.” Dat is hier op zijn plaats. Ik denk dat met het introduceren van een eenvoudige meerlagenarchitectuur hier veel te redden valt. Een laag voor de webpagina, een laag met domeinobjecten en domeinlogica (of met een hip woord: services) en eentje voor de interactie met de database. Dat zou al een hoop ontrafelen. Anti-patterns geeft nog een interessante oorzaak: “A migrated legacy design that has not been properly refactored into an object-oriented architecture.” De spijker op zijn kop. Ik vermoed dat de code afstamt van Visual Basic Classic – en de ontwikkelaars ook.

Wat een heerlijk fris begin van het nieuwe jaar. Een citaat borrelt op. “I love the smell of napalm in the morning”. Er is nog een hoop werk te doen in 2008!