DevDisasters

The .NET Whistleblower

Terry had spent the better part of the past decade digging through the trenches of QuidCorp's flagship application QuidFlow -- a program used to flowchart business processes. Though QuidFlow performed well and, overall, customers were happy with the product, whenever it came time to address a bug or investigate just how the filename validation worked; the source code was beginning to show its age.

Terry raised his concerns to management. Much to his surprise, management approved a plan to transition their C++ developers into the world of .NET through a little on-the-job experience.

Homemade with Love
Paired up with a senior programmer who had been working on QuidFlow, an ASP.NET document control app written in VB.NET, Terry was handed some completed quality assurance (QA) test plans.

"Don't stress yourself out trying to figure out how to solve every problem just yet," the senior programmer advised, "really just get yourself versed in how to check the code out, compile it and poke around a bit."

The application refused to start and when Terry eventually managed to get it going, exceptions were thrown all over the place by the runtime environment when he tried to run the application on his local machine.

Throughout the codebase, there was one section of code common to all the pages. Sharing common code is a great thing -- Terry had employed a similar method in C++. However, in this one module, above all others, there was something funny about how it all worked.

Not in Kansas Anymore
First of all, in his old role functions returned a meaningful value. However, littered through QuidFlow were functions, which always returned the same value of False, whether they were completed successfully or not:

Function UnLockRecord(
strTableName) As boolean
if strTableName = "" then
strSQLText = "DELETE FROM LOCKINFO
WHERE PERSNO=" & SQLQuote(session("LOGGEDUSER"))
Else
strSQLText = "DELETE FROM LOCKINFO
WHERE TABLENAME = " & SQLQuote(strTableName) & " AND PERSNO="
& SQLQuote(session("LOGGEDUSER"))
End If
ExecSQL(strSQLText)
Unlockrecord = false
End Function

Function SystemInfoClear() As boolean
ExecSQL("DELETE FROM SYSTEMINFO")
SystemInfoClear = False
End Function

It was widely known that QuidFlow would kick back strange and frightening messages when things went horribly wrong. As such, Terry could appreciate why a developer would want to shield a division by zero error or a similar condition from a user. However, this feeling of appreciation was reversed somewhat after seeing two similarly named functions immediately thereafter.

Though he wasn't even remotely close to being able to call himself a Web developer, Terry felt that there had to be an easier way of rendering the HTML at the top of each page:

if cSYS_NONAVFRAME<>"1" Then 
response.write("<script language=Javascript>" & Chr(13) & Chr(10))
response.write("if (top.location == self.location) {" & Chr(13) & Chr(10))
if Session("NAV_TOP") Then
response.write("document.write('<html><head><title>"
& session("WINDOWTITLE") & "</title></head>')"
& Chr(13) & Chr(10))
response.write("document.write('<frameset ID=QUIDPROFRAME
rows=" & Chr(34) & "0,25,*" & Chr(34) & " cols=" & Chr(34)
& "*" & Chr(34) & ">');" & Chr(13) & Chr(10))
response.write("document.write('<frame id=USERDEFINEDFRAME
framespacing=0 frameborder=0 border=0 name=USERDEFINEDFRAME>');"
& Chr(13) & Chr(10))
response.write("document.write('<frame id=NAVFRAME
framespacing=0 frameborder=O border=0 name=NAVFRAME >');"
& Chr(13) & Chr(10))
response.write("document.write('<frame id=MAINFRAME
framespacing=0 frameborder=O border=0 name=MAINFRAME>');"
& Chr(13) & Chr(10))
response.write("document.write('</frameset>');"
& Chr(13) & Chr(10))
response.write("document.write('</html>');"
& Chr(13) & Chr(10))
response.write("parent.USERDEFINEDFRAME.location='"
& application("SYS.QUIDPROROOT") & "basetable/general/userframe.aspx';"
& Chr(13) & Chr(10))
response.write("parent.NAVFRAME.location='" & application("SYS.QUIDPROROOT")
& "navigator/top/topnavigation.aspx';" & Chr(13) & Chr(10))
response.write("parent.MAINFRAME.location='" & strRealPage
& "';" & Chr(13) & Chr(10))
Else
response.write("document.write('<html><head><title>"
& session("WINDOWTITLE") & "</title></head>');" & Chr(13)
& Chr(10))
response.write("document.write('<frameset ID=QUIDPROFRAME rows="
& Chr(34) & "0,*,25" & Chr(34) & " cols=" & Chr(34) & "*" & Chr(34)
& ">');" & Chr(13) & Chr(10))
response.write("document.write('<frame id=USERDEFINEDFRAME
framespacing=0 frameborder=0 border=0 name=USERDEFINEDFRAME >');"
& Chr(13) & Chr(10))
response.write("document.write('<frame id=MAINFRAME
framespacing=0 frameborder=O border=0 name=MAINFRAME >');"
& Chr(13) & Chr(10))
response.write("document.write('<frame id=NAVFRAME
framespacing=0 frameborder=O border=0 name=NAVFRAME >');"
& Chr(13) & Chr(10))
response.write("document.write('</frameset>');"
& Chr(13) & Chr(10))
response.write("document.write('</html>');"
& Chr(13) & Chr(10))
response.write("parent.USERDEFINEDFRAME.location='"
& application("SYS.QUIDPROROOT") & "basetable/general/userframe.aspx';"
& Chr(13) & Chr(10))
response.write("parent.NAVFRAME.location='" & application("SYS.QUIDPROROOT")
& "navigator/bottom/bottomnavigation.aspx';" & Chr(13) & Chr(10))
response.write("parent.MAINFRAME.location='" & strRealPage & "';" & Chr(13) & Chr(10))
End If
response.write("}" & Chr(13) & Chr(10))
response.write("</script>" & Chr(13) & Chr(10))
End If

 Whistleblow
Concerned that QuidCorp might actually ship something so fetid and maligned, Terry decided he had to pay a visit to QuidFlow's project manager.

"You're right, Terry, this is in no way a solid application, but unfortunately, it is what it is," the project manager explained. "However, that's why we're assigning all you C++ guys with your awesome track record to look into these bugs so we'll be able to ship QuidFlow!"

Somehow, the compliment didn't feel right. At the end of the week, Terry and his fellow QuidFlow developers were pulled from their on-the-job .NET training. QuidCorp had just sold a motherload of QuidFlow licenses to a corporate client and they were asking for some big-time enhancements, which would of course mean they needed all C++ developers on hand immediately.

While the move of QuidFlow to .NET was on hold until some time freed up, their hands-on .NET training wasn't all for nothing. When the time came, at least they would know how not to develop a .NET app.


Tell Us Your Tale



About the Author

Mark Bowytz is a contributor to the popular Web site The Daily WTF. He has more than a decade of IT experience and is currently a systems analyst for PPG Industries.

comments powered by Disqus

Featured

Subscribe on YouTube