Igniters,

I want to tackle the topic of modules structure in Ignite 3. So far, the
modules in Ignite are mostly defined intuitively which leads to some
complications:

   - Ignite public API is separated from the rest of the code only by
   package name. This leads to private classes leaking to public API which is
   very hard to catch even during the review process (we missed a bunch of
   such leaks for new metrics API [1] and I remember this happening for almost
   every SPI)
   - Classes from 'internal' packages are considered to be 'free for grabs'
   in every place of the code. This leads to tight coupling and abstraction
   leakage in the code. An example of such a case - an often cast of
   WALPointer to FileWALPointer, so that the community decided to get rid of
   the WALPointer interface altogether [2]
   - Overall code complexity. Because of the lack of inter-module
   interaction rules, we are free to add new methods and callbacks to any
   class, which leads to duplicating entities and verbose interfaces. A good
   example of this is the clear duplication of methods in
   IgniteCacheOffheapManager and IgniteCacheOffheapManager.DataStore [3]

I think we need to work out some rules that will help us define and control
both Ignite public API and module internal API which still defines a clear
contract for other modules. Some ideas:

   - Perhaps we can move all user public classed and interfaces to an
   Ignite-API module which will have no dependencies on implementation
   modules. This will prevent private classes from leaking to the API module.
   - We need somehow define which classes from a module are exposed to
   other modules, and which classes are left for module-private usage. Maybe
   Java's jigsaw will help us here, but maybe we will be ok with just more
   strict java access modifiers usage :) The idea here is that a module should
   never touch a dependent module's private classes, ever. The exported
   classes and interfaces are still free to be modified between releases, as
   long as it is not a user public API.
   - A module should be logically complete, thus it may be beneficial if
   module name matches with the code package it provides (e.g. configuration
   -> org.apache.ignite.configuration, replication ->
   org.apache.ignite.replication, raft->org.apache.ignite.raft, etc)

Any other principles/rules we can apply to make the code structure more
concise? Thoughts?

--AG

[1] https://issues.apache.org/jira/browse/IGNITE-12552
[2] https://issues.apache.org/jira/browse/IGNITE-13513
[3] https://issues.apache.org/jira/browse/IGNITE-13220

Reply via email to