Skip to content

Instantly share code, notes, and snippets.

@gemmadlou
Last active October 22, 2017 18:32
Show Gist options
  • Select an option

  • Save gemmadlou/ef2a509e78a1b67ada64817e02f18cd0 to your computer and use it in GitHub Desktop.

Select an option

Save gemmadlou/ef2a509e78a1b67ada64817e02f18cd0 to your computer and use it in GitHub Desktop.
Functional Domain Modelling When You Only Have Classes
class PreFlightService {
goToGate(flight) {
if (flight instanceof Flight !== true) throw new Error('Must be a flight')
if (flight.atGate) throw new Error('Flight is already at the gate');
return new Flight(Object.assign({}, flight, {
atGate: true
}));
}
refuel(flight) {
if (flight instanceof Flight !== true) throw new Error('Must be a flight')
if (flight.refueled) throw new Error('Flight has already been refueld');
return new Flight(Object.assign({}, flight, {
refueled: true
}));
}
restockFood(flight, food) {
if (flight instanceof Flight !== true) throw new Error('Must be a flight')
let instance = Object.assign({}, flight);
instance.food.push(food);
return new Flight(instance);
}
boardFlightTeamMember(flight, member) {
let instance = Object.assign({}, flight)
instance.team.push(member)
return new Flight(instance)
}
boardPassenger(passenger) {
let instance = Object.assign({}, flight)
instance.passengers.push(passenger)
return new Flight(instance)
}
}
class Flight {
constructor(data) {
data = data || {};
this.passengers = data.passengers || [];
this.team = data.team || [];
this.food = data.food || [];
this.refueled = data.refueled || false;
this.atGate = data.atGate || false;
}
}
let service = new PreFlightService;
let flight = new Flight;
service.goToGate(flight);
// Not designed to work - just theoretical as it mixes languages and libraries from non-js langs
var request = {
data: {
attributes: {
title: 'The Oscars',
year: '2017'
}
},
relationships: {
schedule: {
data: {
nomination_start_date: '2017-05-01 00:00:00',
nomination_end_date: '2017-05-30 23:59:59',
voting_start_date: '2017-08-11 00:00:00',
voting_end_date: '2017-09-11 20:00:00'
}
}
}
}
var controller = (request) {
// Pre validation of required elements
// Pre validate - if request.relationship is set
let award = Award.create(
new AwardTitle(request.data.attributes.title),
new AwardYear(request.data.attributes.year)
);
if (request.relationships) {
let nominations = new NominationDates(
Carbon.createFromFormat('Y M j h:m:s', request.relationships.schedule.data.nomination_start_date),
Carbon.createFromFormat('Y M j h:m:s', request.relationships.schedule.data.nomination_end_date)
);
let votes = new NominationDates(
Carbon.createFromFormat('Y M j h:m:s', request.relationships.schedule.data.voting_start_date),
Carbon.createFromFormat('Y M j h:m:s', request.relationships.schedule.data.voting_end_date)
);
award = Award.schedule(
award,
nominations,
votes
);
}
award.save();
return AwardTransformer::item(award)->toType('json');
}
console.clear();
class Page {
constructor(name) {
this.name = name;
this.created_at = new Date()
}
}
class ABTest {
constructor(data) {
if (data.pageA instanceof Page === false || data.pageB instanceof Page === false) {
throw new Error('pageA and pageB must be an instance of Page');
}
if (data.testFor === '' || data.testFor === undefined) {
throw new Error('There must be a reason for testing');
}
this.results = data.results || [];
this.pageA = data.pageA;
this.pageB = data.pageB;
this.testFor = data.testFor;
}
getWinner() {
let pageACount = this.results.filter((page) => {
return page === this.pageA;
}).length;
let pageBCount = this.results.filter((page) => {
return page === this.pageB;
}).length;
return pageACount === pageBCount ? null :
pageACount > pageBCount ? this.pageA : this.pageB;
}
}
class Lab {
test(abtest, winner) {
if (winner !== abtest.pageA && winner !== abtest.pageB) {
throw new Exception('Can not assign a page as winner if it is not within this test');
}
let test = Object.assign({}, abtest);
test.results.push(winner);
return new ABTest(test);
}
}
let a = new Page('Red button');
let b = new Page('Green button');
let test = new ABTest({
pageA: a,
pageB: b,
testFor: 'Button colors'
});
let lab = new Lab();
let loop = Math.ceil(Math.random() * 10000);
for (var i = 0; i < loop; i++) {
let page = Math.ceil(Math.random() * 2) === 2 ? a : b;
test = lab.test(test, page);
}
console.log(test)
console.log(test.getWinner())
console.clear();
class Page {
constructor(name) {
this.name = name;
this.created_at = new Date()
}
}
class ABTest {
constructor(data) {
if (data.pageA instanceof Page === false || data.pageB instanceof Page === false) {
throw new Error('pageA and pageB must be an instance of Page');
}
if (data.testFor === '' || data.testFor === undefined) {
throw new Error('There must be a reason for testing');
}
this.results = data.results || [];
this.pageA = data.pageA;
this.pageB = data.pageB;
this.testFor = data.testFor;
}
getWinner() {
let pageACount = this.results.filter((page) => {
return page === this.pageA;
}).length;
let pageBCount = this.results.filter((page) => {
return page === this.pageB;
}).length;
return pageACount === pageBCount ? null :
pageACount > pageBCount ? this.pageA : this.pageB;
}
}
class Observation {
constructor(abTest, subject, result) {
this.abTest = abTest;
this.subject = subject;
this.positiveResult = result;
}
}
let a = new Page('Red button');
let b = new Page('Green button');
let test = new ABTest({
pageA: a,
pageB: b,
testFor: 'Button colors'
});
let observations = [];
let loop = Math.ceil(Math.random() * 10000);
for (var i = 0; i < loop; i++) {
let page = Math.ceil(Math.random() * 2) === 2 ? a : b;
let result = Math.ceil(Math.random() * 2) === 2;
observations.push(new Observation(test, page, result))
}
console.log(observations)
let obs = observations.filter((observation) => {
return observation.subject === a;
})
console.log(obs.filter((ob) => {
return ob.positiveResult
}).length / obs.length * 100 + '%');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment