Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
*Compatibility Report 5-7* SYS(2018) content different
Message
Information générale
Forum:
Visual FoxPro
Catégorie:
Autre
Divers
Thread ID:
00697397
Message ID:
00699220
Vues:
32
David, thanks once more for your input. Assumed that you started this re because of my last lines, we agreed in advance. One thing : I have to do it.
So let's make this conclusive.
Down the lines I have a few remarks, only for confirmation (and the nice discussion).

>Peter,
>
>>I couldn't agree more on what you say above. But let's say that the way we do it originates from the principle of the really self contained functions ("objects" ...) as we have them from 1987.
>
>I'd argue here that your object is not self contained. Your object is dependent on an external entity (the ON ERROR handler) to do some of its work.

Haha. So would be On Key Label and more of it. But ehh, we don't use that at all ...
But it works the other way around too : sometimes you'd be needing 1:N:1 stuff, the last 1 being about code that has to be redundantly present otherwise. One example : With the VCX as our base, we trigger general UDFs for Keypress, GotFocus, LostFocus and the like. Note that we ALSO make use of the Keypress higher up in the tree (e.g. on the top level Form). So it is not about that. Instead, when creating controls, you end up with similar method code all over the place. IOW, how to create the general method code higher up in the tree for a Textbox and a Spinner at the same time ? There is just no means for letting it come together somewhere. So instead, this can be done the other way around : have the same UDF in the methods concerned. You'd say that this wouldn't be self contained, right ? Well, IMO this is just a matter of structured programming.
The ON ERROR situation is slightly different though, because of, indeed, the tens of CASEs in there. The methods calling the UDF first deal with their own exceptions, and then call the general UDF. No CASE in there.
Would we call the ON ERROR routine an Overloaded function or so ?


>
>In this case I'd say it's better to have all this code encapsulated in a cTableHandler class. Its Error() method can take on the onerous task of opening tables that had not been opened before USE. Now this error handler only has to deal with one or two little possible errors that can happen in the context of a table. The Error() method can probably be coded in 20 lines. If it encounters an error it can't recover from then it can pass the error off to this.parent.Error() to follow a containership delegation of errors, or pass the error off to something like oApp.Error(). By doing this you don't have to have a ON ERROR handler that has hundreds of lines and tens of CASE statements.

Fully agreed.

>
>>Think of it as "header-info" in the function (it's the block of documentation btw), listing all the tables that could be touched somewhere down its lines ... Combine this with the sole fact that back then (FoxBase+) we were all able to open the huge amount of 10 tables at the time. Some late this became the far more huge amount of 25 ... So what to do when you really needed over 50 ? (right now one object may use 80 tables in the one transaction). So see it as the FIFO principle, the one table needed implicitly closing the other.
>
>So this list of needed tables can be an object property. The Error() method can see if the table in error is in the list it can open it. If it isn't in the list then you could throw an error that should happen in design time testing to tell your developers that they've not properly setup the object.

Right. And right now, it exactly works like this. So : whether the developer obtained the table in the official list or not, it just will work (as decently), which doesn't mean the developer shouldn't be notified about him doing something "wrong".
BTW, the same mechanism we use all the time from the command window : SELECT MyTable will open it (or just select it when already open) with its Index file when present (we don't use structural indexes). It's really convenient, because this way we don't need to know where the table is (directory). The Open routine will know.

>
>>So yes, our Open routine is some 5,000 lines already to control all this.
>>When back then the limit was 10 (25), today we limited it ourselves to 80, implying some 220 filehandles open at the time, and allowing for some more for other apps. This limit of 80 is still too few, and the FIFO is still doing it's (very good) work (the app consists of over 1,000 network tables).
>>Also please note that there is some smartness in the opening of groups of tables, knowing that opening a table is the far-most slow process of all of the Fox, and hence this should be avoided whenever possibible.
>
>Sounds like you need a sophisticated TableManager class to keep up with this.

O yes. But of course we already have it, though in a "loose" PRG. Personally I wouldn't change that, as long as it will be called from the TableManager Class. But okay, pasting the code in some Open method will do too.

>
>>Again, I couldn't agree more that the errorhandler shouldn't be used for explicit code. OTOH, it's (IMO) just needed anyway in order ro deal with locking issues (and some more). Rememer, a record being locked is not an error, and just "functionality" to be dealt with properly. And you know, the code behind that could error too. But I agree, this is different.
>
>So the cTableHandler class Error() method can deal with locks errors. But once again you've helped to encapsulate all the highly related code to a single class. It's not spread all over and some of it in the global ON ERROR code block.

Well, it's not all that much spread over. In fact, all is directed from the ON ERROR, and from that point on its one or two UDFs. Anyway, the programs applying the locks don't do more than needed (litterally IF NOT CanLock() - LOOP).
As to my experience, it is overdone to have something like IF NOT This.CanLock() - LOOP. I mean, when the CanLock() function doesn't have any differentiation opposed to situations, why make it harder (less readable) then necessary ?
Further (IMO) one shouldn't be encouraged for making exceptions at any level, and the object hierarchy is the best for enncouraging it. So, putting more in UDFs (not having CASEs) asks more from the higher perception of the developer. But that's our living here ...

>
>>But in case you are interested : in order to capture the exclusive use of tables properly (or it is used exclusively, or you want to use exclusively), there is this oter sneaky means involved : opening the table low level in order to find out this status in advance. It's just another level of error trapping ... Squeeze squeeze squeeze. But at the same time, this is the fun of it all.
>
>There is still a finite probability that another user will open the table between the execution of the fclose() and the USE statement.

Right. But many coincidences are involved here : 1. Exclusive use must be involved (which is very rare already), 2. This table would open via ON ERROR (not so rare), 3. when I need Exclusive Use the table must not be open at that time (very rare) OR 3. when I need normal use the other user apparently just opened for Exclusive Use which again implies that it wasn't open at that time (so again very rare).
But WHEN this happens ... a Fox message pops up.
This is the time when I blame VFP. I've really done all my best ...

>
>>Sidenote :
>>I think there could be some other (error level) possibility in making a class for the open routine and use the Error-method. I never tried it, but maybe I should do that now.
>
>I really think you ought to look in this direction, I think you'll end up with a better system because of it.

So that, by now, is clear.
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform