# HMI Software Architecture

**URL:** <https://forum.inductiveautomation.com/t/hmi-software-architecture/116236>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [July 1, 2026, 6:19pm UTC](https://forum.inductiveautomation.com/t/hmi-software-architecture/116236 "2026-07-01T18:19:16Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![eallenfernandez](https://avatars.discourse-cdn.com/v4/letter/e/e99b99/32.png) [@eallenfernandez](https://forum.inductiveautomation.com/u/eallenfernandez)\
**Post date:** [July 1, 2026, 6:19pm UTC](https://forum.inductiveautomation.com/t/hmi-software-architecture/116236/1 "2026-07-01T18:19:17Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [July 1, 2026, 6:30pm UTC](https://forum.inductiveautomation.com/t/hmi-software-architecture/116236/2 "2026-07-01T18:30:22Z")

</div>

> [@eallenfernandez](#):
>
> - 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.

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)`

```python
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](https://en.wikipedia.org/wiki/Magic_pushbutton)is the bane of my existence modifying existing projects.
