Leo's MVC architecture

7 views
Skip to first unread message

Edward K. Ream

unread,
Oct 12, 2008, 1:59:17 PM10/12/08
to leo-editor
I want to keep this thread as simple as possible, because the
principles are, in fact simple even if the code isn't. Here is the
take-away message:

If you want to understand Leo's design,
**study the base gui classes**.

I. Background

Leo has had a robust MVC (Model,View,Controller) architecture from day
one.

Leo's model are the classes in leoNodes.py. They are completely
independent from the rest of Leo. Many parts of Leo *use* these
classes, but not vice versa!

Leo's controller is everything else in 'Code-->Core classes'. This
code has *no* direct dependencies on Leo's gui, as will be explained
next.

Leo's view has two parts:

1. The classes in the tree 'Code-->Gui Base classes' are part of Leo's
core.

2. The classes in the tree 'Code-->Gui Tkinter classes' are, in
effect, a gui plugin.

**Leo's core consists of the Model, Controller and part 1. of the
View.**

This is the way I use the term 'core'.


II. Why Leo's core is independent of gui.

Leo uses a completely standard way of separating gui-dependent code
from gui-independent code. Base gui classes (part 1 of the view)
define an interface known by Leo's core. Subclasses (part 2 of the
view) implement the interface for a particular gui. This is the
essence of OO programming. To avoid subclasses here would be
perverse.

The essential design rule is: if gui-related code can be made gui-
independent, it should be part of a base class. Otherwise it must be
part of a subclass of a base gui class.

The gui base classes are far more than do-nothing interfaces. Examples
of complex code that reside in base classes:

A. tree.select. I am proud that this method is gui-independent.
Switching nodes is a very tricky business. Making it gui-independent
is a big win.

B. leoFind.py. Finds the next/previous matches, and dealing with an
"idealized" find tab. Adapter classes exist in leoEditCommands.py.

C. Autocompletion and minibuffer code in leoKeys.py. For comparison,
look how simple leoTkinterKeys.py is.

D. A generalized, gui-independent interface to Leo's body pane. The
commands in leoEditCommands.py (part of the controller) use this
interface (baseTextWidget) rather than calling Tk directly. Thus, no
change should be needed to leoEditCommands.py in order to do the Qt
plugin. (There are a few nits on the to-do list).

In my mind, at least, there is no doubt whatever that this is
fundamentally a clean design. I've used it for more than 10 years
without incident.

Edward

P.S. The nullGui class and the curses gui plugin are working guis that
implement the methods of the gui base class. In particular, the
stringTextWidget class shows how to implement a working non-gui text
widget.

P.P.S. The leoFrame base class is a bit complex for my taste.
However, the interface it presents to the world is straightforward, if
a bit difficult to discern. But yes, it could be cleaned up a bit.

EKR

Ville M. Vainio

unread,
Oct 12, 2008, 4:24:38 PM10/12/08
to leo-e...@googlegroups.com
On Sun, Oct 12, 2008 at 8:59 PM, Edward K. Ream <edre...@gmail.com> wrote:

> II. Why Leo's core is independent of gui.
>
> Leo uses a completely standard way of separating gui-dependent code
> from gui-independent code. Base gui classes (part 1 of the view)
> define an interface known by Leo's core. Subclasses (part 2 of the
> view) implement the interface for a particular gui. This is the
> essence of OO programming. To avoid subclasses here would be
> perverse.

Actually, avoiding subclasses is perfectly possible if you just
register observers for particular events from the core. In qt, this
scheme is implemented by signals and slots. Likewise, a GUI plugin
could implement a thin interface that contained a minimal version of
what needs to be implemented. This does not require subclassing, and
the responsibilities of components would be easier to understand.

This may look like just a matter of code organization, but it makes
the code easier to understand by "quick scanning". It also raises
alarm bells if there are suspicious methods, like the ones related to
construction.

> The essential design rule is: if gui-related code can be made gui-
> independent, it should be part of a base class. Otherwise it must be
> part of a subclass of a base gui class.

Yeah, that's one valid design. Personally, I think having
GUI-independent stuff in base makes the design a bit too "thick" -
there is more stuff to understand at a glance. And I am not disputing
that the design works - it's just not trivial to understand for a new
guy, and there seems to be more code than would be strictly necessary.
As long as you understand the ins and outs of the code well, we
probably don't need to think about it too much.

> In my mind, at least, there is no doubt whatever that this is
> fundamentally a clean design. I've used it for more than 10 years
> without incident.

Yeah, it has stood the test of time and you understand the code well,
which is a clear indication of the merits of keeping the design.
Moreover, it can coexists with the GUI-only stuff like the QuickSearch
plugin, which means you don't really have to understand all of the
core, as long as you can work with the gui widgets and know how leo
model (c and p) work. This is good knews because it means you don't
have to read up much to contribute to leo.

--
Ville M. Vainio
http://tinyurl.com/vainio

Edward K. Ream

unread,
Oct 13, 2008, 9:17:22 AM10/13/08
to leo-e...@googlegroups.com
On Sun, Oct 12, 2008 at 3:24 PM, Ville M. Vainio <viva...@gmail.com> wrote:

> Actually, avoiding subclasses is perfectly possible if you just
> register observers for particular events from the core.

Oh, I see what you mean. Yes, I prefer that wrapper classes *have*
widgets rather than *be* (subclasses) of widgets. Don't remember why
some of the classes don't work that way. But this doesn't affect the
general design. Perhaps it does make reading Leo's code a bit
harder...

> Yeah, that's one valid design. Personally, I think having
> GUI-independent stuff in base makes the design a bit too "thick" -
> there is more stuff to understand at a glance.

I actually don't understand much of Leo's code at the code level :-)

> And I am not disputing
> that the design works - it's just not trivial to understand for a new
> guy, and there seems to be more code than would be strictly necessary.
> As long as you understand the ins and outs of the code well, we
> probably don't need to think about it too much.

Ok. The essential point is that support this design in the qt gui
gives the qt version of Leo all of Leo's existing capabilities,
essentially for free. Two steps forward and one-and-a-half steps
backward is not an option for the full qt plugin.

> Moreover, [Leo's design] can coexists with the GUI-only stuff like the QuickSearch


> plugin, which means you don't really have to understand all of the
> core, as long as you can work with the gui widgets and know how leo

> model (c and p) work. This is good news because it means you don't


> have to read up much to contribute to leo.

Exactly. Furthermore, if somebody implements a complex gui widget
with lots of non-gui support code, the pattern is to move the
gui-independent code into a gui base class. This step is optional if
you never intend this code be available for any other gui plugin, but
I'm not willing to declare that Qt will always and forever be Leo's
gui.

Edward

Reply all
Reply to author
Forward
0 new messages