Link Search Menu Expand Document

Setup a Definition of Done (D.o.D) on every project

The Definition of Done is a checklist that has to be fulfilled before a user story can be considered done. If not everything has been checked, your user-story/task is not finished! Google Docs Definition of Done

Open source mindset

Try to open source code where possible. This helps to:

  1. Motivate us to keep code quality high
  2. Helps the developer community
    More inspiration in the Zalando engineering principles

Code structure

Guidelines for structuring your project. Inspired by: i0natan/nodebestpractices

  • Be mentally manageable
    The brain can only deal with and think about a small number of related things at once. That’s why we use directories. It helps us deal with complexity by focusing on small portions.
  • Be size-appropriate
    Don’t create “Mansion Directories” where there’s just 1 file all alone 3 directories down.
  • Be modular but pragmatic
    The node community overall favors small modules. Anything that can cleanly be separated out from your app entirely should be extracted into a module either for internal use or publicly published on npm. However, for the medium-sized applications that are the scope here, the overhead of this can add tedium to your workflow without commensurate value. So for the time when you have some code that is factored out but not enough to justify a completely separate npm module, just consider it a “proto-module” with the expectation that when it crosses some size threshold, it would be extracted out. We can use /lib for this type of code.
  • Be easy to locate code
    Given a feature to build or a bug to fix, our goal is that a developer has no struggle locating the source files involved.
  • Use simple, obvious and context-aware naming
    If you are in order/repository.ts, don’t name your function createOrder(), but create() instead, because this will eventually be be read as OrderRepository.create()
  • Group by Coupling, Not by Function
    Features get added to a full stack, so I want to focus on a full stack of files that are relevant to my feature. When I’m adding a telephone number field to the user model, I don’t care about any controller other than the user controller, and I don’t care about any model other than the user model. So instead of editing 6 files that are each in their own directory and ignoring tons of other files in those directories, this repository is organized such that all the files I need to build a feature are co-located
  • Reduce cross-cutting coupling with Events It’s easy to think “OK, whenever a new Deal is created, I want to send an email to all the Salespeople”, and then just put the code to send those emails in the route that creates deals. Instead, the DealModel should just fire a “create” event and be entirely unaware of what else the system might do in response to that.
  • Program by Interface, not by Implementation
    For example, if the parameter types of a method are concrete classes, then the method is tightly coupled to those classes. It can’t receive anything else, except instances of that specific type. In this case, the method is not easily open to extension.
  • Code is followable
    If your app is so big that doing magicRESTRouter.route(somecontroller, {except: 'POST'}) is a big win for you instead of 3 basic app.get(), app.put(), app.del() calls, you’re probably building a monolithic app that is too big to effectively work on. Get fancy for BIG wins, not for converting 3 simple lines to 1 complex line.
  • Business logic goes in services
    Business logic for i.e. contracts goes in contract.service.ts.