Clean architecture with Streamlit?

What are some examples of programming models that are similar to Streamlit?

My current strategy has been to store ā€œviewā€ controls in a separate module, and then just calling view.put_button_here() while behind the scenes Iā€™m doing state.control = st.button(), and from anywhere else I call state.control whenever I need that state, and then I springle some old school layering on top, like a Repository class to clean up the data access.

Besides that I have really no idea what an ideal architecture should look like.

I donā€™t have much experience outside of Python. Would SwiftUI be a similar analogy to follow? Streamlit projects Iā€™ve looked at are mostly teeming with ā€œbackend logicā€, and really only have a slider and a graph on the frontend, so they donā€™t really have to deal with any of these issues.

2 Likes

Hey @komodovaran

Blockquote

I mean thatā€™s sort of the whole point of Streamlit, isnā€™t it? Instead of having to implement design patterns like MVC within complex frameworks, you can just sprinkle a few Streamlit calls throughout your script and youā€™ve got an app. Thatā€™s the power.

However, I do think your question is interesting because I have also found myself asking, ā€œwhere does it end?ā€ How do I strike a balance between preserving the simplicity of what Streamlit was intended to accomplish, and not ending up with poorly-designed code? As much as I want to embrace the ā€œStreamlit wayā€, if youā€™re working on a larger project itā€™s very easy to end up with a 500 line script, and thatā€™s just not good practice.

What Iā€™ve been trying out in the app Iā€™m working on (code here), is somewhere in-between a single script and full-blown MVC: a separation of concerns by use of modules.

main.py
The script which is run. All Streamlit calls here. Acts a bit like view and controller combined. This is where the app is put together.

data_processor.py
All pandas stuff in here. Data cleaning and manipulation, building DataFrames etc.

data_scraper.py
API calls and data scraping done here. Async functions for speedier API calls in here also.

plotter.py
I style my plots here with plotly express. Not necessary if youā€™re not going to do any fancy plot styles.

For the most part, the latter three donā€™t talk to each other, except trough main.py.

I may add a text.py module too, to store long Strings that I write to the app in main.py.

Iā€™m still getting a feel for it, but I think the question is pertinent. Iā€™m worried that an unintended side effect of this paradigm could be poor code design.

If I work out a more general framework/structure for larger apps Iā€™ll definitely share it!

1 Like

I mean thatā€™s sort of the whole point of Streamlit, isnā€™t it? Instead of having to implement design patterns like MVC within complex frameworks, you can just sprinkle a few Streamlit calls throughout your script and youā€™ve got an app. Thatā€™s the power.

True true. But itā€™s also becoming a framework of its own as more features are added. Itā€™s fast and tempting to create more and more complex applications, but like any project they end up becoming pretty messy without a more stringent measures :stuck_out_tongue:

For example, I like the separation of conerns in your example, but dislike how state must be massaged and managed around by the data_processor. It quickly blows up if you have e.g. several checkboxes and conditionals to manage.

I guess one could study some of the state-management philosophies associated with React, since it feels quite similar to Streamlit (without actually having used it, ever) :slight_smile:

1 Like

Good point, although I havenā€™t run into any difficulties yet. Think of data_processor.py - and all files except main.py - as a helper function module.

Any checkboxes and/or conditionals will be managed exclusively in main.py.