Skip to content

Refactor root command creation to avoid it knowing about packages of sub-commands #164

@maximilien

Description

@maximilien

Currently the root.go file where the root command is created needs to import the packages for all the sub-commands that are created. This makes that file a cyclic dependency hog. I moved it to a solo package called core. There may be ways to solve this w/o a solo package by passing factory functions. As @rhuss mentions below.

Need to investigate if possible and do this refactor.


@maximilien The decoupling works nicely, just as a comment for another approach which might be useful, too, would be to reverse the direction of the commands registration (i.e. letting sub-commands register themselves). It's more a syntactic thing, and I think it can also break dep cycles more easily (maybe even without the introduction of third common package for the KnParams definition).

That's the idea (not fully tested):

  • root.go
package commands

// That unnamed import is crucial here
import _ cmd_service

typ KnParams struct {
  // ...
}

var SubCommandFactories = make([]func(*KnParams) *cobra.Command,0)

func NewKnCommand(params ...common.KnParams) *cobra.Command {

	for _, fact := range SubCommandFactories {
       rootCmd.AddCommand(fact.newCommand(p))
    }
}
  • service.go
package cmd_service

import commands

func init() {
    commands.SubCommandFactories = append(commands.SubCommandFactories, newServiceCreateFactor)
}

func newServiceCreateFactory(p *commands.KnParams) *cobra.Command {
  ////
}

You then can easily add new commands by adding an unnamed import which is used to call its init() method.

I've seen that pattern in the wild quite a bit (I darkly remember its used also for collecting k8s resource schemes), so might make sense here, too.

Originally posted by @rhuss in #145 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/cleanupCategorizes issue or PR as related to cleaning up code, process, or technical debt.kind/refactorCode refactor needed

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions