LUMIERA.clone/doc/devel/rfc/ApplicationStructure.txt
Ichthyostega 051cb31e28 clean-up: re-classify essential RfCs
The RfC documents were written to complement discussions of the Lumiera developers;
yet since the time where ''Ichthyo'' is working basically alone on the project,
this kind of discussions have ceased. During the following years, some ideas
promoted by the existing RfC documents became rather detached from the
actual state of development in the code base.

Many of the existing RfC documents require some commentary to place them
into context, and some of the decisions taken in the early stage of the
project should be **re-assessed**. This includes the decision to reject
some proposals, which initially might have seemed desirable, yet could not
be reconciled with the understanding of the matter and topic in question,
as was gained through the ongoing analysis and development.
2025-10-08 00:48:13 +02:00

229 lines
9.1 KiB
Text

Design Process : Application Structure
======================================
[options="autowidth"]
|====================================
|*State* | _Dropped_
|*Date* | _2008-11-05_
|*Proposed by* | ct
|====================================
Application Structure
---------------------
Here I am going to propose some more refined structure of the application and
its components.
Description
~~~~~~~~~~~
So far we came up with a simplified BACKEND/PROC/GUI structure where each of
this entities defines its own sub subcomponents. We agreed to glue that all
together with some portable versioned interfaces system, but details where not
laid out yet. At the time of this writing the interface system and plugin
loader are reasonable finished to be usable (some small refinements to do).
We recently discussed some details on IRC on how to engage this without a
definitive decision. The topic of this proposal is to make a detailed
description towards how the application components being glued together.
In the discussion mentioned above we concluded that we want a 'lumiera' binary
which in turn loads the optional parts as plugins. There was no consent what
this parts are actually be, except that the GUI should be optional for headless
operation. I suggested to make as much as possible pluginable to make it easier
to validate our interfaces and try different things out.
Now I introduce `"lumiera"` here, this will become a new component in
`./src/lumiera` being the driver application for bootstraping all the rest:
Then our application structure looks somewhat like (please refine):
* the Lumiera loader
- commandline handling
- interface & plugin system
- session manager core
- configuration system
- lua scripting
* backend
- file and io handling
- caches
- streams
- threads
- scheduler
* proc
- asset management
- config rules system
- builder
- render graph management
* gui
- timelines
- viewers
- resources
- preferences
- ...
Furthermore the interface and plugin system is flexible enough to provide things
independently of their origin (if it is either built-in or a plugin/dynamic library).
So deployment (where to link these things) is secondary.
`"lumiera"` will then be the executable the user starts up,
what exactly gets initialized and booted up is then matter
of configuration and commandline options (and maybe Lua scripting?).
Tasks
^^^^^
* create the `lumiera` directory
- setup the build system
- move config, plugin and interfaces therein
- Lua support can be done later
* write the `main()` part of the application
- start config system
- parse commandline opts
* librificate all other components (backend, proc gui)
- define their lumiera interfaces
- decide if they shall be statically linked, becoming shared libs or plugins
This are rather distributed tasks, after the 'lumiera' being set up, all other
components have to be adapted to be loadable from it.
Pros
^^^^
* flexible plugin based architecture
** later: loads only things which are necessary for a given task
* very fast startup
* things which can't be used on a given environment can be left out (no gui on
a headless system, no `$DISPLAY` set)
* inter dependencies between interfaces and plugins are automatically tracked.
Cons
^^^^
_Ichthyo_ raised concerns that this kind of flexibility might attract other
people to write things which are not in our intention and break future design
and compatibility. We need to carefully document and define interfaces that
people don't abuse those!
Alternatives
^^^^^^^^^^^^
We discussed the startup / `main()` through the GUI as it is currently done, it
would be also possible to produce some more executables (lumigui, luminode,
lumiserver, ....). But I think we agreed that a common loader is the best way
to go.
Rationale
~~~~~~~~~
I just think this is the best way to ensure a enduring design even for future
changes we can not foresee yet.
Comments
--------
We discussed this issue lately on IRC and I got the feeling we pretty much
agreed on it.
* we don't want to build a bunch of specialized executables, rather we build
one core app which pulls up optional parts after parsing the config
* we change the GUI to be loaded via the module/interfaces system
From reading the above text, this proposal seems to capture that. But I am
somewhat unsure if the purpose of this proposal isn't rather to load just a
*micro kernel* and then pull up components according to configuration. Because
I wouldn't accept such an architecture, and I clearly stated so right at the
beginning of our project. I accepted a very flexible and language neutral
plugin system on the condition that the core remains in control, stays
``reasonable'' monolithic and componentization doesn't handicap us in creating
an architecture based on abstractions and exploiting the proven design
patterns.
Ichthyo:: '2008-11'
+
--
It has that flexibility, yes. But that means not that we have to abuse it in
any way. The `main()` there and thus the bootstrap of the application is under
our tight control, if we want to reject scriptable/highly configurable
bootstrapping there then we can just do so. Thats more a social than a
technical decision.
I personally don't like if a design is ``nannying'' and puts
too much constraints into unforeseen areas. If the computer can do some task
better than we, it shall do it. This still means that I want to stay very much
in control, it should only do some tedious, error-prone managing tasks for me.
For example the interfaces system already tracks inter-dependencies between
plugins and interfaces automatically, without the programmer needs to care or
define anything. The interface system gets it right and we wont need to care
for the order initialization. I added that because I consider such as
absolutely important for plugins which might be supplied by third parties where
we have no control over. But I now realized that we can nicely use that for our
own internal things too. IMO thats some very valuable service.
ct:: '2008-11-08T06:26:18Z'
--
Some further minor details: We didn't finish the discussion about namespaces on
the last meeting. (I know I still have to write up a proposal showing the two
or three alternatives I see regarding namespace organisation). But probably,
`"lumiera::"` will be our top level interface namespace and then probably the
`./lumiera` directory will be taken by that. I see no problem also putting some
startup facilities in there, but generally, it shouldn't contain implementation
code, only headers and abstract classes. If that's going to become a problem,
we should consider to use a separate package for the startup, e.g. "src/boot".
Another point is, you need not write a `main()`, because there is already one.
Please have a look at it, especially with regards to the
link:{rfc}/GlobalInitialization.html[global initialisation]. Furthermore, last year
I've investigated boost::program_options and think it's fine. I use it for my
test class runner since then. I don't think there is any reason why we should
bother with parsing options (most config is pulled up from the session). I
don't think we get much program options, maybe something to set a GUI skin.
Moreover, I've written last year a thin wrapper around the commandline and
integrated it with the boost options parser such that user code can receive the
remaining options as a vector of `std::string`s. Please have a look at
https://git.lumiera.org/?p=LUMIERA;a=blob;f=tests/common/mainsuite.cpp;h=455bfd98effd0b7dbe6597f712a1bdfa35232308;hb=80e1e382f42512ebf2e10a802f77e50327b8fb73[the test class runner main]
for an usage example. I really want our Lumiera main to be clean and expressive
in the way showed there. Probably the most important part of the startup is
pulling up the session core; because of that I think most of the startup
process falls into the realm of the Proc-Layer. Within Proc, I don't want any
significant string manipulations done with C-strings and I don't want raw
arrays when we can use std::vector.
Ichthyostega:: '2008-11-06T19:28:13Z'
I _dropped_ this now because we do it somewhat differently now and I don't want
to document this here 😛
ct:: '2009-02-03T17:28:28Z'
💡 +
[underline]#Historical remark#: this RfC is related to a series of discussions
and controversies during the early stages of the project -- which eventually
helped to establish a style of internal organisation within the application.
After exploring various angles, Lumiera eventually became a *modularised Monolith*
-- using plug-ins for strictly optional parts of the system. Notably, the GUI
is loaded as a plug-in, and the integration with specific media-handling libraries
will rely on plug-in components as well. On the other hand, the core comprises
a small selection of built-in »Subsystems«, which are started with a formalised
lifecycle and dependency management. Flexibility is not attained by allowing
to totally reconfigure the application structure -- rather we allow for an
unusual degree of flexibility by combination and reconfiguration of
behaviour patterns within the application.
Ichthyotega:: '2025-09-20'
''''
Back to link:/x/DesignProcess.html[Lumiera Design Process overview]