Codebase improvements status

Codebase improvements status

This document attempts to summarize the technical status of the LIteFarm codebase, describing the improvements, best practices and standards the core team has been attempting to implement in a gradual manner.

Database

  • Preference to use auto-incremental integers as primary keys, rather than UUIDs.

  • Preference for all tables to have their own ID column as primary key. A counter-example of this pattern are the tables for specific locations and specific tasks, where for example the table irrigation_task has task_id both as a primary key and a foreign key to the task table.

  • In general, for enum tables where we store all of the different possible values for one field in another table, we are now usually only storing the translation key.

Back-end

  • We’re slowly moving towards more REST-y endpoint routes if possible. The route URL should be a noun describing the resource that will be created/updated/deleted, in singular. There’s currently a mix between this pattern and others that don’t follow rest:

    • Some endpoints currently have verbs in the route describing the action, e.g. PATCH /animal_batch/remove or POST /management_plan/repeat_plan.

    • Some currently have the resource in the URL, followed by the /farm/:farm_id – seemingly implying that the farm is a nested entity within each resource, when it’s actually the other way round.

    • Some are REST but are using a plural noun, such as POST /task/harvest_tasks (nothing inherently wrong about that, but we should strive for consistency either way).

See more details in this section of the sagas RFC RFC: Replacing sagas with RTK Query | RFC:ReplacingsagaswithRTKQuery API Shortcomings .

  • Since most resources in the LiteFarm app are constrained to a specific farm, we’ve decided to start not including the farm ID within the endpoints URL, to avoid having to have this in every single endpoint. The app is already sending the farm ID in the headers of every request, so we can read it from there. There’s still a lot of routes that do include it, and likely a lot of portions of code that attempt to get the farm ID from the URL itself and will need to be updated to extract it from headers in order to be reused for new features. Some methods have already been updated to contemplate both scenarios. Ideally, at some point this shouldn’t be necessary once all of the routes have been migrated to new patterns.

  • We’ve started abstracting business logic to service files that live within packages/api/src/services. The goal is to achieve leaner controllers, since most controller methods are currently bloated with logic instead of taking care of just handling requests and delivering a response. Additionally, by implementing services it should also be easier to share and reuse logic across different controllers.

  • TypeScript has recently been added to the api package. At this point in time, we consider writing new code in TypeScript to be highly preferable but not mandatory, depending on the developer’s level of comfort with it and time/effort constraints. More details in TypeScript PR https://github.com/LiteFarmOrg/LiteFarm/pull/3428 .

Front-end

  • We are in the process of migrating our approach to query from the API from sagas to RTK Query. Right now only some newer modules use RTK Query – Animals, Soil Amendment and Smart Irrigation. A list of all the endpoints currently being queried through RTK Query can be found in packages/webapp/src/store/api/apiSlice.ts. More details behind the change can be found in the RFC RFC: Replacing sagas with RTK Query . There’s a tech debt epic for migrating the remaining modules https://lite-farm.atlassian.net/browse/LF-4657 .

  • Three different styling patterns coexist today in the app, and we’re gradually attempting to consolidate them into one. We have SCSS module files on some places, on others we are using MUI’s useStyles hook, and finally there are still a lot of places where inline styling is used (unnecessarily). We’re making progress towards ensuring all styling in the app is written in SCSS modules. If working on a file where a different pattern is used, updating the styling is preferred if there’s enough time for it.

  • For responsiveness, we have a few mixins for the different breakpoints in packages/webapp/src/assets/mixins. If we need responsive styling in a SCSS file, we use these mixins. If we need the breakpoints within a React component, we’re using MUI’s useMediaQuery. The breakpoints defined in our mixins are the same as the default breakpoints in the MUI theme, so both approaches should match. There’s a bunch of places where media queries are used in the CSS outside of the mixins. This could be either due to the need to use a custom breakpoint outside of the usual ones (could be a valid use case if there’s a UX reason behind it), or because they haven’t been updated/migrated.

  • There’s a mix of forms within the webapp, with most pages using the Form component, and new views generally starting to use the ContextForm component. ContextForm follows the latest designs. On a technical level, the newer form handles navigation and preserving state between steps, and results in a single URL multi-step form as opposed to the previous approach where every step had its own URL and navigation had to be handled outside of the component. Because of this, for new features `ContextForm` is always preferred. See more details behind the technical change in this PR https://github.com/LiteFarmOrg/LiteFarm/pull/3158 .

  • Similarly to the point above, there may be other cases where similar components coexist where one is an improvement of the other, or one implements the latest designs. We often call these components V2, with the hope of eventually achieving consistency throughout the app and removing the original versions. Examples of this are the TableV2, CardV2 and FilterMultiSelectV2 components.

General practices

  • In Jira, we usually have a 3 level approach to ticket breakdown. We use epics to contain all tickets for one project, and then within the epic we create user stories. Then each user story is broken down further into technical work items as subtasks. The verification process is done on user stories rather than on technical work items, since verification consists of manual testing resembling what a real user would do.

  • Subtasks are labeled with `frontend` and `backend` labels for easier identification and assignment.

  • We have stopped pointing tickets to save time, striving instead to make each ticket as granular as possible so that most tickets are more or less the same size (there are of course exceptions, but we’ve deemed that acceptable in comparison with the effort to point every single ticket).

  • There’s currently two labels for tech improvement tickets, `techdebt` and `tech`. `techdebt` is the older one and contains some items that may not be valid anymore and should be cleaned up and others that should be migrated to the newer `tech` label.

  • For proposals of improvements to the codebase, there’s an RFC section in Confluence RFCs .