Everything about development and the OpenMW source code.
User avatar
Site Admin
Posts: 1193
Joined: 05 Aug 2011, 22:21
Location: Wroclaw, Poland


Post by lgromanowski » 13 Aug 2011, 20:31

Zini wrote: The apps/openmw system has grown in an organic way rather than being properly designed. This has resulted in far less structure than I like to see. I would like to start improving that at some point (not necessarily for 0.09).

I especially find the wild growth of dependencies inside of apps/openmw annoying. I would like to reshape the dependencies between mw*-subsystems into an acyclic directed graph. That should impose some additional order and might also help to get compile times down. However that would mean we require additional discipline with dependencies for all codes once the changes are in place, because else we will end up with the same chaos again.

amos wrote: I agree, I was planning to have a bit more look over the code once the windows are completed. I suggest having a look at this after 0.09.

I don't have any specific suggestion yet though.
nicolay wrote: I wholeheartedly agree. Zini, you've made most of the stuff in apps/openmw/ at this point, so you know best what depends on what and how to reorganize it. It's not certain (you know this best) that we need to change dependencies that much, but if not then we should maybe at least have some sort of overview or sketch of how the parts hang together, and what does/doesn't depend on what. That really goes for the entire engine though.

EDIT: Maybe doxygen can make dependency graphs already? Dependencies between files at least could be found just by following includes, so there's no reason not to do it automatically if possible.
Zini wrote: Dependencies between files are not a problem when it comes to analyse them, but they aren't very useful either. There are just to many of them (files). I think we need to look at apps/openmw from a higher level (i.e. mw*-subsystems). I don't know of any means to automate that. I had a solution that enforced these kinds of dependency restrictions. But that was at the time when my operating system of choice was RISC OS and nothing of the stuff is even remotely portable (not even sure if I have it anymore).
So we either have to find an suitable tool, write one (not in favour of this option) or document these restrictions and publicly ridicule any coder who violates them.

Regarding the proposed dependency structure: That is, what I impose on all projects, I have control over. It is based on the book "Large Scale C++ Software Design" from John Lakos and so far it has always served me well. We could try something else, but we would have to work it out first and it would be more complex. An acyclic directed graph is really as simple and as easy to understand as an include-structure can get.
Zini wrote: I added a task to the OpenMW 0.12 roadmap. Its unlikely that I will be able to tackle it earlier, because the tasks I have my eyes on for 0.10 and 0.11 will keep me rather busy.
amos wrote: Great, I was going to suggest that book, learned a lot from it. But I haven't read that in many many years, guess it's time to re-read.
Zini wrote: I recently saw some code maintenance and feature enhancement commits that went (to some degree) against what we had planned for the restructuring mentioned in this thread.

Then I noticed, that I never got around to write down in detail, what I had planned. Oops! Nico's sudden departure really left us in a chaos.

Okay, then. Currently pretty much any mw*-subsystem depends on any other mw*-subsystem. This kind of wild growth isn't exactly easy to maintain and also it can increase compile times quite a bit.

This is the design I had in mind to counter this problem:

1. Create a new subsystem mwbase.

2. Move the World::Environment class to mwbase (this class holds pointers to nearly all subsystems)

3. Move all classes used in communication between the subsystems to base (i.e. classes that are used as arguments in functions of the top-level facade class of each subsystem).

4. Create an interface class for (nearly) each subsystem and replace the pointers in World::Environment with pointers to these interfaces.

5. Derive each subsystem's facade from the corresponding interface class.

6. In each subsystem access other subsystems only via these interface classes.

7. Modify the cmake scripts so that adding code that depends on a subsystem it is not allowed to depends on will yield a compile-time error.

(see the attached sketch; some subsystems omitted for the sake of simplicity).

Render is a special case here, because it should only be used by World internally.

Each subsystem (with the exception of Base and Render) must implement a single facade class through which it is controlled (mostly this is already implemented).

Engine should act as a facade for the whole OpenMW engine and as such it should not do more than bringing the subsystems together.

I hope this makes it clear and we can all agree on this design. It will be quite a bit of work to shape our current wild-growth into this structure, but actually it should impact the regular development process very little (this was an important criteria for me when I developed this design). The change will take some time and we might even do it in smaller incremental steps.
best regards,