Abwärtskompatibilitätsversprechen

Ab der Version 1.0.13 wird dieses Projekt nach dem Semantic Versioning 2.0.0 Prinzip entwickelt. Das bedeutet, dass bei einem Hochzählen der PATCH-Version (z.B. 1.0.1, 1.0.2, …) oder MINOR-Version (z.B. 1.1.0, 1.2.0, …) keine Breaking Changes auftreten werden.

Das Projekt kann also per npm als ^1.0 installiert werden und anschließend problemlos per npm update aktualisiert werden.

Upgrading

Es liegt aber in der Natur der Sache, dass sich Dinge ändern werden, wenn der Styleguide weiterentwickelt wird. Dazu wird es zu einem Punkt kommen, wo Anpassungen gemacht werden müssen, damit die neuste Version des Styleguides verwendet werden kann.

Diese Änderungen werden mit einem Hochzählen des MAJOR-Version (z.B. 2.0.0, 3.0.0, …) angekündigt. Ein Update der MAJOR-Version benötigt also eine npm Installation mit z.B. ^2.0 und wird dann etwas Arbeit machen.

Änderungen am JS- oder CSS-Code

Diese Tabelle zeigt, welche Änderungen innerhalb einer MINOR-Version erlaubt sind. Nicht erlaubte Änderungen sind nur als Breaking Change in einer neuen MAJOR-Version erlaubt.

Art der Änderung Änderung erlaubt?
Neue JS- oder CSS-Dateien erstellen ✅ Ja
Vorhandene JS- oder CSS-Dateien verändern ✅ Ja, außer Einstiegspunte
Vorhandene JS- oder CSS-Dateien löschen ✅ Ja, außer Einstiegspunte
Ein neues Bild oder eine Schriftart ergänzen ✅ Ja
Eine neue Abhängigkeit per npm installieren ✅ Ja

Änderungen am Twig-Code

Diese Tabelle zeigt, welche Änderungen innerhalb einer MINOR-Version erlaubt sind. Nicht erlaubte Änderungen sind nur als Breaking Change in einer neuen MAJOR-Version erlaubt.

Das BC-Versprechen betrifft nur Twig-Templates, die den Status ready haben! Twig-Templates mit dem Status prototype oder wip haben, dürfen nicht in Production verwendet werden und können daher jederzeit geändert oder gelöscht werden.

Art der Änderung Änderung erlaubt?
Neue Twig-Datei erstellen ✅ Ja
Twig-Datei umbenennen ❌ Nein (2)
Twig-Datei löschen ❌ Nein (2)
Twig-Datei verändern, ohne vorhandene Variablen zu ändern ✅ Ja
Twig-Datei verändern und vorhandene Variable wird nicht mehr benötigt ✅ Ja
Twig-Datei verändern und neue Variable wird benötigt ❌ Nein (3)
Twig-Datei verändern und der Typ einer Variable wird verändert ❌ Nein (4)
Twig-Datei verändern und vorhandene Twig-Function wird nicht mehr benötigt ✅ Ja
Twig-Datei verändern und vorhandener Twig-Filter wird nicht mehr benötigt ✅ Ja
Twig-Datei verändern und neuer Twig-Filter wird benötigt ❌ Nein (5)
Twig-Datei verändern und neue Twig-Function wird benötigt ❌ Nein (6)

Deprecating Code

Damit gewährleistet wird, dass Updates der MAJOR-Version möglichst problemlos durchgeführt werden können, werden notwendige Änderungen dokumentiert. Das passiert an folgenden Stellen:

  • In Twig-Templates werden deprecated Tags auf notwendige Änderungen hinweisen
  • Im JS-Code werden Hinweise über console.warn() gesetzt
  • Im CHANGELOG.md werden Änderungen mit einem BREAKING angekündigt

Durch die frühzeitige Ankündigung einer Deprecation und dem Aufzeigen einer Alternative werden im Youthweb-Code nach jedem Update mehr Warnungen angezeigt. Es kann kann dann entschieden werden, ob die Warnungen direkt behoben werden oder ob man sich damit Zeit bis zum Upgrade lässt. Sind alle Warnungen behoben, sollte ein Upgrade mit wenigen Anpassungen möglich sein.

Deprecation im JS-Code

Im JavaScript-Code können deprecated-Hinweise so gesetzt werden:

// BC Hinweis in Console anzeigen
console.warn('Die Verwendung von "foo.bar()" ist deprecated seit Styleguide 1.1, verwende stattdessen "foo.baz()".');

Deprecation in Templates

In Twig-Templates können mit dem deprecated-Tag Nachrichten hinterlegt werden, die dann in Symfony gebündelt als Warnungen angezeigt werden.

{% deprecated 'Die Variable "active_page" muss definiert werden seit Styleguide 1.1' %}
{% set active_page = 'default_value' %}

Beispiele

An den folgenden Beispiele soll gezeigt werden, wie Änderungen, die eine Anpassung am Youthweb-Code benötigen, durchgeführt werden können und dabei einen Hilfestellung für das bevorstehende Upgrade liefern.

  1. Der Webpack-Einstiegspunkt wird verschoben oder umbenannt.
  2. Ein Twig-Template wird entfernt oder umbenannt.
  3. Ein Twig-Template benötigt die Definition einer neuen Variable, bzw. eine vorhandene Variable wird umgenannt.
  4. Ein Twig-Template ändert den Typ einer Variable.
  5. Ein Twig-Template verwendet einen neuen Filter.
  6. Ein Twig-Template verwendet eine neue Funktion.

1. Der Webpack-Einstiegspunkt wird verschoben oder umbenannt.

Beispiel: Der Webpack-Einstiegspunkt unter /assets/js/index.js soll nach /src/index.js verschoben werden.

Im Branch v1.x:

  1. Verschiebe /assets/js/index.js nach /src/index.js.

  2. Erstelle /assets/js/index.js mit diesem Inhalt:

    // BC Hinweis in Console anzeigen
    console.warn('Die Verwendung der "/assets/js/index.js" ist deprecated seit Styleguide 1.1, verwende stattdessen "/src/index.js".');
    
    require('../../src/index.js');
  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Deprecated
    
    - `/assets/js/index.js` ist deprecated, verwende stattdessen `/src/index.js`

Im Branch v2.x:

  1. Merge v1.x nach v2.x

  2. Lösche die /assets/js/index.js.

  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - **BREAKING** `/assets/js/index.js` wurde entfernt, verwende stattdessen `/src/index.js`

2. Ein Twig-Template wird entfernt oder umbenannt.

Beispiel: Das Template /templates/alt.twig soll in /templates/neu.twig umbenannt werden.

Im Branch v1.x:

  1. Erstelle /templates/neu.twig mit folgendem Inhalt:

    {% set forward_compatibility_110 = true %}
    {% extends 'templates/alt.twig' %}
  2. Erstelle in der /templates/alt.twig einge bedinge Deprecation-Warnung:

    + {% if forward_compatibility_110 is not defined %}
    + {% deprecated 'Die Verwendung von "/templates/alt.twig" ist deprecated seit Styleguide 1.1, verwende stattdessen "/templates/neu.twig"' %}
    + {% endif %}
    <h1>Youthweb</h1>
    ...
  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Deprecated
    
    - `/templates/alt.twig` ist deprecated, verwende stattdessen `/templates/neu.twig`

Im Branch v2.x:

  1. Merge v1.x nach v2.x

  2. Lösche die /templates/neu.twig.

  3. Benenne /templates/alt.twig in /templates/neu.twig um.

  4. Entferne in der /templates/neu.twig die Deprecation-Warnung:

    - {% if forward_compatibility_110 is not defined %}
    - {% deprecated 'Die Verwendung von "/templates/alt.twig" ist deprecated seit Styleguide 1.1, verwende stattdessen "/templates/neu.twig"' %}
    - {% endif %}
    <h1>Youthweb</h1>
    ...
  5. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - **BREAKING** `/templates/alt.twig` wurde entfernt, verwende stattdessen `/templates/neu.twig`

3. Ein Twig-Template benötigt die Definition einer neuen Variable, bzw. eine vorhandene Variable wird umgenannt.

Beispiel: Im Template /templates/foo.twig wird eine neue Variable new_variable benötigt.

Im Branch v1.x:

  1. Definiere die Variable in /templates/foo.config.js:

    module.exports = {
        'context': {
            'new_variable': 'default_value',
        },
    };
  2. Prüfe in der /templates/foo.twig, ob die Variable new_variable definiert wurde und definiere sie, falls nötig.

    {% if new_variable is not defined %}
    {% deprecated 'Die Variable "new_variable" muss definiert werden seit Styleguide 1.1' %}
    {% set new_variable = 'default_value' %}
    {% endif %}
    <p>Variable new_variable enthält <code>{{ new_variable }}</code></p>
  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Deprecated
    
    - In `/templates/foo.twig` wurde die Variable "new_variable" eingeführt

Im Branch v2.x:

  1. Merge v1.x nach v2.x

  2. Lösche in /templates/foo.twig die Prüfung und Definition von new_variable.

    - {% if new_variable is not defined %}
    - {% deprecated 'Die Variable "new_variable" muss definiert werden seit Styleguide 1.1' %}
    - {% set new_variable = 'default_value' %}
    - {% endif %}
    <p>Variable new_variable enthält <code>{{ new_variable }}</code></p>
  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - **BREAKING** In `/templates/foo.twig` wurde die Variable "new_variable" eingeführt

4. Ein Twig-Template ändert den Typ einer Variable.

Beispiel: Im Template /templates/foo.twig enthielt die Variable hashtags den String #foo, #bar und muss jetzt ein Array ['#foo', '#bar'] enthalten.

Im Branch v1.x:

  1. Ändere die Variable in /templates/foo.config.js zu einem Array:

    module.exports = {
        'context': {
    -         'hashtags': '#foo, #bar',
    +         'hashtags': [
    +             '#foo',
    +             '#bar',
    +         ],
        },
    };
  2. Prüfe in der /templates/foo.twig, ob die Variable hashtags ein Array enthält und passe sie an, falls nötig.

    {# BC: Prüfen, ob "hashtags" ein Array enthält #}
    {% if hashtags is not iterable %}
    {% deprecated 'Die Variable "hashtags" muss ein Array enthalten seit Styleguide 1.1' %}
    {% set hashtags = hashtags|split(', ') %}
    {% endif %}
    <p>Tags: {% for hashtag in hashtags %}{{ hashtag }}, {% endfor %}</p>
  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - In `/templates/foo.twig` muss die Variable "hashtags" ein Array sein

Im Branch v2.x:

  1. Merge v1.x nach v2.x

  2. Lösche in /templates/foo.twig die Prüfung und Neudefinition von hashtags.

    - {# BC: Prüfen, ob "hashtags" ein Array enthält #}
    - {% if hashtags is not iterable %}
    - {% deprecated 'Die Variable "hashtags" muss ein Array enthalten seit Styleguide 1.1' %}
    - {% set hashtags = hashtags|split(', ') %}
    - {% endif %}
    <p>Tags: {% for hashtag in hashtags %}{{ hashtag }}, {% endfor %}</p>
  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - **BREAKING** In `/templates/foo.twig` muss die Variable "hashtags" ein Array sein

5. Ein Twig-Template verwendet einen neuen Filter.

Beispiel: Im Template /templates/foo.twig soll ein neuer Filter danger_color verwendet werden, der eine eigene Implementierung benötigt (also nicht per default in Twig aktiv ist).

Im Branch v1.x:

  1. Prüfe in der /templates/foo.twig, ob der Filter danger_color existiert und rufe ihn erst dann auf. Dafür stehen die Twig-Funktion twigFilterExists und der Twig-Filter twigFilterCall zur Verfügung. Falls möglich, biete eine Alternative an, wenn der Filter nicht existiert.

    {# BC: Prüfen, ob Filter "danger_color" existiert #}
    {% if twigFilterExists('danger_color') %}
    {{ 'Zeige diesen Text in Rot an'|twigFilterCall('danger_color') }}
    {% else %}
    {% deprecated 'Der Twig-Filter "danger_color" sollte definiert sein seit Styleguide 1.1' %}
    <span class="text-danger">Zeige diesen Text in Rot an</span>
    {% endif %}
  2. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - Ein neuer Twig-Filter "danger_color" wird benötigt, der den Text farblich hervorhebt.

Im Branch v2.x:

  1. Merge v1.x nach v2.x

  2. Entferne in /templates/foo.twig die Prüfung nach der Existenz des danger_color-Filters und verwende ihn direkt.

    - {# BC: Prüfen, ob Filter "danger_color" existiert #}
    - {% if twigFilterExists('danger_color') %}
    - {{ 'Zeige diesen Text in Rot an'|twigFilterCall('danger_color') }}
    + {{ 'Zeige diesen Text in Rot an'|danger_color }}
    - {% else %}
    - {% deprecated 'Der Twig-Filter "danger_color" sollte definiert sein seit Styleguide 1.1' %}
    - <span class="text-danger">Zeige diesen Text in Rot an</span>
    - {% endif %}
  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - **BREAKING** Ein neuer Twig-Filter "danger_color" muss definiert sein, der den Text farblich hervorhebt.

6. Ein Twig-Template verwendet eine neue Funktion.

Beispiel: Im Template /templates/foo.twig soll eine neue Funktion calc_years_from_date() verwendet werden, die eine eigene Implementierung benötigt (also nicht per default in Twig aktiv ist).

Im Branch v1.x:

  1. Prüfe in der /templates/foo.twig, ob die Funktion calc_years_from_date() existiert und rufe sie erst dann auf. Dafür stehen die Twig-Funktionen twigFunctionExists und twigFunctionCall zur Verfügung. Falls möglich, biete eine Alternative an, wenn die Funktion nicht existiert.

    {# BC: Prüfen, ob Funktion "calc_years_from_date" existiert #}
    {% if twigFunctionExists('calc_years_from_date') %}
    <p>Erstellt am {{ date }}, also vor {{ twigFunctionCall('calc_years_from_date', date) }} Jahren</p>
    {% else %}
    {% deprecated 'Die Twig-Funktion "calc_years_from_date" sollte definiert sein seit Styleguide 1.1' %}
    <p>Erstellt am: {{ date }}</p>
    {% endif %}
  2. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - Eine neue Twig-Funktion "calc_years_from_date" wird benötigt, die die Jahre eines Datums zu heute berechnet.

Im Branch v2.x:

  1. Merge v1.x nach v2.x

  2. Entferne in /templates/foo.twig die Prüfung nach der Existenz der calc_years_from_date()-Funktion und verwende ihn direkt.

    - {# BC: Prüfen, ob Funktion "calc_years_from_date" existiert #}
    - {% if twigFunctionExists('calc_years_from_date') %}
    - <p>Erstellt am {{ date }}, also vor {{ twigFunctionCall('calc_years_from_date', date) }} Jahren</p>
    + <p>Erstellt am {{ date }}, also vor {{ calc_years_from_date(date) }} Jahren</p>
    - {% else %}
    - {% deprecated 'Die Twig-Funktion "calc_years_from_date" sollte definiert sein seit Styleguide 1.1' %}
    - <p>Erstellt am: {{ date }}</p>
    - {% endif %}
  3. Erstelle in der CHANGELOG.md den folgenden Eintrag:

    ### Changed
    
    - **BREAKING** Eine neue Twig-Funktion "calc_years_from_date" muss definiert sein, die die Jahre eines Datums zu heute berechnet.