Runtime Code Reuse


#1
  1. Give a description of the problem
    I wrote some complex logic to detect room occupancy.
    This code is inside a piston created for one of the rooms in my house.
    Then I created a piston FOR EACH room in my house that duplicates the original piston and modified some parameters.
    Problem: each time I fix a bug, or add a feature, I am forced to either make that change in each piston or recreate them all, in other words, not maintainable.

  2. What is the expected behavior?
    There should be a mechanism to reuse code, other than duplicate it.
    I was wondering if I could create only one piston with the logic, invoke it from other pistons (for each room), passing necessary parameters and collecting the result.

  3. What is happening/not happening?
    It seems the caller piston is unable to get output from the called piston. Yes, the called pistons could save its output in a global variable, but what will happen when dozens of callers call that same piston? Would other room states be overwritten ? Or is it possible to have a global variable that is a dictionary, so in there the state of multiple rooms can be written to, and later read by each respective caller ?
    Also, what happens to the local variables of called piston when it is called simultaneously by different pistons?

  4. Suggestion:
    It would be nice if I could pass arguments by reference. Then the callee piston could set value, and the caller would have its local variable modified by the callee.


#2

Moved this to feature suggestions.

Also check this out

https://community.webcore.co/t/occupied-room-detection-useful-for-keeping-lights-on-if-a-room-is-occupied-motionless/505?u=c1arkbar


#3

Big +1 from me, I have a bit of feedback based on what I have found so far trying to write a reusable notifications piston.

You’re on the right track, this is absolutely the way to approach reusability at this point. Calling a piston with arguments works very well.

Except for this part, which you already discovered.

This isn’t always an option since any global variables modified by the callee are not available to the caller; each piston gets a snapshot of the globals when it runs. One existing feature I’ve seen that allows both input to and output from external logic is a Web Request.

If your caller runs another piston after the callee returns that second callee would get the global variables but then you would have a potential for concurrency issues. There is probably a way to get more reusable code with several pistons that chain together but it entirely depends on what you’re trying to accomplish.

Someone else may have more insight here but I believe the default settings ensure that the piston is only running one instance at a time. Generally this should not be a problem.

That’s an interesting idea, I don’t know anything about the mechanics of if/how that would work but it seems like a reasonable approach. This might be approachable if implemented as a second list of variables on the Execute Piston action called “Results” allowing variables to be pulled from the callee.

In that case, the callee could mark variables in some way as eligible for extraction as results variables. Tracking that in the callee (rather than allowing the caller to extract any variable) would probably be a path toward including those results in the response from the callee’s External URL. Being able to get results from pistons executed by a web request could be very useful for integrations. Currently we just get { "result": "OK", "timestamp": 1505675073906 } when executing a piston from its external URL.