Best practices for spec development

This guide outlines best practices for developing Brossa specifications, drawn from production implementations across multiple carriers and product types.

Code organization

File structure

///////////////////////////////////////////////////////////////////////////////
// Imports and dependencies
import "currency_layer.art" as CL;

///////////////////////////////////////////////////////////////////////////////
// Conditions
condition decline;
condition refer;

///////////////////////////////////////////////////////////////////////////////
// Constants and configuration
@derived @hidden
const.max_limit: Number<"USD"> = 50_000_000<"USD">;

///////////////////////////////////////////////////////////////////////////////
// Basic information
// ... policy and insured details ...

///////////////////////////////////////////////////////////////////////////////
// Risk information
// ... risk characteristics ...

///////////////////////////////////////////////////////////////////////////////
// Coverage configuration
// ... coverage definitions ...

///////////////////////////////////////////////////////////////////////////////
// Rating calculations
// ... premium calculations ...

///////////////////////////////////////////////////////////////////////////////
// Submission structure
// ... UI organization ...

Naming conventions

  1. Namespacing

    • Use descriptive prefixes: policy., risk., coverage., etc.

    • Group related fields under common namespaces.

    • Keep namespace hierarchy shallow (max 3–4 levels).

  2. Field names

    • Use lowercase with underscores.

    • Be specific but concise.

    • Include units in name if not clear from type.

Example:

risk.building.construction_type: Text;
risk.building.year_built: Year;
risk.building.total_area_sqft: Number;

Data types and validation

Type selection

  1. Basic types

    • Text: For string values.

    • CaselessText: For case-insensitive text.

    • Int: For whole numbers.

    • Number: For decimal values.

    • Decimal: For precise decimal calculations.

    • Date: For dates.

    • YesNo: For boolean values.

    • Percent: For percentage values.

  2. Currency values

    policy.currency: Text = "USD";
    risk.tiv: Number<policy.currency>;
    risk.tiv has minimum 0<policy.currency>;
  3. Sets and collections

    coverage.type: #{Text};
    coverage.type has multi_options #{
        "Property Damage",
        "Business Interruption"
    };

Validation rules

  1. Input validation

    when risk.year_built > current_year()
        then risk.year_built^invalid with "Year built cannot be in the future";
    
    when risk.tiv <= 0<policy.currency>
        then risk.tiv^invalid with "TIV must be greater than zero";
  2. Business rules

    when risk.tiv > const.max_limit * roe_to_policy("USD")
        then refer with "TIV exceeds automatic capacity";
    
    when risk.building_age > 50 and risk.construction_type == "Frame"
        then decline with "Frame construction over 50 years old not eligible";

Rating calculations

CSV integration

  1. Table definition

    csv.construction_factors = table "construction_factors.csv" {
        type: "Construction Type" Text,
        factor: "Factor" Number
    };
  2. Lookups

    @derived
    rating.construction_factor =
        vertical_lookup_first(
            csv.construction_factors,
            "type",
            "factor",
            risk.construction_type
        ) <|> 1.0;

Premium calculation

  1. Factor calculation

    @derived
    rating.technical_premium(coverage_id: Uuid): Number<policy.currency> =
        risk.tiv *
        rating.base_rate(coverage_id) *
        rating.construction_factor *
        rating.age_factor;
  2. Aggregation

    @derived
    rating.total_premium: Number<policy.currency> =
        sum_list([
            rating.technical_premium(id)
            | id <- coverage.ids
        ]);

UI/UX design

Field properties

  1. Labels and prompts

    risk.construction_type: Text;
    risk.construction_type has {
       prompt= "Construction Type",
       description= "Building's primary construction material"
    };
  2. Options and suggestions

    risk.state: Text;
    risk.state has {
       options= column_list(csv.states, "state_code"),
       suggestions= column_list(csv.states, "state_name")
    };

Table rendering

  1. Basic table

    coverage.ids has render {
        type: "table",
        columns: [
            {name: "type", label: "Coverage Type"},
            {name: "limit", label: "Limit ({{policy.currency}})"}
        ],
        rows: [{
            id: id,
            cells: {
                type: data-point(coverage.type(id)),
                limit: data-point(coverage.limit(id))
            }
        } | id <- coverage.ids]
    };
  2. Grouped fields

    risk = {
        risk.construction_type,
        risk.year_built,
        risk.tiv
    };
    risk has heading "Risk Information";

Performance optimization

  1. Derived fields

    • Use @derived for calculated fields.

    • Add @hidden for internal calculations.

    • Cache complex calculations where possible.

  2. Lookup optimization

    @derived @hidden
    const.construction_factors = lookup_from_list([
        {key: row->type, value: row->factor}
        | row <- table_records(csv.construction_factors)
    ]);

Error handling

  1. Graceful fallbacks

    @derived
    rating.factor = lookup(risk.type, const.factors) <|> 1.0;
  2. Clear error messages

    when not(elem(risk.state, column_list(csv.states, "state_code")))
        then risk.state^invalid with "Please select a valid state";

Common pitfalls to avoid

  1. Currency handling

    • Always specify currency units.

    • Use proper currency conversion.

    • Handle exchange rates correctly.

  2. Validation gaps

    • Validate all user inputs.

    • Include range checks.

    • Handle missing values.

  3. Performance issues

    • Avoid unnecessary calculations.

    • Cache lookup results.

    • Use efficient data structures.

  4. UI problems

    • Group related fields.

    • Provide clear labels.

    • Include helpful descriptions.