Last active
October 22, 2017 18:32
-
-
Save gemmadlou/ef2a509e78a1b67ada64817e02f18cd0 to your computer and use it in GitHub Desktop.
Functional Domain Modelling When You Only Have Classes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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'); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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