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:
00699692
Vues:
29
David, okay, still interesting ...

Obviously, by now I read Walter's re to your message, but I'll be objective.


>Peter,
>
>>Haha. So would be On Key Label and more of it. But ehh, we don't use that at all ...
>
>Nope, OKLs are verbotten now too! Form.KeyPress() replaces the need for OKLs.

So, apparently I follow the (for me unknown) rules. But i's by nature, because otherwise you are in trouble all the time.

>
>>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.
>
>Why do you call out to UDFs? Why isn't all of that code encapsulated into the class itself?

Can't (IMO) be done, but depending on the nature of the app of course. Two main arguments here :
1. Thinking of the spinner and textbox example (though you don't see that right now) I would be right in the basis already. And, obviously all is not to be solved by the invocatoin of a method not belonging to the class itself (though technically possible). So, having a Textbox and a Spinner side by side (coming together in the Form only), and when it would be a fact that both need the same method code, a. it won't be logically allowed to call eachothers methods (if possible at all like Resize), and b. it's (IMO) a rather stupid thing to have a custom method on the Form for it. Besides, it isn't necessarily a Form on the top of all, and it could be anything.
From "evolution" we could say that we can have some highest level object where all can go into, but this would come to just the PRG outside the class.

I see you thinking again : "but what about datasesssions, and there will always be some CASE or IF etc.". Well, it's just about that : WHEN you have the general UDF it really must be general. This is hard stuff not for everybody's knowledgde. But the needed skill for it isn't that tough at all. Learn normalization (of processes) and that's it.

David, it would be my very long shot that when you really think that all can be captured in the class, things are redundant after all. For this matter, let me point once more to our class environment that really is nothing less than an OS itself. It's a kind of other world with different requirements.
Maybe it's an idea to look at this from the angle of the really 100 % separeted biz rules and GUI. I seriously wonder : who has that to the 100 %.
See further below at the Textbox/Spinner issue.


>
>>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.
>
>Well I've never come across code that I'd really want to share across Textbox and Spinner.

The examples should be all over the place. Think of this :

The very first thing I created in the OO environment was the general code for GotFocus. Mind you, zilt IF's or Cases in there, if it were for the controls to capture. So it is general. The non-general stuff is in the GotFocus of the controls themselves, and THAT code is therefor legitimate overthere.
Now have a few things for the background info :

The GUI is 100 % nothing more than that. So, it doesn't know what app it is running (for), and it can't anticipate to antything. Get the hunch already ?
One major issue is the Valid. The OO environment doesn't know about it. But, it IS there. So it has to be fed by the app at distance. As you can imagine, the GotFocus has all to do with the Valid preceeding it. Thus, when it rejects, no Focus to the control selected please (note : whether you see this as the When doesn't matter for the discussion).

Our general GotFocus code is around 9,000 lines (okay, including comments), and since it is really general, it would apply to the spinner only just as well. Now, WHEN it were right that all should be in the class itself and WHEN it were right that the code is really general, it would just be the 100 % redundant thing, right ? And that's exactly why it's in in the unbound PRG.
Thus, the 1:N:1 I mentioned is bout (e.g.) Form:Spinner/Textbox/etc.:GotFocusCode.
IMO it is the 100 % legitimate thing, as long as you encounter the redundancy otherwise.

Note that this is one (I think acceptabe) example only, and we are full of it. And for the technichal angle : ever created a general textbox class and approach the GotFocus method from the various instances it has ? THIS ISN'T EVEN SUPPORTED !!! Hence, once you arrive in the GotFocus Event, you can't tell where you are thinking in procedural sequences. Events don't fire, fire in the sequence the user didn't apply, fire recursively ... it one big pile of a mess. That is, when you approach this from the OS angle.
But I got it running. Decently that is.

>
>I'm a very strong believer in only having code in one place, redundant code should be avoided all the time.

Yeah, well David, you never heard me say that redundant code is allowed. It's just the opposite : by having the in fact redundant parts outside the classes, you have the ability to avoid redundancy. So let's not misunderstand eachother. We just agree, and I have apparantly reasons for general code you don't encounter.

>In the PTF OOP book the lowest level classes there all had the exact same Error() method:
>
>
ObjError( this, nError, cMethod, nLine )
Well, if this is lowest level (so not highest like TL Form) it's rather redundant, rihgt ? No matter wether this is one line only.
But I guess you mean highest class ? (i.e. traversing upwards the tree in order to find the only single Error in effect).

>
>they all as a base behavior delegated the error off to a UDF. Then the UDF could go into the details of how the developer really wanted to handle the error. This removed potentially redundant code that would be needed in each class. Any given subclass could override the Error() method to provide special handling as needed.

Yeah, exactly right. But now think of this please :
Let's assume that I indeed have this larger app (okay, I have it). Now, looking at my error handler it's 1,900 lines only. There are two main CASEs in there. One for locking issues, and one for dealing with VFP anomalies (In FPD this latter CASE wasn't there ...).
The first CASE contains some others, dealing with each of the Lock situations. It's completely transparent (i.e. general), but yes, this could be attached to ... Hmmm, general code in a general class. So, wrong solution and the PRG (ON ERROR) will do.
The second CASE, well, this is about stuff like (literal) "Variable not found.". Ever had that one ? It's about the stupid bug of VFP(5) that somewhere down the line a (not LOCAL) variable name is used that higher up is used as a ControlSource. In the end I defined this as logic (for VFP, and hence not a real bug at all), but VERY inconcienent at the same time. And, waht we do with these variables is just as well legitimate. And (please) don't tell that these variables should be Properties on the Form, because it's all completely overdone AND it doesn't bind them to the (distance running !!) app. So I use VFP in the wrong way. Suits me. But, this error IS just stupid and shouldnt be there. Hence it can be captured and its contents can be recovered. We do that. But not in each other Error method, because it is just a completely general failure.
I've just looked, we have 8 of them.

This concluded, I'd only use the Error method for technical reasons, like the possible possibilty of having another error-level (but I doubt that).

>
>So, yes I agree if your UDFs give the same functionality across multiple subclasses that's a good way to remove redundant code. If on the other hand your UDF has IF or CASE statements that make it behave differently for the kind of control calling it, I'd say no, put the relevant code in the relevant subclass where it belongs.

So, we agree. Right ?

>
>>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.
>
>I'm saying to localize (encapsulate) the relevant CASE statements to the type of class that can throw the particular errors.

As I explained, it appears (!) that we don't have that applications. It ("appears") tells one thing though : we do this stuff correct by nature (for what it's worth).

>
>>Would we call the ON ERROR routine an Overloaded function or so ?
>
>Yes, it's overloaded.

So, in VFP9 there should be a command like ON ERROR("Variable not found') ...
What about that ?
Unless we all start to agree upon overloaded functions (methods), which I certainly not agree upon.

>
>>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.
>
>It's definately a good RAD feature, although it can lead to sloppy code, that your client will end up suffering for. Right, having the ON ERROR open the table on a SELECT statement is slower that the developer having "properly" opened the table before hand.
>
>>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).
>
>It's not spread all over, but it's not encapsulated right inside the class. It's an external dependency/association that you are adding to the class.

Okay ... So I never read the theories, was rather ignorant for that, but now I have my own. But David, it is really difficult, because obviously theories are about consistent situations.
Look around for ERP (Enterprise Resource Plannkng) apps; really, the real OO apps in there count on one hand. This is not for nothing. This is because the normal OO model (and OOP environment) doesn't suit really. When inheritance is applied to (e.g.) bizobjects, you find yourself programming exceptions all over the place. Start with NODEFAULT and you have a chance ...
We dont't talk 100 bizobjects, we talk thousands and more. IMO it doesn't work in OO. But :
What we did becauser of that, is doing it some other way around : Let the OO OS have control over all of it.
Reality is also that only two ERP apps converted to the OO environment. One of them is us, and the other applied the same as we did. Independently btw.
However one thing : my approach suits the normal environment (smaller) just as well.
But it's getting vague at this point. So never mind please.

Thanks for the discussion again.
Peter
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform