Skip to content

Instantly share code, notes, and snippets.

View gushakov's full-sized avatar

George Ushakov gushakov

  • Lausanne, Switzerland
View GitHub Profile
@gushakov
gushakov / GenerateInvoiceWebPresenter.java
Last active January 30, 2024 11:27
Example of a presenter in Clean DDD
import lombok.Getter;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Currency;
@gushakov
gushakov / notes.md
Last active July 31, 2023 14:14
Notes for Alex D

Hi Alex,

Wow! What an impressive endeavor you've embarked on with your Bid Binding engine. It's really rare to have someone sharing complete design and development process with the public. Here are some of my thoughts...

Your domain is an intrinsically asynchronous and a parallelized domain. This naturally warrants an EDA approach. So I can understand the direction of your thought and the general enthusiasm for event-driven canvas of the overall design.

As you may have seen in some of my articles on Medium, several years ago I was quite into EDA and CQRS. Here and here are some of my projects leveraging Axon platform. I'm not at all familiar with AWS stack, but I can guess that AWS EventBridge plays the same role as Axon.

Not to discourage you by any means, but let me tell your that I've been somewhat disenchanted with EDA since. Here are some of my frustrations with this architecture.

@gushakov
gushakov / CleanController.java
Last active December 16, 2022 15:28
Clean Controller
public class CleanController {
// autowire an instance of a use case
UsecaseInputPort useCase;
// note the "void" of the request handler method
public void handleRequest(RequestModel inputDto) {
// execute the use case
useCase.execute(inputDto);
@gushakov
gushakov / Controller.java
Last active January 13, 2023 05:58
Controller calling a use case
public class Controller {
// autowire a presenter through constructor argument injection,
// for example
PresenterOutputPort presenter;
// also autowire any output ports to any of the secondary adapters
// needed to perform use case logic
SecondaryAdapterOutputPort someOperations;
@gushakov
gushakov / RoutingUseCase.java
Last active November 26, 2022 19:49
Calling security from a use case
@Transactional
@Override
public void assignRoute(String trackingId, RouteDto selectedRoute) {
try {
// RBAC check: user must at least have Agent role
securityOps.assertThatUserIsAgent();
// make sure we retrieved candidate route from the session successfully
@gushakov
gushakov / SecurityOutputPort.java
Last active November 20, 2022 14:23
Security output port
public interface SecurityOutputPort {
// Roles for the Cargo tracking application users
String ROLE_CARGO_AGENT = "CARGO_AGENT";
String ROLE_CARGO_MANAGER = "CARGO_MANGER";
// Special region used for routing permission check
Region SPECIAL_REGION = Europe;
// this is the only method which needs to be implemented in
@gushakov
gushakov / SecurityConfig.java
Last active November 20, 2022 13:31
HTTP security configuration
@Bean
public SecurityFilterChain webSecurityFilterChain(HttpSecurity http) throws Exception {
// no RBAC configuration here: all security is in use cases
http.authorizeRequests()
.anyRequest()
.permitAll()
.and()
.formLogin()
@gushakov
gushakov / SecurityConfig.java
Last active November 20, 2022 11:10
Roles for Cargo tracking application
@Bean
public UserDetailsService inMemoryUserDetailsService() {
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
userDetailsManager.createUser(
User.withDefaultPasswordEncoder()
.username("agent")
.password("test")
.authorities(ROLE_CARGO_AGENT)
@gushakov
gushakov / Delivery.java
Created November 11, 2022 17:11
Constructor used when updating delivery progress
private Delivery(HandlingEvent lastEvent, Itinerary itinerary, RouteSpecification routeSpecification) {
this.lastEvent = lastEvent;
this.misdirected = calculateMisdirectionStatus(itinerary);
this.routingStatus = notNull(calculateRoutingStatus(itinerary, routeSpecification));
this.transportStatus = notNull(calculateTransportStatus());
this.lastKnownLocation = calculateLastKnownLocation().orElse(null);
this.currentVoyage = calculateCurrentVoyage().orElse(null);
this.eta = calculateEta(itinerary);
this.nextExpectedActivity = calculateNextExpectedActivity(routeSpecification, itinerary);
}
@gushakov
gushakov / Delivery.java
Created November 11, 2022 17:02
Constructor with validation assertions
@Builder
public Delivery(TransportStatus transportStatus, UnLocode lastKnownLocation, VoyageNumber currentVoyage,
UtcDateTime eta, RoutingStatus routingStatus, boolean misdirected,
HandlingActivity nextExpectedActivity) {
this.transportStatus = notNull(transportStatus);
this.lastKnownLocation = lastKnownLocation;
this.currentVoyage = currentVoyage;
this.lastEvent = null;
this.eta = eta;
this.routingStatus = notNull(routingStatus);