Skip to content

Instantly share code, notes, and snippets.

@VaughnVernon
Last active April 12, 2024 11:03
Show Gist options
  • Save VaughnVernon/d96bba02909503097db252129b8b7b7c to your computer and use it in GitHub Desktop.
Save VaughnVernon/d96bba02909503097db252129b8b7b7c to your computer and use it in GitHub Desktop.
Hexagonal / Ports and Adapters Is Just This Simple
//=====================================
// INSIDE
//=====================================
//
// Inside: Model: Person
//
package people.model.person;
public class Person extends Entity {
private String id;
private String name;
private String emailAddress;
public static Person with(String name, String emailAddress) {
return new Person(name, emailAddress);
}
public String id() {
return this.id;
}
public void changeName(String name) {
this.name = name;
}
public String name() {
return this.name;
}
public void changeEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String emailAddress() {
return this.emailAddress;
}
private Person(String name, String emailAddress) {
this.id = uniqueId();
this.name = name;
this.emailAddress = emailAddress;
}
}
//=====================================
// INSIDE
//=====================================
//
// Inside: Application: PersonData
//
package people.application.data;
public final class PersonData {
public final String id;
public final String name;
public final String emailAddress;
public static PersonData from(Person person) {
return new PersonData(person.id(), person.name(), person.emailAddress());
}
private PersonData(String id, String name, String emailAddress) {
this.id = id;
this.name = name;
this.emailAddress = emailAddress;
}
}
//=====================================
// INSIDE
//=====================================
//
// Inside Driven-side Port: Model: PersonRepository
//
package people.model.person;
public interface PersonRepository {
public void add(Person person);
public Person personOf(String personId);
}
//=====================================
// OUTSIDE
//=====================================
//
// Outside: Driver-side HTTP Adapter: PersonResource
//
package people.infrastructure.resource;
public class PersonResource extends Resource {
private PersonService service;
public PersonResource(PersonService service) {
this.service = service;
}
public Respose get(String personId) {
PersonData person = service.personOf(personId);
return Response.ok(serialize(person));
}
public Response post(String name, String emailAddress) {
PersonData person = service.personFrom(name, emailAddress);
return Response.created(serialize(person), Header.of(Header.Location, pathOf(person)));
}
public Response patchName(String personId, String name) {
PersonData person = service.changeName(personId, name);
return Response.ok(serialize(person));
}
public Response patchEmailAddress(String personId, String emailAddress) {
PersonData person = service.changeEmailAddress(personId, emailAddress);
return Response.ok(serialize(person));
}
}
//=====================================
// INSIDE
//=====================================
//
// Inside Driver-side Port: Application: PersonService
//
package people.application;
public class PersonService extends ApplicationService {() {
private PersonRepository repository;
public PersonService(PersonRepository repository) {
this.repository = repository;
}
@Transactional(READ_ONLY)
public PersonData personOf(String personId) {
Person person = repository.personOf(personId);
return PersonData.from(person);
}
@Transactional
public PersonData personFrom(String name, String emailAddress) {
Person person = Person.with(name, emailAddress);
repository.add(person);
return PersonData.from(person);
}
@Transactional
public PersonData changeName(String personId, String name) {
Person person = repository.personOf(personId);
person.changeName(name);
return PersonData.from(person);
}
@Transactional
public PersonData changeEmailAddress(String personId, String emailAddress) {
Person person = repository.personOf(personId);
person.changeEmailAddress(emailAddress);
return PersonData.from(person);
}
}
//=====================================
// OUTSIDE
//=====================================
//
// Outside: Driven-side Persistence Adapter: PostgresPersonRepository
//
package people.infrastructure.persistence;
public class PostgresPersonRepository extends Repository implements PersonRepository {
private Session session;
public PostgresPersonRepository(Session session) {
this.session = session;
}
public void add(Person person) {
session.save(person);
}
public Person personOf(String personId) {
Person person = session.get(personId, Person.class);
return person;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment