Skip to content

Split code into multiple modules #26

@tmaxmax

Description

@tmaxmax

I've been contemplating for a while now this change.

At the point of writing this, all code in go-sse is lumped in a single package: sse. Inside this package there are multiple logical units of code:

  • an SSE client
  • an SSE server
  • an implementation of a Provider – that is, a message broker – for servers
  • an event serializer & deserializer

There are some pain points which come with this configuration:

  • polluted public API
    How can FiniteReplayProvider and Backoff reside in the same package? Which type is for what exactly? Is the Logger for the client or for the server? API discoverability also suffers because of this – when typing sse. code completion goes crazy with all the names in the package.
  • names of all entities in the package must be unique
    sse.Message is a direct victim – it is actually an event, which is sent from the server. The name Message is non-sense here, but a different name than Event is required because Event is an event parsed by the client. They could be named ServerEvent and ClientEvent respectively but that doesn't sit right with me – if I have multiple types like this with Client- or Server- prefix it'd be as if there'd be multiple packages
  • updates to a certain part of the package must bump the version of the entire package
    Should someone that uses only the client have to update the library because something server related was updated?
  • dependent code must import unused code
    Why should a new provider implementation import the client and the default provider when it really only needs the event serializer and maybe the server?

Furthermore, if for example other providers or logger adapters are implemented, where would they reside? They could live in another repository – but that would mean to either pollute my account with multiple repositories related to go-sse or create an organization and to spread issues, PRs and discussions across multiple places, which would make maintenance more difficult.

Here's the layout I propose (open to suggestions for new names):

  • sseclient – the SSE client
  • sseserver – the SSE server
  • providers/ssejoe – the Joe provider
  • ssewire – event serialization & deserialization ("wire" from "wire format")

Other modules that could exist:

  • ssedge – experimental APIs
  • providers/sse* – other providers
  • loggers/sse* – logger adapters for the server
  • examples – for various example usages of go-sse

This split into multiple modules is also important for the implementation of other providers and logger adapters. Without it, library users would pull in their projects transitive dependencies (hefty message broker clients, loggers) which they don't use.

Better modularity would also be encouraged, as API boundaries are clearly defined.

Disadvantages that I can see would be:

  • the short and convenient sse package name would be lost
    If the API surface of sseclient and sseserver is small enough then maybe they could be merged into sse?
  • there will be some technical hurdles in implementing this (from the separations into modules itself, to CI and versioning)
    The good part is that they must be get right only once. To do the splitting go.work is probably the tool – it must be investigated what can be done and what cannot.

Looking forward on feedback on this possibly new layout! Do you prefer the current one instead? What's your take?

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalNew APIs, changes to existing APIs and behaviors

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions