Last active
September 28, 2022 13:16
-
-
Save LukasRychtecky/e597a6b45b51ae5c3fc86284d8c3c43b to your computer and use it in GitHub Desktop.
OOP vs. FP approach
This file contains 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
// ----------------------------------------------------- common -------------------------------------------------------------- | |
package io.applifting.jbtesting.module.usergist; | |
public class Email { | |
private final String email; | |
private Email(String email) { | |
this.email = email; | |
} | |
public static Email of(String input) { | |
throw new RuntimeException("Implement me"); | |
} | |
} | |
public class UserId { | |
public UserId(Long id) { | |
this.id = id; | |
} | |
private final Long id; | |
public Long getId() { | |
return id; | |
} | |
} | |
// unifed user without any behaviour | |
public class User { | |
private final UserId id; | |
private final Email email; | |
private final OffsetDateTime invitedAt; | |
private final Optional<OffsetDateTime> confirmedAt; | |
private final UserStatus status; | |
public User(UserId id, Email email, OffsetDateTime invitedAt, Optional<OffsetDateTime> confirmedAt, UserStatus status) { | |
this.id = id; | |
this.email = email; | |
this.invitedAt = invitedAt; | |
this.confirmedAt = confirmedAt; | |
this.status = status; | |
} | |
} | |
public class UserInvitation { | |
public final String email; | |
public UserInvitation(String email) { | |
this.email = email; | |
} | |
} | |
public class UserNotFoundError extends Exception {} | |
// ------------------------------------------------ ala OOP approach -------------------------------------------------------- | |
public class ConfirmedUser { | |
private final UserId id; | |
private final Email email; | |
private final OffsetDateTime invitedAt; | |
private final OffsetDateTime confirmedAt; | |
public ConfirmedUser(UserId id, Email email, OffsetDateTime invitedAt, OffsetDateTime confirmedAt) { | |
this.id = id; | |
this.email = email; | |
this.invitedAt = invitedAt; | |
this.confirmedAt = confirmedAt; | |
} | |
} | |
public class InvitedUser { | |
private final UserId id; | |
private final Email email; | |
private final OffsetDateTime invitedAt; | |
public InvitedUser(UserId id, Email email, OffsetDateTime invitedAt) { | |
this.id = id; | |
this.email = email; | |
this.invitedAt = invitedAt; | |
} | |
public static InvitedUser of(Supplier<OffsetDateTime> now, UserInvitation invitation) { | |
throw new RuntimeException("Implement me"); | |
} | |
public ConfirmedUser confirm(Supplier<OffsetDateTime> now) { | |
return new ConfirmedUser(id, email, invitedAt, now.get()); | |
} | |
} | |
public interface UserRepository { | |
Optional<InvitedUser> getInvitedUserById(UserId id); | |
Optional<ConfirmedUser> getConfirmedUserById(UserId id); | |
InvitedUser saveUser(InvitedUser user); | |
ConfirmedUser saveUser(ConfirmedUser user); | |
Optional<User> getById(UserId id); | |
} | |
public class UserService { | |
private final UserRepository repository; | |
public UserService(UserRepository repository) { | |
this.repository = repository; | |
} | |
public InvitedUser inviteUser(UserInvitation invitation) { | |
InvitedUser user = InvitedUser.of(OffsetDateTime::now, invitation); | |
return repository.saveUser(user); | |
} | |
public ConfirmedUser confirmUser(UserId id) throws UserNotFoundError { | |
Optional<InvitedUser> maybeUser = repository.getInvitedUserById(id); | |
InvitedUser user = maybeUser.orElseThrow(UserNotFoundError::new); | |
ConfirmedUser confirmedUser = user.confirm(OffsetDateTime::now); | |
return repository.saveUser(confirmedUser); | |
} | |
} | |
// ------------------------------------------------ ala FP approach --------------------------------------------------------- | |
public class ConfirmedUser { | |
private final UserId id; | |
private final Email email; | |
private final OffsetDateTime invitedAt; | |
private final OffsetDateTime confirmedAt; | |
public ConfirmedUser(UserId id, Email email, OffsetDateTime invitedAt, OffsetDateTime confirmedAt) { | |
this.id = id; | |
this.email = email; | |
this.invitedAt = invitedAt; | |
this.confirmedAt = confirmedAt; | |
} | |
} | |
public class InvitedUser { | |
public final UserId id; | |
public final Email email; | |
public final OffsetDateTime invitedAt; | |
public InvitedUser(UserId id, Email email, OffsetDateTime invitedAt) { | |
this.id = id; | |
this.email = email; | |
this.invitedAt = invitedAt; | |
} | |
} | |
public class UserConfirmer { | |
private final Supplier<OffsetDateTime> now; | |
public UserConfirmer(Supplier<OffsetDateTime> now) { | |
this.now = now; | |
} | |
public ConfirmedUser confirm(InvitedUser user) { | |
return new ConfirmedUser(user.id, user.email, user.invitedAt, now.get()); | |
} | |
} | |
public class UserInviter { | |
private final Supplier<OffsetDateTime> now; | |
public UserInviter(Supplier<OffsetDateTime> now) { | |
this.now = now; | |
} | |
public InvitedUser invite(UserInvitation invitation) { | |
throw new RuntimeException("Implement me"); | |
} | |
} | |
public interface UserRepository { | |
Optional<InvitedUser> getInvitedUserById(UserId id); | |
Collection<InvitedUser> getInvitedUsersByIds(Collection<UserId> ids); | |
Optional<ConfirmedUser> getConfirmedUserById(UserId id); | |
InvitedUser saveUser(InvitedUser user); | |
ConfirmedUser saveUser(ConfirmedUser user); | |
Collection<ConfirmedUser> saveUsers(Collection<ConfirmedUser> users); | |
Optional<User> getById(UserId id); | |
} | |
public class UserService { | |
private final UserRepository repository; | |
public UserService(UserRepository repository) { | |
this.repository = repository; | |
} | |
public InvitedUser inviteUser(UserInvitation invitation) { | |
InvitedUser user = new UserInviter(OffsetDateTime::now).invite(invitation); | |
return repository.saveUser(user); | |
} | |
// with optional | |
public ConfirmedUser confirmUser(UserId id) throws UserNotFoundError { | |
Optional<InvitedUser> maybeUser = repository.getInvitedUserById(id); | |
InvitedUser user = maybeUser.orElseThrow(UserNotFoundError::new); | |
ConfirmedUser confirmedUser = new UserConfirmer(OffsetDateTime::now).confirm(user); | |
return repository.saveUser(confirmedUser); | |
} | |
// without optional | |
public Collection<ConfirmedUser> confirmUsers(Collection<UserId> ids) { | |
return repository.getInvitedUsersByIds(ids) | |
.stream() | |
.map(new UserConfirmer(OffsetDateTime::now)::confirm) | |
.collect(Collectors.toList()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment