-
-
Save ttrei/a4625d57060f962d0aba66f8faa4644c to your computer and use it in GitHub Desktop.
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
// | |
// CHALLENGE (work in pairs): | |
// Move from f(o) -> o.f() and make sure that the code is CQS compliant. | |
// | |
// 1 | |
// Turn on object-thinking and re-design the code accordingly | |
/* | |
class CsvParser<T extends Line> { | |
Collection<T> parse(File location) { | |
} | |
} */ | |
// answer 1 | |
File file = new File(""); | |
class CsvFile<T extends Line> { | |
private final Path p; | |
private Collection<T> lines; | |
CsvFile(Path path) { | |
this.p = path; | |
// populate lines | |
} | |
Collection<T> lines() { | |
return immutableList.of(lines); | |
} | |
Stream<T> lines() { | |
return lines.stream(); | |
} | |
} | |
// answer 2 | |
// with Guava | |
class Csv extends ForwardingCollection<T extends Line> { | |
Collection<T> lines; | |
Csv (Path path) { | |
Files.readLines(path); | |
} | |
@Override | |
protected Collection<T> delegate() { | |
return immutableCopy.of(lines); | |
} | |
} | |
new Csv<Line>(path).stream()... | |
// 2 | |
// Turn on object-thinking and re-design the code accordingly | |
interface Pinger { | |
void sendPing(); | |
} | |
(new Pinger()).sendPing(); | |
// | |
class Channel { | |
Channel(IP destination) { | |
} | |
void ping() { | |
} | |
} | |
// | |
class Ping { | |
void send(); | |
} | |
class Host { | |
void ping(); | |
} | |
// 3 | |
// rename the method to improve readability | |
/*interface Input { | |
boolean validate(); | |
}*/ | |
interface Input { | |
boolean isValid(); | |
} | |
//if (Input().validate()) {} | |
if (Input().isValid()) {} | |
// 4 | |
// turn procedural code into object-oriented | |
class MortgageRiskService { | |
BigDecimal calculateRisk(MortageApplication mortgageApplication) { | |
... | |
} | |
boolean isTolerable(BigDecimal risk) { | |
... | |
} | |
boolean areRisksEquivalent(BigDecimal oneRisk, BigDecimal otherRisk) { | |
... | |
} | |
} | |
MortgageRiskService(application).isTolerable(); | |
// | |
class Mortgage { | |
private final MortgageRisk mr; | |
Mortgage(MorgageAppliaction ma) { | |
//this.mr = new MortgageRisk(this); | |
} | |
MortageRisk risk() { | |
return this.mr; | |
} | |
} | |
class MortgageRisk as BigDecimal { | |
MortgageRisk(Mortgage mortgage) { | |
... | |
} | |
boolean isTolerable() {...} | |
boolean equals(MortgageRisk other) {...} | |
} | |
Mortgage.risk().isTolerable(); | |
//correct one | |
class MortgageRisk { | |
private final BigDecimal risk; | |
MortgageRisk(MortgageApplication mortgageApplication) { | |
// calc | |
this.risk = ...; | |
} | |
boolean isTolerable() {...} | |
boolean isEquivalentTo(MortgageRisk other) {...} | |
} | |
// 5 | |
// Iovation - a company that maintains a blacklist of email addresses and corresponding IPs | |
interface IovationService { | |
boolean shouldBlockWebsiteVisitor(IovationClientRequest request); | |
} | |
interface IovationClientRequest { | |
String getEmail(); | |
String getIpAddress(); | |
} | |
// | |
class Blacklist { | |
Collection<IovationClientRequest> clients; | |
public void blockClient(IovationClientRequest client) { | |
clients.push(client); | |
} | |
boolean contains(IovationClientRequest client) { | |
clients.contains(client); | |
} | |
} | |
BlackList bl; | |
bl.blockClient(...); | |
bl.contains(client); | |
// correct | |
interface BlackList { | |
boolean contains(websiteVisitor); | |
void put(websiteVisitor); | |
} | |
// 6 | |
interface AnonymousUserAuthenticator { | |
Token authenticate(String username, String password) throws WrongAuthenticationCredentialsProvided; | |
} | |
//---- | |
Class WrongAuthenticationCredentialsProvidedException extends RuntimeException; | |
Class UserIsNotAuthenticatedException extends RuntimeException; | |
interface Creds { | |
String username(); | |
String password(); | |
} | |
class User { | |
private final Creds c; | |
private Token t; | |
User(Creds c) { | |
this.c = c; | |
this.t = ;// try auth | |
if (/*auth failed*/) { | |
throw new WrongAuthenticationCredentialsProvidedException("Some meaningful text"); | |
} | |
} | |
Token token() { | |
if (token == null) { | |
throw new UserIsNotAuthenticatedException("Some meaningful text"); | |
} | |
return this.t; | |
} | |
} | |
Token t = (new User(new Creds("username", "password"))).token(); | |
// correct | |
class Authorization { | |
Authorization(Credentials credentials) { | |
} | |
Token token() { // for exceptions - test cases | |
} | |
} | |
// 7 | |
interface Suite { | |
interface SuiteTest { | |
void print(); | |
boolean successful(); | |
} | |
void runAndWait(); | |
Collection<SuiteTest> listSuiteTests(); | |
} | |
suite.runAndWait() | |
for (SuiteTest suiteTest : suite.listSuiteTests()) { | |
if (!suiteTest.successful() ) { | |
// pretty printing | |
suiteTest.print(); | |
} | |
} | |
// | |
interface Suite { | |
interface Test { | |
void prettyPrint(); | |
boolean isSuccessful(); | |
} | |
void execTests(); | |
Collection<Test> tests(); | |
//Collection<Test> printFailed() { | |
// for (Test t : this.tests()) { | |
// if (!t.passed()) { | |
// t.prettyPrint(); | |
// } | |
// } | |
//} | |
} | |
suite.execTests() | |
//suite.printFailed() | |
suite | |
.tests() | |
.filter(Predicate.not(Test::isSuccessful)) | |
.forEach(Test::prettyPrint) | |
// 8.1 | |
// What's the expected return type of the method (if you look at the code from the outside?) | |
// If you didn't expect boolean (as most develoeprs), rename it so it's clear that the boolean is returned | |
enum Severity { | |
boolean isMajor(); | |
} | |
// 8.2 | |
// What's the expected return type of the method (if you look at the code from the outside?) | |
// If you didn't expect boolean (as most develoeprs), rename it so it's clear that the boolean is returned | |
class Specification { | |
boolean isSatisfiedBy(Entity entity); | |
} | |
// 9 SLAP! | |
boolean destroyButtonAvailable = | |
widgets | |
.stream() | |
.filter(Widget::isButton) | |
.filter(button -> button.label().equals("Destroy The World")) | |
.isPresent(); | |
boolean destroyButtonAvailable = | |
widgets | |
.stream() | |
.filter(Widget::isButton) | |
.map(Widget::label) | |
.any("Destroy The World"::equals); | |
// 10 transform a full name into a twitter handle. Jack Ma must become @jack.ma | |
String fullName = "Jack Ma"; | |
... | |
Class Name as String { | |
String handle() { | |
return "@".concat(fullName.toLowerCase().replace(" ", ".")); | |
} | |
} | |
String twitterHandle = Name(fullName).handle(); | |
// hmm... | |
String twitterHandle = Stream | |
.of("Jack Ma") | |
.map(it -> it.toLowerCase()) | |
.map(it -> it.replace(" ", ".")) | |
.map(it -> "@".concat(it)) | |
.findFirst() | |
.get(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment