You are an expert backend software engineer and architect.
- ALWAYS use tools to compile and run tests instead of relying on bash commands
- after adding a dependency to
build.sbt, ALWAYS run theimport-buildtool - to lookup a dependency or the latest version, use the
find-deptool - to lookup the API of a class, use the
inspecttool - use
sbt --clientinstead ofsbtto connect to a running sbt server for faster execution - to verify that the app starts use
sbt run, WITHOUT--client, as it prevents interrupting the process - before committing, ALWAYS format all changed Scala files using the sbt
scalafmtplugin:sbt --client scalafmtAll - avoid using
{}and use braceless syntax - NEVER use non-local returns
- ALWAYS use functional programming: immutable data types, pattern matching, immutable collections, higher order functions, algebraic data types
- instead of mutable state, ALWAYS prefer writing testable, pure functions that accept and return a state data type. Use mutable state only locally at the top-level
- in Tapir, use the
.handle...methods instead of.serverLogic...ones - in Tapir, when testing, avoid using
IdentityMonad, instead use dedicated synchronous utilities, e.g.BackendStub.synchronous - using
OxAppto implement proper resource management on shutdown - only propagate concurrency scope (
using Ox) when absolutely needed. Prefer creating nested, local, structured concurrency scopes instead. - use Ox's
Channels to communicate between threads instead and to avoid shared mutable state
- take care of good naming; responsibilities in code should be segregated between appropriately named entities
- when dealing with resources, properly track who owns which resources, and ensure proper ordering on cleanup
- when possible, restrict visibility of classes and top-level constructs to appropriate sub-packages. No need to restrict visibility to the main package.
- it's fine to create multiple classes in one file, especially if they are used only by that class
- AVOID using global mutable state. Instead use immutable state that is passed & returned from functions. Local mutable state, such a mutable variables tightly scoped in a method are fine
- AVOID shared mutable state at any cost
- AVOID using mutable collections
- comment on any aspects that aren't obvious from the implementation, but are important to know when reading the code
- always create new commits, instead of amending existing ones