2

I have a Node.js web application that's written in CoffeeScript, which has a set of "services". These various services are currently exposed as a CoffeeScript class, which does a few things that I like.

For one, I get a method that gets ran once as the instance of the service is started. On some services this allows me to fetch authentication tokens, create connections, etc. that are requirements for said services. Using CS classes also allows me to have properties that can be referenced in the specific methods exposed to the class instance (status, helper methods, etc.)

Originally when I took over the application services were exposed similar to this:

class SchedulerService
  constructor: (@msgBus, connStr) ->
    # Some logic setting up service.
  somePublicMethod: (cb) ->
    cb()

module.exports = SchedulerService

More recently, I've taken up the habit of not exposing the class itself, but an instance of the class.

# Some code that grabs msgBus connection, dbConnStr

class SchedulerService
  constructor: (@msgBus, connStr) ->
    # Some logic setting up service.
  somePublicMethod: (cb) ->
    cb()

module.exports = new SchedulerService(msgBus, dbConnStr)

If you look at the docs these modules will be cached, allowing for these services to be required and have initialization be done once per service.

Are there any downsides to this sort of module pattern? One thing I'd have to worry about is having the module cache invalidated, but it seems like that wouldn't likely happen under normal circumstances.

Another worry is boilerplate code to grab these common values, but I feel like that's solvable by a module whose only job is to supply these sort of arguments.

Any other things that I'm missing here? Seems like a viable service pattern with CoffeeScript.

AlbertEngelB
  • 213
  • 2
  • 8

1 Answers1

2

I can think of a few reasons to expose the class and not the singleton instance.

  1. Testability of the service
  2. Reusability of the class
  3. Life cycle management of service instances

If you are purposefully hiding the class constructor, how can you ever write unit tests that exercise only its code and none of its dependencies (its constructor arguments). You have just removed the ability to mock out it's depencies and test the class in isolation.

If the class is not meant to be part of a public API, reusability isn't much of an issue as you can always change the code later. However, structuring your code for reusability upfront costs very little and has the potential to save you a lot of work down the road if your singleton pattern doesn't work for some class of problems.

My third point is less common, but should you ever want services instances to be created and managed in the context of something like a database connection it becomes more important. Managing the resource creation/cleanup life cycle becomes a lot easier when you can encapsulate the concept in its own little box.

mortalapeman
  • 1,613
  • 9
  • 20
  • Those are very valid arguments against exposing the instance vs. the class. I think that adding a "service initialization" that wraps classes to ensure they get created as singletons would be a good move, thanks for the insite. – AlbertEngelB Mar 02 '15 at 19:45
  • No problem, I think your service initialization idea is an excellent solution. – mortalapeman Mar 02 '15 at 19:48