Marc : Conversion process and questions about it

User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: Marc : Conversion process and questions about it

Post by Marc Venken »

James,

One of your favorites is also a question....

I used in early days rather small object programming, and at this point i'm not going to changes a lot of it, more if new stuff wil be added it will become a option.

I used

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 ?

If I reachs the process of TDATABASE i will come back on this options...
Marc Venken
Using: FWH 20.08 with Harbour
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Re: Marc : Conversion process and questions about it

Post by James Bott »

Marc,

You really need to avoid filters. Filters require reading the entire database each time you call them. So for an incremental search of 10 characters you are going to read the entire database 10 times.

Even if you don't do an incremental search, you still have to read the entire database using a filter. Using a scope you only read the database records you need. Way faster!

Another possibility is to use a scope, then filter only the records in the scope.
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: Marc : Conversion process and questions about it

Post by Marc Venken »

James Bott wrote:Marc,

You really need to avoid filters. Filters require reading the entire database each time you call them. So for an incremental search of 10 characters you are going to read the entire database 10 times.

Even if you don't do an incremental search, you still have to read the entire database using a filter. Using a scope you only read the database records you need. Way faster!

Another possibility is to use a scope, then filter only the records in the scope.
I use scoped filter... They are fast.

BTW : Speed is not the problem. All by all... it is fast enough, but optimising code can speed things up, unless the functions I posted are not correct ??
Marc Venken
Using: FWH 20.08 with Harbour
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Re: Marc : Conversion process and questions about it

Post by James Bott »

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

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

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

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.

Code: Select all

oCustomer:AcceptPayment( nAmount, dDate)
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.
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: Marc : Conversion process and questions about it

Post by Marc Venken »

For my customer update, i'm going for objects ....

I found this template sample from Mr. Rao

http://forums.fivetechsupport.com/viewt ... 80#p221386

This has several of the basic commands to start with OOP.

Which are the most used methods that I have to look into ? File is classes/database
Marc Venken
Using: FWH 20.08 with Harbour
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Re: Marc : Conversion process and questions about it

Post by James Bott »

Marc,

Well this seems to be an example of how to edit the properties of a database. I would not get sidetracked with that right now in your learning curve.

Most object programming texts advocate separating the interface code from real-world objects. Thus a customer object should emulate a real-world customer and not include data entry screens, browses, etc. There is nothing wrong with creating classes for those types of things too, but I suggest you trying emulating real-world objects first. They are simpler and easier to grasp, IMHO.

Have you read my introductory articles about OOP https://gointellitech.com/program.html? If not, I think they will help. Note that they are very dated so some of the things I wrote then I would not advocate today.
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: Marc : Conversion process and questions about it

Post by Marc Venken »

I wonder if we can use this technique also for the mem variables ?
During programming we define a lot of local variables

local cNum:="", nTel:=0 .....

Maybe you also make a object out of it, so that ALL vars or at least those that are used othen on several places can be set into the object so that they can be easily passed..

I'm thinking more of system variables that are used public at my software.

Sys_date, Sys_Path, Sys_Periode (public variables set at startup)

can become :

oSystem:Date
oSystem:Path

The ease would be that they are all located into the object.
Marc Venken
Using: FWH 20.08 with Harbour
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: Marc : Conversion process and questions about it

Post by Marc Venken »

I see that there is a advice to use a prg for each object.

So the intension would be a

prg file for Customers
prg file for Xbrowsers
....

I see the goal of that of having all customers stuff in a customer file

This is still correct anno 2020 FWH ?
Marc Venken
Using: FWH 20.08 with Harbour
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Marc : Conversion process and questions about it

Post by Antonio Linares »

Marc,

To use oSystem:Date and oSystem:Path, you need to use an object of a class like this:

#include "hbclass.ch"

CLASS System
DATA date
DATA path
ENDCLASS

oSystem = System()
oSystem:date = Date()
oSystem:path = hb_CurDrive() + ":\" + CurDir()

another alternative is to use a "hash" where you don't need a class:

local hSystem := {=>}

hSystem[ "date" ] = Date()
hSystem[ "path" ] = hb_CurDrive() + ":\" + CurDir()
hSystem[ "another" ] = 123

as you see you can have more info inside it without having to keep a Class updated

Yes, use different PRGs to keep properly organized the different parts of your app.
"Divide and conquer", the key of structured programming :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
anserkk
Posts: 1280
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Re: Marc : Conversion process and questions about it

Post by anserkk »

Another option is to use a CLASS already developed by Andrade A. Daniel. The CLASS's name is TPublic

Code: Select all

// Usage
oBill:=TPublic():New(.T.)

// Vaiables Declaration
oBill:nBillNo:=100
oBill:dBillDate:=Date()
oBill:cCustCode:=Space(10)
oBill:cCustName:=Space(35)
Instead of passing many variables to other functions as parameters, you can simply pass one single object
For eg
Instead of using YourFuncName(nBillNo,dBillDate,cCustCode,cCustName,......)
You can easily pass this one single object ie
YourFuncName(oBill)

This will help you to maintain your code neatly. On a later date if you need to pass one more additional variable to the function, then you don't have to modify the function "YourFuncName(oBill)" to receive more parameters.

The Hash is also a good alternative as shown by Mr.Antonio
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: Marc : Conversion process and questions about it

Post by Marc Venken »

Exactly what I was thinking about. Thanks eveyone.

I found the class in the forum : http://forums.fivetechsupport.com/viewt ... it=tpublic

Antonio asked about it. Maybe it is inside FWH already ?? I have to test/see in the source files

Otherwise, If I want to use it, I copy it to tpublic.prg and just link it in? And this is so for every class I would make.
Marc Venken
Using: FWH 20.08 with Harbour
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Re: Marc : Conversion process and questions about it

Post by James Bott »

Marc,

From a previous post near the top of this message topic you said:
I used

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 ?
Not exactly. Remember you need to write each piece of code only once. Thus, define a class for each database like the sample below. I put all the database classes into one PRG. Now your database filenames are all in one place, and thye only exist in that one place. So if you need to change them, it requires only one simple name change.

Code: Select all

Class TCustomers from TDatabase
   Method New()
Endclass

Method New( lShared ) Class TCustomers
   Default lShared:= .T.
   super:new(,"Customers",,lShared)  // database filename only exists here.
   ::use()
Return Self
So now everywhere you need to use the customers database, you just do:

oCustomers:= TCustomers:New()

Simple!

That alone will probably eliminate hundreds of lines of code in your program.

The variable oCustomers should be declared as LOCAL. Note that you can still pass oCustomers to a function if you wish.

One last thing, I am using CDXs that auto-open when the database is opened thus you don't need to deal with them. I also always have the primary key index as the first index so you don't need to set it as the current index when opening the file. More lines of code are eliminated this way.
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: Marc : Conversion process and questions about it

Post by Marc Venken »

The variable oCustomers should be declared as LOCAL. Note that you can still pass oCustomers to a function if you wish.
Why not public ? Then the oCustomers is visible everywhere and we don't have to paste them by a function.
Marc Venken
Using: FWH 20.08 with Harbour
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Marc : Conversion process and questions about it

Post by Antonio Linares »

Think about the app as an entire object. The app has its own datas and methods (behaviors) of its class.

CLASS TApp

DATA aPublics INIT {}

METHOD New( ... )
....

ENDCLASS

The entire app is just an object
regards, saludos

Antonio Linares
www.fivetechsoft.com
Post Reply