Last active
December 8, 2020 19:25
-
-
Save rahulbir/cbf24c3c65a59f1fc45e078c364a7493 to your computer and use it in GitHub Desktop.
Pseudo code for refactoring appointment_routes
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
//api-export-action /the/route/here/cancel | |
func Cancel(request WebRequest) (WebResponse, error){ | |
validateRequest() | |
// AppointmentRepository is injected here so that we can test CancelConsumerAction by stubbing the interface | |
result, err := CancelConsumerAction(mapFromWebRequest(request), AppointmentRepository{}) | |
if err return err | |
return mapToWebResponse(result), nil | |
} |
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
// repository interface, defines functions that determine how to obtain | |
// data from different sources like database, salesforce, other external services | |
type AppointmentRepository interface { | |
Fetch(appt.ID) LogisticAppointment // Shorten to `fetch` probably | |
Save(appt) error | |
List() []*LogisticAppointment | |
} | |
type CancelInput struct { | |
ID | |
Reason | |
} | |
type CancelResult struct { | |
ID | |
} | |
// In some cases these functions could be shared between ops/ios/consumer/etc. | |
// This example will show the case where ops and consumer have different implementations | |
func (input *CancelInput) CancelConsumerAction(repository AppointmentRepository) (CancelResult, error) { | |
appt := repository.Fetch(input.ID) | |
logisticAppointment.Cancel(appt, input.Reason) | |
err := repository.Save(appt) | |
if err return err | |
// Depending on the action...might not need a Result object | |
return CancelResult{ | |
id: appt.ID | |
} | |
} | |
func CancelOpsAction(input CancelInput) (CancelResult, error) { | |
appt := repository.fetchAppointment(input.ID) | |
logisticAppointment.Cancel(appt, input.Reason) | |
appt.canceledBy = input.Admin // extra functionality specific to ops | |
err := repository.Save(appt) | |
if err return err | |
// Depending on the action...might not need a Result object | |
return CancelResult{ | |
id: appt.ID | |
} | |
} |
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
// tests at the action logic level are much simpler to test now since we can stub out the repository | |
testCancelAction() { | |
stubAppt := {ID: "appt", status: "ACTIVE"} | |
stub := stubRepository{ | |
appt: stubAppt | |
} | |
result, err := cancelAction(input.ID = "appt", reason = "test reason") | |
assert.Equal(result, whatever) | |
assert.Equal(stub.savedAppt, {status: CANCELLED, reason: "test reason"...}) | |
} | |
stubRespository.Fetch() { | |
return this.appt | |
} | |
stubRespository.Save(appt) { | |
this.savedAppt = appt | |
} |
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
// Our new public facing business model | |
type LogisticAppointment { | |
id | |
starttime | |
endtime | |
status | |
} | |
func logisticAppointment.Cancel(appt LogisticAppointment, reason string /*or bigger struct*/) LogisticAppointment { | |
appt.canceledAt = now() | |
appt.status = "CANCELLED" | |
appt.reason = reason | |
return appt | |
} |
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
// This file implements the functions that the AppointmentRepository interface needs | |
AppointmentRepository.Fetch(id) { | |
appt := frunkTable.Get(id) | |
logisticsAppt := //map from current appointment model to LogisticsAppointment | |
return logisticsAppt | |
} | |
AppointmentRepository.Save(logisticsAppt LogisticsAppointment) { | |
appt := // map from LogAppt to frunky appt | |
frunkTable.UpdateWithID(appt) | |
} | |
AppointmentRepository.List() { | |
appts := frunkTable.List(appt) | |
logisticsAppt := //map from appointments model to LogisticsAppointments | |
return logisticsAppts | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment