HMI Software Architecture

Currently, our team is in the process of decoupling the business logic out of our HMI project (specifically the logic contained within perspective components) in an attempt to reduce complexity and improve maintainability and extensibility. We are exploring different ways to structure our projects and are curious about how others are doing so. Some things we are considering are...

  • A decoupled version of what we currently have, where all scripting logic lives in the scripting module and perspective components call the scripting module directly.
  • A frontend-backend solution, where the perspective components would live in one HMI frontend project and any scripting logic would live in a different backend project.
  • A microservices-like solution, where logic is separated into individual projects each acting as their own self-contained service. Each service would then be accessed by a main HMI project.

Is there something else we should be considering? How are people structuring their systems?

Do this.The other two are likely overkill and I personally don't see the benefit.

I'll tell you how I do it in vision but should translate direclty to perspective. Have your button onAction be a one-liner

MyModule.doBusinessThingGUI(event)

def doBusinessThing(someValue, anotherValue):
   # Now here is where you can do your contract, raise errors, fail fast
   if someValue < 0:
        raise ValueError("Some Value must be above 0")
   # do whatever logic
   return someResult

def doBusinessThingGUI(event):
    someValue = event.source.someValue
    anotherValue = event.source.anotherValue
    try:
        result = doBusinessThing(someValue, anotherValue)
    except ValueError, e:
        # Present to user
    # you may well need finally instead of else depending on the flow, like closing a db transaction should occur in error or success cases
    else:
        # no error occured
        # Present success message to user

The benfeit of breaking it up here

Only one line on the button is good. Scripting is much more git friendly than either front end.

Breaking up the functions where one function parses the GUI and feeds to a more "pure" function - that pure function can be called anywhere or at least thats the intent, in the event you ever need to call through a script where you parse a CSV and backfill data, now its trivial. Or if you want to write tests against it, it is much easier.

The magic push button is the bane of my existence modifying existing projects.