Marc : Conversion process and questions about it
- Marc Venken
- Posts: 727
- Joined: Tue Jun 14, 2016 7:51 am
Re: Marc : Conversion process and questions about it
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...
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
Using: FWH 20.08 with Harbour
- 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
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.
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
- Marc Venken
- Posts: 727
- Joined: Tue Jun 14, 2016 7:51 am
Re: Marc : Conversion process and questions about it
I use scoped filter... They are fast.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.
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
Using: FWH 20.08 with Harbour
- 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
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.).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 ?
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
Code: Select all
oCustomers := TCustomers():new() // create the table object
oCustomers:seek("12345")
Now we can create a single customer object.
Code: Select all
oCustomer:= TCustomer():New(oCustomers:custno) // create a customer object
Code: Select all
oCustomer:AcceptPayment( nAmount, dDate)
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
- Marc Venken
- Posts: 727
- Joined: Tue Jun 14, 2016 7:51 am
Re: Marc : Conversion process and questions about it
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
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
Using: FWH 20.08 with Harbour
- 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
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.
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
- Marc Venken
- Posts: 727
- Joined: Tue Jun 14, 2016 7:51 am
Re: Marc : Conversion process and questions about it
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.
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
Using: FWH 20.08 with Harbour
- Marc Venken
- Posts: 727
- Joined: Tue Jun 14, 2016 7:51 am
Re: Marc : Conversion process and questions about it
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 ?
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
Using: FWH 20.08 with Harbour
- 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
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
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
Re: Marc : Conversion process and questions about it
Another option is to use a CLASS already developed by Andrade A. Daniel. The CLASS's name is TPublic
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
Code: Select all
// Usage
oBill:=TPublic():New(.T.)
// Vaiables Declaration
oBill:nBillNo:=100
oBill:dBillDate:=Date()
oBill:cCustCode:=Space(10)
oBill:cCustName:=Space(35)
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
- Marc Venken
- Posts: 727
- Joined: Tue Jun 14, 2016 7:51 am
Re: Marc : Conversion process and questions about it
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.
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
Using: FWH 20.08 with Harbour
- 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
Marc,
From a previous post near the top of this message topic you said:
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.
From a previous post near the top of this message topic you said:
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.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 ?
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
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
- Marc Venken
- Posts: 727
- Joined: Tue Jun 14, 2016 7:51 am
Re: Marc : Conversion process and questions about it
Why not public ? Then the oCustomers is visible everywhere and we don't have to paste them by a function.The variable oCustomers should be declared as LOCAL. Note that you can still pass oCustomers to a function if you wish.
Marc Venken
Using: FWH 20.08 with Harbour
Using: FWH 20.08 with Harbour
- 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
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
CLASS TApp
DATA aPublics INIT {}
METHOD New( ... )
....
ENDCLASS
The entire app is just an object