On a recent project, I inherited a rather large code base. The developers had long since moved on and all the in-house knowledge of the application left with them. Before I could even really get down to business I had some logistical problems to work out. The source control system in place wasn't accessible from my remote location and the build system was very dependent on the network layout. The code had been under development for nearly 10 years and was a mix of PC-based code and cross-platform shared code with the firmware for several hardware products. It was pretty hard to know where one product ended and another began. It was a mix of C++, Python and C. And this code was very technical. Lots of concurrency, thread management, parts made heavy use of COM, rendering stuff, low-level bit-twiddling stuff, you name it.
But, the code was neat. There was a consistent coding style. It was well structured with clear delineation between modules. In several places there were API's established for third-party integration. There was an architecture and good attempts at getting some automated tests in place. Pattern names were used and standard development idioms were followed. Sure, much of it was organic growth and you could see where the developers had some crosses to bear, but there was clear evidence of intelligent life and a passion for the code base. All in all, it was pretty darn impressive.
One of my first tasks was to get the code running again. I needed to get it moved over to a new version control system and then get it working with the latest compilers and libraries. From there I could work on getting the much needed new features in place that the the customer needed. It was a big task, but it was fun to dig through a nice code base and see how the previous people did it. It was like discovering a nice old house and walking through the rooms to admire the craftsmanship without a guide.
With that one under my belt, I got the "lucky" task of being given another legacy code base. This one wasn't as big as the previous. It wasn't as technically complicated either. Yes, there was multi-threading, interprocess communications and some tricky GUI stuff going on there, but all in it nothing that you couldn't wrap your head around. It was just C++ with MFC. Very little COM. Windows only. I had a little bit of guidance from a couple of the last developers to work on it, but once they left I was really on my own to understand all the nooks and crannies of the product. Again, I had to move it over to the new source control system and update the compilers and libraries and make the build system less rigid.
But this second code base was a mess. There was no coding style. Variable names were cryptic with a mishmash of Hungarian Notation forms. Every class (when classes were used) was tightly coupled to each other. There was no modularity to the architecture. There was no structured exception handling, no provisions for automated tests, no organized logging to speak of. Constants changed. Code was copy pasted everywhere it was needed. One feature I needed to remove, which was essentially a boolean check, touched over 40 files across four applications. Data lived everywhere and had no core data dictionary of usage, so you had to trace the code to find out what the intended use was.
Basically, the second code base was buried in technical debt.
This is not to blame the developers or the management. There are no fingers to point here ... there's no one left to point them at anyway. It's like an archaeologist stumbling on a lost city and learning that the citizens died of a common disease ... it wasn't their fault. But we now know that, with some basic medicine and health practices, it could have been avoided.
I'm an Agile guy. I love the innovations in the software development process of the last ten years. But this experience opened my eyes to where the real work of software development needs to be done ... in the code. I have no idea what the development methodologies used were when these code bases were being developed. Perhaps they were Waterfall? Perhaps they were some Scrum/XP hybrid? Who knows? Who cares. The code is the only thing left that matters. Developers need to remember that the process, the methodology, should not take precedence over code craftsmanship. Don't get so mired in the busy work to lose track of what you're doing in the first place ... writing code. The code is paramount.
I'll follow up this post soon with some of my other insights on this experience and recommend some steps that could have been taken to help Project 2 out.
Tuesday, January 26, 2010
Friday, January 08, 2010
Installing IronPython 2.6RC1
I'm not a .NET guy at all. I'm in the process of working with a third party C# library, but would rather use IronPython instead of C#, so I tried to install IronPython 2.6 RC1 ... it didn't go well. The installer would get to about 90% complete, but then fail and rollback without any info as to what went wrong.
By manually running the .msi installer we can get a log file:
msiexec /i IronPython-2.6.msi /log install.log
The offending operation seems to be:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ngen.exe install C:\Program Files\IronPython 2.6\Microsoft.Scripting.dll /queue:1The /queue parameter is to kick off the .NET Optimizing compiler service ... but this seemed to be failing. I could verify this when I ran the ngen.exe command directly:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>ngen queue statusMicrosoft (R) CLR Native Image Generator - Version 2.0.50727.3053
Copyright (c) Microsoft Corporation. All rights reserved.
The specified service does not exist as an installed service. (Exception from HRESULT: 0x80070424)
Hmm, where's my JIT?
Turns out my .NET Runtime Optimization Service v2.0.50727_X86 service is either not running or not installed. In my case it was not installed. Very odd as I have .NET 2.0 -> 3.5.1 installed and everything else works. Oh well.
After some poking around I found you can register the service manually via:
%WINDIR%\Microsoft.NET\Framework<64>\v2.0.Number\mscorsvw.exe -i
Or, in my case, C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>mscorsvw.exe -i
That got the service installed and the IronPython install worked fine afterwards.
Hope this saves someone some time.
Subscribe to:
Posts (Atom)