Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
*Compatibility Report 5-7* SYS(2018) content different
Message
General information
Forum:
Visual FoxPro
Category:
Other
Miscellaneous
Thread ID:
00697397
Message ID:
00700641
Views:
30
Peter,

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

I think these things all come about as "rules" that we develop ourselves over time. There really are few "hard and fast rules" that fit every programming solution.

>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.

A form method can be a good place to locate this kind of code. The only constraint is that your controls need to be hosted by a subclass of the form that supports this interface. You controls can actually make a test to see if the interface exists before they try to use it.

I only have 3 resizeable controls: grid, pageframe and listbox. These are the only UI elements that I believe benefit from resizing. They are all packaged in a resizeable classlib. To make each of the classes self sufficient each one contains similar code. All of this is is in one spot so if I ever need to revisit this code there is one classlib involved.

>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.

If the UDF has code like this:
do case
   case poCaller.ParentClass = "textbox"
      ....
   
   case poCaller.ParentClass = "spinner"
      ....
Then I'd say a UDF shouldn't be used. Each respective subclass should just have the code. But this is just a matter of opinion. As long as what you are doing works in your environment and is not causing undo maintenance work then there is not a huge reason to change.

>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.

I put this kind of common control behavior in form methods.

>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).

I've pretty much stopped doing control level valids, because they force the enduser into proceeding through a form in too much of a controlled manner, the user can not move freely between controls as their task might need to warrant. I validate the entire dataset only at Save() time.

>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.

That seems like it would make moving between your controls take a very long time to execute. I have to say that it seems overly complex to have a 9k line block of code controlling whether or not a user can put focus into a control.

>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 not following your description of the problem here Peter.

>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.

I was agreeing with you. I think redundant code needs to be eliminated. It can be elimiated by both class methods and UDFs.

>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 it's much better than having code like this replicated in each of those classes:
if ( type( "oApp" ) == "O" )
   oApp.Error( ... )
else
   ...
endif
Using the ObjError() UDF allows me two things:

1) all the complexity of determining what error handling objects are available is put in one place.

2) it allows me to change out the whole error handling scheme by replacing a single UDF.


>But I guess you mean highest class ? (i.e. traversing upwards the tree in order to find the only single Error in effect).

As I replied to Walter, I treat errors as failures in the code, the application is going to be shutdown in an orderly process if the error ever makes it to the ObjError() UDF. There are a few cases where overridden Error() methods locally trap and resolve a few sort of errors that can't be easily defensively coded around.

>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.

Ok variable not found errors are ones that ought to be discovered by a test plan.

And yes I think they are frustrating things that I'd rather have a compiler detect at compile time. But Xbase architecture doesn't allow this to be a compiler error. The fact that the architecture allows this is also what makes Xbase such a powerful language and give us a much more dynamic runtime environment.

At any rate a variable not found error is one that will cascade rapidly and I think that stopping the app at the first error is the best thing to do.

>So, we agree. Right ?

see my above caveat to complete agreement... but yes I think we are pretty much in agreement.


>So, in VFP9 there should be a command like ON ERROR("Variable not found') ...
>What about that ?

I'm not so sure about this one. Maybe it's something that ought to be discussed in a separate focused thread or Wiki topic. We can already handle this by testing the nError value coming into the Error() method.

>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.

That's why it's important to read, and study and adapt your designs as time goes on. What was the best solution in a FPD app is fundamentally different than what makes a good solution in VFPx. There's also several solutions to most problems, so what works well for me might not work well for you.
df (was a 10 time MVP)

df FoxPro website
FoxPro Wiki site online, editable knowledgebase
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform