The working architecture of NodeJs applications Viktor Turskyi
Viktor Turskyi ● CEO and principal architect at WebbyLab ● Open source developer ● More than 15 years of experience ● Delivered more than 60 projects of different scale ● Did projects for 5 companies from Fortune 500 list
Why do I talk about architecture? ● The importance of good architecture is often underestimated. ● There are a lot of “Hello, world” tutorials for NodeJs but no one explain how to build a large scale project. ● A lot of frontend developers want to be full stack but do know how to structure backend code. ● I want to share our experience with the community
Why do I call it the working architecture? ● It is in production for 8 years. ● It is battle tested with more than 60 projects of different scale. ● It proved itself as working approach in NodeJs, PHP, Perl web application
During this talk I will: ● I will answer what to choose Monolith or Microservices? ● Will answer which web-framework to choose. ● Explain basic ideas behind the architecture ● Show real code, not only diagrams.
Monolith or Microservices by default?
What is the most popular architecture today?
Big Ball of Mud http://www.laputan.org/mud/mud.html#BigBallOfMud
If Monolith is a big ball of mud. Will it be better with Microservices?
Microservices: Big and distributed ball of mud
"If you cannot build a monolith what makes you think that you can build Distributed Microservices" Simon Brown
Microservice architecture visualized https://twitter.com/ThePracticalDev/status/845285541528719360
Microservices drawbacks ● High operational complexity (increases costs) ● Versions compatibility issues (harder to track all dependencies in consistent state, reduces iterations speed) ● Extremely hard to support transactions (risks of inconsistencies) ● Distribution issues (harder to program) ● Traceability issues (harder to debug) ● Technology diversity (mixing languages increases support costs, standardization issues, hiring issues etc) ● You need more experienced team (hiring issues)
Key microservices issue
What is the best architectural decision?
Robert Martin: “The job of architect is not to make decision, the job of the architect is to defer decisions as long as possible” “Good architecture maximizes number of decisions not made” https://www.youtube.com/watch?v=o_TH-Y78tt4
Martin Fowler: ● But when your components are services with remote communications, then refactoring is much harder than with in-process libraries. ● Another issue is If the components do not compose cleanly, then all you are doing is shifting complexity from inside a component to the connections between components. Not just does this just move complexity around, it moves it to a place that's less explicit and harder to control. https://martinfowler.com/bliki/MonolithFirst.html
So, we start with monolith in 90% of cases
What is Monolith?
Usually it looks like
Which web-framework to choose?
NodeJs frameworks ● Express ● Koa ● Sails ● Nest ● Feathers ● Derby ● Kraken ● Hapi ● etc
It doesn’t matter!
Your application architecture should not depend on a web framework
Web frameworks we use NodeJs: Express PHP: Slim3 Perl : Mojolicious
“We use MVC why do we need another architecture?”
MVC (from wikipedia)
Where to place this code? Model or Controller?
Fat Stupid Ugly Controllers “The M in MVC: Why Models are Misunderstood and Unappreciated” Pádraic Brady http://blog.astrumfutura.com/2008/12/the-m-in-mvc-why-models-are-misunderstoo d-and-unappreciated/
Is Model (MVC) and Domain Model the same?
Model (from MVC)/Domain Logic ● Domain model ● Transaction script ● Table module ● Service layer
Domain model An object model of the domain that incorporates both behavior and data. (M. Fowler) Works well for medium and large applications
Transaction script Organizes business logic by procedures where each procedure handles a single request from the presentation (M. Fowler). Works well for small projects
Controllers Services Domain model Data access layer Dispatcher
The way of thinking about Controllers ● Extremely thin layer ● Protects underneath layers from everything related to HTTP ● If you change JSON to XML (or even CLI), only controllers should be rewritten
The way of thinking about Domain Model ● Belongs to Model layer of MVC ● The core part of your application ● You have almost all of your business logic here (not only database access)!!! ● Knows nothing about service layer and upper layers ● Responsible for data storing and data integrity ● Fine grained API (not suited for remote invocation)
The way of thinking about Services ● Belongs to Model layer of MVC ● Contains application logic ● Does not trust any incoming params ● You should keep thin if possible ● Knows nothing about controllers/transport/UI. ● Use cases based API ● Knows about context (what user asks for data) ● Knows when and how to notify user (emails etc) ● Does coordination and security ● Coarse grained API (well suited for remote invocation)
Core patterns in the architecture Application level (Martin Fowler): ● MVC ● Service layer ● Domain model Class level (GoF): ● Template method ● Command
How do we cook the service layer?
Rule 1: Separate service class (implemented a command) for each endpoint
Real code (with meta programming)
NodeJs example of a Service class
Base class (the simplest version)
“run” method Template method in base class Guarantees that all procedures are kept: ● Data was validated ● “execute” will be called only after validation ● “execute” will receive only clean data ● Checks permissions before calling “execute” ● Throws exception in case of validation errors. Can do extra work like caching validator objects, etc.
Rule 2: Never return objects directly Whitelist every object property: 1. You know what you return (that no internal/secret data there) 2. Your API is stable
Rule 3: There is no excuse for not using Promises or await/async today ● Error handling - one of the most powerful promise features. You can structure your error processing in a much better way with promises. ● You will never see “uncaughtException” ● You will have manageable code
Rule 4: Unified approach to validation ● DO NOT TRUST ANY USER INPUT! NEVER!!! ● Declarative validation ● Exclude all fields that do not have validation rules described ● Returns understandable error codes (neither error messages nor numeric codes) ● It should be clear for the service user what is wrong with his data
We use LIVR for the validation It supports: ● JavaScript ● Perl ● Perl 6 ● PHP ● Go ● Erlang ● Python ● Ruby ● Java ● Lua Details are here - http://livr-spec.org/
It should be clear where any code should be! Otherwise you do not architecture. One of the risks, than you can end up with an “Anemic domain model” (https://www.martinfowler.com/bliki/AnemicDomainModel.html) If you have a large project, this can be a reason of project failure as you will implicitly switch to “transaction script” approach which is not well suited for large applications. Rule 5: Be aware of “Anemic domain model” antipattern
Perl example of a Service class
GraphQL support
Full example: User registration
User registration: controller/dispatcher
Controllers
Service
User model
Action model
Main benefits ● NodeJs, PHP, Perl - the same architecture. ● Works with small and large projects ● Extremely flexible. ● Ease to start. ● Much cheaper for company to support the same approach on all projects. ● Web framework agnostic and based on micro frameworks which is easy to learn for new person. ● Cheaper technology switch (for example from PHP to NodeJs). ● Cheaper communication. ● Knowledge sharing (larger core). ● Higher resources utilization. ● Monolith first approach and modular architecture allows us to switch to Microservices later
FAQ Q: Do we use 12-factor approach? A: Yes, it is a part of boilerplate. Q: Is it ok to call a service from service A: We do not do this. If you need the same logic reuse, possibly it should go to Domain Model. Q: Is it ok to place methods in sequelize models? A: Yes, it the idea of any ORM! Otherwise it will be Anemic Domain Model
Useful links MonolithFirst by Martin Fowler Microservice Trade-Offs by Martin Fowler PresentationDomainDataLayering by Martin Fowler The Principles of Clean Architecture by Uncle Bob Martin The Clean Architecture by Robert Martin Microservice Architecture at Medium https://12factor.net/
NodeJs Starter Kit (this year) ● Based on ideas of Clean Architecture ● Works with small and large projects ● Follows 12 factor app approach ● Modern JS (including ES6 for Sequalize) ● Supports both REST API and GraphQL ● Follows security best practices. ● Docker support ● Covered with tests ● Battle tested ● Built on top of express.js ● Users management
Telegram: @JABASCRIPT
Viktor Turskyi @koorchik

The working architecture of node js applications open tech week javascript 2019

  • 1.
    The working architectureof NodeJs applications Viktor Turskyi
  • 2.
    Viktor Turskyi ● CEOand principal architect at WebbyLab ● Open source developer ● More than 15 years of experience ● Delivered more than 60 projects of different scale ● Did projects for 5 companies from Fortune 500 list
  • 3.
    Why do Italk about architecture? ● The importance of good architecture is often underestimated. ● There are a lot of “Hello, world” tutorials for NodeJs but no one explain how to build a large scale project. ● A lot of frontend developers want to be full stack but do know how to structure backend code. ● I want to share our experience with the community
  • 4.
    Why do Icall it the working architecture? ● It is in production for 8 years. ● It is battle tested with more than 60 projects of different scale. ● It proved itself as working approach in NodeJs, PHP, Perl web application
  • 5.
    During this talkI will: ● I will answer what to choose Monolith or Microservices? ● Will answer which web-framework to choose. ● Explain basic ideas behind the architecture ● Show real code, not only diagrams.
  • 6.
  • 7.
    What is themost popular architecture today?
  • 8.
    Big Ball ofMud http://www.laputan.org/mud/mud.html#BigBallOfMud
  • 9.
    If Monolith isa big ball of mud. Will it be better with Microservices?
  • 10.
  • 12.
    "If you cannotbuild a monolith what makes you think that you can build Distributed Microservices" Simon Brown
  • 14.
  • 15.
    Microservices drawbacks ● Highoperational complexity (increases costs) ● Versions compatibility issues (harder to track all dependencies in consistent state, reduces iterations speed) ● Extremely hard to support transactions (risks of inconsistencies) ● Distribution issues (harder to program) ● Traceability issues (harder to debug) ● Technology diversity (mixing languages increases support costs, standardization issues, hiring issues etc) ● You need more experienced team (hiring issues)
  • 16.
  • 17.
    What is thebest architectural decision?
  • 18.
    Robert Martin: “The jobof architect is not to make decision, the job of the architect is to defer decisions as long as possible” “Good architecture maximizes number of decisions not made” https://www.youtube.com/watch?v=o_TH-Y78tt4
  • 19.
    Martin Fowler: ● Butwhen your components are services with remote communications, then refactoring is much harder than with in-process libraries. ● Another issue is If the components do not compose cleanly, then all you are doing is shifting complexity from inside a component to the connections between components. Not just does this just move complexity around, it moves it to a place that's less explicit and harder to control. https://martinfowler.com/bliki/MonolithFirst.html
  • 20.
    So, we startwith monolith in 90% of cases
  • 21.
  • 22.
  • 24.
  • 25.
    NodeJs frameworks ● Express ●Koa ● Sails ● Nest ● Feathers ● Derby ● Kraken ● Hapi ● etc
  • 26.
  • 27.
    Your application architectureshould not depend on a web framework
  • 28.
    Web frameworks weuse NodeJs: Express PHP: Slim3 Perl : Mojolicious
  • 29.
    “We use MVCwhy do we need another architecture?”
  • 30.
  • 31.
    Where to placethis code? Model or Controller?
  • 32.
    Fat Stupid UglyControllers “The M in MVC: Why Models are Misunderstood and Unappreciated” Pádraic Brady http://blog.astrumfutura.com/2008/12/the-m-in-mvc-why-models-are-misunderstoo d-and-unappreciated/
  • 33.
    Is Model (MVC)and Domain Model the same?
  • 34.
    Model (from MVC)/DomainLogic ● Domain model ● Transaction script ● Table module ● Service layer
  • 35.
    Domain model An objectmodel of the domain that incorporates both behavior and data. (M. Fowler) Works well for medium and large applications
  • 36.
    Transaction script Organizes businesslogic by procedures where each procedure handles a single request from the presentation (M. Fowler). Works well for small projects
  • 38.
  • 40.
    The way ofthinking about Controllers ● Extremely thin layer ● Protects underneath layers from everything related to HTTP ● If you change JSON to XML (or even CLI), only controllers should be rewritten
  • 41.
    The way ofthinking about Domain Model ● Belongs to Model layer of MVC ● The core part of your application ● You have almost all of your business logic here (not only database access)!!! ● Knows nothing about service layer and upper layers ● Responsible for data storing and data integrity ● Fine grained API (not suited for remote invocation)
  • 42.
    The way ofthinking about Services ● Belongs to Model layer of MVC ● Contains application logic ● Does not trust any incoming params ● You should keep thin if possible ● Knows nothing about controllers/transport/UI. ● Use cases based API ● Knows about context (what user asks for data) ● Knows when and how to notify user (emails etc) ● Does coordination and security ● Coarse grained API (well suited for remote invocation)
  • 43.
    Core patterns inthe architecture Application level (Martin Fowler): ● MVC ● Service layer ● Domain model Class level (GoF): ● Template method ● Command
  • 44.
    How do wecook the service layer?
  • 45.
    Rule 1: Separateservice class (implemented a command) for each endpoint
  • 46.
    Real code (withmeta programming)
  • 47.
    NodeJs example ofa Service class
  • 48.
    Base class (thesimplest version)
  • 50.
    “run” method Template methodin base class Guarantees that all procedures are kept: ● Data was validated ● “execute” will be called only after validation ● “execute” will receive only clean data ● Checks permissions before calling “execute” ● Throws exception in case of validation errors. Can do extra work like caching validator objects, etc.
  • 51.
    Rule 2: Neverreturn objects directly Whitelist every object property: 1. You know what you return (that no internal/secret data there) 2. Your API is stable
  • 52.
    Rule 3: Thereis no excuse for not using Promises or await/async today ● Error handling - one of the most powerful promise features. You can structure your error processing in a much better way with promises. ● You will never see “uncaughtException” ● You will have manageable code
  • 53.
    Rule 4: Unifiedapproach to validation ● DO NOT TRUST ANY USER INPUT! NEVER!!! ● Declarative validation ● Exclude all fields that do not have validation rules described ● Returns understandable error codes (neither error messages nor numeric codes) ● It should be clear for the service user what is wrong with his data
  • 54.
    We use LIVRfor the validation It supports: ● JavaScript ● Perl ● Perl 6 ● PHP ● Go ● Erlang ● Python ● Ruby ● Java ● Lua Details are here - http://livr-spec.org/
  • 55.
    It should beclear where any code should be! Otherwise you do not architecture. One of the risks, than you can end up with an “Anemic domain model” (https://www.martinfowler.com/bliki/AnemicDomainModel.html) If you have a large project, this can be a reason of project failure as you will implicitly switch to “transaction script” approach which is not well suited for large applications. Rule 5: Be aware of “Anemic domain model” antipattern
  • 56.
    Perl example ofa Service class
  • 59.
  • 62.
    Full example: Userregistration
  • 63.
  • 64.
  • 65.
  • 67.
  • 68.
  • 69.
    Main benefits ● NodeJs,PHP, Perl - the same architecture. ● Works with small and large projects ● Extremely flexible. ● Ease to start. ● Much cheaper for company to support the same approach on all projects. ● Web framework agnostic and based on micro frameworks which is easy to learn for new person. ● Cheaper technology switch (for example from PHP to NodeJs). ● Cheaper communication. ● Knowledge sharing (larger core). ● Higher resources utilization. ● Monolith first approach and modular architecture allows us to switch to Microservices later
  • 70.
    FAQ Q: Do weuse 12-factor approach? A: Yes, it is a part of boilerplate. Q: Is it ok to call a service from service A: We do not do this. If you need the same logic reuse, possibly it should go to Domain Model. Q: Is it ok to place methods in sequelize models? A: Yes, it the idea of any ORM! Otherwise it will be Anemic Domain Model
  • 71.
    Useful links MonolithFirst byMartin Fowler Microservice Trade-Offs by Martin Fowler PresentationDomainDataLayering by Martin Fowler The Principles of Clean Architecture by Uncle Bob Martin The Clean Architecture by Robert Martin Microservice Architecture at Medium https://12factor.net/
  • 72.
    NodeJs Starter Kit(this year) ● Based on ideas of Clean Architecture ● Works with small and large projects ● Follows 12 factor app approach ● Modern JS (including ES6 for Sequalize) ● Supports both REST API and GraphQL ● Follows security best practices. ● Docker support ● Covered with tests ● Battle tested ● Built on top of express.js ● Users management
  • 73.
  • 74.