Let's talk about software quality
A car?
A truck?
A spaceship?
The business is extremely frustrated with
engineering’s inability to deliver features rapidly and reliably.
Slow delivery
Buggy software releases
Poor scalability
Some organizations have difficulty eliminating technical debt because past attempts were too ambitious and didn’t provide much benefit.
As a result, the business becomes reluctant to invest in further clean up efforts.
The Law of Holes states that
"if you find yourself in a hole, stop digging"
"Any organization that designs a system (defined more broadly here than just information systems) will inevitably produce a design whose structure is a copy of the organization's communication structure."
CHANGE
states of change
The reliance on manual testing isn’t because of a lack of tooling and frameworks. For
example, JUnit, which is a popular Java testing framework, was first released in 1998.
The reason for lack of automated tests is mostly cultural: "testing is QA’s job", "it’s
not the best use of a developers’s time", etc. It also doesn’t help that developing a fast
running, yet effective, maintainable test suite is challenging. Also, a typical large
monolithic application is extremely difficult to test.
Since we don’t have unlimited budget for
development and testing, we want to focus on writing tests that have small scope
without compromising the effectiveness of the test suite.
Silos and pairing
Why architecture matters?
without software quality
Scalability
Maintainability
Testability
Extensibility
Availability
https://en.wikipedia.org/wiki/List_of_system_quality_attributes
Understandability
Durability
Manageability
...
Will you build a factory, hire all the engineers and pieces without knowing what to build?
https://dzone.com/articles/measuring-technical-debt
System.out.println(1)
System.out.println(2)
System.out.println(FIZZ)
System.out.println(4)
System.out.println(BUZZ)
System.out.println(6)
System.out.println(1)
System.out.println(2)
System.out.println(FIZZ)
System.out.println(4)
System.out.println(BUZZ)
System.out.println(6)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment[a, b] = [10, 20];
console.log(a);
// expected output: 10
console.log(b);
// expected output: 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest);
// expected output: [30,40,50]
var o = {p: 42, q: true};
var {p, q} = o;
console.log(p); // 42
console.log(q); // trueconst person = { name: 'David Walsh', gender: 'Male' };
const tools = { computer: 'Mac', editor: 'Atom' };
const summary = {...person, ...tools};
/*
Object {
"computer": "Mac",
"editor": "Atom",
"gender": "Male",
"name": "David Walsh",
}
*/function drawES6Chart({size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}) {
console.log(size, cords, radius);
// do some chart drawing
}
drawES6Chart({
cords: {x: 18, y: 30},
radius: 30
});
drawES6Chart()function drawES5Chart(options) {
options = options === undefined ? {} : options;
var size = options.size === undefined ? 'big' : options.size;
var cords = options.cords === undefined ? {x: 0, y: 0} : options.cords;
var radius = options.radius === undefined ? 25 : options.radius;
console.log(size, cords, radius);
}
drawES5Chart({
cords: {x: 18, y: 30},
radius: 30
});var metadata = {
title: 'Scratchpad',
translations: [
{
locale: 'de',
localization_tags: [],
last_edit: '2014-04-14T08:43:37',
url: '/de/docs/Tools/Scratchpad',
title: 'JavaScript-Umgebung'
}
],
url: '/en-US/docs/Tools/Scratchpad'
};
var {title: englishTitle, translations: [{title: localeTitle}]} = metadata;
console.log(englishTitle); // "Scratchpad"
console.log(localeTitle); // "JavaScript-Umgebung"var people = [
{
name: 'Mike Smith',
family: {
mother: 'Jane Smith',
father: 'Harry Smith',
sister: 'Samantha Smith'
},
age: 35
},
{
name: 'Tom Jones',
family: {
mother: 'Norah Jones',
father: 'Richard Jones',
brother: 'Howard Jones'
},
age: 25
}
];
for (var {name: n, family: {father: f}} of people) {
console.log('Name: ' + n + ', Father: ' + f);
}https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generatorsfunction makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
};
}var it = makeIterator(['yo', 'ya']);
console.log(it.next().value); // 'yo'
console.log(it.next().value); // 'ya'
console.log(it.next().done); // truefunction* idMaker() {
var index = 0;
while(true)
yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// ...var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
for (let value of myIterable) {
console.log(value);
}npm install mocha --save-devvar assert = require('assert');
describe('Array', function() {
describe('#indexOf()', function() {
it('should return -1',() => {
assert.equal([1,2,3].indexOf(4), -1);
});
});
});{
"name": "myawesomeapp",
"version": "1.0.0",
"description": "my awesome app",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "mocha test/* --recursive",
"debug": "node --inspect-brk index.js"
},
"keywords": [
"rest",
"mongodb"
],
"author": "alex",
"license": "ISC",
"dependencies": {
"handlebars": "^4.0.11",
"hapi": "^17.5.1",
"mongodb": "^3.0.10",
"vision": "^5.3.2"
},
"devDependencies": {
"mocha": "^5.2.0"
}
}
{
"name": "myawesomeapp",
"version": "1.0.0",
"description": "my awesome app",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "nyc mocha test/* --recursive",
"debug": "node --inspect-brk index.js"
},
"keywords": [
"rest",
"mongodb"
],
"author": "alex",
"license": "ISC",
"dependencies": {
...
},
"devDependencies": {
"mocha": "^5.2.0",
"nyc": "^12.0.2"
}
}npm install nyc --save-dev
server.route(PeopleController.getPeople)
server.route(PeopleController.getPerson)
server.route(PeopleController.renderPerson)server.route({
method: 'GET',
path: '/people',
handler: (request) => {
return Db.getPeople()
}
})
server.route({
method: 'GET',
path: '/people/{name}',
handler: (request) => {
return Db.getPerson(request.params.name)
}
})
server.route({
method: 'GET',
path: '/render/people/{name}',
handler: async (request, h) => {
const person = await Db.getPerson(request.params.name)
return h.view('person', {
message: 'Hello Handlebars!',
person: person
});
}
})