Skip to content

[DISCUSSION] Refactor project architecture #7543

@kroune

Description

@kroune

Describe your feature request.

Current issue of the project I want to address:

  1. Modules lack clear public api, which sometimes causes properties/handlers to become public by accident
  2. When Module code becomes big it is harder to distinguish simple variable from user settings (those that you can change at clickgui), so when you see autoSpeed or forceSneak (in ModuleScaffold) it isn't clear whether it is a settings or a value
  3. Modules directly depend on each other and can change each other state
Image Image

it isn't obvious when variable can change from the code
4. Small change causes entire project to recompile. The project is basically a single module, project has ~136 000 lines of code, so sometimes relatively simple changes causes a long recompile time

My idea:
we can separate public api from Module implementation and keep Module entirely hidden

Example of possible way to implement this

// publicFacade (gradle module)

// Base classes:
class ModulePublicFacade {
    fun intRange() = null
}

// Actual Module
object ModuleScaffoldPublicFacade : ModulePublicFacade() {
    val something = intRange()
    var somePublicVariable = 0
}


// clientModules (gradle module)
// Base classes:

object ModuleManager {
    ...
}
sealed class ClientModule<T: ModulePublicFacade>(protected val publicFacade: T) {
    fun handler(lambda: () -> Unit) {
        println("handler")
    }
}


// Actual Module
internal object ModuleScaffold : ClientModule<ModuleScaffoldSettings>(ModuleScaffoldSettings) {
    private val a = handler {
        publicFacade.intRange()
        publicFacade.somePublicVariable++
    }
}

publicFacade (gradle module) doesn't depend on any other modules

clientModules (gradle module) depend on publicFacade(gradle module)
clientModules (gradle module) has every module marked as internal, only some other classes/objects can be exposed

main (gradle module) depends on publicFacade, clientModules (gradle modules)

Benefits of this separation:

  1. Modules have a clear public facade, you will call it explicitly. Which makes it much easier to read/write code.
  2. Modules can be prevented from exposing internal state in ci (using binary-compatibility-validator) in clientModules (gradle module), you would almost never need to expose/change smth public.
  3. You rarely change user settings, most of the time you only change Module's code. That means that most of the time only a clientModules (gradle module) will be rebuilt and main module won't need to recompile. Which improves build times
  4. Client modules don't depend on each other, only on public facade.

I know this would require a big refactoring and I am ready to make it myself

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions