title: Node.JS service layer design
body: <p>I have a very simple express js server that accepts a request from a client, performs some business logic and respond back to the client. The request - response pipeline is handled by a controller and the business logic is performed inside the service layer. The code is functional but I am not sure the way I return errors to the controller from the service layer is correct.</p>
  
  <p>The controller looks something like this:</p>
  
  <pre><code>async createAnOrder(req, res, next) {
      try {
  
          // Input validations
          if (!req.body.name){
              throw new ClientFacingError(ERROR_CODES.BAD_REQUEST, "Name is missing")
          }
  
          let newOrder = new Order();
          let validationDictionary = new ValidationDictionary();
  
          if (!await orderService.createOrder(newOrder, validationDictionary)){
              return next(new ClientFacingError(ERROR_CODES.BAD_REQUEST, validationDictionary.getErrorMessage()));
          }
  
          res.json({
              orderId: newOrder.id
          })
  
      } catch (err) {
          if (err instanceof ClientFacingError) {
              res.status(err.code).json({ message: err.message })
          } else {
              res.status(500).json({ message: "Internal Error" })
          }
      }
  }
  </code></pre>
  
  <p>The orderService looks something like this:</p>
  
  <pre><code>async createOrder(newOrder, validationDictionary) {
  
      // Business logic validation
      if (await orderDb.hasOrder(newOrder)) {
          validationDictionary.addError("Invalid Order", "Order already exists");
          return false;
      }
  
      await orderDb.createOrder(newOrder);
      return true;
  }
  </code></pre>
  
  <p>I am trying to aim for separation of concern between the business layer to everything else. I also want a smart contract between the service layer methods and the controllers.</p>
  
  <p>I think what I was trying to do was:</p>
  
  <ol>
  <li>Input validation happens in the controller (infrastructure) layer and business related validations only happen in the service layer</li>
  <li>Service layer methods return true if operation was successful and false if there are business validation errors.</li>
  <li>Any errors thrown by the service layer methods are Runtime errors which is caught by controllers and returned to the client as an Internal Error.</li>
  </ol>
  
  <p>Another way is to adhere to the CQS principle. The service layer method should not return a value but instead throw an exception to indicate failure. The problem with this approach is that the controllers do not have context of whether or not the error message can be returned to the client. I may be able to throw ClientFacingError exception from the service layer which can be used by the controller to decide whether or not the error message can be returned to the client but that feels like I'm coupling the service layer to the infrastructure layer.</p>