David:
Whether or not my approach is valid, it appears that I can at least explain
it to someone. :-)
Kirk hasn't had to, AFAIK, get to the level of putting a project method in
every object but, as we know from experience, there's huge variation in how
applications are structured so the approach that works for one developer
may not work for another. I found no other way to get around "losing
events" so I had to resort to putting a PM in each OM. In addition, because
there's an event cycle, I need to use the *_Clear* method in many
situations.
Part of the reason why I created the ability to assign an event value is
that IP messaging essentially requires that. Working with ITK was the first
place that I ran into setting up a messaging queue and the fundamental
design hasn't changed since I snarfed the code from the ITK demo back in
1997. The biggest change I've made have been to set up a
Repeat…Until(message queue empty) but, since it took forever for 4D V6 to
parse the source for a literal value, I set up a MSGIP_Vars_Init method
which allows me to standardize on a set of messages and then, since they're
IP vars, 4D can find them very easily.
BTW, AreaList Pro has a command (IIRC, *AL_SendEvent*) which makes it
really easy to code a re-entrant style of programming.
As you state, we should have had Call worker and Call form all along. The
ability to open a dialog with the optional asterisk is really nice but it's
*much* more valuable with Call form. I tried using my standard On outside
call methods on an asterisked window that had dynamic variables and it was
tres ugly. Things will be *much* easier with Call form.
Couldn't agree more about 4D fixed parameter list even though I still enjoy
listening to disco. Well, OK, "hearing" disco.
Unless I'm writing a routine that's drop dead never ever going to be more
than a utility routine, every method starts with c_longint($h_;$1). That's
in my default method header, in fact. In many situations, I pass 0 at $1
but, overall, having set up 4D to write accessor methods for me I've
shifted my perspective to design code from the perspective of how will the
data be used so my code tends to be littered with _Set and _Get methods.
Process variables - someone real smart said that they were evil. I concur -
that's one of the reasons why you saw g_tablePtr_Get (or whatever) in the
code sample. I've spent too much time doing click, click, click tracing
through code to see where a value changes.
Set process variable - well said. It's brutal. I liken that ("liken that" -
just love the American language!) to a FedEx delivery. Instead of leaving
on the doorstep and ringing the bell, Set process variable would have the
fellow kick down the door, rip out the old item, and install the new one.
Not my cup of tea at all.
As a side note, one thing that is interesting is the technique of putting
values in process 1 and then calling Get process variable. I'm not quite
sure exactly what that buys me but it's something to keep in the buffer, I
suppose.
McConnell had/has a strong influence on me and he writes, at length, about
"coupling and cohesion" and "orthogonality" I don't recall that he delves
into MVC but imbuing myself with those three concepts has been part of the
move to what could be extended into MVC.
That's all well and good but there's also the issue that too much is too
much. One of 4D's many strengths is that it allows us to create
applications quickly simply by putting fields on forms and getting on with
it. Yes, that can (will) lead to issues should the application grow
significantly but I think that KISS approach is good to keep in lest I
wander too far down the de-coupling path. Just a thought.
"We've got reliable *asynchronous* messaging."
Needed to be stated again.
Amen. Thank you 4D.
Thinking about the brouhaha over Call worker and IP data, I had to wonder
just how many 4D apps really need to tap into multiple threads. No doubt,
some apps will benefit greatly but, by and large, my take is that the long
term benefit of not being able to use IP data is beneficial. In the short
term, it will be frustrating for developers who want to tap into more
horsepower but won't be able do so until their IP data has been banished.
In the longer term, the benefit will be that it will force us to spend more
time designing code than we do now. The result will be that, over time, our
code quality will improve.
Anyway, enough of this. Time to grapple with these Southern California
temps and go outside and fire up the grill for dinner. It only got up to
68º today. Brutal, that. ;-)
--
Douglas von Roeder
949-336-2902
On Sat, Jan 7, 2017 at 3:46 PM, David Adams <[email protected]> wrote:
> If I'm following your example, it's something like this:
>
> -------------------------
> Object script
> -------------------------
> -- Package up details about
> -- what got the event
> -- what the event is
> -- Pass this package of data up to a project method for this form named
> Proposals_FM
>
> In native V13, this would be something like this:
>
> Proposals_FM ("PROP_F029Networkrb";On Clicked)
>
> (You're packaging more information than this, obviously...but just to
> translate...)
>
> Meaning that the object PROP_F029Networkrb got an on click, please deal
> with it.
>
> -------------------------
> Proposals_FM
> -------------------------
> -- Unpackage the details provided
> -- Generate pointers to the focus object and current object
> -- Extract the name of the focus object
> -- Extract the event code
>
> Then you've got some kind of case like
>
> Case of
> :($form_event=On Clicked)
>
> :($form_event=On Data Changed)
>
> else
>
> End case
>
> Something like that?
>
> It also looks like you've got various bits of housekeeping code. More
> interesting is that you're being open-minded about setting events manually,
> rather than just passing through events from 4D. If so, I'd say that's the
> most powerful part of the system, as I understand it. You can then "send"
> events "to" various objects without having to click (etc.) them at all.
> That's great for complex widget interactions, testing mode emulations, etc.
>
> So, am I on track with what you're suggesting? I'm primarily interested in
> division of labor/delegation of responsibility questions and I've got
> Model-View-Controller in the front of my mind.
>
> For those that don't know, Model-View-Controller (MVC) is a common pattern
> in most of the development world. Well, all of it. Aparajita explained it
> to me once about 20 years ago. He's one of those people that makes complex
> concepts easy to understand...I always feel so much smarter afterwards ;-)
> MVC is one of those subjects that has gotten a bit messy as people use the
> term in different ways, think they know what it is when they don't, mistake
> a specific implementation they know for the pattern in general, use it
> without realizing, etc. So, yeah, it's a bit of a struggle sometimes to
> find a clear and meaningful description out there. And there are tons of
> valid variants around. The basic idea is to have a clear "separation of
> concerns" between your data (Model - but it might be a bit more than what
> we normally think of as data - it's also the rules for the data),
> presentation (View - like a form, in a 4D context) and the code to mediate
> them (Controller - scripts, form methods and subroutines, in 4D.)
>
> Since MVC comes from the OOA/OOD world, it's not an algorithm, it's a
> "pattern." Implementation details are left as an exercise to the reader ;-)
> But in a good way. It's a nice clean design, and then we hit the real
> world. Sometimes it feels weird to have all of the rules in the Model and
> it's quite tempting to put them into the Controller. Sometimes it's hard to
> figure out if you've got one model or two. For example, let's say you use a
> listbox to display some data calculated out of 4D. So, the data is in the
> "model" and so are the calculations. The view is the listbox, and the
> controller just needs to know how to ask the model for the data (think of
> an API call for data), and knows how to pass it into the view for display.
> Okay, that's not too hard to follow. But what if you want to do something
> like track the state of the listbox? Like, what the user last clicked on to
> sort, how they've resized columns, how they've reordered columns. Where
> does that state data go? It's not part of the business data, it's part of
> the current presentation. But it's important. If you reload the data, you
> want to leave the users settings in place rather than wipe them out with
> defaults. Anyway, you may end up with one of several designs - including
> have a state manager that stores models of states.
>
> A helpful (read: "essential") component of MVC is having a messaging system
> to coordinate communications amongst the parts of the system.
> Traditionally, what we had was
>
> * Parameter passing:
> Real 4D, straight from it's Pascal/Structured Programming roots. Very
> respectable, but limited because there's only one thread of execution in a
> process.
>
> * Parameter passing (2):
> Bundle stuff up into a BLOB, record, bag, OT object, etc. and pass that.
>
> * Stuffing things into globals and sharing them:
> Pathological, just a bad, bad idea. With rare exceptions, but this is the
> source of so much pain in the 4D world. Well, in any language...but lots of
> languages at least make it harder to do. (Still, programmers are a creative
> lot...people always find a way to inject bad globals...they are so
> temptingly, superficially "easier" than well managed, modular data.)
>
> * SET PROCESS VARIABLE/Etc.
> The date rape drug of 4D commands. They should never have been put in the
> language. We should have had CALL WORKER and CALL FORM (or similar) all
> along.
>
> So, you can see why I'm interested in V15/V16 and am curious about how
> other people are approaching UI development given the new option of a
> message bus. We've got reliable *asynchronous* messaging. Too sweet. Anyone
> deliberately implementing an MVC pattern in V16? Comments on trade-offs in
> a 4D-specific implementation? Anyone want to chime in and correct whatever
> errors that I've made in explaining MVC? I'm sure there are important parts
> of left out and/or explained poorly/incorrectly.
> **********************************************************************
> 4D Internet Users Group (4D iNUG)
> FAQ: http://lists.4d.com/faqnug.html
> Archive: http://lists.4d.com/archives.html
> Options: http://lists.4d.com/mailman/options/4d_tech
> Unsub: mailto:[email protected]
> **********************************************************************
>
**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ: http://lists.4d.com/faqnug.html
Archive: http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub: mailto:[email protected]
**********************************************************************