@JulienTopcu
@JulienTopcu
?🤪?
@JulienTopcu
I want to search for trains going to my destination
@JulienTopcu
Architectural Styles and the Design of Network-based Software Architectures - Roy Fielding
@JulienTopcu
© Paramount Pictures - Interstellar
@JulienTopcu
© Paramount Pictures - Interstellar
@JulienTopcu
@JulienTopcu
@JulienTopcu
© Lucasfilms - "STAR WARS: Revenge of the Sith"
@JulienTopcu
interface BookSpaceTrains {
Booking fromTheSelectionOf(Search search)
}POST /bookings@JulienTopcu
interface RebookSpaceTrains {
Booking atANewDate(UUID bookingId, LocalDate newdate)
}interface BookSpaceTrains {
Booking fromTheSelectionOf(Search search)
}POST /bookings@JulienTopcu
interface RebookSpaceTrains {
Booking atANewDate(UUID bookingId, LocalDate newdate)
}POST /bookingsinterface BookSpaceTrains {
Booking fromTheSelectionOf(Search search)
}POST /bookings@JulienTopcu
bookSpaceTrains.fromTheSelectionOf(search)rebookSpaceTrains.atANewDate(bookingId,newdate)POST /bookings{
"searchId" : "...",
}POST /bookings{
"bookingId" : "...",
"newDate": "..."
}I book what I have selected
I'm rebooking the same train at a new date
Loss of the notion of Selection
Semantic confusion with the previous use case
@JulienTopcu
BookSpaceTrains.fromTheSelectionOf(search)rebookSpaceTrains.atANewDate(bookingId,newdate)POST /rebookings{
"searchId" : "...",
}POST /bookings{
"bookingId" : "...",
"newDate": "..."
}@JulienTopcu
Re-booking
Pseudo-fonctionnel
@JulienTopcu
@JulienTopcu
@JulienTopcu
POST /bookings/{id}/rebook{
"newDate": "..."
}booking {
"bookingId": "{newId}",
"date": "{newDate}"
}GET /bookings/{newId}@JulienTopcu
@JulienTopcu
At no time whatsoever do the server or client software need to know or understand the meaning of a URI -- they merely act as a conduit through which the creator of a resource (a human naming authority) can associate representations with the semantics identified by the URI
Architectural Styles and the Design of Network-based Software Architectures - Roy Fielding
@JulienTopcu
@JulienTopcu
© Lucasfilms - "STAR WARS: Revenge of the Sith"
@JulienTopcu
@JulienTopcu
Search
|_ availableSpaceTrains
|_ selection
|_ selectedSpaceTrainsPATCH /searches/{id}/selection@JulienTopcu
I select a fare on a train
@JulienTopcu
@JulienTopcu
@JulienTopcu
@JulienTopcu
© Lucasfilms - "STAR WARS: Revenge of the Sith"
@JulienTopcu
class Search {
UUID id
Criteria criteria
SpaceTrains spaceTrains
Selection selection
UUID getId() {...}
void setId(UUID id) {...}
Criteria getCriteria() {...}
void setCriteria(Criteria criteria) {...}
/* only getters and setters */
}
@JulienTopcu
data class Search { //Aggregate
/*attributes*/
/*no setters*/
fun changeCriteria(criteria : Criteria) : Search {
return this.copy(criteria = criteria, spaceTrains = emptyList())
}
}@JulienTopcu
GET /searches/{id}
{
"id": "c956d89b-73fc-49ce-a911-f0058c0672f6",
"criteria": {/*...*/},
"spaceTrains": [/*...*/],
"selection": {/*...*/}
}@JulienTopcu
© Lucasfilms - "STAR WARS: Attack of the Clones"
@JulienTopcu
@JulienTopcu
bookSpaceTrains.fromTheSelectionOf(search)rebookSpaceTrains.atANewDate(bookingId,newdate)POST /bookings{
"searchId" : "...",
}POST /bookings{
"bookingId" : "...",
"newDate": "..."
}We have to read the payload to deduce the use case
@JulienTopcu
@JulienTopcu
PATCH /searches/{id}/selection
[
{
"op": "add",
"path": "/selectedSpaceTrains/-",
"value": {"trainNumber" : "MOON421", "fare" : "FIRST"}
}
]Accidental Complexity of adaptation
De-encapsulation
@JulienTopcu
POST /searches/{id}/spaceTrains/{number}/fares/{code}/selectSearch /* Domain Model */
|_ availableSpaceTrains
|_ selection
|_ selectedSpaceTrains@JulienTopcu
POST /searches/{id}/spaceTrains/{number}/fares/{code}/select© Touchstone Pictures - "The Hitchhiker's Guide to the Galaxy"
@JulienTopcu
© Marvel Studio - "Guardians of the Galaxy Vol.1"
regarding the workflow...
@JulienTopcu
@JulienTopcu
POST /searches /*RoundTrip Criteria Submitted*/
GET /searches/{id}/spaceTrains?bound=OUTBOUND
POST /searches/{id}/spaceTrains/{number}/fares/{code}/select
GET /searches/{id}/spaceTrains?bound=INBOUND
POST /searches/{id}/spaceTrains/{number}/fares/{code}/select
POST /bookings /*Trip Booked*/
@JulienTopcu
@JulienTopcu
@JulienTopcu
if(searchType == "roundtrip" && outBoundIsSelected && inBoundIsSelected){
displayBookingButton()
}@JulienTopcu
if(searchType == "roundtrip" && outBoundIsSelected && inBoundIsSelected){
displayBookingButton()
}@JulienTopcu
© Paramount Pictures - "Star Trek: The Next Generation"
@JulienTopcu
© martinfowler.com - "Richardson Maturity Model"
@JulienTopcu
Hypermedia As The Engine of Application State
@JulienTopcu
@JulienTopcu
@JulienTopcu
❌
❌
❌
❌
✔️
✔️
✔️
✔️
@JulienTopcu
❌
❌
❌
❌
✔️
✔️
✔️
✔️
@JulienTopcu
Repository
@JulienTopcu
© Paramount Pictures - "Star Trek"