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