Skip to content

Hermeneus Coding-Guidelines

Einführung

Zweck des Dokuments

Das Ziel dieses Dokuments ist die Etablierung eines konsistenten und wartbaren Codierungsstandards für das Hermeneus-Projekt, um die Zusammenarbeit zu erleichtern und eine hohe Softwarequalität sicherzustellen.


Allgemeine Projektprinzipien

Projektprinzipien

Orientierung an Standards

Die Hermeneus-Codebasis sollte sich an die allgemein anerkannten Best Practices und Standards der Laravel-Community halten (https://laravel.com/docs/11.x/contributions#coding-style). Zudem sollte bei der Konzeption eines neuen Features eruiert werden, ob es bereits ausgearbeitete Standards gibt, an die sich zu halten, künftig sinnvoll wäre.

Beispiele:

  • Hermeneus-Texte sind im sog. TEI-Format enkodiert. Alle Textelemente sind, wo es möglich ist, nach den Regeln der TEI-Guidelines enkodiert (https://tei-c.org/release/doc/tei-p5-doc/en/html/index.html), um das Format innerhalb der Geisteswissenschaften einheitlich zu halten.
  • Für die Enkodierung morphologischer Formen nutzt Hermeneus die sog. Perseus-Notation und erweitert diese um weitere Kategorien, wo es nötig ist. Künftige Abgleiche mit anderen APIs oder automatische Transformationen gestalten sich damit einfacher.

Kontinuierliche Verbesserung und Gradual Shift

Code sollte regelmäßig refaktoriert und optimiert werden, um mit aktuellen Best Practices Schritt zu halten. Sollten Standards geändert werden, wird der Code nicht rückwirkend angepasst, sondern nur bei neuen Features oder Refactorings. Dies gilt ebenso für die hier festgelegten Richtlinien.

Beispiele:

  • Falls eine neue Komponentenbibliothek hinzugefügt wird, ist es nicht zwingend, alle bisherigen Komponenten zu erneuern. Dies geschieht dann im Falle eins Refactorings.
  • Refactorings sollten so oft wie möglich stattfinden, auch wenn dadurch die Software instabiler werden könnte. Die Reduktion von Komplexität und damit einhergehender technischer Schuld verbessert die Wartbarkeit und ist eine Investition in die Zukunft.

Expressivität und Verständlichkeit

Der Code sollte sich möglichst an die natürliche Sprache anlehnen und selbsterklärend sein. Komplexe Programmlogik ist in expressiven Methoden- bzw. Variablennamen enkapsuliert.

Beispiele:

php
/**
 * Policy-Methode, die festlegt, wann ein Nutzer Zugriff auf eine Ressource haben darf.
 */
public function view(User $user, Ressource $resource)
{
    return $user->hasRole('editor') || 
           $user->hasSubscription() ||
           $resource->isPublished();
}

Ein Methoden- oder Klassenname mit zu vielen Prä- oder Suffixen zeigt, dass in einer Methode/Klasse zu viele Vorgänge stattfinden (Single Responsibility-Prinzip). Es besteht Refaktorierungsbedarf.

php
/**
 * :FIXME:.
 */
public function createLerneinheitAndSendUserMail($request)
{
 //... Code
}

Dateiorganisation

Verzeichnisstruktur im Core

Organisiere Dateien entsprechend der Standardstruktur von Laravel:

app/
  Http/
  Models/
  Providers/
config/
database/
resources/

Verzeichnisstruktur in Modulen

Bei Modulen wird die Hauptstruktur der Core-Struktur repliziert:

app/
  modules/
    Uebungen/
        NameDesModuls/
            app/
                Http/
                Models/
                Providers/
            resources/
            ...

Dateinamenkonventionen

  • Klassen-Dateien: PascalCase, z. B. UserService.php.
  • Laravel-Klassen wie Controller, Middleware, Requests, Jobs, Observer etc. werden im PascalCase benannt und mit dem Suffix versehen, z. B. UserController.php, UserRequest.php, UserObserver.php.
  • Interfaces: PascalCase mit dem Suffix Interface, z. B. LoggerInterface.php.
  • Traits: camelCase mit der Formulierung als Methode, z. B. logsActivity.php oder hasRoles.php.
  • Blade-Templates: snake_case, z. B. user_profile.blade.php.
  • Blade-Templates als Partials: vorangestellte __, z. B. __header.blade.php.
  • Vue-Komponenten:
    • SFC: PascalCase, z. B. Wörterbuch.vue.
    • Kindkomponenten: PascalCase, mit entsprechendem Suffix z. B. WörterbuchEintrag.vue, WörterbuchEintragListe.vue.

Maximale Dateigröße

  • Dateien sollten wenn möglich nicht mehr als 300 Zeilen umfassen. Falls notwendig, refaktorieren.

Code-Formatierung

Einrückung

Egal ob Tabs oder Leerzeichen, die Einrückung sollte konsistent sein. In Laravel wird eine Einrückung von 4 Leerzeichen verwendet.

Zeilenumbrüche und Klammern

Klassen und Funktionen

php
class User extends Authenticatable
{
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }

    protected function validateUser(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
        ]);
    }
}

Bedingungen und Schleifen

php
if ($user->isAdmin()) {
    // Code hier
} elseif ($user->isManager()) {
    // Code hier
} else {
    // Code hier
}

foreach ($users as $user) {
    // Code hier
}

while ($active) {
    // Code hier
}

Leerzeichen

Um Operatoren

php
// Richtig:
$a = $b + $c;

// Falsch:
$a=$b+$c;

Nach Kommas

php
// Richtig:
array(1, 2, 3);

// Falsch:
array(1,2,3);

Bei Funktionsaufrufen

php
// Richtig:
myFunction($arg1, $arg2);

// Falsch:
myFunction( $arg1 ,$arg2 );

Mehrzeilige Methodenaufrufe

php
// Richtig:
$this->method()
    ->anotherMethod()
    ->thirdMethod();

$users = User::select('name', 'email')
    ->where('active', true)
    ->orderBy('name')
    ->get();

// Falsch:
$this->method()->anotherMethod()->thirdMethod();

$users = User::select('name', 'email')->where('active', true)->orderBy('name')->get();

Array-Formatierung

php
// Einzeiliges Array
$names = ['John', 'Jane', 'Joe'];

// Mehrzeiliges Array
$config = [
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3',
];

Type Hints und Return Types

php
public function calculateTotal(int $quantity, float $price): float
{
    return $quantity * $price;
}

public function getUser(string $email): ?User
{
    return $this->users->firstWhere('email', $email);
}

Klammersetzung

  • Verwende den "OTBS"-Stil für Klassen- und Funktionsdefinitionen:
php
class Example
{
    public function showTestFunction() {
        // code
    }
}

Laravel-Namenskonventionen

Die folgende Tabelle zeigt die wichtigsten Namenskonventionen in Laravel-Projekten:

TypRegelRichtigFalsch
ControllersingularArticleControllerArticlesController
Routepluralarticles/1article/1
Named routesnake_case mit dot notationusers.show_activeusers.show-active, show-active-users
ModelsingularUserUsers
hasOne/belongsTo BeziehungsingulararticleCommentarticleComments, article_comment
Andere BeziehungenpluralarticleCommentsarticleComment, article_comments
Tabellepluralarticle_commentsarticle_comment, articleComments
Pivot-Tabellesingular, Modelnamen alphabetischarticle_useruser_article, articles_users
Tabellenspaltesnake_case ohne Modelnamemeta_titleMetaTitle, article_meta_title
Fremdschlüsselsingular Modelname mit _id Suffixarticle_idArticleId, id, article_articles_id
Primärschlüssel-idcustom_id
Migration-2017_01_01_000000_create_articles_table2017_01_01_000000_articles
MethodecamelCasegetAllUsersget_all_users
Funktionsnake_caseabort_ifabortIf
Methode in Resource Controllermehr Infos: [table]storesaveArticle
Methode in TestklassecamelCasetestGuestCannotSeeArticletest_guest_cannot_see_article
Model-Propertysnake_case$model->model_property$model->modelProperty
VariablecamelCase$anyOtherVariable$any_other_variable
Collectionbeschreibend, plural$activeUsers = User::active()->get()$active, $data
Objektbeschreibend, singular$activeUser = User::active()->first()$users, $obj
Config/Language Dateiensnake_casearticles_enabledArticlesEnabled, articles-enabled
Viewkebab-caseshow-filtered.blade.phpshow_filtered.blade.php
Configkebab-casegoogle-calendar.phpgoogleCalendar.php, google_calendar.php
Contract (Interface)Adjektiv oder NomenAuthenticatableAuthenticationInterface, IAuthentication
TraitAdjektivNotifiableNotificationTrait

Best Practices für Laravel-Entwicklung

Domain-Driven Design (DDD)

  • Strukturiere den Code nach fachlichen Domänen statt technischen Schichten
  • Gruppiere zusammengehörige Funktionalitäten in Module/Bounded Contexts
  • Verwende eine ubiquitäre Sprache im Code und in der Dokumentation

Fat Models, Skinny Controllers

  • Halte Controller schlank - sie sollten nur HTTP-Requests koordinieren
  • Verlagere Business-Logik in die Models oder dedizierte Service-Klassen
  • Verwende Eloquent-Relationships statt komplexer Queries in Controllern

Request-Validierung

  • Nutze dedizierte Request-Klassen für komplexe Validierungslogik
  • Zentralisiere Validierungsregeln in Request-Klassen statt in Controllern
  • Verwende type-hinting und Docblocks für bessere IDE-Unterstützung

Service-Layer für Business-Logik

  • Lagere komplexe Business-Logik in Service-Klassen aus
  • Ein Service sollte eine spezifische Domänenfunktionalität kapseln
  • Services können von mehreren Controllern wiederverwendbar genutzt werden

Eloquent Best Practices

  • Nutze Eloquent ORM statt Query Builder wo möglich
  • Verwende Eager Loading um N+1 Probleme zu vermeiden
  • Definiere Relationships und Scopes im Model
  • Schütze Models vor Mass Assignment durch $fillable oder $guarded

Blade Template Best Practices

  • Vermeide Datenbankabfragen in Blade Templates
  • Nutze View Composer für wiederkehrende Template-Daten
  • Verwende Blade Components für wiederverwendbare UI-Elemente

Clean Code Prinzipien

  • Schreibe selbsterklärenden Code statt vieler Kommentare
  • Halte Methoden kurz und fokussiert (Single Responsibility)
  • Verwende aussagekräftige Namen für Variablen, Methoden und Klassen

Performance Best Practices

  • Cache häufig genutzte Daten
  • Nutze Eager Loading für Relationships
  • Verwende Database Indexing für häufige Queries
  • Implementiere Queue Jobs für zeitintensive Operationen