- Exceptions: function templates that must stay in the header, `constexpr` functions where the compiler requires the definition to be visible, and functions with an empty body (`{}`) or a short initializer list.
Why: keeps headers light (faster builds, smaller include surface), keeps the implementation file as the single source of truth for behavior, and matches the existing style across `ApplicationLibCode`.
Use `std::format` to build log messages — not `QString(...).arg(...)`.
- `RiaLogging::info` / `warning` / `error` take `std::string_view`. Passing a `QString` requires a trailing `.toStdString()`; `std::format` avoids that and reads better.
- `QString` arguments can be passed directly to `std::format` — include `RiaQStringFormatter.h`, which provides a `std::formatter<QString>` specialization.
```cpp
// Bad – QString with positional placeholders, manual conversion
RiaLogging::info( QString( "Exported %1 cells for well '%2'." ).arg( count ).arg( wellName ).toStdString() );
// Good – std::format, QString passed directly
RiaLogging::info( std::format( "Exported {} cells for well '{}'.", count, wellName ) );
Use `CAF_ASSERT` (`cafAssert.h`). Do not add new `CVF_ASSERT`, `CVF_ASSERT_MSG`, `CVF_FAIL_MSG` or `CVF_TIGHT_ASSERT` — those are legacy and are being migrated away from.
An assert documents an invariant that holds whenever the program is correct. It is not error handling. Conditions that can legitimately occur at run time — a missing file, a malformed input deck, a failed network call, a user selecting nothing — must be handled with a return value, `std::optional`, `std::expected` or a logged error message, never with an assert.
```cpp
// Bad – a missing file is a run-time condition, not a broken invariant
CAF_ASSERT( QFile::exists( fileName ) );
// Good – handled and reported
if ( !QFile::exists( fileName ) )
{
RiaLogging::error( std::format( "File not found: {}", fileName ) );
return {};
}
// Good – a broken invariant, unreachable unless the code is wrong
CAF_ASSERT( index >= 0 && index < m_values.size() );
```
`CAF_ASSERT` follows the semantics of the standard `assert()`:
- **Debug builds**: active. A failure prints file, line and expression, then calls `std::abort()`.
- **Optimized builds** (Release, RelWithDebInfo): compiled out. The expression is still type checked but never evaluated, so it must be free of side effects — never put work inside the assert that the surrounding code depends on.
Configure with `-DRESINSIGHT_ENABLE_ASSERTS_IN_RELEASE=ON` to keep the asserts active in an optimized build, which is useful when reproducing a problem in RelWithDebInfo with a debugger attached.
A failing assert aborts via `SIGABRT`, which the crash handler installed in `RiaMain.cpp` picks up: the failure is written to the log file and reported to OpenTelemetry with a stack trace.
When adding or modifying context-menu items for a PDM object, override `appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder )` on that object and add the entries there.
- Do **not** modify `RimContextCommandBuilder` to add object-specific menu items. It dispatches to each object's `appendMenuItems`; keep object-specific logic in the object.
```cpp
// Good – menu items added in the object's own appendMenuItems override