@FGRibreau
DEVELOPMENT
PRINCIPLES
&
PHILOSOPHY
François-Guillaume
RIBREAU
@FGRibreau
Bringr
Bringr
Performance oriented
Social MediaManagement
Bringr
Leader européen de
l'engagement client en
temps réel.
(click2chat, click2call,
click2video, community, ...)
#sold
Bringr
Developer oriented
real-time monitoring and
administration service
for Redis
@FGRibreau
COMPUTER SCIENCE IS
ABOUT TRADEOFFS
@FGRibreau
VS
WHEN YOU FIGHT TO SURVIVE
BETTER CHOOSE THE RIGHT PATH
@FGRibreau
How can I make the
right choice
while coding?
@FGRibreau
EASY.
@FGRibreau
FOLLOW AND DISCOVER
PRINCIPLES
@FGRibreau
SEPARATION OF
CONCERNS
@FGRibreau
SEPARATION OF
CONCERNS
@FGRibreau
A.K.A THINK ABOUT ____#ROLES
@FGRibreau
MONOLITH(S)
@FGRibreau
Bringr
#monolith
Use the Separation of Concerns Luke!
Morpheus
(not sure about this one)
@FGRibreau
Bringr
Bringr
Strategy
Bringr
Impact
Bringr
...
Bringr
Sourcing
Bringr
...
Bringr
Alerts
@FGRibreau
Bringr
Strategy
Bringr
Impact
Bringr
...
Bringr
Sourcing
Bringr
...
Bringr
Alerts
@FGRibreau
Bringr Strategy Bringr Impact
Bringr Backend
....
Bringr Sourcing Bringr Account
...
Bringr Alerts
@FGRibreau
Bringr Strategy Bringr Impact
Bringr Backend
....
Bringr Sourcing Bringr Account
...
Bringr Alerts
Filtering
Statistics
Rules EnginePublishing
Statistics Updater
UIUIUI
Indexing
G+
Vimeo
Facebook
Youtube
Wordpress
Twitter
Notifications
... ... ...
@FGRibreau
“DIVIDE MICROSERVICES
BETWEEN ACTIVE AND
PASSIVE ONES
@FGRibreau
MICROSERVICE TYPE DEFINITION
ACTIVE ACT ON SOMETHING
PASSIVE REACT TO SOMETHING
@FGRibreau
MICROSERVICE TYPE e.g. IN THE ASYNC WORLD
ACTIVE PUBLISHER
PASSIVE CONSUMER
#AMQP #RabbitMQ
@FGRibreau
THE LESS ACTIVE ONES, THE BETTER
@FGRibreau
THE LESS ACTIVE ONES, THE BETTER
THE MORE PASSIVE ONES, THE BETTER
@FGRibreau
“DIVIDE STATE AND LOGIC
INSIDE MICROSERVICESMICROSERVICES
@FGRibreau
“DIVIDE STATE AND LOGIC
INSIDE MICROSERVICESCOMPONENTS
@FGRibreau
My Worker My Worker My Worker
State Repository
#atomic
#concurrency #resilient #scaleOut
@FGRibreau
State Repository
#parallelism #resilient #scaleOut
State Repository
My Worker A My Worker B
@FGRibreau
EACH MICROSERVICE SHOULD
HAVE ITS OWN RESPONSIBILITY
@FGRibreau
EACH MICROSERVICE SHOULD
HAVE ITS OWN RESPONSIBILITY
limit bug
domain
@FGRibreau
EACH MICROSERVICE SHOULD
HAVE ITS OWN RESPONSIBILITY
limit bug
domain
clear
contracts
@FGRibreau
EACH MICROSERVICE SHOULD
HAVE ITS OWN RESPONSIBILITY
limit bug
domain
clear
contracts
easier
scaling
@FGRibreau
EACH MICROSERVICE SHOULD
HAVE ITS OWN RESPONSIBILITY
limit bug
domain
improved
velocity
clear
contracts
easier
scaling
LET’S ADD
ANOTHER
PRINCIPLE
@FGRibreau
“FAIL FAST, FAIL OFTEN
@FGRibreau
crash process as soon as possible
log errors
restart process
alert developer
@FGRibreau
(NodeJS) process
ramcpu I/O
OS
fail fast, fail often
@FGRibreau
(NodeJS) process
ramcpu I/O
OS
fail fast, fail often
CPU, RAM and I/O are limited
NodeJS process can’t always monitor himself
@FGRibreau
WE DO WANT
CONSTRAINTS
@FGRibreau
WE DO WANT
CONSTRAINTS
No more than 90% CPU during X mins
@FGRibreau
WE DO WANT
CONSTRAINTS
No more than 90% CPU during X mins
No more than 512Mo of RAM during X mins
LET’S ADD
ANOTHER
PRINCIPLE
@FGRibreau
“EVERYTHING SHOULD
BE LIMITED IN BOTH
SPACE & TIME
@FGRibreau
NodeJS process
ramcpu I/O
OS
fail fast, fail often
@FGRibreau
NodeJS process
ramcpu I/O
OS
fail fast, fail often
Supervisor
@FGRibreau
NodeJS process
ramcpu I/O
OS
fail fast, fail often
Supervisor
limited in space &
time
@FGRibreau
NodeJS process
dev staging prod
CONFIGURATION
MANAGEMENT
@FGRibreau
//	
  config.js
module.exports	
  =	
  function(){
	
  	
  	
  	
  switch(process.env.NODE_ENV){
	
  	
  	
  	
  	
  	
  	
  	
  case	
  'development':
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  {dev	
  setting};
	
  	
  	
  	
  	
  	
  	
  	
  case	
  'production':
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  {prod	
  settings};
	
  	
  	
  	
  	
  	
  	
  	
  default:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  {error	
  or	
  other	
  settings};
	
  	
  	
  	
  }
};
@FGRibreau
app.configure('development',	
  function(){
	
  	
  app.set('configPath',	
  './confLocal');
	
  	
  //	
  “./confLocal”	
  is	
  a	
  constant
});
app.configure('production',	
  function(){
	
  	
  app.set('configPath',	
  './confProduction');
	
  //	
  “./confProduction”	
  is	
  a	
  constant
});
@FGRibreau
NodeJS process
dev staging prod
SHOULD MY PROCESS KNOW
ITS OWN CONFIGURATION?
NOPE.
@FGRibreau
constants files
environment
variables
distributed
CONFIGURATION
@FGRibreau
constants files
environment
variables
distributed
Simplicity Genericity
Knowing every running
environments
One configuration
to rule them all
CONFIGURATION
LET’S INVENT
A NEW
PRINCIPLE
@FGRibreau
“EVERY CONSTANT
NUMBER, BOOLEAN OR STRING*
SHOULD BE
CONFIGURABLE
@FGRibreau
var env = require('common-env')(logger);
var config = env.getOrElseAll({
amqp: {
login: 'guest',
password: 'guest',
host: 'localhost',
port: 5672,
reconnect: false
}
});
var conn = require('amqp').createConnection(config.amqp);
AMQP_LOGIN="user" AMQP_PASSWORD="azerty" node server.js
npm install common-env
https://github.com/FGRibreau/common-env
@FGRibreau
NodeJS processLauncher
SoC FTW
env. vars.
@FGRibreau
But my cloud provider uses
AMQP_ADDON_LOGIN
what should I do?
@FGRibreau
?
var config = env.getOrElseAll({
amqp: {
addon:{
login: 'guest',
password: 'guest',
host: 'localhost',
port: 5672,
reconnect: false
}
}
});
var conn = amqp.createConnection(config.amqp.addon);
@FGRibreau
NOPE.
@FGRibreau
NodeJS processLauncher
SoC
env. vars.
@FGRibreau
NodeJS processLauncher
SoC
env. vars.
Internal code
is dependent from
external naming convention
@FGRibreau
var config = env.getOrElseAll({
amqp: {
login: {
$default: 'guest',
$aliases: ['AMQP_ADDON_LOGIN']
},
password: 'guest',
host: 'localhost',
port: 5672,
reconnect: false
}
});
var conn = amqp.createConnection(config.amqp);
// /config.js
var logger = require('my-logger').createLogger();
var env = require('common-env')(logger);
module.exports = env.getOrElseAll({
amqp: {
login: 'guest'
// ...
}
});
// /app.js
var config = require('./config');
// /src/my/own/module.js
var config = require('../../../config');
@FGRibreau
Does it respect
SoC?
NOPE.
var logger = require('my-logger').createLogger();
var env = require('common-env')(logger);
module.exports = env.getOrElseAll({
amqp: {
login: 'guest'
// ...
}
});
/config.js
var logger = require('my-logger').createLogger();
var env = require('common-env')(logger);
module.exports = env.getOrElseAll({
amqp: {
login: 'guest'
// ...
}
});
/config.js
var logger = require('my-logger').createLogger();
var env = require('common-env')(logger);
module.exports = env.getOrElseAll({
amqp: {
login: 'guest'
// ...
}
});
/config.js
// config now asks for logger
module.exports = function (logger) {
var env = require('common-env')(logger);
return env.getOrElseAll({
amqp: {
login: 'guest'
// ...
}
});
};
/config.js
// config now asks for logger
module.exports = function (logger) {
var env = require('common-env')(logger);
return env.getOrElseAll({
amqp: {
login: 'guest'
// ...
}
});
};
/config.js
// caller, must specify logger to use config
// app.js
var logger = require('my-logger').createLogger();
var config = require('./config')(logger);
HUM I THINK
I KNOW THIS
PRINCIPLE
@FGRibreau
DEPENDENCY
INVERSION
This is the D from S.O.L.I.D:
@FGRibreau
AGAIN.
// /app.js
var config = require('./config')(logger);
// /src/my/own/module.js
var config = require('../../../config')(logger);
✘ DI
✘ DRY
// /app.js
var config = require('./config')(logger);
// /src/my/own/module.js
module.exports = function (config) {
};
✔ DI
✔ DRY
HUM, LET CREATE US
A REMINDER
@FGRibreau
“”../“ IS A CODE SMELL
@FGRibreau
LET’S TALK ABOUT
CRON
@FGRibreau
CRON
@FGRibreau
CRON
#USERS
CRON IS NOT
WORKING ANYMORE
#YOU
@FGRibreau
CRON
@FGRibreau
CRON
#USERS
CRON IS NOT
WORKING ANYMORE
#YOU
@FGRibreau
@FGRibreau
Process (e.g. cron)
ramcpu I/O
OS
@FGRibreau
server
Process (e.g. cron)
ramcpu I/O
OS
Supervisor
@FGRibreau
@FGRibreau
?
@FGRibreau
?
@FGRibreau
IT’S ALL ABOUT
TRADEOFFS
LET’S INVENT
A NEW
PRINCIPLE
@FGRibreau
“I SHOULD ALWAYS BE
PROACTIVELY ALERTED
@FGRibreau
NOTIFICATIONS
ALERTS
!=
@FGRibreau
OK.
LET’S RECAP
@FGRibreau
“DIVIDE MICROSERVICES
BETWEEN ACTIVE AND
PASSIVE ONES
@FGRibreau
“DIVIDE STATE AND LOGIC
@FGRibreau
“EVERYTHING SHOULD
BE LIMITED IN BOTH
SPACE & TIME
@FGRibreau
“EVERY CONSTANT
NUMBER, BOOLEAN OR STRING*
SHOULD BE
CONFIGURABLE
@FGRibreau
“”../“ IS A CODE SMELL
@FGRibreau
“I SHOULD ALWAYS BE
PROACTIVELY ALERTED
@FGRibreau
“[add your own]...
@FGRibreau
THE MOST IMPORTANT
PRINCIPLE BEING
@FGRibreau
SEPARATION
of
CONCERNS
@FGRibreau
LET’S GO FURTHER
@FGRibreau
PRINCIPLE
Code dependencies should
always be up-to-date
@FGRibreau
AUTOMATION
Build should break if code dependencies are
not up-to-date
@FGRibreau
PRINCIPLE
Code style should
always be consistent
@FGRibreau
AUTOMATION
Run a style-checker at each build
@FGRibreau
PRINCIPLE
Every developers should follow D.R.Y.
(Don’t Repeat Yourself)
@FGRibreau
AUTOMATION
Run a structural code similarities tool
at each build
@FGRibreau
HERE IS WHAT
WE DID
@FGRibreau
https://github.com/FGRibreau/check-build
ONE LAST
THING
@FGRibreau
“DON’T CREATE
CONVENTIONS
YOU CAN’T
ENFORCE
@FGRibreau
PRINCIPLES
@FGRibreau
PRINCIPLES
CONSTRAINTS
@FGRibreau
PRINCIPLES
AUTOMATION
CONSTRAINTS
@FGRibreau
PRINCIPLES
CONVENTIONS
AUTOMATION
CONSTRAINTS
@FGRibreau
PRINCIPLES
CONVENTIONS
AUTOMATION
CONSTRAINTS
CODE
Follow me @FGRibreau
Questions?
Join us @iAdvize!
Thank you!

Development Principles & Philosophy