Final conversion 16 bit to FWH

Re: Final conversion 16 bit to FWH

Postby James Bott » Fri Jul 07, 2017 10:20 pm

Marc,

OK, I see, you were just trying to update the DBF/DBT file structure to the current format.

I will be interested to hear how your conversion from TSBrowse to XBrowse goes.

James
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: Final conversion 16 bit to FWH

Postby Marc Venken » Fri Jul 07, 2017 10:52 pm

James,

I implemented my first little OOP (for now with standard FWH :wink: )

Code: Select all  Expand view

DATABASE oDbfklant

   REDEFINE GET oDbfklant:Naam_1   ID 110  OF oDlg UPDATE on change oBtn1:enable()
   REDEFINE GET oDbfklant:Naam_2   ID 120  OF oDlg UPDATE on change oBtn1:enable()
   REDEFINE GET oDbfklant:Straat   ID 130  OF oDlg UPDATE on change oBtn1:enable()
   REDEFINE GET oDbfklant:Postcode ID 140  OF oDlg UPDATE on change oBtn1:enable()
   REDEFINE GET oDbfklant:Gemeente ID 150  OF oDlg UPDATE on change oBtn1:enable()
   REDEFINE GET oDbfklant:Tel_nr   ID 160  OF oDlg UPDATE on change oBtn1:enable()
   REDEFINE GET oDbfklant:Fax_nr   ID 170  OF oDlg UPDATE on change oBtn1:enable()
   ///.....


//and for saving

function endklant(oDbfklant,oDlg)
   if oDbfklant:modified()
      if msgyesno("Gewijzigde gegevens bewaren")
         oDbfklant:save()
         If !dial->(dbseek(oDbfklant:tel_nr))
            dial->(dbappend())
            dial->tel      = TrimTelFax(oDbfklant:tel_nr)
            dial->firma    = oDbfklant:naam_1
            dial->code     = oDbfklant:klant_nr
            dial->type     = "K"
            dial->toestel  = "T"
         endif
         If !dial->(dbseek(oDbfklant:fax_nr))
            dial->(dbappend())
            dial->tel      = TrimTelFax(oDbfklant:fax_nr)
            dial->firma    = oDbfklant:naam_1
            dial->code     = oDbfklant:klant_nr
            dial->type     = "K"
            dial->toestel  = "F"
         endif
      endif
   endif
return(.t.)

 


In this code is see a 'James Bott' OOP

The code for changing the oDbfklant:tel_nr and oDbfklant:fax_nr could be changed into a new method from the save() as you told early.
So when saving, the update is performent. Not for now, but this will happen at the end of the conversion, and when I build new functions.
Just wanted to let you know, since this stuff I have learned from you. Thanks BTW.
Marc Venken
Using: FWH 23.04 with Harbour
User avatar
Marc Venken
 
Posts: 1341
Joined: Tue Jun 14, 2016 7:51 am
Location: Belgium

Re: Final conversion 16 bit to FWH

Postby James Bott » Fri Jul 07, 2017 11:40 pm

Well, kudos, Marc. I'm glad to see you starting to try OOP.

I like to make the object names as much like real-world names as possible. And I try to make table objects plural so I can use a singular object of the same type later. For instance oCustomers and oCustomer. So, I would suggest for you to use oKlants now so you can use oKlant later. It seems that if you are using oKlants it is obvious that it is a DBF (or table).

And rather than opening the table using conventional syntax, I would create a subclass and open the database and indexes in that as I have shown before in other messages. Then it takes only one line of code to create the table object and if you need to change or add indexes you do that in the class for that object. It is a good rule to write each piece of code only once--not only for less work, but you only have to change it in one place.

oKlants := TKlants():new()

I recently calculated (for some very old code) that I could eliminate over 2000 lines of code that were used for opening files and their indexes, just by converting to database classes.

I am so glad to see you recognize that your function should be a method. And that you see how you can convert a little at a time instead of all or nothing.

Keep at it.

James
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: Final conversion 16 bit to FWH

Postby James Bott » Fri Jul 07, 2017 11:59 pm

Marc,

The code for changing the oDbfklant:tel_nr and oDbfklant:fax_nr could be changed into a new method from the save()


I'm not sure what you meant, but you should make a new Save() method in the TKlants class and add that code to the new save method.

Code: Select all  Expand view
Class TKants from TDatabase
   Method New()
   Method Save()
Endclass

Method New()
...
Return Self

Method Save() Class TKants
   ::super:save() // call the parent save method
   // add code to save phone numbers
   // add code to save fax numbers
Return nil
 

Now you just do:

oKlants:save()

I suggest opening the Dial database INSIDE the TKlants class. And closing it too, of course. This encapsulates the database--you don't have to rely on the database being open before saving the oKlants record. Whew, you might have to read that twice--it is a new concept; a database class inside a database class.

James
Last edited by James Bott on Sat Jul 08, 2017 6:12 am, edited 1 time in total.
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: Final conversion 16 bit to FWH

Postby James Bott » Tue Jul 11, 2017 6:13 pm

Marc,

While looking at your EndKlant() function I noticed that it contains user interface code:

Code: Select all  Expand view
if msgyesno("Gewijzigde gegevens bewaren")
...
endif

User interface code should not be inside any buisness object, so this should be moved to outside the function when it is changed to a method of the customer class. Here are a couple of reasons why.

1) Granularity--you want to strive for small pieces of code that have a single purpose.

2) Automation-- For instance, if you wanted to update all the records with new data, you need to be able to call the Save() method once per record. Thus you cannot have user interface code popping up for each record.

Business objects and human interface objects should be totally separate. You can, of course, have an edit-business-object class, for instance EditCustomer. You then can then pass a customer object to that class for editing.

Code: Select all  Expand view
oCustomer:=TCustomer():New(cCustNo)
oEditCustomer:=TEditCustomer():New()
oEditCustomer:edit(oCustomer)

Simple.

James
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: Final conversion 16 bit to FWH

Postby Marc Venken » Tue Jul 11, 2017 7:55 pm

Thanks James, I will take this info in my further devellopments.

You know that I'm transferrings into Xbrowse, so It is also possible to give the save() functions from Xbrowse a extra method ?

Let say 'as example' that I also want to save a extra phone number and Fax nummer into a second database, when I add a record into a Xbrowse,
you would probably add a method like below ?

Code: Select all  Expand view

Class MyBrowse from Xbrowse
   Method New()
   Method XB_Save()
Endclass

Method xB_save() Class MyBrowse
   ::super:save() // call the parent save method from xbrowse and let Xbrowse do all it normaly does.
   // add code to save phone numbers
   // add code to save fax numbers
Return nil

 


This can be done for all classes.
I remember that you normaly put 1 class in a prg file. Is this also for addind smaller methods like above ?
Marc Venken
Using: FWH 23.04 with Harbour
User avatar
Marc Venken
 
Posts: 1341
Joined: Tue Jun 14, 2016 7:51 am
Location: Belgium

Re: Final conversion 16 bit to FWH

Postby James Bott » Wed Jul 12, 2017 6:44 am

Marc,

Sorry, no that is not how you do it.

Since you are using a database object, you don't have to do anything!

To prove it, just define a test database class with a new() method and a test save() method like this:

Code: Select all  Expand view
Method New() Class TKlants
   ::super():New(,"klant") // or whatever the filename is
   ::use()
   ::load()
Return self

Method Save() Class TKlants
   msgInfo("Save method called")
Return nil
 

Then create and run a test browse.

Code: Select all  Expand view
  oKlants := TKlants():New()

   @ 0, 0 XBROWSE oBrw OF oWnd OBJECT oKlants
   ...

Then run the test program and when the data is saved the msgInfo() will popup.

So if you add the updating of the other database to the oKlants:Save() method it will get updated also. XBrowse already calls oDBF:save() so your object's Save() method gets called.

See is it simpler than you thought.

James
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: Final conversion 16 bit to FWH

Postby Marc Venken » Thu Jul 13, 2017 7:34 pm

James,

A other issue I have,

In this case, I read emails from the testpop3.prg sample (source class = Tpop3.prg)

Insite the class, there is in the method NEW

::lDelMsgs := .t.
::lHeaderOnly:=.F.

I want to change this in the testpop3.prg , so I thought changing simply

oInMail:lHeaderOnly:=.T.
oInMail:lDelMsgs := .F.

would work, but it seems not ? Afther reading the mail (that works) the mails still is erased on the server, and as far as I can tell,
putting the lDelMsgs := .F. would prevent this from happening

Code: Select all  Expand view

function GetMail()

   local oInMail

   oWnd:SetMsg( "Geting Internet email..." )

   oInMail = TPop3():New( "MycIp",110,"MyAccount", "MyPaswoord" )  // mail server IP

   oInMail:lHeaderOnly:=.T.
   oInMail:lDelMsgs  := .F.

   oInMail:bConnecting = { || oWnd:SetMsg( "Connecting to 194.224.203.2..." ) }
   oInMail:bConnected  = { || oWnd:SetMsg( "Connected" ) }
   oInMail:bDone       = { || ReadEmails( oInMail ) }

   oInMail:GetMail()

return nil

//----------------------------------------------------------------------------//

function ReadEmails( oInMail )

   local n

   MsgInfo( "Total emails: " + Str( Len( oInMail:aMsgs ) ) )

   for n = 1 to Len( oInMail:aMsgs )
      MsgInfo( oInMail:aMsgs[ n ] )
   next

return nil

//----------------------------------------------------------------------------//

 
Marc Venken
Using: FWH 23.04 with Harbour
User avatar
Marc Venken
 
Posts: 1341
Joined: Tue Jun 14, 2016 7:51 am
Location: Belgium

Re: Final conversion 16 bit to FWH

Postby James Bott » Thu Jul 13, 2017 10:08 pm

Marc,

I looked at the TPop3.prg and I don't see any problems with it.

I think the issue is that when you execute the getMail() routine it issues a "quit" when it is done, which is probably disconnecting from the server. Then your getEmails() function is trying to read emails from a disconnected server.

Instead of using your getEmails() function, try to read them with the GetMail() function again, after the first time, to see if they are still there.
-----

Did you try your browse with a customer class yet?

James
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: Final conversion 16 bit to FWH

Postby James Bott » Thu Jul 20, 2017 5:21 pm

Marc,

I had a few mintues to kill, so I wrote up a sample customer class for you.

If you are using MS Edge, don't copy the source from it--use a different browser. Edge puts in invisible characters which will give you syntax errors that will drive you crazy.

The code will need a few additions to be workable (see the comments).

Regards,
James

Code: Select all  Expand view
/*
Purpose  : Customer class
Program  : TKlants.prg
Author   : James Bott
Date     : 07/20/2017 10:09:18 AM
Company  : Intellitech
Copyright:
Language : Fivewin/xHarbour
Updated  :
Notes    : For Marc Venken

*/


#include "fivewin.ch"

Function Main()

   Local oKlants
   
   Field klant_nr, naam_1
   
   REQUEST DBFCDX
   rddsetdefault( "DBFCDX" )
   SET(_SET_AUTOPEN, .T. )
   SET EXCLUSIVE OFF
   
   // Test only
   use Klant
   index on klant_nr tag "klant_nr" to klant
   index on naam_1 tag "naam_1" to klant
   use
   // End test
   
   oKlants:= TKlants():New()
   
   msgInfo( oKlants:naam_1, "Naam_1")
   
   oKlants:end()

Return nil

//---------------------------------------------------------------------------//  
// Customers database class
// Question, do the phone and fax numbers need to be loaded from the dial database?
// If so then a Load() method will also be needed.
   
Class TKlants from TDatabase
   Data oDial
   Method New()
   Method Save()
   Method TrimTelFax()
   Method End()
endclass
   
Method New() Class TKlants
  ::super:new(,"klant")
  ::use()
  ::setOrder(1)  // primary key index
  ::oDial:= TDial():New()
  //::oDail:setOrder( ? ) // phone number index
Return Self

// Function endKlant made into TKlants:save() method
Method Save() Class TKlants
   ::super:save()
   
   If ! ::oDial:seek(::tel_nr)
      ::oDial:append()
      ::oDial:tel      = ::TrimTelFax(::tel_nr)
      ::oDial:firma    = ::naam_1
      ::oDial:code     = ::klant_nr
      ::oDial:type     = "K"
      ::oDial:toestel  = "T"
      ::oDial:save()
   endif
   If ! ::oDial:seek(::fax_nr)
      ::oDial:append()
      ::oDial:tel      := ::TrimTelFax(::fax_nr)
      ::oDial:firma    = ::naam_1
      ::oDial:code     = ::klant_nr
      ::oDial:type     = "K"
      ::oDial:toestel  = "F"
      ::oDial:save()
   endif
   
Return nil

Method End() Class TKlants
   ::oDial:close()
   ::super:close()  // Because TDatabase doesn't have an End method
Return nil

Method TrimTelFax(cNumber) Class TKlants
  // cNumber := ?
return cNumber

//---------------------------------------------------------------------------//

Class TDial from TDatabase
   Method New()
Endclass

Method New() Class TDial
   ::super():New(,"dial")
   ::use()
   //::setOrder( ? )  // the primary key index
Return self

//---------------------------------------------------------------------------//

// EOF
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: Final conversion 16 bit to FWH

Postby Marc Venken » Fri Jul 21, 2017 11:26 am

Thanks,

Will look into this in a fex days.

Marc
Marc Venken
Using: FWH 23.04 with Harbour
User avatar
Marc Venken
 
Posts: 1341
Joined: Tue Jun 14, 2016 7:51 am
Location: Belgium

Re: Final conversion 16 bit to FWH

Postby James Bott » Mon Jul 24, 2017 3:00 pm

Marc,

I forgot to mention a few things.

Notice that we use total encapsulation in this class. You don't have to open either the customer database or the dial database. Nor do you have to remember which indexes to set. And there are no work areas or aliases to worry about. Finally, you don't have to remember to save the phone numbers to a different database. All you have to do is:

oKlants := TKlants():New()

Then everything is all setup and ready to go.

If you need to make any modifications to the behavior of this class, there is only one place that needs to be modified.

This provides very easy to use and update code. And very stable code.

Regards,
James
FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Previous

Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 26 guests