-
Notifications
You must be signed in to change notification settings - Fork 6
How to refactor a Backend API
Here is an example PR which performs a refactor, along with some other changes.
You will most likely be assigned a single function, such as db#DB.GetUser
, to refactor into a handler function.
The first step you will take is likely to simply copy-paste the old function into the corresponding handler
file, or creating one if it does not exist (e.g. db/program.go
-> handler/program.go
). First, the parameter of the method should be swapped from c echo.Context
to cc echo.Context
. Near the start of the function, add the line c := cc.(*db.DBContext)
. If you are creating a new file, make sure the package name is handler
and that you are importing "github.com/uclaacm/teach-la-go-backend/db"
.
Currently, all the CRUD functions (create, retrieve, update, delete) are housed within db/db.go
. If the CRUD function does not exist already, it should be added here. In the future, these will be moved out into separate files, but since those are undergoing refactors it is easier to keep them all together.
These CRUD functions generally involve a single firebase call, as well as some basic error handling. For example:
func (d *DB) CreateProgram(ctx context.Context, p Program) (Program, error) {
newProg := d.Collection(programsPath).NewDoc()
p.UID = newProg.ID
if _, err := newProg.Create(ctx, p); err != nil {
return p, err
}
return p, nil
}
Next, you will want to replace any direct calls to the firebase API present in the function with the TLADB equivalents. There's no simple 100% consistent method to find these, but here is an example from the above PR:
doc, err := d.Collection(usersPath).Doc(c.QueryParam("uid")).Get(c.Request().Context())
if err != nil {
return c.String(http.StatusNotFound, err.Error())
}
if err := doc.DataTo(&resp.UserData); err != nil {
return c.String(http.StatusInternalServerError, err.Error())
}
The line which actually interfaces with firebase is the first, while the rest just checks for errors and moves the data from firebase into our own struct (resp.UserData
). The replacement code would be:
user, err := c.LoadUser(c.Request().Context(), c.QueryParam("uid"))
resp.UserData = user
The first line essentially performs the same function as the old lines 1-4, while the second is equivalent to the rest.
Here are some common firebase
functions in the codebase:
Collection
Doc
NewDoc
Set
Update
DataTo
Tests should be moved from the corresponding files (e.g. db/program_test.go
to handler/program_test.go
). As we are moving tests to using a mock DB, the line d := db.OpenMock()
should be included at the start of each test. Additionally, the call to the function being tested will need a small adjustment:
OLD:
d.GetUser(c)
NEW:
handler.GetUser(&db.DBContext{
Context: c,
TLADB: d,
})