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] **********************************************************************

