DEV Community

Discussion on: Composing packages into applications?

joncalhoun profile image
Jon Calhoun • Edited on

Try this instead:

  1. Create a "top level" package. Call it catfacts or whatever else. In this define the things you need to build your app.
package catfacts

type Subscriber struct {
  Email string

// Feel free to tweak method names.
type SubscriberStore interface {
  Find(email string) (*Subscriber, error)
  Create(s *Subscriber) error
  List() ([]Subscriber, error)
  Delete(email string) error

type Sender interface {
  Send(s *Subscriber, message string) error

// In the context of your app, Sender and Retriever are probably descriptive enough. You could also call this FactStore if you want to be more consistent with the SubscriberStore.
type Retriever interface {
  Retrieve() (string, error)

Now when you want to implement Sender with say Twilio, create a package for that.

package twilio

type Sender struct {
  // ...

func (s *Sender) Send(subscriber *catfacts.Subscriber, message string) error {
  // ...

Now if you ever want to create a new sender, you just create a new package based on the impl. I just needs to implement catfacts.Sender.

Back to catfacts, you can create SendFactToSubscribers using your interfaces:

package catfacts

func SendFactToSubscribers(store SubscriberStore, retriever Retriever, sender Sender) {
  subs, _ := store.List()
  fact, _ := retriever.Retrieve()
  for _, sub := range subs {
    sender.Send(sub, fact)
  return nil

Rinse and repeat for any other impls you need - eg package sqlite might have an sqlite impl of the SubscriberStore.

This may be a good point to continue this thinking:

I also started writing about this and hope to have more examples in the future, but I'll admit this series has taken the back seat to other work lately:

There isn't a single "best way" to write apps in Go, but this approach tends to work better for me.

jsmithdenverdev profile image
Jacob Smith Author

Awesome! Thanks for such an informative response :) . I think when learning a new language it's good to try out different approaches to writing apps since like you said there is no one best way, this was a fantastic look at a way to organize code.

joncalhoun profile image
Jon Calhoun

You should definitely experiment a bit. Almost all of the pros/cons of each approach need to be learned firsthand to really sink it, and every approach doesn't fit every problem.

It can be a bit challenging with smaller apps because some of the problems (cyclical deps, etc) won't show up until an app gets to a certain size, but still worth experimenting.