-1

At work, we are creating an android app. We have a business logic module for talking to an API for CRUD operations. The app I'm working on, the UI module, speaks to the business logic module to create, update, delete and get entities. These entities can be in various states (not started, awaiting, started, ended as well as a few others). The problem being, some of these entities come from different sources, some of the sources are stateless (and therefore we need to manually manage the state of these) and, some are state full (for these we trust the sources state). The business logic module needs to consolidate the sources into a unified model for the UI module (as we don't want the UI module to be concerned with the nitty gritty details of the entity sources).

I am working on the UI component, and there was a discussion with the developers working on the business logic module about how state should be handled. We were talking about if the UI layer should manage the state of the domain objects or if the business logic module should handle it. I argued that the business logic module should maintain an FSM for each entity, such that the UI layer can issue a command to the business logic layer for a given entity, and that command will be executed if it's valid for the entities current state. If the command was valid, then the FSM would transition to a new state, executing side effect such as API calls if required.

The general idea being, the UI layer should not be able to put business entities into invalid states, this would be enforced by an underlying FSM and side effects could be maintained in a single place - the state transition table. This also has the benefit that we can re-use the business logic model for completely different UI modules (with possibly completely different UX/ flows) and be guaranteed that the business logic behaves as intended across multiple client applications.

This suggestion didn't fly, and instead we've landed on a proposed solution which involves partially managing each entities state in the UI layer and partially in the business logic layer, which concerns me. For instance, the UI layer will query the business logic layer for entities and may possibly need to decide the initial state for an entity, depending on that entities current state. But the UI layer should only do this if the entities current state is x or y, not a, b or c. On top of that, the actual idea of using an FSM to manage the state at all seemed to be a no-flyer (perhaps I didn't explain myself well enough as the meeting was called at short notice).

From what I've said here, does an FSM sound like a reasonable solution, and am I on the right path in thinking that splitting the state management across the business logic and UI layers is a bad idea ?

I'm aware the question is quite vague, but I am not allowed to discuss the specifics of the project outside the company. I could create a contrived example that reflects the domain entities, states and transitions if it would help.

EDIT:

To clarify; the UI layer will maintain it's own FSM to manage it's state (i.e. the user tapped a button, issue a command to the UI FSM, if there is a valid transition, then execute side effects and transition to new state). The UI FSM may issue commands to entity FSM's as side effects of the transitions.

  • 1
    This is actually hard to answer without knowing which kind of abstraction has to be modeled for your case. If there is some state which could be better implemented in the UI than directly than in the objects, because that state fits better to the visual appearance, then splitting the state may make sense. I suggest you find a way to become a little bit more concrete of what kind of entities and what kind if state you are talking - I am sure there is a way without disclosing company secrets, if you try a little harder ;-) – Doc Brown Dec 13 '18 at 19:04
  • @DocBrown - Yes, I am planning on maintaining a separate FSM for the state of the UI, but that is separate to the state of the entities. Should I edit my question to make this clear? – Thomas Cook Dec 13 '18 at 19:06
  • @DocBrown - Or rather, the UI FSM will have state transitions be triggered by the state of the business entities. But the business entities should have no idea about the state of the UI (in my opinion) – Thomas Cook Dec 13 '18 at 19:07
  • 1
    Not sure if that would clarify things. As long as you just talk in very abstract terms of "state", "entitites", and "FSM", without naming things or giving a realistic example, your question will stay vague. – Doc Brown Dec 13 '18 at 19:09
  • Ok, I will create a contrived domain and give some examples of how I propose it should work and examples of how it will work with the current plan. Will take me about an hour to create the examples. – Thomas Cook Dec 13 '18 at 19:11
5

Splitting the state management across the business logic and UI layers is a bad idea.

You keep going on about Finite State Machine (FSM) in a way that is fairly off putting. I think I know what you really mean but you sound like one of those goofs that turns off their brain and chants pattern jargon. You need to be clear about what you really mean by this.

The reason splitting "state management" across the layers is a bad idea is because you need a single source of truth. You really need to make this idea clear though because it's a tricky idea. The UI should not be where the state of your model of the world is kept. It should only be a reflection of what the user wants and knows. Nothing more. The world may have changed since the UI last looked it. There should be no decisions being made in UI code. "State" in the UI, if you insist on calling it that, should never be more than "this is what the user selected".

Done that way the UI is dumb. It's a pretty place to watch and click things. Nothing here even needs tests written against it because it's just boring obvious structural code. Nothing interesting allowed.

That means that logic you were going to put in the UI has to move somewhere else. I keep at least one layer between the UI and the model. That layer, which people give tons of different names, can soak up that homeless logic.

This idea even has a pattern named after it called the humble object. It's centers around the idea that objects near boundaries (like the UI) are inherently hard to test. So rather then kill ourselves trying to test the untestable we move the suspiciously interesting logic into a testable object that doesn't touch the boundary. Being easy to test is nice but it's not the main justification for this move.

By moving the logic into an isolated object you're free to define an interface/API for talking to it that makes sense in your domain. Something simple, readable, and free of details like understanding what a textbox is. So much so that you can get your DDD ubiquitous language going and write business rules that a domain expert, who's never written code before, could actually read and tell you if you have it wrong.

That bit of business logic is the guardian of the model/entities. It ensures that what we're doing to them follows the rules.

This suggestion didn't fly, and instead we've landed on a proposed solution which involves partially managing each entities state in the UI layer and partially in the business logic layer, which concerns me. For instance, the UI layer will query the business logic layer for entities and may possibly need to decide the initial state for an entity, depending on that entities current state. But the UI layer should only do this if the entities current state is x or y, not a, b or c. On top of that, the actual idea of using an FSM to manage the state at all seemed to be a no-flyer (perhaps I didn't explain myself well enough as the meeting was called at short notice).

The best thing to do when ambushed like that is to say "I'll get back to you". Don't agree to anything. Don't present anything. Don't let them get away with anything.

This is important stuff and your voice is being stiffed by meeting engineering. Build your own support base with one on one conversations then call your own meeting. It's nasty and political but it's the world we live in.

Your post mentions some ideas I like (regardless of whose they were):

  • The ui module, speaks to the business logic module to create, update, delete and get entities.
  • These entities can be in various states (not started, awaiting, started, ended as well as a few others)
  • The business logic module needs to consolidate the sources into a unified model for the UI module (as we don't want the UI module to be concerned with the nitty gritty details of the entity sources).

Some ideas I don't:

UI layer should manage the state of the domain objects

NO. Here I agree with you that the UI shouldn't know the domain objects exist. It should only know how to request things through controller logic and how to display responses from presenter logic. The UI shouldn't be able to directly touch those domain objects. If the UI can touch them then the domain isn't properly encapsulated.

I argued that the business logic module should maintain an FSM for each entity, such that the UI layer can issue a command to the business logic layer for a given entity, and that command will be executed if it's valid for the entities current state. If the command was valid, then the FSM would transition to a new state, executing side effect such as API calls if required.

Here you went wrong because you were giving them a design for their stuff. You should have stuck to getting inter layer communication requirements ironed out.

Now if the worst happens and they just wont work with you don't give in and shove logic into the UI. Make your own layer between the UI and their stuff to handle their shenanigans. Don't package this layer with the UI. Do that and you can ensure the UI has a clean API that you can test quickly when fingers start pointing.

TL;DR You need a better counter design argument than "Use FSM".

Some additional rants: MVC, Clean Architecture1,2, inter layer communication, abstraction

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.