DATABASE oKlant // my early way
and then stuff for oKlant
I see many times :
oCustomers:= TDatabase():New(,"temp",,.f.)
oCustomers:use()
Is the second way the way it should be done in order to use ALL options in FWH or is it the same ?
You can use all options of the database when it is an object. One of the great things when you use an object is that you don't have to deal with workareas at all. You can even have multiple copies of the same database open at the same time, even in the function. This allows you to open a database in a function, use it, then close it, even while it is open in another function. Without this capability you had to save and restore the database state (including workarea, indexes, filters, scopes, recno, etc.).
Also you should not open a database object like in your second example. You should always try to write code only once. This reduces code and thus the chance of errors.
Also you want to emulate the real world, so you create a customers class and open the database and index(s) in the class.
Code: Select all | Expand
Class TCustomers from TDatabase
Method New()
Endclass
Method New Class TCustomers
::use(,"Customers","customers")
Return self
Note that I use the class name "Customers" (plural). This is because the database is full of single customer records and we also need a "TCustomer" class for a single customer object. So now we can do:
Code: Select all | Expand
oCustomers := TCustomers():new() // create the table object
oCustomers:seek("12345")
Now the code to open a database exists only in the object's new method. Thus if you want to change or add an index, you only have one place to modify. Also if you want to change the location of the database, you do it in the new method only. Actually better would be to create a parent object for all databases, that specifies the location, then all database class inherit from that parent class. Now the location only exists in one place.
Now we can create a single customer object.
Code: Select all | Expand
oCustomer:= TCustomer():New(oCustomers:custno) // create a customer object
So now we can use the customer object to query for name, address, balance, past due, last invoice, etc. You can also pass it to another object or function and within that object or function you can get access all the object's data and methods. Note that you add methods to the object instead of using functions. This follows the rule of "encapsulation." You encapsulate "functions" for customers into methods of that object.
Since the customer object is a smart object it knows how to update any appropriate databases with the payment information.
Using this technology I have taken existing programs and reduced the code by 50-70 percent. This is because you can eliminate a lot of repetitive code, and less code means less chance of errors, and it is much easier to read and understand.