Best Practices & Style

41.1 Style guide highlights

4-space indentation; lowercase function names (add underscores when readability suffers); CamelCase types and modules; UPPER_CASE constants.

Append ! to functions that mutate arguments; put the mutated argument first.

Write generic code: accept AbstractArray, Real, AbstractString rather than concrete types.

Prefer short, composable functions; one concept per method.

Use isnothing, ismissing, === comparisons with singletons.

Use eachindex, axes, firstindex/lastindex instead of assuming 1:length(x).

Formatters: JuliaFormatter.jl (format("."), styles: Blue, SciML, YAS), Runic.jl.

41.2 Design guidelines

Structure programs around types + generic functions (multiple dispatch), not class hierarchies.

Keep structs immutable and concretely typed (use type parameters).

Separate type-unstable "glue" from type-stable kernels with function barriers.

Avoid type piracy; extend functions only for types you own.

Don't overuse macros; prefer functions.

Export a small, well-documented API.

Use environments for every project.

Write tests and doctests; run Aqua and JET in CI.

Measure before optimizing; benchmark with $-interpolation.

Document performance-critical assumptions.

41.3 Common pitfalls

Benchmarking at global scope wrap in functions, use BenchmarkTools with $ b = a expecting a copy copy(a) / deepcopy(a) Integer overflow (2^64 == 0) use BigInt, Int128, or floats; Base.checked_mul Vector{Any} from [] Float64[] or typed comprehension Abstract struct fields

Global loop variable scope errors in scripts wrap in a function or use global Row-major loop order iterate first index in the innermost loop using everything → name clashes import/using Pkg: f Comparing floats with == ≈ / isapprox String indexing by character position use eachindex, nextind, collect First-call slowness surprises precompilation, sysimages, Revise-based workflows