views:

290

answers:

7

I would like to refactor a large legacy application originally written in VB6 and subsequently ported to .NET. In order to do this with confidence, I want to have unit tests around the existing code so I can compare before and after. What's the easiest and most effective way of doing this?

There's a book called "Working Effectively with Legacy Code" that looks like it might help me. However, it looks like it only deals with object-oriented languages and VB6 is not necessarily OO. Can this book still help me? I'm hoping someone who's read it can vouch for it.

Specifically, this application uses no classes other than the forms themselves. It accesses the db directly from the forms, and not consistently. There were several people working on this project all using their own styles with no standards whatsoever.

Final Edit: As I said, this project has been ported to VB.NET. However, it's only ported in the sense that it compiles under VS2008. All of the coding concepts are VB6.

+6  A: 

It does not just deal with oo languages large sections are how to deal with legacy code in C.

So yes buy it!


There is a whole chapter (Chapter 19) called:

My project is not object oriented. How do I make safe changes?

Also there is vbunit an xunit implementation that may help you use TDD with VB6.

Actually I misread the question and thought you were going to port not that already have ported. In this case you have a ton of 'legacy' VB.Net code that this is totally the book for you. You can take advantage of VB.Net's OO capabilities and use the rest of the book.

I really cannot recommend this book more.

John Nolan
+1. One tiny niggle though. The question says the app has been ported to VB.NET so vbunit won't be relevant.
MarkJ
thanks MarkJ I've edited as appropriate
John Nolan
Thank you, that's what I needed to know. I'll pick up the book. Also, Thank MarkJ for your various comments -- they're spot-on.
awhite
+2  A: 

Yes; the book's concepts are great and powerful and extend beyond OOP. And VB6 can be object oriented, although it's not as thoroughly object-oriented a language as some.

Among the most powerful concepts in the book is that of "seams," essentially places where you can break your code up, to inject tests or to isolate or abstract bits of functionality. This is but one of the concepts that applies even to procedural code.

Carl Manaster
+2  A: 

You may want to make the questions more specific.

While VB6 isn't a pure OO language per se, there are enough elements of OO that things ought to be familiar; also, there are a number of unit testing plug-ins for the VB6 IDE.

But let's consider some of the high-level VB6 components:

  • Forms ARE objects (you can create new instances).
  • Modules behave like classes with only static methods.
  • Classes & UserControls are as close to objects you'll get. The lack of constructor makes things rough, but hopefully the original developer stayed with Initialize or wrote a consistent Init sub.
  • Events in VB are odd; it's also what'll probably trip you up the most. Hidden, stateful code that depends on a particular ordering of events are no doubt scattered all over the place.
  • Property pages. Well, it is what it is.

Start with VB's best-practices. If the app wasn't written with best-practices code in mind, I think taking that step will save you a lot of trouble down the road.

hythlodayr
Fair enough. I'll edit my question to highlight my concerns.
awhite
+1  A: 

I would suggest taking a look at Martin Fowler's Refactoring: Improving the design of existing code, which is an excellent must-read.

You might be looking for something along the lines of Professional Refactoring in Visual Basic. I haven't read it, but it looks applicable.

Jacob
I read Martin Fowler's Refactoring book which is what made me realize I need tests around my legacy code. You are correct, it is an excellent must-read.
awhite
+1  A: 

Sorry for the "double post", but it's a bit hard to answer within 600 characters..

You definitely have some work cut out for you, but here's a strategy to consider before doing ANY .NET work.

Move out as much of the underlying FORM code as you can into a class: One class file per form as a start. In essence, the form event handlers should do nothing but proxy calls to methods in an underlying class instance; all of the custom methods can obviously be shifted over to the class file.

After reading the best practices guide (etc.) by Microsoft and others to help you to prepare for .NET migration, you're basically set for the little bits of hell you'll have to recode/refactor: Annoyances such as error handling, event ordering, late bound objects/variants, collections, etc.

A word on error handled code: It's is especially hard to duplicate spaghetti on-errors, particularly since the average VB coder had a bad knack for using it as a flow-of-control logic. It's almost worth breaking apart each On Error block into separate sub-routines, if you have more than a two in a routine.

Once the code has been cleaned-up, you may also consider refactoring the VB code into sensible abstractions (e.g., a single data adapter class & connection, etc.), but you'll be the best judge of that.

You may not like this approach, so definitely test the waters with one form.

hythlodayr
Reasonable advice, but putting in unit tests should probably be the very first job (as in the original question)
MarkJ
Unit testing FORMs (as written) is hard.It's more manageable to create classes that capture the form's event/stateful logic in all its glory and simulate events in the unit test.But you're right. The rest of the advice should come AFTER the unit tests are written.
hythlodayr
You're right about unit testing forms. RS Conley has written some interesting answers elsewhere on Stackoverflow about using forms that are thin wrappers delegating to a class, which he says has many advantages including testability. He calls it the "passive screen" approach (after Martin Fowler).
MarkJ
+2  A: 

I own a copy, that I purchased to try get our C/C++ project under control. As I missed the functionality C#/.Net has to offer.

The books is very C/C++ ish, but as John say there is the chapter of working without objects.

But, if as you say, your code is ported to .Net it is not longer VB6 code. .Net has lots of VB/C# ways of letting you hook into your code and test. But that said the book will give you a good overview of the different ways you can hook into an application, and strategies for getting a large old project under-control.

Simeon Pilgrim
A: 

I think that you will find characterization tests the most benefit. They should be automated. Without characterization tests you will then be left with testing your application/code manually by actually running it. It is so easy to miss testing critical functionality when adding new code. This comes from my own experience.

Sprout Method and Sprout Class are important when adding new code.

Gutzofter