On Tue, Mar 21, 2017 at 4:45 AM, James Crate via 4D_Tech <
[email protected]> wrote:

Hey Jim, it's good to have you chiming in.

> I was looking forward to finally having something better than CALL PROCESS
> available, but it is disappointing to see the level of coupling required
to
> utilize the new commands. Something more similar to Cocoa’s
NotificationCenter
> or javascript custom events would have been far more preferable.

You know how to pack a lot into a paragraph ;-) I haven't used Cocoa's
NotificationCenter to I looked it up. It looks like it implements
Publish/Subscribe and Observer. No, 4D's new commands do nothing like that.
The 'messages' aren't messages and the definitely aren't events. They're
blocks of code appended to the end of an existing thread of execution.
Arguably, it's meaningless to even talk about a 'queue' since we can't see
it, size it, or control it. (From inside of 4D, it makes sense to talk of a
queue - but as a 4D programmer? We have zero queue-like properties
available.)

In any case, you can use the new tools to write a publish-subscribe system
pretty nicely. (I've been doing this recently.) In fact, you can implement
publish-subscribe pretty well in 4D V14+ using its C_OBJECT data structure.
Peter Hay, Cannon Smith, Welsh Harris and other all seem to be pursuing
variations on Publish/Subscribe and/or MVVC.  Here's a relevant feature
request that needs your vote:

Automatically Associate C_Object With Form Objects (and the Window)
http://forums.4d.fr/Post/EN/19051683/1/19051684

If you don't know how to vote, it seems to be that you click on the 'rate'
stars at the top of the first post. From Tim Penner:

Tech Tip: How to vote for a feature request
http://kb.4d.com/assetid=76726

With the new commands, we definitely get some new options. If you're
comparing them to a full-on customizable event/event-injection framework,
you'll be disappointed. But if you take the new commands for what they are,
they're pretty great. As far as the degree of coupling, it's kind of up to
you to a degree. It's going to be simple for people to code things with
pathological coupling and it's also not hard to build very loose coupling.
For those of you following along at home that consider yourself "folk
programmers", "coupling" is the term for how different bits of a system are
connected. That can be different methods, different pieces of software
connecting over the network, whatever. "Tight" coupling is "bad" because it
means a change in one area requires or causes change in another. In a
"loosely" coupled system, whole sections of a system can be replaced or
rewritten without the rest of the world knowing a thing about it. CALL FORM
is kind of a good example here. Some off-the-top-of-my-head illustrative
code:

CALL FORM(DashboardWindow;"UpdateTickerText";->StatusTicker;"3 packages
received at 1:30 PM")

So, some bit of code pushes this code over for execution. It says "run the
UpdateTickerText method in the DashboardWindow. And tell UpdateTickerText
to change text of the variable StatusTicker to read or include the text "3
packages received at 1:30 PM!". While there are some situations that
justify this approach (testing, quick-and-dirty-demo...that's all I've
got), it's *tightly coupled.* The code that sends the command to the
dashboard has to know a lot about the dashboard. For example, the name of
the display variable. What if you want to change that variable? What if you
want to use an object name and not use a variable? You break the outside
world. So

CALL FORM(DashboardWindow;"HandleNotification";"3 packages received at 1:30
PM")

The "HandleNotification" method takes care of dealing with the data.
Doesn't look very different, but this kind of approach can be very
different. Taking things further, think about the code that's sending the
notifications to the dashboard. Sounds handy having a stream of
notifications about stuff that's happening. It might be nice to
-- Log these to a disk file, SQL database, or 4D
-- Update a Web page with some sort of timeline showing activity
-- Forward specific events to someone for handling - like if there's
spillage or something

So, a stream of events/notifications might have a lot of uses. But you've
got a 1:1 binding between the 'send notification' code and the dashboard
code. That's where a publish-subscribe system comes into play. With such a
system, the notification code publishes a service (you could call it
something else.) Something like this:

PublishService("WarehouseUpdates":"Receive real-time notifications of
important warehouse activities.")
Now the DashboardWindow, LogWorker, WebUpdater, etc. need to do this:

SubscribeToService("WarehouseUpdates";DashboardWindow;"Dashboard_HandleWarehouse")
SubscribeToService("WarehouseUpdates";LogWorker;"Log_HandleNotification")
SubscribeToService("WarehouseUpdates";WebUpdater;"WebUpdater_HandleWarehouse")
Something like that. When an event happens at the warehouse, you would call
something like

Warehouse_SendNotification (Message)
Notifications_Send("Warehouse";Message")
Notifications_GetSubscriptionList("Warehouse")
For($i;1;subscribers)
$target:=subscriber.identifier
$method:=subscriber.method
CALL FORM/WORKER (target;$method;$message)
End for
So, the same message (notification text, in this case) is sent to

Dashboard_HandleWarehouse
Log_HandleNotification
WebUpdater_HandleWarehouse
This is loosely coupled:

* The Warehouse module knows nothing about the subscribers. It doesn't even
know if there are any. There could be 0, there could be 12. It makes no
difference. Warehouse delegates notification and subscription management to
the Notification module. Notification, for its part, knows nothing about
the content, source, or target for the messages. All it knows how to do is
move a message from one place to another. To do this, it manages the
subscription list. And on the recipient side, it doesn't need to know
anything about notifications (apart from how to subscribe/unsubscribe) and
doesn't need to know anything about Warehouse, other than how to interpret
the notifications.

So, no, none of that's written into 4D out of the box but it is doable. My
own version is a late alpha right now. (Adding more test code for the
calls...which is hard to do...then adding the last tranche of
functionality.) For the record, I send around C_OBJECT messages in $1 and
that's it. It makes the system much more like a message queue or event
notification dispatcher. It's cool that you can call method parameters
directly with CALL FORM and CALl WORKER...but for a more loosely coupled
system, it's easier to pack that stuff into a generalized parameter. The
cost is that the parameters are opaque and you've got to do more custom
type/value/range checking yourself.

> If you use a string literal for the method name, does the compiler check
that
> the method exists? It would be nice if the tokenized method name could be
> used; parenthesis could be required to also allow using the return value
of a
> method as the parameter value. (This would be nice for any command that
takes
> a method name, like New Process.)

Yeah, sadly, no :( Another feature request that really needs some love:

Compiler/Typing Improvements: Detect some runtime errors in advance
http://forums.4d.fr/Post/EN/19107688/1/19107689

Several of us have resorted to writing custom code parsers to add this
test, check parameter lists, etc. Not a reasonable amount of work. 4D
really needs to add more checks into the compiler.

> Since using these will require code to be in project methods instead of
> object/form methods (I hate the invisibility of object methods, but also
hate
> the pollution of the single namespace with thousands of tiny code snippets
> relevant to a single item),

...hence the common practice in 4D of having ginormous 'handler' methods
with a fat case statement for different things. Sigh. In the case of forms,
it's not necessarily the worst approach available in 4D. But, ugh.

Oh, and speaking of namespaces - we need more than 31 characters for names,
largely because it's hard to avoid burning through a lot of characters to
implement pseudo-namespaces. Here's another feature request...this one
seems to have some momentum, but more votes can't hurt:

Raise the 31 character name limit on methods
http://forums.4d.fr/Post/EN/18946884/1/18946885

> is there any general recommendation on project
> method organization? I have not been able to get project method folders to
> work myself. I’m also not sure if it’s even desirable to have project
method
> folders, considering that there is only a single global namespace maybe
it is
> better to have the hundreds to thousands of project methods in a single
list?

! I use Explorer folders for everything. It makes it way easier to
navigate. They're hardly the ultimate feature, but they help me a lot. I
don't know about retrofitting them into an existing project with thousands
of methods. In my big code bases, I have custom screens for searching on
methods by name, attributes, etc. Between the commands to get process names
and the automatic option to open a method in Design, you can do a lot. Find
in Design is okay too, but it doesn't always do what you need and doesn't
let you save all of the results. (You can drag the results to a method and
you'll get a top-level summary.)

> Is there some sort of “quick open” functionality for project methods that
I
> haven’t found yet?

Yes! Great feature:

METHOD OPEN PATH
http://doc.4d.com/4Dv16/4D/16/METHOD-OPEN-PATH.301-3037152.en.html
**********************************************************************
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]
**********************************************************************

Reply via email to