Skip to content

Instantly share code, notes, and snippets.

@ttrei
Forked from sizovs/EffectiveJavaExercises.java
Last active January 31, 2019 15:04
Show Gist options
  • Save ttrei/a4625d57060f962d0aba66f8faa4644c to your computer and use it in GitHub Desktop.
Save ttrei/a4625d57060f962d0aba66f8faa4644c to your computer and use it in GitHub Desktop.
//
// 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