A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.
Have you done a conversion like this or are you in the middle of one now?
What are your ideas from the trenches on transforming a legacy Windows app to .NET... Did you rewrite from scratch? Wrap "unmanaged" C++ objects? Use IJW (It Just Works)? Are you happy with results? Anything you'd do differently? Advice for others on the trail behind you?
We've got a 10yr old, heavily OO C++ financial app that's built with an outdated framework/IDE, and we'd like to shovel the app over to dotNET. The UI's gotta go, but what we do with our business objects/rules, etc, is up for grabs -- programmers lean toward full rewrite for a clean code & long term maintainability, but mgmt will no doubt push for a shorter path.
Your thoughts appreciated!
Write the UI in .Net if you want, and refactor the C++ back-end to make it up to date.
Thursday, September 29, 2005
Do you have a COM/DCOM interface to your apps? Then you could use COM/.NET interoperability for the migration (if your COM interfaces are "nice").
First you could make the new .NET GUIs use the COM interfaces. Then, if there's a reason why you'd need to migrate the server stuff to .NET (I don't know why you would, it's not obvious), you can actually set the /CLR switch on individual .cpp files and make IJW do the interoperability work, to do a migration part by part of the server components. At least, you could then start by replacing the COM interfaces by web service interfaces (if that's OK for performance). Otherwise you'll have to wait for Indigo to become stable...
Something like that. Makes sense in your situation?
>> We've got a 10yr old, heavily OO C++ financial app
So it's got a huge amount of intricate and badly-documentd functionality, I'm going to guess.
>> what we do with our business objects/rules, etc, is up for grabs -- programmers lean toward full rewrite for a clean code & long term maintainability
That might be why they claim to lean toward full rewrite, but in reality they lean that way because writing from scratch (what does 'rewrite' mean apart from 'write' ?) is MORE FUN than maintaining an old codebase. Don't let them do this.
>> but mgmt will no doubt push for a shorter path.
Shorter and *safer*.
Things you should never do (part 1)
"the single worst strategic mistake that any software company can make: ... to rewrite the code from scratch."
There are lots of ways to wrap exisitng C++ code in such a way that a .NET front end can call it, with very little in the way of seams. So write the new UI in .NET; write new 'business rules' in .NET; write wrappers for the old code in .NET; *leave the existing functionality in the C++ code that already implements it*
I agree. Don't rewrite! I'd say upgrading the C++ version from the "old" version (10 years ago?) to Visual Studio .NET would be a good idea anyway; that would then fall under "refactoring".
I left out the fact that our app is essentially COM ignorant (built with Borland's old OWL framework). In tests, we've used an OWL trick to host an entire "old" window in .NET - as an ActiveX object I believe - but some scary instability showed up as well. It appears the typical COM paths to .NET are closed to us. Ugh...
Your post and the joel article are sobering indeed.
The "rewrite" view is that our app's key pieces are:
1) numerous simple screens with lots of get/set UI: no problem for rewrite, just ship off data to db!
2) data integrity/validity: 95% of business rules/logic are imbedded in "old" client/server UI(ouch), so moving to .NET UI forces reinvention of most bus. logic regardless of migration/refactoring path chosen.
3) a few key business processes: thoughtful new design on key transaction processing area will take serious time, but will create overall mtce savings over the life of the product
...Obviously its not an attempt to describe architecture, but just my take on the "key task" thoughts of the rewrite advocates. And believe me, there are days when it looks compelling.
Anyway, post on, brothers and sisters. I'm interested in more stories form the "legacy to .NET migration" swamp; They can help us and others make our way through the swamp to the other side.
My gut feeling is that shifting business logic out of the UI first makes quite a lot sense. After that it should be relatively easy/inexpensive to port the application to any modern UI, not necessarily the .NET one.
By the way, at the very moment I am trying to ditch some 100 KLOC of MFC/Fox-Toolkit/C++ in a favor of Whidbey C#. It is quite a forced decision, since in my home country all good C++ programmers I know of are working at Skype and there is no way I can offer competitive salary. There is a lot of homework to do, since my applications span quite a wide area - OpenGL, DirectShow, serial ports, networking, interfaces to custom-made hardware, memory-mapped data files, etc. It is not impossible that I have to re-think my decision after doing the homework.
Sounds like programmers running amuck, and the business people are no longer in charge (what's the requirement for the move to .Net in the first place). There was a story called "The Titanic" but anyway, I digress.
Thursday, September 29, 2005
OK, so it's not even Microsoft's C++, then. Borland C++ Builder? I'm afraid I'm not familiar with that. Can you link the .obj files from C++ builder with the .obj files from Microsoft Visual C++ (should be compatible, right?) and write wrappers for the external interfaces, to link them together? Just a thought; could be easier than some other migration paths. If the interfaces are still evolving, that would probably be too painful in the long run.
Probably Borland C++ 5.02, right? That was the last version before C++ Builder.
I think you have some good advice here.
Have one team start on the new UI using .NET managed code.
Have another team move the business layer to DLLs.
Call the DLLs from the UI.
Move the DLLs to .NET at the pace you desire.
Yep, BC++5.02 is on the money.
Much of bus layer is in plain vanilla DLLs already - as I said before, no COM here. I think that means wrapping "unmanaged" business layer code is in our future as you noted... __gc, managed extensions and the like, right?
So has anybody wrapped a sizable C++ app for .NET in this fashion? One thing that's easy to find is people writing about how to do it; see http://www.ondotnet.com/pub/a/dotnet/2004/03/29/mcpp_part3.html?page=2 for a sample walkthrough.
The thing that seems harder to find is people who have actually done it. Is that because people see all the code involved in wrapping even a simple demo/toy class at links like the one above and then they think: "Oh sh*t, looks like wrapping everything is pretty painful and requires lots more effort than we thought...if it's gonna take all that time and extra code to wrap for .NET, we might as well rewrite for .NET"?
OK, so you've got a DLL interface, of course.
What about the "DllImport" attribute, then?
Could be useful.
Friday, September 30, 2005
I used to be a big OWL proponent, until I started seeing it get crushed by MFC. That kinda fed my NIH problem.
The best suggestion I have seen here is is moving business logic to DLL's and rewriting the UI in dotNet. I wouldn't do that though.
If I were you I would avoid DLL's entirely - they were a bad idea when they were introduced, and they become more pointless as they age.
Tying the UI to dotNet ties you to dotNet. After getting burnt by one tie-in, volunteering to get burnt by the next earns you a front seet on the short bus. (*SMACK*)
That criticism might be too harsh. But dotNet is set to do another revision. The revision of tie-ins (IE and COMCTL32.OCX - I curse thee!) has caused me both problems and embarrassment.
What I think you should do is try a sample applications (small) using GCC and an open source GUI library. If that works well then port using those tools.
The upside(s) are 1) You can reuse most of your code, 2) you have control over the source. It should immunize you against changes in operating systems and compilers.
Disclaimer: This advice doesn't make sense for applications with short lifespans. In that case always choose the most productive tool, which is usualy microsoft.
Friday, September 30, 2005
What I was suggesting is you rewrite the GUI in the .NET language of your choice and move all the guts and business logic to DLLs that export a standard "C" interface. You can still use your C++ code inside the DLLs. You can make your C++ classes available to the .NET layer via handles (Like the Windows API does with HWNDs). It's not the most elegant solution, but it gives you a place to start.
Eventually, you can move the business logic into a web service or business layer component, etc., that is callable via XML or another protocol.
Once all this is done, you can begin porting the business layer to .NET, if you wish.
The goal is to avoid having to port everything at once.
I have just gone through a situation very similar to the one described in this thread. The scenario at my company involves a C/C++ graphics toolkit (in a dll) that has traditionally been used with an MFC front-end when in Windows. Lately, we've been getting requests for a .NET solution.
The first kick-at-the-can involved using the IJW (it just works) methodology, informing our customers that the integration was successful. We did not encounter a single problem, other than an apparent reclaimation of a window handle with transparencies, but that's for a different thread. Well, our company viewed it as successful, our customers, well, they must have had some dire need for a .NET library.
Ideally, since we needed to produce a .NET library, the coder-preferred solution was to take a year and re-write the code in Managed C++. Being a coder myself, I appreciate this view, but realistically, that is never really an option when customers are waiting. The only available solution was to wrap the C++ dll. Using DllImport was not an option due to the large number of classes and the resulting inelegance.
Wrapping the library was mostly simple grunt work, however there is one major pitfall to watch out for: passing memory across the managed/unmanaged boundary. The problem comes about when you have a wrapped object, B, containing an instance of unmanaged class, A. Consider what happens when A is passed into the dll space for management (placed into a container, etc). Object B is still being used in the developers eyes, and should not get GC'ed. However, the CLR does not know this. If object B goes out of scope and gets GC'ed, object A has just had its legs cut off at the knees, the dll now pointing to dead memory. To avoid this, GCHandle was used when such a situation existed in our wrapping.
Hopefully that makes sense, if not, feel free to email me and I'll clear it up.
>> Can you link the .obj files from C++ builder with the .obj files from Microsoft Visual C++ (should be compatible, right?) >>
Now *that's* funny. You can't make this stuff up...
Tuesday, October 11, 2005
This topic is archived. No further replies will be accepted.Other recent topics
Powered by FogBugz