I was messing around yesterday and looking for alternatives to putting the same block of code in methods on multiple components within the same view/flex container. Not sure if this has been said before, but I discovered that a method can be called from a sibling component by using self.getSibling("component name").methodname(). I thought this was super cool and I couldn't find any posts about it.
Not very useful, as the self
in such a method is always the component it is attached to, not the calling component. It also ties your hands on how you arrange your components in a view.
Most developers who wish to not repeat themselves put common code in the project script library. I recommend all scripts in user interface events (all events, really) be one-liners that just delegate to a library script function. Then you can share code across all components and views in the entire project, not just among siblings.
An important callout (in my opinion, anyways):
As much as possible, for future maintenance, you should also try to only pass in "primitive" data to these library functions that hold your business logic.
That is, resist the temptation (as much as possible, there are exceptions) to pass "self" or "session" or whatever complex, rich, stateful objects. Instead, pass pure data (strings, booleans, numbers, etc) so that if you ever need to, you can separate your presentation logic from your business logic. It's also much, much nicer to test, recycle in different visualization systems, etc.
Strongly disagree. For maintainable one-liners called from any UI event, passing self
and event
are almost always necessary.
Yes, separation of presentation from business logic is a very good practice, but that should happen inside the project library, not at the event. That is, presentation logic should also be in the project library.
That's fair. Out of curiosity, then, is the main driver towards the project library at that point the fact that it's cleanly versionable and maintainable as a separate resource?
That is, in a perfect world where legacy concerns like the scoping in gateway event scripts weren't a problem, would you still advocate pushing all logic into the project library? In my (naive, never-had-to-deploy-an-actual-Ignition-system) head, I would have assumed that locality of "presentation" logic (i.e. on the view/component/etc) would be generally preferred to going all the way out to the project library; if nothing else than for a nicer editing experience within the Designer.
Yes, the main driver. Keeping python in resource files that are cleanly identifiable as python by external tool in source code control is part of that motivation.
Yes.
?
What do you mean by "all the way out" ? Library scripts are easily floated to be accessible while working on UI components and all kinds of gateway resources. Total win. And even if not floated, the script editors help you pick the function you need.
Oy! The designer's plethora of event resource dialogs are not "nice", IMNSHO.
And further, the business/presentation boundary, in a well-organized gateway, is managed with inheritance, like the hierarchy I recommend over here:
Well tested business logic, that is not context-specific, belongs in that "universe" project. Shared presentation logic belongs in "ui_common", "perspective_common", or "vision_common". Project-specific presentation logic stays at the leaf, but in a project library script, to cover its possible future promotion to a shared resource.
Good news: as part of the script config migration to individual resources in 8.3, we're also revamping the editing experience (and ditching the bespoke dialogs). Each category of event scripts will now just open as tabs in the associated workspace, with the same ability to 'float' tabs as the project library (something I suspect the vast majority of people didn't know existed). Plus finally paying down the scoping technical debt and putting everything in an extension function.
I'd like to see a workshop, demo, or something similar on the structure that Phil is talking about. I think the magic pushbutton pitfall is too easy to fall into. I'm to the point of getting most of my business logic into libraries, but I'd like to see something tangible for the presentation logic side as I'm not sure what that exactly looks like. This would probably be a good forum sticky.
What I'd really love to implement some day is smarter inline refactoring, akin to what proper IDEs can do. Imagine writing your magic pushbutton, then just pressing the "extract method" shortcut, and we automatically migrate the method to the project library at a given location.
ICC table talk, perhaps?