Pureline Crystal
Eigene Identität, expliziter Kontrollfluss.
Crystal behält seine eigene Sprachidentität und folgt dabei den Pureline-Prinzipien. Kurze Postfix-Guards bleiben erlaubt, komplexer Kontrollfluss wird zum expliziten Block, nil wird sichtbar behandelt und Macros bleiben die Ausnahme.
Profilregeln
Idiomatische Postfix-Guards sind erlaubt
Crystal-Postfix-Bedingungen sind Pureline-konform, wenn sie einen kurzen, offensichtlichen Guard ausdrücken. Sie halten Guard-Logik kompakt und den Happy Path linear.
Wird die Bedingung oder die geschützte Aktion komplexer, kommt ein expliziter Block. Die Regel lautet nicht „keine Postfix-Bedingungen“, sondern: die Form wählen, bei der die Absicht sofort klar ist.
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 else vermeiden
Wie in allen Pureline-Profilen: Sonderfall zuerst, früh verlassen, dann linear weiter.
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 Idiomatische Namen
Variablen und Methoden in snake_case, Typen in PascalCase.
class Session_Service
def loadUser(userId)
packetRegistry = PacketRegistry.new
end
end session_service
packet_registry
load_user
create_session SessionService
PacketRegistry
UserStorage Typinferenz bevorzugen
Crystal inferiert lokale Typen zuverlässig. Redundante Annotationen sind Lärm.
session : Session = create_session(user) session = create_session(user) Explizite nil-Guards
Erwartete nil-Fälle werden sichtbar behandelt, statt sie in tief verschachtelten Ketten oder mit not_nil! zu vergraben.
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 für Ausnahmezustände
Erwartete Ergebnisse werden über normale Domain-Modellierung abgebildet: nil, Union Types, Result-artige Strukturen oder Enums. Exceptions stehen für echtes Versagen, nicht für gewöhnliche Verzweigung.
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 Keine Macro-Cleverness ohne Not
Macros sind mächtig. Pureline versteckt gewöhnliches Verhalten aber nicht hinter Metaprogrammierung, außer die Abstraktion bringt einen klaren architektonischen Vorteil. Generiertes Verhalten bleibt vorhersehbar und auffindbar.
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
Ein Crystal-Quell- oder Namespace-Ordner enthält standardmäßig höchstens **10 produktive .cr-Dateien**.
Specs, generierte Dateien, Bindings und reine Metadaten-Dateien zählen nicht mit.
Wird das Limit überschritten, wird der Namespace nach Verantwortung geteilt, unter Beibehaltung idiomatischer Crystal-Struktur.
Core-Regeln im Crystal-Checker
Zusätzlich zu den Profilregeln prüft der Checker für Crystal diese Regeln aus dem Pureline Core: