Separation von Anforderungen

In diesem Blog soll ein aktuelles Problem aus meinem Projektalltag beleuchtet werden. Wie können in einem Produkt die Standardanforderungen von kundenspezifischen Anforderungen getrennt werden?

Aktuell wird die Standardimplementierung (Java-Klasse) in das Kundenmodul kopiert und dort entsprechend den Anforderungen des Kunden angepasst. Die Kopie liegt dabei im gleichen Package und hat auch den gleichen Namen wie die Originalklasse. Über den Classpath wird sichergestellt, dass der Classloader zuerst die kundenspezifische Implementierung findet.

Diese Vorgehensweise hat ein paar Nachteile:

  • Code wird dupliziert
  • Erweiterungen des Standards müssen in allen Kopien nachgezogen werden
  • Das gleiche gilt auch für Fehlerbehebungen

Folgende Ziele sollen mit dem neuen noch zu findenden Ansatz gelöst werden:

  • Trennung von Standard- und Kundencode in eigenen Klassen (keine Steuerung z.B. über if-Anweisungen)
  • Keine Codepublizierung (oder zumindest sehr viel geringer als jetzt)
  • Einfach(er) zu testen
  • Keine Änderung des Klassennamen, da die Instanziierung von Klassen teilweise über Reflection erfolgt und die Aufrufe nicht geändert werden sollen

Zwei Varianten kommen zur Lösung in die engere Wahl:

Jede dieser Techniken werde ich in nachfolgenden Artikeln in diesem Blog vorstellen und erörtern.

Als Beispiel wird ein konkretes Problem aus dem Projektalltag verwendet: Erzeugen von Edifact-Nachrichten im Bereich von Gas-Nominierungen.
Die Ausgangsklasse hat folgendes Aussehen und Erzeugt NOMINT-Dateien:

public class NomintFilter {
  public void filter(InputStream is, OutputStream os) throws IOException {
    // Create BufferedReader and -Writer
    BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
    try {
      // Start filter
      Date now = new Date();
      NumberFormat nfParse = NumberFormat.getInstance();
      SimpleDateFormat sdfYMDHM = new SimpleDateFormat("yyyyMMddHHmm");
      sdfYMDHM.setTimeZone(TimeZone.getTimeZone("UTC"));
      SimpleDateFormat sdfUnique = new SimpleDateFormat("yyyyMMddHHmmssSSS");
      SimpleDateFormat sdfYMD = new SimpleDateFormat("yyMMdd");
      SimpleDateFormat sdfHM = new SimpleDateFormat("HHmm");

      String uniqueId = sdfUnique.format(now).substring(3); // 1
      nfParse.setGroupingUsed(false);
      NumberFormat nfEdi = new DecimalFormat();
      nfEdi.setGroupingUsed(false);
      nfEdi.setMinimumIntegerDigits(1);
      nfEdi.setMinimumFractionDigits(0);
      nfEdi.setMaximumFractionDigits(0);

      // Header information
      out.write("UNA:+.? '");
      out.write("UNB+UNOA:3+Absender:501" + "+Receiver:502" + "+" + sdfYMD.format(now) + ":" + sdfHM.format(now) + "+"
           + uniqueId + "++++++0" + "'");
      out.write("UNH+1+ORDERS:D:07A:UN:EG4003'");
      out.write("BGM+01G::321+NOMINT" + uniqueId + "+9'");
      out.write("DTM+Z05:0:805'");
      out.write("DTM+137:" + sdfYMDHM.format(now) + ":203'");
      out.write("RFF+CT:NORFF'");
      out.write("NAD+ZSY+Absender::321'");
      out.write("NAD+ZSO+Receiver::502'");
      int segmentCnt = 8; // Don’t count UNA und UNB

      // Omit loop through LIN data to simplify the sample
      out.write("UNS+S'");
      segmentCnt++;
      // Count UNT
      out.write("UNT+" + (segmentCnt + 1) + "+1'");
      out.write("UNZ+1+" + uniqueId + "'");
    } finally {
      // Close Reader and Writer
      in.close();
      out.close();
    }
  }
}

Der Kunde wünscht nun eine Anpassung der Unique-Id (Zeile // 1) in der Ausgabe. Sie soll jeweils am Anfang und am Ende um zwei Zeichen gekürzt werden, da der nachfolgende Prozess die Unique-Id noch ergänzen muss und dazu vier Zeichen Platz benötigt.

Die Umsetzung mit den einzelnen Techniken wird nachfolgenden Blogartikeln beschrieben. Der Code zu diesen Artikeln ist über Github inklusive Unittests verfügbar.

Hier geht es direkt zu den einzelnen Artikeln:

5 Gedanken zu „Separation von Anforderungen

  1. Pingback: Seperation von Anforderungen – Hookup-Methoden « 7droids

  2. Pingback: Seperation von Anforderungen – DI mit JBoss Weld « 7droids

  3. Pingback: Seperation von Anforderungen – DI mit Google Guice « 7droids

  4. Pingback: » Seperation von Anforderungen – DI mit JBoss Weld 7droids

  5. Pingback: » Seperation von Anforderungen – Hookup-Methoden 7droids

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.