Skip to content

Instantly share code, notes, and snippets.

@sizovs
Last active March 3, 2025 16:29
Show Gist options
  • Save sizovs/927a445203f885547976ef36fa0a978b to your computer and use it in GitHub Desktop.
Save sizovs/927a445203f885547976ef36fa0a978b to your computer and use it in GitHub Desktop.
// 1. Fix bad naming.
class ShoppingCart {
UUID getShopingCartId() { ... }
boolean checkFreeShippingEligibility() { ... }
void removeOrderItem(OrderItem orderItem) { ... }
void addOrderItem(OrderItem orderItem) { ... }
Collection<OrderItem> getOrderItems() { ... }
}
// 2. Eliminate noise.
void openNewBankAccount() {
var bankAccountWithdrawalLimits = WithdrawalLimitFactory.defaultWithdrawalLimits();
var bankAccountHolder = new BankAccountHolder(...);
var bankAccount = new BankAccount(bankAccountHolder, bankAccountWithdrawalLimits);
bankAccount.openAccount();
bankAccount.depositAmount(clientSignupBonus());
bankAccountRepository.add(bankAccount);
}
// 3. Inline nesting is hard to reason about, as it doesn't convey the transformation order. Please refactor.
String normalize(String fullName) {
return stripEmojis(stripAccents(capitalize(fullName)));
}
// 4. Refactor Member data class into an object
member.getAssignedOffers().add(offer);
member.setNumberOfAssignedOffers(member.getNumberOfAssignedOffers() + 1);
// 5. Find a missing domain object, and eliminate a meaningless domain object (service) with it.
class MortgageRiskService {
BigDecimal calculateRisk(MortgageApplication mortgageApplication) {
...
}
boolean isTolerable(BigDecimal risk) {
...
}
boolean areRisksEquivalent(BigDecimal oneRisk, BigDecimal otherRisk) {
...
}
}
// 6. Find a missing domain object, and meaningless domain object(s) with it.
class BankruptcyProbabilityCalculator {
BigDecimal calculate(Business business) { ... }
}
class BankruptcyProbabilityUtils {
boolean isHigh(BigDecimal decimal) { ... }
}
// 7. Find a missing domain object, and eliminate CsvParser.
class CsvParser<T extends Line> {
Collection<T> parse(File location) {
}
}
// 8. Find a missing domain object, and eliminate Pinger.
interface Pinger {
void sendPing();
}
// 9. Find a missing domain object, and eliminate MoneyFormatter. Limitation: you can't change Money class.
interface MoneyFormatter {
String format(Money money);
}
// 10. Turn XmlMarshaller into a class Xml
// + Make the class generic (decouple it from Invoice)
// + Use try-with-resources block
// + Minimize noise
class XmlMarshaller {
byte[] marshallToXml(Invoice invoice) {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
JaxbMarshaller jaxbMarshaller = new JaxbMarshaller(Invoice.class);
jaxbMarshaller.marshallObject(invoice, outStream);
byte[] resultXml = outStream.toByteArray();
IOUtils.closeQuietly(outStream);
return resultXml;
}
}
// 11. make class null-safe with Optionals, and replace a dumb setter with a domain-specific method.
class User {
private Permissions permissions;
void setPermissions(Permissions permissions) {
this.permissions = permissions
}
}
// 12. Can you resolve a naming conflict? no getters & setters allowed!
user.ban() // returns user's ban and the corresponding information (if any)
user.ban() // bans a user
// 13. Can you spot a domain object that hides behind a BlacklistingService and refactor the code accordingly?
interface BlacklistingService {
boolean shouldBlockWebsiteVisitor(BlacklistRequest request);
}
record BlacklistRequest(String email, String ipAddress) { }
// 14. Introduce meaningful objects, and replace exception throwing with Monads.
interface AnonymousUserAuthenticator {
// returns authentication token or throws exception
String authenticate(String username, String password) throws AuthenticationFailed;
}
// 15. fix different naming issues
interface Suite {
interface SuiteTest {
void print();
boolean successfulTest()
}
void runAndWait();
Collection<SuiteTest> listSuiteTests();
}
suite.runAndWait()
for (SuiteTest suiteTest : suite.listSuiteTests()) {
if (!suiteTest.successfulTest() ) {
// pretty printing
suiteTest.print();
}
}
// 16. Can you stop mixing method refences with lambdas and SLAP (Single Level of Abstraction Principle) the code?
boolean destroyButtonAvailable =
widgets
.stream()
.filter(Widget::isButton)
.filter(button -> button.label().equals("Destroy The World"))
.findAny()
.isPresent();
// 17.
// implement the /fullName/ method so that it:
// 1. returned "firstName lastName" if nickname is missing
// 2. returned "firstName <nickname> lastName" if nickname is present.
// For example: "Robert Martin" or "Robert <Uncle Bob> Martin"
class User {
private final Optional<String> nickName;
private final String firstName;
private final String lastName;
String fullName() {
// ...
}
}
// 18. Checked exceptions don't work well with lambdas, and the Java community has largely moved away from using them.
// Unfortunately, sometimes checked exception come with legacy code we cannot change.
// Do you know how to fix this w/o modifying the Port class?
int availablePort = IntStream
.rangeClosed(8000, 9000)
.filter(num -> {
try {
var port = new Port(num);
return port.isAvailable();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
})
.findFirst();
// 19. Can you make SecurePassword fetch the remote Vault lazily when toString() is called,
// ensuring the same password is returned on subsequent calls to toString()?
class SecurePassword {
private final String password;
private SecurePassword(Vault vault) {
this.password = vault.verySecurePassword();
}
@Override
public String toString() {
return password;
}
}
// 20. Well done! Have a break! 🎉
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment