Pureline Crystal
Own identity, explicit control flow.
Crystal keeps its own language identity while following Pureline principles. Short postfix guards remain allowed, complex control flow becomes an explicit block, nil is handled visibly, and macros stay the exception.
Profile rules
Idiomatic Postfix Guards Are Allowed
Crystal postfix conditions are Pureline-compliant when they express a short, obvious guard. They keep guard logic compact and preserve a linear happy path.
Use an explicit block when either the condition or the guarded action becomes more complex. The rule is not “avoid postfix conditions.” The rule is: use the form that keeps the intent immediately obvious.
return unless session && session.valid? && !session.expired? && limiter.allow?(user) logger.info("Session #{session.id} closed") if session.closed? return unless !closed return unless valid
return if closed if session.closed? || session.expired?
logger.info("Session is no longer usable")
return
end Avoid `else`
As in all Pureline profiles: handle the special case first, exit early, then continue linearly.
if valid
execute
else
reject
end if admin?
grant_all
elsif member?
grant_default
else
deny
end if !valid
reject
return
end
execute case role
when .admin? then grant_all
when .member? then grant_default
end Idiomatic Naming
Variables and methods use snake_case; types use PascalCase.
class Session_Service
def loadUser(userId)
packetRegistry = PacketRegistry.new
end
end session_service
packet_registry
load_user
create_session SessionService
PacketRegistry
UserStorage Prefer Type Inference
Crystal reliably infers local types. Redundant annotations are noise.
session : Session = create_session(user) session = create_session(user) Explicit Nil Guards
Expected nil cases are handled visibly instead of being buried in deeply nested chains or behind not_nil!.
session = create_session(users.find(id).not_nil!) name = users.find(id).try &.profile.try &.display_name.try &.strip user = users.find(id)
if user.nil?
return
end
session = create_session(user) user = users.find(id)
return if user.nil?
session = create_session(user) Exceptions Are for Exceptional States
Expected outcomes should preferably use normal domain modeling such as nil, union types, result-like structures, or enums. Exceptions represent exceptional failure, not ordinary branching.
def find_user(id)
users.fetch(id)
rescue KeyError
nil
end begin
connect
rescue
retry_later
end def find_user(id) : User?
users[id]?
end Avoid Macro Cleverness Without Need
Crystal macros are powerful, but Pureline avoids hiding ordinary behavior behind metaprogramming unless the abstraction produces a clear architectural benefit. Generated behavior should remain predictable and discoverable.
macro delegate_all(target)
{% for method in @type.methods %}
def {{method.name}}
@{{target}}.{{method.name}}
end
{% end %}
end delegate open, close, to: @connection Folder Density
A Crystal source or namespace folder may contain at most **10 production .cr files** by default.
Specs, generated files, bindings, and metadata-only files do not count.
When the limit is exceeded, split the namespace by responsibility while preserving idiomatic Crystal structure.
Core rules in the Crystal checker
In addition to the profile rules, the Crystal checker verifies these rules from the Pureline Core: