^ https://www.flickr.com/photos/avidday/9173790839
^ "Duck Typing, Compatibility and the Adaptor Pattern"
^ https://www.flickr.com/photos/avidday/9173790839
^ "Duck Typing, Compatibility and the Adaptor Pattern"
^ https://www.flickr.com/photos/davelawler/5744858794
^ time is in short supply, so we'll jump right into talking about duck typing
Duck typing is a style of typing in which an object's methods and properties determine the valid semantics,
...rather than its inheritance from a particular class or implementation of an explicit interface.
^ https://www.flickr.com/photos/macieklew/3986974018
^ "tastes like fruit"
^ https://www.flickr.com/photos/macieklew/3986974018
^ https://www.flickr.com/photos/yimhafiz/4547999416
^ "also tastes like fruit"
^ https://www.flickr.com/photos/yimhafiz/4547999416
"Write code that depends upon tastes-like(fruit) rather than depending upon is-a(fruit)."
^ https://www.flickr.com/photos/hoeken/2692040215
^ "duck typing is a compatibility technique"
^ https://www.flickr.com/photos/hoeken/2692040215
^ https://www.flickr.com/photos/davies/3231308527
^ https://www.flickr.com/photos/davies/3231308527
^ https://www.youtube.com/watch?v=DD0B-4KNna8
^ https://www.youtube.com/watch?v=DD0B-4KNna8
"Conway's Game of Life is a two-state cellular automata."
- Cells,
- Cells,
- Universe,
- Cells,
- Universe, and
- View.
- Neighbours,
- Neighbours, and
- State.
function StandardCell () {
this._neighbours = [];
this._alive = false;
}
StandardCell.prototype.neighbours =
function neighbours (neighbours) {
return this._neighbours;
};
StandardCell.prototype.setNeighbours =
function setNeighbours (neighbours) {
this._neighbours = neighbours.slice(0);
return this;
};
StandardCell.prototype.alive =
function alive () {
return this._alive;
};
StandardCell.prototype.setAlive =
function setAlive (alive) {
this._alive = alive;
return this;
};
^ https://www.flickr.com/photos/gsfc/9524854754
^ https://www.flickr.com/photos/gsfc/9524854754
- Neighbours,
- State, and
- Transformation of State.
- Neighbourhoods (not shown),
- Neighbourhoods (not shown), and
- Transformation of States.
StandardCell.prototype.nextAlive =
function nextAlive () {
var alives =
this._neighbours.filter(function (n) {
return n.alive();
}).length;
if (this.alive()) {
return alives === 2 ||
alives == 3;
}
else {
return alives == 3;
}
};
Universe.prototype.iterate =
function iterate () {
var aliveInNextGeneration = this.cells().map(
function (c) {
return [c, c.nextAlive()];
}
);
aliveInNextGeneration.forEach(function (a) {
var cell = a[0],
next = a[1];
cell.setAlive(next);
});
};
^ https://www.flickr.com/photos/oskay/6838117968
^ https://www.flickr.com/photos/oskay/6838117968
- Drawing a Cell:
View.prototype.drawCell =
function drawCell (cell, x, y) {
var xPlus = x + this.cellSize(),
yPlus = y + this.cellSize()
this._canvasContext.clearRect(x, y, xPlus, yPlus);
this._canvasContext.fillStyle = this.cellColour(cell);
this._canvasContext.fillRect(x, y, xPlus, yPlus);
return self;
};
View.prototype.cellColour =
function cellColour (cell) {
return cell.alive()
? WHITE
: BLACK;
};
^ https://www.flickr.com/photos/ourmaninjapan/6340506358
^ "5 minutes"
^ https://www.flickr.com/photos/nanagyei/6636632951
^ https://www.flickr.com/photos/nanagyei/6636632951
^ https://www.youtube.com/watch?v=etUZw_xm-98 by Marcel Rodrigues
^ https://www.youtube.com/watch?v=etUZw_xm-98 by Marcel Rodrigues
function ColourCell () {
this._neighbours = [];
this._age = 0;
}
ColourCell.prototype.neighbours =
StandardCell.prototype.neighbours;
ColourCell.prototype.setNeighbours =
StandardCell.prototype.setNeighbours;
ColourCell.prototype.age =
function age () {
return this._age;
};
ColourCell.prototype.setAge =
function setAge (age) {
this._age = age;
return this;
};
^ https://www.flickr.com/photos/dexxus/2599093453
^ https://www.flickr.com/photos/dexxus/2599093453
ColourCell.prototype.nextAge =
function next () {
var alives =
this._neighbours.filter(function (n) {
return n.age() > 0;
}).length;
if (this.age() > 0) {
return (alives === 2 || alives == 3)
? (this.age() + 1)
: 0;
}
else {
return (alives == 3)
? (this.age() + 1)
: 0;
}
};
Universe.prototype.iterate =
function iterate () {
var ageInNextGeneration = this.cells().map(
function (c) {
return [c, c.nextAge()];
}
);
ageInNextGeneration.forEach(function (a) {
var cell = a[0],
next = a[1];
cell.setAge(next);
});
};
^ https://www.flickr.com/photos/kara_allyson/4360710819
^ https://www.flickr.com/photos/kara_allyson/4360710819
var COLOURS =
[ BLACK, GREEN, BLUE, YELLOW, WHITE, RED ];
View.prototype.cellColour =
function cellColour (cell) {
return COLORS[
(cell.age() >= COLOURS.length)
? (COLOURS.length - 1)
: cell.age()
];
};
// ...
^ https://www.flickr.com/photos/juliusprinz/8709649221
^ https://www.flickr.com/photos/juliusprinz/8709649221
Object.keys(StandardCell.prototype)
// =>
[ 'neighbours',
'setNeighbours',
'alive',
'setAlive',
'nextAlive' ]
Object.keys(ColourCell.prototype)
// =>
[ 'neighbours',
'setNeighbours',
'age',
'setAge',
'nextAge' ]
The state of a cell is now "age" instead of "aliveness."
^ https://www.flickr.com/photos/120600995@N07/14262980504
^ https://www.flickr.com/photos/120600995@N07/14262980504
^ https://www.flickr.com/photos/maxwarren/183318800
^ "ten minutes"
^ https://www.flickr.com/photos/ter-burg/9704526768
^ https://www.flickr.com/photos/ter-burg/9704526768
"Make a coloured cell behave like a standard cell."
ColourCell.prototype.alive =
function alive () {
return this._age > 0;
};
ColourCell.prototype.setAlive =
function setAlive (alive) {
if (alive) {
this.setAge(this.age() + 1);
}
else this.setAge(0);
return this;
};
ColourCell.prototype.nextAlive =
StandardCell.prototype.nextAlive;
Object.keys(ColourCell.prototype)
// =>
[ 'neighbours',
'setNeighbours',
'age',
'setAge',
'nextAge',
'alive',
'setAlive',
'nextAlive' ]
^ https://www.flickr.com/photos/91553413@N00/253281960
^ https://www.flickr.com/photos/91553413@N00/253281960
^ https://www.flickr.com/photos/66971402@N04/7569786950
^ https://www.flickr.com/photos/66971402@N04/7569786950
^ https://www.flickr.com/photos/bitterjug/7670055210
^ https://www.flickr.com/photos/bitterjug/7670055210
^ https://www.flickr.com/photos/angeloangelo/4423502365
^ https://www.flickr.com/photos/angeloangelo/4423502365
"Make a cell that behaves like a Standard Cell, but is implemented in terms of a Coloured Cell."
function AsStandard (colouredCell) {
this._colouredCell = colouredCell;
}
var tastesLikeAStandardCell =
new AsStandard(aColourCell);
AsStandard.prototype.neighbours =
function neighbours () {
return this._colouredCell.neighbours();
};
AsStandard.prototype.setNeighbours =
function setNeighbours (neighbours) {
this._colouredCell.setNeighbours(neighbours);
return this;
};
AsStandard.prototype.alive =
function alive () {
return this._colouredCell.age() > 0;
};
AsStandard.prototype.setAlive =
function setAlive (alive) {
if (alive) {
this._colouredCell.setAge(this._colouredCell.age() + 1);
}
else this._colouredCell.setAge(0);
return this;
};
AsStandard.prototype.nextAlive =
function nextAlive () {
return this._colouredCell.nextAge() > 0;
}
Object.keys(AsStandard.prototype)
// =>
[ 'neighbours',
'setNeighbours',
'alive',
'setAlive',
'nextAlive' ]
- View can depend upon ColourCell,
- View can depend upon ColourCell, and
- Universe can depend upon AsStandard.
- Universe is decoupled from changes to Cell,
^ https://www.flickr.com/photos/56832361@N00/3705717858
- Universe is decoupled from changes to Cell, and
- ColourCell isn't burdened with backwards compatibility.
^ https://www.flickr.com/photos/56832361@N00/3705717858
^ https://www.flickr.com/photos/theincidental/3459777668
^ https://www.flickr.com/photos/theincidental/3459777668
The adapter (sic) pattern is a software design pattern that allows the interface of an existing class to be used from another interface...
^ Wikipedia
It is often used to make existing classes work with others without modifying their source code.
^ Wikipedia
^ https://www.flickr.com/photos/fhke/3268894584
^ "good programmers borrow from smalltalk, great programmers steal from C++"
^ https://www.flickr.com/photos/fhke/3268894584
^ "copy constructors are value adaptors"
function colourFromStandard (standard) {
return new ColourCell()
.setNeighbours(standard.neighbours())
.setAge(standard.alive() ? 1 : 0);
}
function standardFromColour (colour) {
return new StandardCell()
.setNeighbours(colour.neighbours())
.setAlive(colour.age() > 0);
}
^ https://www.flickr.com/photos/e3000/6885969828
^ "Can we create co-proxies instead of wrappers?"
^ https://www.flickr.com/photos/e3000/6885969828
^ https://www.flickr.com/photos/zeevveez/6273266577
^ "fifteen minutes"
^ https://www.flickr.com/photos/warriorwoman531/6081198171
^ "The conclusion is near"
^ https://www.flickr.com/photos/warriorwoman531/6081198171
^ https://www.flickr.com/photos/samsaunders/11689309615
^ "separate the concern of how to interact with a model from the concern of what the model does"
^ https://www.flickr.com/photos/samsaunders/11689309615
^ "separate the concern of how to interact with a model from the concern of what the model does"
^ https://www.flickr.com/photos/xlibber/14944977391
^ https://www.flickr.com/photos/xlibber/14944977391
^ https://www.flickr.com/photos/94418464@N08/9631393073
^ https://www.flickr.com/photos/94418464@N08/9631393073
^ https://www.flickr.com/photos/janitors/14188094421
^ "adaptors solve compatibility problems"
^ https://www.flickr.com/photos/janitors/14188094421
^ https://www.flickr.com/photos/highwaysagency/14874539886
^ "but they also gives us the freedom to make changes, safely"
^ https://www.flickr.com/photos/highwaysagency/14874539886
^ https://www.flickr.com/photos/jacme31/6970784086
^ https://www.flickr.com/photos/jacme31/6970784086
^ https://www.flickr.com/photos/peddhapati/11671457605
^ THE END
^ https://www.flickr.com/photos/swimparallel/3391592144/
^ "eighteen minutes"
one more thing:
^ https://www.flickr.com/photos/49889874@N05/4772680734
^ "packages"
^ https://www.flickr.com/photos/seeminglee/7994149144
^ https://www.flickr.com/photos/seeminglee/7994149144
^ https://www.flickr.com/photos/jameshammond/8733249464
^ https://www.flickr.com/photos/jameshammond/8733249464
^ https://www.flickr.com/photos/poorfish/7213010794
^ https://www.flickr.com/photos/poorfish/7213010794
^ https://www.flickr.com/photos/imazerart/4918018946
^ https://www.flickr.com/photos/imazerart/4918018946
^ https://www.flickr.com/photos/sidelong/3466699346
^ "semver: does a new version have to be duck-compatible? Or can it adapt?"
^ https://www.flickr.com/photos/sidelong/3466699346
^ https://www.flickr.com/photos/aigle_dore/13026781635
^ https://www.flickr.com/photos/aigle_dore/13026781635
^ https://www.flickr.com/photos/drphotomoto/14040288979
^ https://www.flickr.com/photos/drphotomoto/14040288979
^ https://www.flickr.com/photos/streetmatt/15083719955
^ https://www.flickr.com/photos/streetmatt/15083719955
^ https://www.flickr.com/photos/sputnik_mania/2216528316
^ "adaptors can provide safe backwards-compatibility without debt"
^ https://www.flickr.com/photos/sputnik_mania/2216528316
^ https://www.flickr.com/photos/halfbisqued/2353845688
^ What would an adaptor-aware package manager look like?
^ https://www.flickr.com/photos/halfbisqued/2353845688
- Interfaces and Implementations would be independantly versioned,
- Interfaces and Implementations would be independantly versioned,
- Interfaces would have a many-to-many relationship with Implementations, mediated by Adaptors,
- Interfaces and Implementations would be independantly versioned,
- Interfaces would have a many-to-many relationship with implementations, mediated by adaptors,
- Clients would specifiy the required interface and implementation,
- Interfaces and Implementations would be independantly versioned,
- Interfaces would have a many-to-many relationship with implementations, mediated by adaptors,
- Clients would specifiy the required interface and implementation, and
- Old clients can benefit from bug fixes without rewrites.
^ https://www.flickr.com/photos/wackybadger/6171444454
^ https://www.flickr.com/photos/wackybadger/6171444454
^ https://www.flickr.com/photos/esoastronomy/8271747835
^ "and that provides food for thought for a very long time indeed"
^ https://www.flickr.com/photos/esoastronomy/8271747835
^ https://www.flickr.com/photos/lionsthlm/14175437597
^ "tack så mycket"
^ https://www.flickr.com/photos/lionsthlm/14175437597
^ https://www.flickr.com/photos/w00ter/13262702873
Nordic JS Artipelag, Stockholm, September 19, 2014