tags:

views:

136

answers:

2

I have been assigned the task of refactoring a legacy database application and I am trying to create objects that incapsulate the old code. It is the first time I use real OODesign, for now I just used OO to encapsulate some legacy login and refactor a subset of functionalities from an application. (Now it is the classic client server app with all the business logic in the UI, the idea is to make it multilayer in order to use the clients against an application server and eventually write a web interface.)

I'll make an simplified example to explain what I want to accomplish:

I have many instances of this class:

type
  TCustomer = class(TObject)
  private
    FOrders: TList<TOrder>; // or how do implement this?
    // the idea is that the TCustomer "owns" the TOrder, anyway in the 
    // legacy DB I just have an orders table with FK to the customer table
    // not the contrary. 
    // But if I do that the Customer object "loses" the TOrders???
    [...] // Many other fields
  public
    [...]
  end;

How do I query the Orders of all the customers? Imagine I want to query all the orders from September 2007.

If I have 10000 TCustomer objects I don't want for sure to create them all (that means retrieveing them all from the database: I would retrieve too many info I don't need).

In the current software of course it is done with a simple query to the orders table.

But how this is accomplished in the OO world?

Which is the approach you suggest me?

Moreover: in refactoring a this kind of database applications do you suggest using an ORM (that means creating a new database and migrating all the data) or simply use existing DB (that is not bad in my case)?

+4  A: 

The solution is not trivial and I wouldn't call it simple. What you are looking for is called lazy loading.

The basic idea is to create a proxy object that will load the objects from database on request and preferably do some smart caching as well. In your case this object would be your own implementation of TList - just derive from it and override corresponding methods to load and construct objects from the database.

There are mature frameworks that do object-relational mapping, including lazy loading. One of such examples is Hibernate. If you are allowed to use .NET within your Delphi application, you may check a .NET port of it called NHibernate. Another option would be to use iBatis or any of the frameworks listed at Wikipedia.

dark_charlie
Why there are no Delphi examples on wikipedia (or almost not). Unfortunately I cannot contribute since I don't define me as expert, but it would be very good that all OOPatterns would be written in Delphi too. Do you think it is possible to have this?
But are you sure lazy loading is what I need? I mean do I need to create TCUstomers or should I have something like TOrdersConsultation object that somehow bypasses the TCustomer object=
I would create a list of orders that maps to the database. You can access this list either directly (when listing all orders) or point to its items from TCustomer objects. This list would be the interface between database and your objects. And yes, you will need lazy loading, unless you want to always load all orders when initializing the list.
dark_charlie
+2  A: 

I agree with dark_charlie that doing this kind of work is not trivial or simple and I would recommend going with a framework.

Apart from the two commercial ones for Delphi listed on the Wikipedia page he mentions, there are several Open Source ones for Delphi as well.

A couple of others are mentioned in the answers to this stack overflow question: http://stackoverflow.com/questions/422426/orm-for-delphi-win32

Most if not all will support using them against an existing database, though that may require some coding/handiwork on your part to tell the framework how to map your classes to the existing tables and columns.

Marjan Venema