We're in the process of redesigning the customer-facing section of our site in .NET 3.5. It's been going well so far, we're using the same workflow and stored procedures, for the most part, the biggest changes are the UI, the ORM (from dictionaries to LINQ), and obviously the language. Most of the pages to this point have been trivial, but now we're working on the heaviest workflow pages.
The main page of our offer acceptance section is 1500 lines, about 90% of that is ASP, with probably another 1000 lines in function calls to includes. I think the 1500 lines is a bit deceiving too since we're working with gems like this
function GetDealText(sUSCurASCII, sUSCurName, sTemplateOptionID, sSellerCompany, sOfferAmount, sSellerPremPercent, sTotalOfferToSeller, sSellerPremium, sMode, sSellerCurASCII, sSellerCurName, sTotalOfferToSeller_SellerCurr, sOfferAmount_SellerCurr, sSellerPremium_SellerCurr, sConditions, sListID, sDescription, sSKU, sInv_tag, sFasc_loc, sSerialNoandModel, sQTY, iLoopCount, iBidCount, sHTMLConditions, sBidStatus, sBidID, byRef bAlreadyAccepted, sFasc_Address1, sFasc_City, sFasc_State_id, sFasc_Country_id, sFasc_Company_name, sListingCustID, sAskPrice_SellerCurr, sMinPrice_SellerCurr, sListingCur, sOrigLocation)
The standard practice I've been using so far is to spend maybe an hour or so reading over the app both to familiarize myself with it, but also to strip out commented-out/deprecated code. Then to work in a depth-first fashion. I'll start at the top and copy a segment of code in the aspx.cs
file and start rewriting, making obvious refactorings as I go especially to take advantage of our ORM. If I get a function call that we don't have, I'll write out the definition.
After I have everything coded I'll do a few passes at refactoring/testing. I'm just wondering if anyone has any tips on how to make this process a little easier/more efficient.
Believe me, I know exactly where you are coming from.. I am currently migrating a large app from ASP classic to .NET.. And I am still learning ASP.NET! :S (yes, I am terrified!).
The main things I have kept in my mind is this:
- I dont stray too far from the current design (i.e. no massive "lets rip ALL of this out and make it ASP.NET magical!) due to the incredibly high amount of coupling that ASP classic tends to have, this would be very dangerous. Of course, if you are confident, fill your boots :) This can always be refactored later.
- Back everything up with tests, tests and more tests! I am really trying hard to get into TDD, but its very difficult to test existing apps, so every time I remove a chunk of classic and replace with .NET, I ensure I have as much green-light tests backing me as possible.
- Research a lot, there are some MAJOR changes between classic and .NET and sometimes what can be many lines of code and includes in classic can be achieved in a few lines of code, think before coding.. I've learnt this the hard way, several times :D
Its very much like playing Jenga with your code :)
Best of luck with the project, any more questions, then please ask :)
After I have everything coded I'll do a few passes at refactoring/testing. I'm just wondering if anyone has any tips on how to make this process a little easier/more efficient.
Normally I'm not a fan of TDD, but in the case of refactoring it really is the way to go.
Write some tests first which verify what the bit you're looking at is actually doing. Then refactor. This is a LOT more reliable than just 'it looks like it still works.'
The other huge benefit to this is that when you're refactoring something which is further down the page, or in a shared library or something, you can just re-run the tests, as opposed to finding out the hard way that a seemingly unrelated change was actually related
You're going from classic ASP to ASP with 3.5 without just re-writing? Skillz. I've had to deal with some legacy ASP @work and I think it's just easier to parse it and re-write it.
A 1500-line ASP page? With lots of calls out to include files? Don't tell me -- the functions don't have any naming convention that tells you which include file has their implementation... That brings back memories (shudder)...
It sounds to me like you have a pretty solid approach -- I'm not sure if there is any magical way to mitigate your pain. After your conversion effort, the architecture of your app will still be messy and UI-heavy (i.e. code-behind running workflows), and it will probably still be fairly painful to maintain, but the refactoring you are doing should definitely help.
I hope you have weighed the upgrade you are doing against just rewriting from scratch -- as long as you are not intending to extend the app too much and you are not primarily responsible for maintaining the app, upgrading a complex workflow-based app like you are doing may be cheaper and a better choice than rewriting it from scratch. ASP.NET should give you better opportunities to improve performance and scalability, at least, than Classic ASP. From your question I imagine that it is too late in the process for that discussion anyway.
Good luck!
Sounds like you have a pretty good handle on things. I've seen a lot of people try to do a straight-line transliteration, includes and all, and it just doesn't work. You need to have a good understanding of how ASP.Net wants to work, because it's much different from Classic ASP, and it sounds like maybe you have that.
For larger files, I'd try to get a higher level view first. For example, one thing I've noticed is that Classic ASP was horrible about function calls. You'd be reading through some code and find a call to a function with no clue as to where it might be implemented. As a result, Classic ASP code tended to have long functions and scripts to avoid those nasty jumps. I remember seeing a function that printed out to 40 pages! Parsing straight through that much code is no fun.
ASP.Net makes it easier to follow function calls around, so you might start by breaking out your larger code blocks into several smaller functions.
Don't tell me -- the functions don't
have any naming convention that tells
you which include file has their
implementation... That brings back
memories (shudder)...
How did you guess? ;)
I hope you have weighed the upgrade
you are doing against just rewriting
from scratch -- as long as you are not
intending to extend the app too much
and you are not primarily responsible
for maintaining the app, upgrading a
complex workflow-based app like you
are doing may be cheaper and a better
choice than rewriting it from scratch.
ASP.NET should give you better
opportunities to improve performance
and scalability, at least, than
Classic ASP. From your question I
imagine that it is too late in the
process for that discussion anyway.
This was something we talked about. Based on timing (trying to beat a competitor's site to launch) and resources (basically two developers) it made sense to not nuke the site from orbit. Things have actually gone much better than I expected. We were aware even from the planning stages that this code was going to give us the most problems. You should see the revision history of the classic ASP pages involved, it's a bloodbath.
For larger files, I'd try to get a
higher level view first. For example,
one thing I've noticed is that Classic
ASP was horrible about function calls.
You'd be reading through some code and
find a call to a function with no clue
as to where it might be implemented.
As a result, Classic ASP code tended
to have long functions and scripts to
avoid those nasty jumps. I remember
seeing a function that printed out to
40 pages! Parsing straight through
that much code is no fun.
I've actually had this displeasure of working with the legacy code quite a bit so I have a decent high level understanding of the system. You're right about the function length, there are some routines (most I've refactored down into much smaller ones) that are 3-4x as long as any of the aspx pages/helper classes/ORMs on the new site.
I once came across a .Net app that was ported from ASP. The .aspx pages were totally blank. To render the UI, the developers used StringBuilders in the code behind and then did a response.write. This would be the wrong way to do it!
I once came across a .Net app that was ported from ASP. The .aspx pages were totally blank. To render the UI, the developers used StringBuilders in the code behind and then did a response.write. This would be the wrong way to do it!
I've seen it done the other way, the code behind page was blank, except for declaration of globals, then the VBScript was left in the ASPX.