- Attitude of Professional craftmanship
Text
@kokkisajee
In a nutshell
Communities
Social Developer
Recognitions
www.sajeetharan.com
and we have only 150 minutes to get there!
👍A “crash course"
👍It won’t teach you everything, But it will help you learn what you need to know
👍A mixture of discussion and exercises
👍Be prepared to talk to each other!
#!/usr/bin/python
import sys
def p2(sum):
ps = []
x = 1
while (sum > 0):
if (sum % 2):
ps.insert(0, x)
x = x * 2 # Multiply by 2. Is this a bug?
sum = sum >> 1 # Do a shift.
# Print the powers.
for x in ps:
print x
return ps
if __name__ == '__main__':
# TODO Convert sys.arvg[1] into an integer.
value = int(sys.argv[1])
p2(value)
How easy it is to read?
How easy it is to understand?
How the code is structured or designed?
How the code is documented?
Anything else you think is a problem?
Leave the campground
cleaner than you found it
An acronym that defines bad practices used by programmers good and bad that promotes technical debt.
An acronym that defines 5 principles that promote cleaner, more reusable code and generally lowers technical debt.
If anyone can understand the code, then:
Good naming of variables, functions, classes…
Good comments
Consistent coding standards
KISS
Conscious usage of OOP principles, Design patterns
SOLID principles
DRY
Unit Testing with high code coverage
Test Driven Development (TDD)
Many places to change
Hard to find impact
More mistakes = Bugs!
Few places to change… Easy to find impact… Less mistakes!
Quality should start early!
Learn by reading good code (..and bad code!)
Code reviews - give feedback, get feedback
Know your tools - IDE, Source Control, Frameworks, etc.
Passion - Love, care and be proud of your code.
Practice, practice and practice!
Annotation changes - Being able to annotate
Reversibility - Not overwriting/losing work during collaboration
Concurrency - Keeping track of all changes and being able to revert back at any point
A method of finding software issues as early as possible within the development cycle and ensuring all parts of the overall platform talk to each other correctly.
Something to be ignored or bypassed because it takes effort.
“ Continuous Delivery is a way of quick and reliable switch between different versions of application in production environment"
# Tools
Linters
"Good Practices"
# Tools
Metrics
"Measure everything"
Tools
Codescene
Sonarqube
Veracode
CodeChef
CodeClimae
If tests aren't green, deploy fail
VARIABLES
Bad:
const yyyymmdstr = moment().format('YYYY/MM/DD');
Good:
const currentDate = moment().format('YYYY/MM/DD');
INTRO TO CLEAN CODE IN JS
Bad:
getUserInfo();
getClientData();
getCustomerRecord();
Good:
getUser();
INTRO TO CLEAN CODE IN JS
VARIABLES
Bad:
// What the heck is 86400000 for?
setTimeout(blastOff, 86400000);
Good:
// Declare them as capitalized `const` globals.
const MILLISECONDS_IN_A_DAY = 86400000;
setTimeout(blastOff, MILLISECONDS_IN_A_DAY);
We will read more code than we will ever write. It's important that the code we do write is readable and searchable. By notnaming variables that end up being meaningful for understanding our program, we hurt our readers. Make your names searchable.
INTRO TO CLEAN CODE IN JS
VARIABLES
Explicit is better than implicit.
Bad:
const locations = ['Austin', 'New York', 'San Francisco'];
locations.forEach((l) => {
doStuff();
doSomeOtherStuff();
// ...
// ...
// ...
// Wait, what is `l` for again?
dispatch(l);
});
INTRO TO CLEAN CODE IN JS
VARIABLES
Good:
const locations = ['Austin', 'New York', 'San Francisco'];
locations.forEach((location) => {
doStuff();
doSomeOtherStuff();
// ...
// ...
// ...
dispatch(location);
});
Explicit is better than implicit.
INTRO TO CLEAN CODE IN JS
VARIABLES
Good:
const Car = {
make: 'Honda',
model: 'Accord',
color: 'Blue'
};
function paintCar(car) {
car.color = 'Red';
}
If your class/object name tells you something, don't repeat that in your variable name.
Bad:
const Car = {
carMake: 'Honda',
carModel: 'Accord',
carColor: 'Blue'
};
function paintCar(car) {
car.carColor = 'Red';
}
INTRO TO CLEAN CODE IN JS
VARIABLES
Bad:
function createMicrobrewery(name) {
const breweryName = name || 'Hipster Brew Co.';
// ...
}
Good:
function createMicrobrewery(breweryName = 'Hipster Brew Co.') {
// ...
}
INTRO TO CLEAN CODE IN JS
VARIABLES
FUNCTIONS SHOULD DO ONE THING
This is by far the most important rule in software engineering. When functions do more than one thing, they are harder to compose, test, and reason about. When you can isolate a function to just one action, they can be refactored easily and your code will read much cleaner. If you take nothing else away from this guide other than this, you'll be ahead of many developers.
FUNCTIONS
INTRO TO CLEAN CODE IN JS
Bad:
function addToDate(date, month) {
// ...
}
const date = new Date();
// It's hard to to tell from the function name what is added
addToDate(date, 1);
Good:
function addMonthToDate(month, date) {
// ...
}
const date = new Date();
addMonthToDate(1, date);
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Bad:
function emailClients(clients) {
clients.forEach((client) => {
const clientRecord = database.lookup(client);
if (clientRecord.isActive()) {
email(client);
}
});
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Good:
function emailClients(clients) {
clients
.filter(isClientActive)
.forEach(email);
}
function isClientActive(client) {
const clientRecord = database.lookup(client);
return clientRecord.isActive();
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
FUNCTIONS SHOULD ONLY
BE ONE LEVEL OF ABSTRACTION
When you have more than one level of abstraction your function is usually doing too much. Splitting up functions leads to reusability and easier testing.
FUNCTIONS
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Bad:
function parseBetterJSAlternative(code) {
const REGEXES = [
// ...
];
const statements = code.split(' ');
const tokens = [];
REGEXES.forEach((REGEX) => {
statements.forEach((statement) => {
// ...
});
});
const ast = [];
tokens.forEach((token) => {
// lex...
});
ast.forEach((node) => {
// parse...
});
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
INTRO TO CLEAN CODE IN JS
Good:
function tokenize(code) {
const REGEXES = [
// ...
];
const statements = code.split(' ');
const tokens = [];
REGEXES.forEach((REGEX) => {
statements.forEach((statement) => {
tokens.push( /* ... */ );
});
});
return tokens;
}
function lexer(tokens) {
const ast = [];
tokens.forEach((token) => {
ast.push( /* ... */ );
});
return ast;
}
function parseBetterJSAlternative(code) {
const tokens = tokenize(code);
const ast = lexer(tokens);
ast.forEach((node) => {
// parse...
});
}
Do your absolute best to avoid duplicate code. Duplicate code is bad because it means that there's more than one place to alter something if you need to change some logic.
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Bad:
function showDeveloperList(developers) {
developers.forEach((developer) => {
const expectedSalary = developer.calculateExpectedSalary();
const experience = developer.getExperience();
const githubLink = developer.getGithubLink();
const data = {
expectedSalary,
experience,
githubLink
};
render(data);
});
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
function showManagerList(managers) {
managers.forEach((manager) => {
const expectedSalary = manager.calculateExpectedSalary();
const experience = manager.getExperience();
const portfolio = manager.getMBAProjects();
const data = {
expectedSalary,
experience,
portfolio
};
render(data);
});
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Good:
function showList(employees) {
employees.forEach((employee) => {
const expectedSalary = employee.calculateExpectedSalary();
const experience = employee.getExperience();
let portfolio = employee.getGithubLink();
if (employee.type === 'manager') {
portfolio = employee.getMBAProjects();
}
const data = {
expectedSalary,
experience,
portfolio
};
render(data);
});
}
A DON'T USE FLAGS
AS FUNCTION PARAMETERS
FUNCTIONS
Flags tell your user that this function does more than one thing. Functions should do one thing. Split out your functions if they are following different code paths based on a boolean.
INTRO TO CLEAN CODE IN JS
Bad:
function createFile(name, temp) {
if (temp) {
fs.create(`./temp/${name}`);
} else {
fs.create(name);
}
}
Good:
function createFile(name) {
fs.create(name);
}
function createTempFile(name) {
createFile(`./temp/${name}`);
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
AVOID SIDE EFFECTS (PART 1)
FUNCTIONS
A function produces a side effect if it does anything other than take a value in and return another value or values. A side effect could be writing to a file, modifying some global variable, or accidentally wiring all your money to a stranger.
INTRO TO CLEAN CODE IN JS
Bad:
// Global variable referenced by following function. // If we had another function that used this name, now it'd be an array and it could break it. let name = 'Ryan McDermott'; function splitIntoFirstAndLastName() { name = name.split(' '); } splitIntoFirstAndLastName(); console.log(name); // ['Ryan', 'McDermott'];
Good:
function splitIntoFirstAndLastName(name) { return name.split(' '); } const name = 'Ryan McDermott'; const newName = splitIntoFirstAndLastName(name); console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott'];
INTRO TO CLEAN CODE IN JS
FUNCTIONS
FUNCTIONS
INTRO TO CLEAN CODE IN JS
Bad:
const programmerOutput = [
{
name: 'Uncle Bobby',
linesOfCode: 500
}, {
name: 'Suzie Q',
linesOfCode: 1500
}, {
name: 'Jimmy Gosling',
linesOfCode: 150
}, {
name: 'Gracie Hopper',
linesOfCode: 1000
}
];
let totalOutput = 0;
for (let i = 0; i < programmerOutput.length; i++) {
totalOutput += programmerOutput[i].linesOfCode;
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Good:
const programmerOutput = [
{
name: 'Uncle Bobby',
linesOfCode: 500
}, {
name: 'Suzie Q',
linesOfCode: 1500
}, {
name: 'Jimmy Gosling',
linesOfCode: 150
}, {
name: 'Gracie Hopper',
linesOfCode: 1000
}
];
const INITIAL_VALUE = 0;
const totalOutput = programmerOutput
.map((programmer) => programmer.linesOfCode)
.reduce((acc, linesOfCode) => acc + linesOfCode, INITIAL_VALUE);
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Bad:
if (fsm.state === 'fetching' && isEmpty(listNode)) {
// ...
}
Good:
function shouldShowSpinner(fsm, listNode) {
return fsm.state === 'fetching' && isEmpty(listNode);
}
if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
// ...
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
AVOID CONDITIONALS
FUNCTIONS
A function should only do one thing. When you have classes and functions that have if statements, you are telling your user that your function does more than one thing. Remember, just do one thing.
INTRO TO CLEAN CODE IN JS
Bad:
function isDOMNodeNotPresent(node) {
// ...
}
if (!isDOMNodeNotPresent(node)) {
// ...
}
Good:
function isDOMNodePresent(node) {
// ...
}
if (isDOMNodePresent(node)) {
// ...
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Bad:
class Airplane {
// ...
getCruisingAltitude() {
switch (this.type) {
case '777':
return this.getMaxAltitude() - this.getPassengerCount();
case 'Air Force One':
return this.getMaxAltitude();
case 'Cessna':
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Good:
class Airplane { // ... } class Boeing777 extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude() - this.getPassengerCount(); } } class AirForceOne extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude(); } } class Cessna extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude() - this.getFuelExpenditure(); } }
INTRO TO CLEAN CODE IN JS
FUNCTIONS
DON'T OVER-OPTIMIZE
FUNCTIONS
Modern browsers do a lot of optimization under-the-hood at runtime. A lot of times, if you are optimizing then you are just wasting your time. There are good resources for seeing where optimization is lacking. Target those in the meantime, until they are fixed if they can be.
INTRO TO CLEAN CODE IN JS
Bad:
// On old browsers, each iteration with uncached `list.length` would be costly
// because of `list.length` recomputation. In modern browsers, this is optimized.
for (let i = 0, len = list.length; i < len; i++) {
// ...
}
Good:
for (let i = 0; i < list.length; i++) {
// ...
}
INTRO TO CLEAN CODE IN JS
FUNCTIONS
REMOVE DEAD CODE
Dead code is just as bad as duplicate code. There's no reason to keep it in your codebase. If it's not being called, get rid of it! It will still be safe in your version history if you still need it.
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Bad:
function oldRequestModule(url) {
// ...
}
function newRequestModule(url) {
// ...
}
const req = newRequestModule;
inventoryTracker('apples', req, 'www.inventory-awesome.io');
Good:
function newRequestModule(url) {
// ...
}
const req = newRequestModule;
inventoryTracker('apples', req, 'www.inventory-awesome.io');
INTRO TO CLEAN CODE IN JS
FUNCTIONS
Use promises
not callbacks.
CONCURRENCY
Callbacks aren't clean, and they cause excessive amounts of nesting. With ES2015/ES6, Promises are a built-in global type. Use them!
INTRO TO CLEAN CODE IN JS
Bad:
require('request').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin', (requestErr, response) => {
if (requestErr) {
console.error(requestErr);
} else {
require('fs').writeFile('article.html', response.body, (writeErr) => {
if (writeErr) {
console.error(writeErr);
} else {
console.log('File written');
}
});
}
});
CONCURRENCY
INTRO TO CLEAN CODE IN JS
CONCURRENCY
Good:
require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
.then((response) => {
return require('fs-promise').writeFile('article.html', response);
})
.then(() => {
console.log('File written');
})
.catch((err) => {
console.error(err);
});
INTRO TO CLEAN CODE IN JS
Async/Await are even cleaner than Promises.
CONCURRENCY
Promises are a very clean alternative to callbacks, but ES2017/ES8 brings async and await which offer an even cleaner solution. All you need is a function that is prefixed in an async keyword, and then you can write your logic imperatively without a then chain of functions. Use this if you can take advantage of ES2017/ES8 features today!
INTRO TO CLEAN CODE IN JS
Bad:
require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
.then((response) => {
return require('fs-promise').writeFile('article.html', response);
})
.then(() => {
console.log('File written');
})
.catch((err) => {
console.error(err);
});
CONCURRENCY
INTRO TO CLEAN CODE IN JS
Good:
async function getCleanCodeArticle() {
try {
const response = await require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin');
await require('fs-promise').writeFile('article.html', response);
console.log('File written');
} catch(err) {
console.error(err);
}
}
CONCURRENCY
INTRO TO CLEAN CODE IN JS
ERROR HANDLING
Thrown errors are a good thing! They mean the runtime has successfully identified when something in your program has gone wrong and it's letting you know by stopping function execution on the current stack, killing the process (in Node), and notifying you in the console with a stack trace.
DON'T IGNORE CAUGHT ERRORS
Doing nothing with a caught error doesn't give you the ability to ever fix or react to said error. Logging the error to the console (console.log) isn't much better as often times it can get lost in a sea of things printed to the console. If you wrap any bit of code in a try/catch it means you think an error may occur there and therefore you should have a plan, or create a code path, for when it occurs.
INTRO TO CLEAN CODE IN JS
Bad:
try {
functionThatMightThrow();
} catch (error) {
console.log(error);
}
Good:
try { functionThatMightThrow(); } catch (error) { // One option (more noisy than console.log): console.error(error); // Another option: notifyUserOfError(error); // Another option: reportErrorToService(error); // OR do all three! }
INTRO TO CLEAN CODE IN JS
ERROR HANDLING
Don't ignore rejected promises
For the same reason you shouldn't ignore caught errors from try/catch.
ERROR HANDLING
Bad:
getdata()
.then((data) => {
functionThatMightThrow(data);
})
.catch((error) => {
console.log(error);
});
Good:
getdata()
.then((data) => {
functionThatMightThrow(data);
})
.catch((error) => {
// One option (more noisy than console.log):
console.error(error);
// Another option:
notifyUserOfError(error);
// Another option:
reportErrorToService(error);
// OR do all three!
});
INTRO TO CLEAN CODE IN JS
Formatting is subjective.
The main point is DO NOT ARGUE over formatting.
There are tons of tools to automate this. Use one!
FORMATTING
Use consistent capitalization
Capitalization tells you a lot about your variables, functions, etc. These rules are subjective, so your team can choose whatever they want. The point is, no matter what you all choose, just be consistent.
INTRO TO CLEAN CODE IN JS
FORMATTING
Bad:
const DAYS_IN_WEEK = 7;
const daysInMonth = 30;
const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude'];
const Artists = ['ACDC', 'Led Zeppelin', 'The Beatles'];
function eraseDatabase() {}
function restore_database() {}
class animal {}
class Alpaca {}
Good:
const DAYS_IN_WEEK = 7;
const DAYS_IN_MONTH = 30;
const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude'];
const artists = ['ACDC', 'Led Zeppelin', 'The Beatles'];
function eraseDatabase() {}
function restoreDatabase() {}
class Animal {}
class Alpaca {}
INTRO TO CLEAN CODE IN JS
FUNCTION CALLERS AND CALLEES SHOULD BE CLOSE
FORMATTING
If a function calls another, keep those functions vertically close in the source file. Ideally, keep the caller right above the callee. We tend to read code from top-to-bottom, like a newspaper. Because of this, make your code read that way.
INTRO TO CLEAN CODE IN JS
FORMATTING
Bad:
class PerformanceReview {
constructor(employee) {
this.employee = employee;
}
lookupPeers() {
return db.lookup(this.employee, 'peers');
}
lookupManager() {
return db.lookup(this.employee, 'manager');
}
getPeerReviews() {
const peers = this.lookupPeers();
// ...
}
perfReview() {
this.getPeerReviews();
this.getManagerReview();
this.getSelfReview();
}
getManagerReview() {
const manager = this.lookupManager();
}
getSelfReview() {
// ...
}
}
const review = new PerformanceReview(user);
review.perfReview();
INTRO TO CLEAN CODE IN JS
Good:
class PerformanceReview { constructor(employee) { this.employee = employee; } perfReview() { this.getPeerReviews(); this.getManagerReview(); this.getSelfReview(); } getPeerReviews() { const peers = this.lookupPeers(); // ... } lookupPeers() { return db.lookup(this.employee, 'peers'); } getManagerReview() { const manager = this.lookupManager(); }
lookupManager() { return db.lookup(this.employee, 'manager'); } getSelfReview() { // ... } } const review = new PerformanceReview(employee); review.perfReview();
INTRO TO CLEAN CODE IN JS
FORMATTING
"Good code is its own best documentation. As you’re about to add a comment, ask yourself, ‘How can I improve the code so that this comment isn’t needed?"
- Steve McConnell
Use comments judiciously, because they get easily outdated, leading to misinformation.
If your code can only be understood with comments, try to rewrite it.
The first line of document must be your code.
Don't comment code that you don't want anymore
( we have version control systems now )
Only comment things that has business logic complexity.
Comments are an apology, not a requirement. Good codes mostly documents itself.
COMMENTS
Bad:
function hashIt(data) {
// The hash
let hash = 0;
// Length of string
const length = data.length;
// Loop through every character in data
for (let i = 0; i < length; i++) {
// Get character code.
const char = data.charCodeAt(i);
// Make the hash
hash = ((hash << 5) - hash) + char;
// Convert to 32-bit integer
hash &= hash;
}
}
Good:
function hashIt(data) {
let hash = 0;
const length = data.length;
for (let i = 0; i < length; i++) {
const char = data.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
// Convert to 32-bit integer
hash &= hash;
}
}
PRESENTED BY BIANCA GANDOLFO
INTRO TO CLEAN CODE IN JS
Don't leave commented out code in your codebase
Version control exists for a reason. Leave old code in your history.
Bad:
doStuff();
// doOtherStuff();
// doSomeMoreStuff();
// doSoMuchStuff();
Good:
doStuff();
INTRO TO CLEAN CODE IN JS
COMMENTS
Don't have journal comments.
Remember, use version control! There's no need for dead code, commented code, and especially journal comments. Use git log to get history!
Bad:
/**
* 2016-12-20: Removed monads, didn't understand them (RM)
* 2016-10-01: Improved using special monads (JP)
* 2016-02-03: Removed type-checking (LI)
* 2015-03-14: Added combine with type-checking (JR)
*/
function combine(a, b) {
return a + b;
}
Good:
function combine(a, b) { return a + b; }
INTRO TO CLEAN CODE IN JS
COMMENTS
Avoid positional markers
They usually just add noise. Let the functions and variable names along with the proper indentation and formatting give the visual structure to your code.
Bad:
///////////////////////////////////////
// Scope Model Instantiation
///////////////////////////////////////
$scope.model = {
menu: 'foo',
nav: 'bar'
};
///////////////////////////////////////
// Action setup
///////////////////////////////////////
const actions = function() {
// ...
};
Good:
$scope.model = { menu: 'foo', nav: 'bar' }; const actions = function() { // ... };
INTRO TO CLEAN CODE IN JS
COMMENTS
<?php
class TemperatureCalculator
{
public static function getTemp() {
global $sunnyDays, $snowyDays;
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
$avg = 0;
$cnt = 0;
foreach($t as $temp) {
switch($temp->condition){
case 'snowy':
$avg += $temp->getTemp();
$cnt++;
$snowyDays++;
break;
case 'sunny':
$avg += $temp->getTemp();
$cnt++;
$sunnyDays++;
break;
}
}
return $avg / $cnt;
}
}
class TemperatureCalculatorFarenheit extends TemperatureCalculator
{
public static function getTemp() {
return parent::getTemp() * (9 / 5) + 32 ;
}
}
//Declared globals are affected by tempCalculator cause i'm using the temp calculator a lot
//and i don't want to change the signature
$sunnyDays = 0;
$snowyDays = 0;
if($userOptions['scale'] == 'f') {
$avgTemp = TemperatureCalculatorFarenheit::getTemp();
} else {
$avgTemp = TemperatureCalculator::getTemp();
}
echo 'The average temperature between december 2014 and march 2015 is '.$avgTemp.$userOptions['scale'].'<br/>';
echo 'There has been '.$sunnyDays.' days of sun and '.$snowyDays.' days of snow.';
Previous code
<?php
class TemperatureCalculator
{
public static function getTemp() {
global $sunnyDays, $snowyDays;
//Get the temperature logs to work with
$thermometherLog = new thermometerLog('south-side');
$records = $thermometherLog->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
$avg = 0;
$cnt = 0;
foreach($records as $temp) {
switch($temp->condition){
case 'snowy':
$avg += $temp->getTemp();
$cnt++;
$snowyDays++;
break;
case 'sunny':
$avg += $temp->getTemp();
$cnt++;
$sunnyDays++;
break;
}
}
return $avg / $cnt;
}
}
class TemperatureCalculatorFarenheit extends TemperatureCalculator
{
public static function getTemp() {
return parent::getTemp() * (9 / 5) + 32 ;
}
}
//Declared globals are affected by tempCalculator cause i'm using the temp calculator a lot
//and i don't want to change the signature
$sunnyDays = 0;
$snowyDays = 0;
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$avgTemp = TemperatureCalculatorFarenheit::getTemp();
} else {
$avgTemp = TemperatureCalculator::getTemp();
}
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
New code
<?php
class TemperatureCalculator
{
public static function getTemp() {
global $sunnyDays, $snowyDays;
//Get the temperature logs to work with
$thermometherLog = new thermometerLog('south-side');
$records = $thermometherLog->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
$avg = 0;
$cnt = 0;
foreach($records as $temp) {
switch($temp->condition){
case 'snowy':
$avg += $temp->getTemp();
$cnt++;
$snowyDays++;
break;
case 'sunny':
$avg += $temp->getTemp();
$cnt++;
$sunnyDays++;
break;
}
}
return $avg / $cnt;
}
}
class TemperatureCalculatorFarenheit extends TemperatureCalculator
{
public static function getTemp() {
return parent::getTemp() * (9 / 5) + 32 ;
}
}
//Declared globals are affected by tempCalculator cause i'm using the temp calculator a lot
//and i don't want to change the signature
$sunnyDays = 0;
$snowyDays = 0;
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$avgTemp = TemperatureCalculatorFarenheit::getTemp();
} else {
$avgTemp = TemperatureCalculator::getTemp();
}
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
Previous code
<?php
class TemperatureCalculator
{
/**
* @param TemperatureLogRecords[] $temperatureLogRecords
*/
public static function getTemp(array $temperatureLogRecords) {
global $sunnyDays, $snowyDays;
$avg = 0;
$cnt = 0;
foreach($temperatureLogRecords as $temp) {
switch($temp->condition){
case 'snowy':
$avg += $temp->getTemp();
$cnt++;
$snowyDays++;
break;
case 'sunny':
$avg += $temp->getTemp();
$cnt++;
$sunnyDays++;
break;
}
}
return $avg / $cnt;
}
}
class TemperatureCalculatorFarenheit extends TemperatureCalculator
{
/**
* @param TemperatureLogRecords[] $temperatureLogRecords
*/
public static function getTemp(array $temperatureLogRecords) {
return parent::getTemp($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
//Get the temperature logs to work with
$thermometherLog = new thermometherLog('south-side');
$t = $thermometherLog->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Declared globals are affected by tempCalculator cause i'm using the temp calculator a lot
//and i don't want to change the signature
$sunnyDays = 0;
$snowyDays = 0;
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$avgTemp = TemperatureCalculatorFarenheit::getTemp($t);
} else {
$avgTemp = TemperatureCalculator::getTemp($t);
}
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
New code
<?php
class TemperatureCalculator
{
/**
* @param TemperatureLogRecords[] $temperatureLogRecords
*/
public static function getTemp(array $temperatureLogRecords) {
global $sunnyDays, $snowyDays;
$avg = 0;
$cnt = 0;
foreach($temperatureLogRecords as $temp) {
switch($temp->condition){
case 'snowy':
$avg += $temp->getTemp();
$cnt++;
$snowyDays++;
break;
case 'sunny':
$avg += $temp->getTemp();
$cnt++;
$sunnyDays++;
break;
}
}
return $avg / $cnt;
}
}
class TemperatureCalculatorFarenheit extends TemperatureCalculator
{
/**
* @param TemperatureLogRecords[] $temperatureLogRecords
*/
public static function getTemp(array $temperatureLogRecords) {
return parent::getTemp($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$thermometherLog = new thermometherLog('south-side');
$t = $thermometherLog->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Declared globals are affected by tempCalculator cause i'm using the temp
//calculator a lot and i don't want to change the signature
$sunnyDays = 0;
$snowyDays = 0;
global $sunnyDays, $snowyDays;
//Get the items based on the scale
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$avgTemp = TemperatureCalculatorFarenheit::getTemp($t);
} else {
$avgTemp = TemperatureCalculator::getTemp($t);
}
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
New code
<?php
class TemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public static function getTemp(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemp();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public static function getSunnyDays(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'sunny';
}
)
);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public static function getSnowyDays(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'snowy';
}
)
);
}
}
class TemperatureCalculatorFarenheit extends TemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getTemp(array $temperatureLogRecords) {
return parent::getTemp($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$thermometherLog = new thermometherLog('south-side');
$t = $thermometherLog->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the items based on the scale
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$avgTemp = TemperatureCalculatorFarenheit::getTemp($t);
$sunnyDays = TemperatureCalculatorFarenheit::getSunnyDays($t);
$snowyDays = TemperatureCalculatorFarenheit::getSnowyDays($t);
} else {
$avgTemp = TemperatureCalculator::getTemp($t);
$sunnyDays = TemperatureCalculator::getSunnyDays($t);
$snowyDays = TemperatureCalculator::getSnowyDays($t);
}
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
New code
<?php
class TemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public static function getTemp(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemp();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public static function getSunnyDays(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'sunny';
}
)
);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public static function getSnowyDays(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'snowy';
}
)
);
}
}
class TemperatureCalculatorFarenheit extends TemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getTemp(array $temperatureLogRecords) {
return parent::getTemp($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$thermometherLog = new thermometherLog('south-side');
$t = $thermometherLog->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the items based on the scale
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$avgTemp = TemperatureCalculatorFarenheit::getTemp($t);
$sunnyDays = TemperatureCalculatorFarenheit::getSunnyDays($t);
$snowyDays = TemperatureCalculatorFarenheit::getSnowyDays($t);
} else {
$avgTemp = TemperatureCalculator::getTemp($t);
$sunnyDays = TemperatureCalculator::getSunnyDays($t);
$snowyDays = TemperatureCalculator::getSnowyDays($t);
}
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
Previous code
<?php
class TemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getTemp(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemp();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSunnyDays(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'sunny';
}
)
);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSnowyDays(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'snowy';
}
)
);
}
}
class TemperatureCalculatorFarenheit extends TemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getTemp(array $temperatureLogRecords) {
return parent::getTemp($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the items based on the scale
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$temperatureCalculator = new TemperatureCalculatorFarenheit();
} else {
$temperatureCalculator = new TemperatureCalculator();
}
$avgTemp = $temperatureCalculator->getTemp($t);
$sunnyDays = $temperatureCalculator->getSunnyDays($t);
$snowyDays = $temperatureCalculator->getSnowyDays($t);
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
Previous code
<?php
class AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSunnyDayCount(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'sunny';
}
)
);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSnowyDayCount(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'snowy';
}
)
);
}
}
class AverageTemperatureCalculatorInFarenheit extends AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
return parent::getAverageTemperature($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the items based on the scale
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$$temperatureCalculator = new AverageTemperatureCalculatorInFarenheit();
} else {
$$temperatureCalculator = new AverageTemperatureCalculatorInCelcius();
}
$avgTemp = $temperatureCalculator->getAverageTemperature($t);
$sunnyDays = $temperatureCalculator->getSunnyDayCount($t);
$snowyDays = $temperatureCalculator->getSnowyDayCount($t);
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
New code
<?php
class AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSunnyDayCount(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'sunny';
}
)
);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSnowyDayCount(array $temperatureLogRecords) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item){
return $item->condition == 'snowy';
}
)
);
}
}
class AverageTemperatureCalculatorInFarenheit extends AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
return parent::getAverageTemperature($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the items based on the scale
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$$temperatureCalculator = new AverageTemperatureCalculatorInFarenheit();
} else {
$$temperatureCalculator = new AverageTemperatureCalculatorInCelcius();
}
$avgTemp = $temperatureCalculator->getAverageTemperature($t);
$sunnyDays = $temperatureCalculator->getSunnyDayCount($t);
$snowyDays = $temperatureCalculator->getSnowyDayCount($t);
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
Previous code
<?php
class AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSunnyDayCount(array $temperatureLogRecords) {
return $this->countDaysBasedOnCondition($temperatureLogRecords, 'sunny');
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSnowyDayCount(array $temperatureLogRecords) {
return $this->countDaysBasedOnCondition($temperatureLogRecords, 'snowy');
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
* @param string $condition
*/
private function countDaysBasedOnCondition(array $temperatureLogRecords, $condition) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item)use($condition){
return $item->condition == $condition;
}
)
);
}
}
class AverageTemperatureCalculatorInFarenheit extends AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
return parent::getAverageTemperature($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the items based on the scale
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$$temperatureCalculator = new AverageTemperatureCalculatorInFarenheit();
} else {
$$temperatureCalculator = new AverageTemperatureCalculatorInCelcius();
}
$avgTemp = $temperatureCalculator->getAverageTemperature($t);
$sunnyDays = $temperatureCalculator->getSunnyDayCount($t);
$snowyDays = $temperatureCalculator->getSnowyDayCount($t);
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
New code
<?php
class AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSunnyDayCount(array $temperatureLogRecords) {
return $this->countDaysBasedOnCondition($temperatureLogRecords, 'sunny');
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSnowyDayCount(array $temperatureLogRecords) {
return $this->countDaysBasedOnCondition($temperatureLogRecords, 'snowy');
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
* @param string $condition
*/
private function countDaysBasedOnCondition(array $temperatureLogRecords, $condition) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item)use($condition){
return $item->condition == $condition;
}
)
);
}
}
class AverageTemperatureCalculatorInFarenheit extends AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
return parent::getAverageTemperature($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the items based on the scale
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$temperatureCalculator = new AverageTemperatureCalculatorInFarenheit();
} else {
$temperatureCalculator = new AverageTemperatureCalculatorInCelcius();
}
$avgTemp = $temperatureCalculator->getAverageTemperature($t);
$sunnyDays = $temperatureCalculator->getSunnyDayCount($t);
$snowyDays = $temperatureCalculator->getSnowyDayCount($t);
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
Previous code
<?php
class TemperatureConditionCounter
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSunnyDayCount(array $temperatureLogRecords) {
return $this->countDaysBasedOnCondition($temperatureLogRecords, 'sunny');
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSnowyDayCount(array $temperatureLogRecords) {
return $this->countDaysBasedOnCondition($temperatureLogRecords, 'snowy');
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
* @param string $condition
*/
private function countDaysBasedOnCondition(array $temperatureLogRecords, $condition) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item)use($condition){
return $item->condition == $condition;
}
)
);
}
}
class AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class AverageTemperatureCalculatorInFarenheit extends AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
return parent::getAverageTemperature($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$$temperatureCalculator = new AverageTemperatureCalculatorInFarenheit();
} else {
$$temperatureCalculator = new AverageTemperatureCalculatorInCelcius();
}
$avgTemp = $temperatureCalulator->getAverageTemperature($t);
//Get the condition counts
$temperatureConditionCounter = new TemperatureConditionCounter();
$sunnyDays = $temperatureConditionCounter->getSunnyDayCount($t);
$snowyDays = $temperatureConditionCounter->getSnowyDayCount($t);
//Output
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
New code
<?php
class TemperatureConditionCounter
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSunnyDayCount(array $temperatureLogRecords) {
return $this->countDaysBasedOnCondition($temperatureLogRecords, 'sunny');
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getSnowyDayCount(array $temperatureLogRecords) {
return $this->countDaysBasedOnCondition($temperatureLogRecords, 'snowy');
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
* @param string $condition
*/
private function countDaysBasedOnCondition(array $temperatureLogRecords, $condition) {
return count(
array_filter(
$temperatureLogRecords,
function(TemperatureLogRecord $item)use($condition){
return $item->condition == $condition;
}
)
);
}
}
class AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class AverageTemperatureCalculatorInFarenheit extends AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
return parent::getAverageTemperature($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$temperatureCalculator = new AverageTemperatureCalculatorInFarenheit();
} else {
$temperatureCalculator = new AverageTemperatureCalculatorInCelcius();
}
$avgTemp = $temperatureCalulator->getAverageTemperature($t);
//Get the condition counts
$temperatureConditionCounter = new TemperatureConditionCounter();
$sunnyDays = $temperatureConditionCounter->getSunnyDayCount($t);
$snowyDays = $temperatureConditionCounter->getSnowyDayCount($t);
//Output
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$sunnyDays.' sunny days and '.$snowyDays.' snowy days.';
}
}
Previous code
<?php
class TemperatureConditionCounter
{
/**
* @var TemperatureCondition[]
*/
protected $supportedConditions;
/**
* @return TemperatureCondition[]
*/
public function getSupportedConditions() {
return $this->supportedConditions;
}
/**
* @param TemperatureCondition $condition
*/
public function addSupportedCondition(TemperatureCondition $condition) {
$this->supportedConditions[$condition->getCondition()] = $condition;
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function countDaysByCondition(array $temperatureLogRecords) {
$results = [];
foreach($this->getSupportedConditions() as $supportedCondition) {
$results[$supportedCondition->getCondition()] = 0;
}
foreach ($temperatureLogRecords as $temperatureLogRecord) {
if (isset($this->supportedConditions[$temperatureLogRecord->getCondition()]) {
$results[$temperatureLogRecord->getCondition()]++;
}
}
return $results;
}
}
class AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class AverageTemperatureCalculatorInFarenheit extends AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
return parent::getAverageTemperature($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$temperatureCalculator = new AverageTemperatureCalculatorInFarenheit();
} else {
$temperatureCalculator = new AverageTemperatureCalculatorInCelcius();
}
$avgTemp = $temperatureCalulator->getAverageTemperature($t);
//Get the condition counts
$temperatureConditionCounter = new TemperatureConditionCounter();
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition('sunny'));
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition('snowy'));
$conditions = $temperatureConditionCounter->countDaysByCondition($t);
//Output
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$conditions['sunny'].' sunny days and '.$conditions['snowy'].' snowy days.';
}
}
New code
<?php
class TemperatureConditionCounter
{
/**
* @var TemperatureCondition[]
*/
protected $supportedConditions;
/**
* @return TemperatureCondition[]
*/
public function getSupportedConditions() {
return $this->supportedConditions;
}
/**
* @param TemperatureCondition $condition
*/
public function addSupportedCondition(TemperatureCondition $condition) {
$this->supportedConditions[$condition->getCondition()] = $condition;
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function countDaysByCondition(array $temperatureLogRecords) {
$results = [];
foreach($this->getSupportedConditions() as $supportedCondition) {
$results[$supportedCondition->getCondition()] = 0;
}
foreach ($temperatureLogRecords as $temperatureLogRecord) {
if (isset($this->supportedConditions[$temperatureLogRecord->getCondition()]) {
$results[$temperatureLogRecord->getCondition()]++;
}
}
return $results;
}
}
class AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class AverageTemperatureCalculatorInFarenheit extends AverageTemperatureCalculatorInCelcius
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
return parent::getAverageTemperature($temperatureLogRecords) * (9 / 5) + 32 ;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$temperatureCalculator = new AverageTemperatureCalculatorInFarenheit();
} else {
$temperatureCalculator = new AverageTemperatureCalculatorInCelcius();
}
$avgTemp = $temperatureCalulator->getAverageTemperature($t);
//Get the condition counts
$temperatureConditionCounter = new TemperatureConditionCounter();
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition('sunny'));
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition('snowy'));
$conditions = $temperatureConditionCounter->countDaysByCondition($t);
//Output
echo 'The temp between Dec. 2014 and Mar. 2015 is '.$avgTemp.$scale.'<br/>';
echo 'There has been '.$conditions['sunny'].' sunny days and '.$conditions['snowy'].' snowy days.';
}
}
Previous code
<?php
class TemperatureConditionCounter
{
/**
* @var TemperatureCondition[]
*/
protected $supportedConditions;
/**
* @return TemperatureCondition[]
*/
public function getSupportedConditions() {
return $this->supportedConditions;
}
/**
* @param TemperatureCondition $condition
*/
public function addSupportedCondition(TemperatureCondition $condition) {
$this->supportedConditions[$condition->getCondition()] = $condition;
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function countDaysByCondition(array $temperatureLogRecords) {
$results = [];
foreach($this->getSupportedConditions() as $supportedCondition) {
$results[$supportedCondition->getCondition()] = 0;
}
foreach ($temperatureLogRecords as $temperatureLogRecord) {
if (isset($this->supportedConditions[$temperatureLogRecord->getCondition()]) {
$results[$temperatureLogRecord->getCondition()]++;
}
}
return $results;
}
}
class AverageTemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class FarenheitTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature * (9 / 5) + 32;
}
}
class CelsiusTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$converter = new FarenheitTemperatureConverter();
} else {
$converter = new CelsiusTemperatureConverter();
}
$averageTemperatureCalculator = new AverageTemperatureCalculator();
$averageTemperature = $averageTemperatureCalculator->getAverageTemperature($t);
echo 'The average temperature is '.$converter->convert($averageTemperature).$scale.'<br />';
//Get the condition counts
$temperatureConditionCounter = new TemperatureConditionCounter();
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition('sunny'));
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition('snowy'));
$conditions = $temperatureConditionCounter->countDaysByCondition($t);
echo 'There has been '.$conditions['sunny'].' sunny days and '.$conditions['snowy'].' snowy days.';
}
}
New code
<?php
class TemperatureConditionCounter
{
/**
* @var TemperatureCondition[]
*/
protected $supportedConditions;
/**
* @return TemperatureCondition[]
*/
public function getSupportedConditions() {
return $this->supportedConditions;
}
/**
* @param TemperatureCondition $condition
*/
public function addSupportedCondition(TemperatureCondition $condition) {
$this->supportedConditions[$condition->getCondition()] = $condition;
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function countDaysByCondition(array $temperatureLogRecords) {
$results = [];
foreach($this->getSupportedConditions() as $supportedCondition) {
$results[$supportedCondition->getCondition()] = 0;
}
foreach ($temperatureLogRecords as $temperatureLogRecord) {
if (isset($this->supportedConditions[$temperatureLogRecord->getCondition()]) {
$results[$temperatureLogRecord->getCondition()]++;
}
}
return $results;
}
}
class AverageTemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class FarenheitTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature * (9 / 5) + 32;
}
}
class CelsiusTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$converter = new FarenheitTemperatureConverter();
} else {
$converter = new CelsiusTemperatureConverter();
}
$averageTemperatureCalculator = new AverageTemperatureCalculator();
$averageTemperature = $averageTemperatureCalculator->getAverageTemperature($t);
echo 'The average temperature is '.$converter->convert($averageTemperature).$scale.'<br />';
//Get the condition counts
$temperatureConditionCounter = new TemperatureConditionCounter();
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition('sunny'));
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition('snowy'));
$conditions = $temperatureConditionCounter->countDaysByCondition($t);
echo 'There has been '.$conditions['sunny'].' sunny days and '.$conditions['snowy'].' snowy days.';
}
}
Previous code
<?php
class TemperatureConditionCounter
{
/**
* @var TemperatureConditionInterface[]
*/
protected $supportedConditions;
/**
* @return TemperatureConditionInterface[]
*/
public function getSupportedConditions() {
return $this->supportedConditions;
}
/**
* @param TemperatureConditionInterface $condition
*/
public function addSupportedCondition(TemperatureConditionInterface $condition) {
$this->supportedConditions[$condition->getCondition()] = $condition;
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function countDaysByCondition(array $temperatureLogRecords) {
$results = [];
foreach($this->getSupportedConditions() as $supportedCondition) {
$results[$supportedCondition->getCondition()] = 0;
}
foreach ($temperatureLogRecords as $temperatureLogRecord) {
if (isset($this->supportedConditions[$temperatureLogRecord->getCondition()]) {
$results[$temperatureLogRecord->getCondition()]++;
}
}
return $results;
}
}
class AverageTemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class FarenheitTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature * (9 / 5) + 32;
}
}
class CelsiusTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$converter = new FarenheitTemperatureConverter();
} else {
$converter = new CelsiusTemperatureConverter();
}
$averageTemperatureCalculator = new AverageTemperatureCalculator();
$averageTemperature = $averageTemperatureCalculator->getAverageTemperature($t);
echo 'The average temperature is '.$converter->convert($averageTemperature).$scale.'<br />';
//Get the condition counts
$temperatureConditionCounter = new TemperatureConditionCounter();
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition2('sunny', 'sun'));
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition2('snowy', 'snow'));
$conditions = $temperatureConditionCounter->countDaysByCondition($t);
echo 'There has been '.$conditions['sunny'].' sunny days and '.$conditions['snowy'].' snowy days.';
}
}
New code
<?php
class TemperatureConditionCounter
{
/**
* @var TemperatureConditionInterface[]
*/
protected $supportedConditions;
/**
* @return TemperatureConditionInterface[]
*/
public function getSupportedConditions() {
return $this->supportedConditions;
}
/**
* @param TemperatureConditionInterface $condition
*/
public function addSupportedCondition(TemperatureConditionInterface $condition) {
$this->supportedConditions[$condition->getCondition()] = $condition;
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function countDaysByCondition(array $temperatureLogRecords) {
$results = [];
foreach($this->getSupportedConditions() as $supportedCondition) {
$results[$supportedCondition->getCondition()] = 0;
}
foreach ($temperatureLogRecords as $temperatureLogRecord) {
if (isset($this->supportedConditions[$temperatureLogRecord->getCondition()]) {
$results[$temperatureLogRecord->getCondition()]++;
}
}
return $results;
}
}
class AverageTemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class FarenheitTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature * (9 / 5) + 32;
}
}
class CelsiusTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature;
}
}
class TemperatureController
{
public function index() {
//Get the temperature logs to work with
$t = thermometerLog::get('south-side')->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = Session::getUser()->getOption('scale');
if($scale == 'f') {
$converter = new FarenheitTemperatureConverter();
} else {
$converter = new CelsiusTemperatureConverter();
}
$averageTemperatureCalculator = new AverageTemperatureCalculator();
$averageTemperature = $averageTemperatureCalculator->getAverageTemperature($t);
echo 'The average temperature is '.$converter->convert($averageTemperature).$scale.'<br />';
//Get the condition counts
$temperatureConditionCounter = new TemperatureConditionCounter();
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition2('sunny', 'sun'));
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition2('snowy', 'snow'));
$conditions = $temperatureConditionCounter->countDaysByCondition($t);
echo 'There has been '.$conditions['sunny'].' sunny days and '.$conditions['snowy'].' snowy days.';
}
}
Previous code
<?php
class TemperatureConditionCounter
{
/**
* @var TemperatureConditionInterface[]
*/
protected $supportedConditions;
/**
* @return TemperatureConditionInterface[]
*/
public function getSupportedConditions() {
return $this->supportedConditions;
}
/**
* @param TemperatureConditionInterface $condition
*/
public function addSupportedCondition(TemperatureConditionInterface $condition) {
$this->supportedConditions[$condition->getCondition()] = $condition;
}
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function countDaysByCondition(array $temperatureLogRecords) {
$results = [];
foreach($this->getSupportedConditions() as $supportedCondition) {
$results[$supportedCondition->getCondition()] = 0;
}
foreach ($temperatureLogRecords as $temperatureLogRecord) {
if (isset($this->supportedConditions[$temperatureLogRecord->getCondition()]) {
$results[$temperatureLogRecord->getCondition()]++;
}
}
return $results;
}
}
class AverageTemperatureCalculator
{
/**
* @param TemperatureLogRecord[] $temperatureLogRecords
*/
public function getAverageTemperature(array $temperatureLogRecords) {
//Calculate the sum
$sum = array_sum(
array_map(
function(TemperatureLogRecord $item){
return $item->getTemperatureReading();
},
$temperatureLogRecords
)
);
$cnt = count($temperatureLogRecords);
return ($sum / $cnt);
}
}
class FarenheitTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature * (9 / 5) + 32;
}
}
class CelsiusTemperatureConverter implements CelsiusBasedTemperatureConverterInterface
{
/**
* @param double $temperature
*/
public function convert($temperature) {
return $temperature;
}
}
class TemperatureController
{
public function __construct(
ThermometerLog $thermometerLog,
SessionManagerInterface $sessionManager,
TemperatureConversionManagerInterface $temperatureConversionManager,
AverageTemperatureCalculatorInterface $averageTemperatureCalculator,
TemperatureConditionCounterInterface $temperatureConditionCounter
) {
$this->thermometerLog = $thermometerLog;
$this->sessionManager = $sessionManager;
$this->temperatureConversionManager = $temperatureConversionManager;
$this->averageTemperatureCalculator = $averageTemperatureCalculator;
$this->temperatureConditionCounter = $temperatureConditionCounter;
}
public function index() {
//Get the temperature logs to work with
$t = $this->thermometerLog->find([
'after' => '2014-12-21',
'before' => '2015-03-21'
]);
//Get the temperature average
$scale = $this->sessionManager->getUser()->getOption('scale');
$converter = $this->temperatureConversionManager->getConverter($scale);
$averageTemperature = $this->averageTemperatureCalculator->getAverageTemperature($t);
echo 'The average temperature is '.$converter->convert($averageTemperature).$scale.'<br />';
//Get all the different conditions instead of just sun and snow
foreach($this->temperatureConditionCounter->getSupportedConditions() as $condition) {
$count = $this->temperatureConditionCounter->countDaysBasedOnCondition($t, $condition);
echo 'There has been '.$count.' days of '.$condition->label.'<br />';
}
}
}
New code
(Laravel)
<?php
$temperatureConversionManager = new TemperatureConversionManager();
$temperatureConversionManager->addSupportedConverter('c', new FarenheitTemperatureConverter());
$temperatureConversionManager->addSupportedConverter('f', new CelsiusTemperatureConverter());
$temperatureConditionCounter = new TemperatureConditionCounter();
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition2('sunny', 'sun'));
$temperatureConditionCounter->addSupportedCondition(new TemperatureCondition2('snowy', 'snow'));
$controller = new Controller(
ThermometerLog::get('south-side'),
new SessionManager(),
$temperatureConversionManager,
new AverageTemperatureCalculator(),
$temperatureConditionCounter
);
$controller->index();
<?php
//Bindings file
$ioc = new Illuminate\Container\Container();
$ioc->bind('ThermometerLog', function() { return ThermometerLog::get('south-side'); });
$ioc->bind('SessionManagerInterface', 'SessionManager');
$ioc->bind('TemperatureConversionManagerInterface', 'TemperatureConversionManager');
$ioc->bind('AverageTemperatureCalculatorInterface', 'AverageTemperatureCalculator');
$ioc->bind('TemperatureConditionCounterInterface', 'TemperatureConditionCounter');
$ioc->resolving('TemperatureConversionManagerInterface', function($object, $ioc) {
$object->addSupportedConverter('c', new FarenheitTemperatureConverter());
$object->addSupportedConverter('f', new CelsiusTemperatureConverter());
});
$ioc->resolving('TemperatureConditionCounterInterface', function($object, $ioc) {
$object->addSupportedCondition(new TemperatureCondition2('sunny', 'sun'));
$object->addSupportedCondition(new TemperatureCondition2('snowy', 'snow'));
});
//Front controller file
$controller = $ioc->make('TemperatureController');
$controller->index();
<?php
//Bindings file
$ioc = new Illuminate\Container\Container();
$ioc->bind('ThermometerLog', function() { return new ThermometerLog('south-side'); });
$ioc->bind('SessionManagerInterface', 'SessionManager');
$ioc->bind('TemperatureConversionManagerInterface', 'TemperatureConversionManager');
$ioc->bind('AverageTemperatureCalculatorInterface', 'AverageTemperatureCalculator');
$ioc->bind('TemperatureConditionCounterInterface', 'TemperatureConditionCounter');
$ioc->tag('FarenheitTemperatureConverter', ['TemperatureConverters']);
$ioc->tag('CelsiusTemperatureConverter', ['TemperatureConverters']);
$ioc->resolving('TemperatureConversionManagerInterface', function($object, $ioc) {
foreach($ioc->tagged('TemperatureConverters') as $converter){
$object->addSupportedConverter($converter->getScale(), $converter);
}
});
$ioc->resolving('TemperatureConditionCounterInterface', function($object, $ioc) {
$object->addSupportedCondition(new TemperatureCondition2('sunny', 'sun'));
$object->addSupportedCondition(new TemperatureCondition2('snowy', 'snow'));
});
//Front controller file
$controller = $ioc->make('TemperatureController');
$controller->index();
Finding out a programming bug
Code formatting, linting
Discussing the specification
Sharing knowledge
Sharing skill
Making a good product through discussion
I couldn't explain my code to a junior. That means I don't really understand my code.
Repairing a defect in acceptance test is 50 times as expensive than in requirement review
Reviews find between 51% – 70% of the defects in documents
Every hour spend in inspection saves 2,3 hours in system test
# Tools
ok,
but the
part?