tryexceptpass / sofi

an OS agnostic UI module for Python
MIT License
387 stars 49 forks source link

MVC pattern #94

Open alensiljak opened 5 years ago

alensiljak commented 5 years ago

I'm just throwing an idea here to see what you think of it. Looking at the Python web UI libraries, I find them unnecessarily complex. They introduce another layer and a framework to learn. If they stop being maintained, all the effort goes down the drain, both for the library and the code that uses it. I would prefer to see the use of widely accepted standards, like HTML and CSS, and some separation of concerns into an MVC pattern. The view would be created in HTML, allowing anything that is currently available in the standard and not waiting for the implementation in the framework. I see your issue list is pretty long and does exactly that - translates HTML elements into Python, or rather into a specific framework, making it non-transferable in the process. HTML is supported by many tools created in the past 30 years. Many more people are familiar with it than with Python, for that matter. It also allows the use of any CSS framework for customising the look and feel of the final product.

What you have here is the heart of the system: linking HTML elements' events to the code in Python. Some additional tools would be useful, like parser of the HTML view, getting all the element IDs, and generating a Python link file, which gets imported into the main app.

Manipulation of the elements can happen through editing the properties, style elements, and assigned classes.

I hope such an approach would speed up the development of the libraries, make it easier to implement, would not waste time on reinventing the wheel, would allow introduction of new elements and CSS frameworks, and so on.

So far I've tried PySimpleGUI, Remi, Reahl, and Sofi. They all suffer from the same issues, listed at the top. A lot of time is spent on reimplementation of the HTML elements, which have been around for decades, instead of creating something usable and independent of the view technology. I'd wish to see your thoughts on the topic and hopefully find a library that does not get in the way but builds on what is already there. Cheers

tryexceptpass commented 5 years ago

Hi there, thanks for this issue. One of the reasons I built Sofi in the first place was because of what you're talking about. And as I put it together, I found that we could actually split up functions into separate individually-installable packages.

Conceptually we just need a base to start from. A core command and eventing system that handles communication over a common protocol. Everything else can live at its periphery. In fact, I proved that this can work well when I built the sofi-unity3d project, which essentially does the same thing but with a game engine GUI instead of a browser.

This is the approach I would use:

I can even see other python packages building on top of these to distribute various GUI widgets or even event behaviors. For example, someone could make a d3js chart widget.

Lately I've had to work on pure javascript frameworks again, and I might have a few improvements other ideas that I could build on too.

Unfortunately, I haven't had a lot of time to really dedicate to this project. Not as much as I want to at least. Maybe with a little help, we could accomplish all this stuff.

I do think this is a great conversation to have and I'm open to any and all ideas.

alensiljak commented 5 years ago

Thanks for the feedback! That's an interesting direction. I'd just like to clarify a bit what I thought of the base. To me, it makes sense to do the View component entirely in its native technology - HTML (+ CSS + JS). JS is a tricky topic but let's include it for now, as per "the more options the better" general rule.

Speaking hypothetically (as I still don't have a clear vision), I would start with an HTML file. The tooling is widely available, so I create a form with a few controls. Then I add Bulma framework, for example (it could be anything). Additionally I could have any combination of CSS, images, fonts, scripts, on that page. But note that this is only for the purpose of the View element. The next step would be to create a link between Python and this View. A tool would be handy - it would generate some binding .py file that would pick up the element IDs from the HTML. Rule 1: all referenced elements would need to have an ID attribute. The generated reference .py file (probably just a dictionary of element ids?) gets imported into the actual code file. This is where we create the application, add event handlers, and so on.

Elements are referenced and manipulated by id. Additionally, if there was some sort of jQuery-like functionality (i.e. operating on all class elements, etc.) that would be a bonus but it also seems too specific for HTML. Scope of operations? Manipulating attributes, and eventually having proxies for Style and Class attributes, might be enough. Perhaps showing/hiding elements, etc. Not sure but this can ironed out later.

I agree that it seems quite useful to have a discussion about possible roads ahead. Some useful ideas might pop up.

What you were referring to, with bs3/4, are probably libraries that generate the HTML widgets. I'm no fan of this simply because creating a proxy for a library is a never-ending rabbit hole. And it almost never reaches the functionality of the original framework/library so I'd rather do the UI with Bootstrap 4 in HTML, SCSS, and JavaScript, than write it in Python and hope that it gets translated into what I want in the end. I'd prefer to work on the end result as the UI requires immediate feedback during development. That leaves the question open on what would be the best way to link to Python. You already inject a .js file into the resulting HTML, and it talks to the server, passing the events. This is a good concept. From the "code" file, the handlers could be collected and attached to the HTML nodes in .js. They pass the events to the server component. That part is understandable. The question is which level of accessibility should be available to Python code. Manipulate DOM nodes directly? Abstract them into higher-level components, like panels? I would not (at least initially) go so far because any CSS framework will have a different way of implementing components. And the freedom to pick any CSS framework seems the way not to get deprecated very quickly. Anyways, let's keep the discussion going and come up with answers to some questions that will necessarily pop up. Cheers!

tryexceptpass commented 5 years ago

That's an interesting approach. I actually hate writing the HTML and find it repetitive (mostly due to the things I work with), so I like having python build the components for me, especially because I can make a composite module and reuse it (yah I know angular / react do that too). But I do very much agree that maintaining "wrappers" like the bs3/4 stuff I have here leads to quick obsolescence.

So given a repo split like I mentioned earlier, it's very easy to distribute the js "client" lib separately. It's not hard to enhance it such that you can drop it in any webpage your building for the sole purpose of ferrying events and commands back and forth with a python backend. This let's you build the site with native tools like you're talking about, while still enabling python to do more processing for you.

It even enables a hybrid system, where you can use js-native libs for what they're good at (like say d3 charts), while having python do what it's good at, like business logic or machine learning.

The rest of the modules could still exist for those of us that would rather work at their level.

alensiljak commented 5 years ago

I can't say that I really enjoy writing HTML but I enjoy even less writing and fixing the translation libraries. :) I prefer to do less work, if possible, and get the same results. I mean, just think about when BS5 is out. Or Bulma, Framework 7, or anything else that makes things easier. How about Vue.js? Single-page application could soon be the only viable way to write JavaScript. Or there could come some completely new concept. With SPA, the only way is a proxy code, I guess. That might still be doable. In any case, the concept sounds interesting. What would be your idea of the next steps in that direction? I'll try to get more familiar with Sofi internals in the meantime, as I'd like to contribute and get a prototype going.