0

Module A contains a gap buffer for manipulating text and some associated methods. Relevant to this question is the dependency on a Module B, used for syntax highlighting of text.

Module A also provides a type that wraps its gap buffer with more stuff, and brings in some convenience methods for dealing with syntax highlighting, putting Module B in a public API.

This looks like the leaking of an implementation detail: depending modules must know about Module B to use A, even if all they really want is what A provides, and couldn't care less about B.

Is this an (anti-)pattern? If so, does it have a common name, and how can I refactor it out?

5
  • Are you the owner of both modules? Can you clarify why the Module A needs to exist at all instead of being exposed by Module B? Oct 31, 2021 at 22:41
  • @VincentSavard both modules are open source, and I can modify them as necessary. Module A provides a context within which constructs from Module B operate, in a fairly awkward way where A almost encapsulates B, but 'requires' B to be exposed for coherent APIs, if that makes any sense. Thanks!
    – user361757
    Oct 31, 2021 at 22:57
  • @DocBrown thanks for the feedback; I've added some specifics and rephrased most of it. Tell me if you have any more questions!
    – user361757
    Oct 31, 2021 at 23:41
  • 2
    This is still context dependent. For example, if you're using a UI Framework or library such as Angular/React/Vue, then you may have other libraries which are built specifically for that framework/library, but the developer will need to know about both. (For example: Ionic builds on top of Angular, NuxtJS builds on top of Vue, etc.) Nov 1, 2021 at 5:45
  • @CtrlAltF2: ok, I think this edit heavily improves your question, retracted my close vote.
    – Doc Brown
    Nov 1, 2021 at 8:36

1 Answer 1

3

This is neither a pattern or an anti-pattern, it is simply a trade-off between two valid design choices:

  1. Designing Module A in a way that the usage of Module B is just an implementation detail, or

  2. Designing Module A in a way it exposes parts (for example, types) from Module B in public.

Each of those two options can be sensible, and there is no hard-and-fast-rule which one is "better", or which one to prefer over the other. Choice #1 may require a lot of additional encapsulating code. It may require to replicate types in A which are already there in B, maybe more boilerplate code than code which is reused from B. On the other hand, it has the advantage that a user of A does not have to deal with B, and B can be more easily updated or exchanged.

To make a choice, you need to assess if exposing B is really a problem or perfectly acceptable. There are a lot of factors which come into play here, starting from who maintains B, how often B gets changed, how often the public API of B gets changed, how large B is, how much code from B is used inside A, how much code can be saved by exposing B, up to license considerations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.