How / if to refactor a Delphi program using only forms and data modules
Asked Answered
E

6

20

After years of coding Delphi programs as untestable code in forms and datamodules, including global variables, and the only classes are the forms themselves, containing all the code I need for the form UI itself.

How would I convert the code to a set of classes that do the actual work? would I need to stop using the datasources/datasets and do everything in classes? do I need an ORM?

There's usually zero need for reuse of the code in the forms, so does it make sense to convert the logic to classes?

Exsiccate answered 14/2, 2009 at 17:4 Comment(0)
P
28

If I encounter a form (or other class) with too much responsibility, I usualy follow the pattern below:

  1. Define a new class for the logic.
  2. Create a member variable of the new class in the form.
  3. Create the class in the onCreate and free it in the onDestroy of the form.
  4. Move a single piece of logic (for example a variable) to the new class.
  5. Move or create all methods to the new class.
  6. Compile and test.
  7. Continue until all logic is put in the new class.
  8. Try to decouple the logic class from the form class. (You can even work with interfaces if you like).

There are situations where a single class is not enough, so it is no problem to create more classes. And these classes can have other classes to.

With these steps, you can tackle most of these problems.

Periodate answered 14/2, 2009 at 19:32 Comment(4)
Good steps, but one tip: for minimum coupling possible do not pass any visual controls to your new classes. If you do then you restrict your ability to swap out UI controls. If you must pass visual controls (especially grids, etc.) then isolate all of it in one other class with no business logic.Lycia
I agree, visible controls are the responsibility of the form. It is possible to use frames, but I don't really like them for production code.Periodate
All good points. What about unit-testability of something which relies on a particular database connection, and data table objects (TTable, ADO datasets, or datasnap, etc)....Howardhowarth
@Warren P, with a database you can either mock the entire database interface, or you can use a special test database that is set up for each test. I prefer the later, but it slows the tests down a bit.Periodate
S
8

To start with I can highly recommend reading the book Refactoring by Martin Fowler.

This will give you a real understanding about how best to sensibly approach introducing changes to the existing (non OO) code to improve maintainability.

I would not look at an ORM until you have a clear understanding about what benefits (if any) one would bring to your application.

Summers answered 14/2, 2009 at 17:11 Comment(0)
M
5

I have encoured problem like this with one application, I start doing the following:

  1. Define main classes for most general logic in the code.
  2. In each form, move the code that process the business logic inside the events as function / procedures in that form.
  3. Then Move these functions/procedures to those classes as static methods.
  4. Finally make only the needed code inside forms like validation UI, and calls to the classes.
  5. For the global variables try to omit as much as you can, and just pass the values as parameters to the methods.

I used static methods, because it's easier for you to remove the code from events and just call them without requiring to Create/Free object for each operation. The original design was not designed to separate the forms from business logic code.

The final application was not full OO, but it least it was easier to test the methods without requiring interacting with the forms and events like before.

Sometimes you feel if you redesign the application from scratch it will be easier than to made changes to make it real OO design.

Madwort answered 15/2, 2009 at 7:50 Comment(0)
K
4

Another book I can highly, highly recommend - in my personal opinion even better suited than the "generic" refactoring book by Fowler - is "Working Effectively with Legacy Code" by Michael Feathers. It truly showcases the major bumps you will hit while doing that kind of work. Oh, and: Refactoring legacy code can be quite hard on your psyche. I hope you can handle frustration... I like this quote (don't remember where I got it from): "God was able to create the world in 6 days, just because there wasn't any legacy code". Good luck. ;)

Katherinkatherina answered 14/2, 2009 at 20:44 Comment(0)
F
4

Importing into Modelmaker is my first action when confronted with an existing Delphi project. Modelmaker will assist you in refactoring your code because:

  • It graphically represents all the classes, methods, variables, etc.
  • It is very tightly integrated in the Delphi IDE (main menu, popup menu, separate Modelmaker explorer, toolbar, keyboard shortcuts). This integration allows you to quickly perform the necessary actions without leaving the IDE
  • It has a dedicated "refactoring" module allowing you to quickly create, move and rename classes and variables without having to worry about changing the underlying code. Modelmaker will automagically change names and references in all units.

The basic functionality of Modelmaker is easy to learn. Modelmaker is like any other good productivity tool - The more you put into it, the more you get out of it. Modelmaker is not free but easily pays for itself in increased productivity. I have not found a better tool for refactoring legacy Delphi code. They offer a free trial and some decent tutorial movies. Give Modelmaker a try and good luck...

Flit answered 21/2, 2009 at 3:6 Comment(4)
Nothing against ModelMaker, but all of the things that you've mentioned are built in nowadays. Still, +1 for being helpful in case you've got an older Delphi.Phaeton
Thanks - I'm still using Delphi 5. I know that the Modelmaker boys had a code sharing agreement with Borland. Lots of Modelmaker functionality was integrated in the Delphi IDE. I guess if all the Modelmaker functionality is integrated in the IDE then nobody will be spending 199 Euros for a license.Flit
@Kris, Actually refactoring functionality integrated is not from ModelMaker but from Borland Together (which is MUCH more unfriendly). I used both Delphi default modeling and ModelMaker is much easier to grasp for a Delphi developer.Twyla
+1; note that ModelMaker and ModelMaker Code Explorer are two distinct products. ModelMaker is the UML tool, ModelMaker Code Explorer the refactoring tool that tightly integrates in the Delphi IDE. It works much better than the refactorings that are already in the IDE (for one, because it can operate on code that does not fully compile, but also because it has more and better refactorings). A few eons ago, ModelMaker was included in Delphi (before the Together integration). I wish they had continued that. A good thing about the built in rename symbol refactoring: it covers your whole project.Stacey
D
1

After understand what you need to refactory your code, and if you want an OPF/ORM, I suggest Jazz SDK

Ditmore answered 14/2, 2009 at 18:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.