(Best Practice) Verarbeitung von Protokoll Befehlen

  • Also, ich habe eine Client/Server Anwendung geschrieben, die Daten und Befehle (einfache Strings) hin und her schickt. Die Verarbeitung übernimmt dabei ein eigenes Protokoll. Bislang sieht das so aus, das ich Konstanten habe, die die Befehle definieren und eine Methode mit sehr vielen If-Bedingungen, welche die weitere Verarbeitung übernimmt (je nachdem welcher Befehl gesendet wurde).
    Dafür hab ich ein Interface,..

    Code
    public interface Protocol
    {
       public static final String COMMAND_1 = "befehl1";
       //[...]
    
    
       public void process(String input);
    }


    ... welches von zwei Klassen implementiert wird (jeweils ein ServerProtocol und ein ClientProtocol).

    Code
    public class ServerProtocol implements Protocol
    {
       public void procss(String input)
       {
          if(input.equals(Protocol.COMMAND_1)
          {   // tu was
          }
         // [... und viele weitere]
       }
    }


    Das ist jedoch sehr Erweiterungs- und Wartungsunfreundlich wie ich finde. Wie könnte man das anders lösen?


    Mein bisherigen Idee ist folgende:
    Ich habe eine abstrakte Klasse für einen Befehl:


    In dem ServerProtocol gibt es nun eine Map, in der alle möglichen Befehle für die Server-Seite eingefügt werden.


    Aufgerufen wird das dann durch die process(String input) Methode.

    Code
    @Override
        public void processInput(String data)
        {
    	commands.get(data).execute();
        }


    Das ist schon besser als vorher, jedoch auch nicht ganz optimal, da man auch hier wieder suchen muss, wenn man einen Befehl ändern will. Hab da gedacht, man könnte eventuell etwas mit Reflection machen, aber das funktioniert auch nicht, da ich das nicht automatisieren kann, da die Verarbeitung eines Behfels ja immer unterschiedlich ist.


    Also nochmal die Frage, gibt es eine bessere Möglichkeit?


    block_

  • Also so wie du es machst, ist es denke ich nicht schlecht gelöst.
    Ansonsten gibt es noch Switch oder ein eigenes Paket, wo du die Klassen definierst (also ein Interface und die Commands die davon erben.(Ist zwar nicht performance technisch besser, aber übersichtlicher)
    Ansonsten fällt mir grade nichts anderes ein

    MfG,
    Christopher


    Eine gewisses Maß an Freundlichkeit kann man auch von Menschen im Internet erwarten.
    Das Forum basiert komplett auf der Freiwilligkeit ihrer Nutzer und diese sollen sich wohlfühlen! Daher seid bitte freundlich. Danke

  • Ein Paket mit den Klassen hab ich mir auch schon überlegt, allerdings bin ich mir nich sicher ob das so sinnvoll ist, da es schon jetzt eine Menge Befehle sind. Wenn man das laden dann noch mit Reflection lösen könnte, würde ich mir das nochmal überlegen, aber wie ich das gesehen hab geht das nicht so wirklich.
    Müsste man mal ausporbieren, welche der beiden Methoden praktikabler ist.


    block_

  • Es wurde kein Framework genutzt. Der Server, und der Client auch, wurde mit Java(Android) selbst implementiert (Plain Sockets).
    Also die ganze App sieht bisher so aus:
    In der App ist sowohl der Client-Anteil, als auch der Server-Anteil, damit die App unabhängig von externen Server ist (und man in jedem Netzwerk, in das man reinkommt, die App nutzen kann). Kommuniziert wird nur über WLAN, nicht übers Internet. Befinden sich mehrere Geräte im WLAN, kann eines davon einen Server starten mit dem sich die anderen verbinden und Daten austauschen können.


    block_

  • Ich fürchte, ich verstehe das Grundproblem nicht so ganz.


    Wenn du deine Befehlsliste erweitern willst/musst, dann musst du das sowohl im Client als auch im Server machen.


    In deinem Fall hätte ich (verdammter C-Hintergrund. ^^) statt einer Klasse für jeden Befehl einfach ein Enum für die Befehle gebaut.
    Die IFs wird man ja nicht los, aber man kann sie kurz halten.


    Als grobes Beispiel:


    So hast du einerseits die Hilfe, dass dir ein nicht implementierter Befehl sofort auffällt.
    Andererseits musst du noch immer an drei Stellen pro Seite anpassen: ENUM, Switch und eine neue Funktion.
    Nur wirst du ohne Anpassungen niemals neue Befehle hinzugefügt bekommen. ;)


    Dein Objektansatz ist zwar recht schön, doch verstößt er für mich gegen das Prinzip der Kapselung. Es sollten ja Daten und Logik getrennt sein.
    Wirklich übersichtlicher wirkt es übrigens auch nicht.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Das ich das auf beiden Seiten (Client/Server) ändern muss, dessen bin ich mir schon bewusst. Ich versuche halt einen möglichst guten Kompromiss zu finden, der das ganze übersichtlicher macht, aber auch das man an so wenig Stellen wie möglich Änderungen durchführen muss.
    Deine Kombination aus enum+int und switch würde mir bisher nicht viel bringen, da ich die Befehle als String brauche ( "server_tu_dies"). Allerdings könnte man den enum auch eine String Varaiable verpassen, wodurch aber die switch nicht mehr funktionieren würde (Strings in switch erst ab java7). Würde ich dann für jeden Befehl eine Klasse anlegen und dazu ein enum mit dem Namen der Klasse, könnte man das laden mit Reflection lösen und man hätte nur noch zwei Stellen die man ändern muss. Da es aber sowieso darauf hinaus läuft, an mehreren Stellen zu bearbeiten muss ich mir erst angucken, welche Methode einfacher und schneller zu handhaben ist.


    Dein Objektansatz ist zwar recht schön, doch verstößt er für mich gegen das Prinzip der Kapselung. Es sollten ja Daten und Logik getrennt sein.


    Wo siehst du hier eine Verletzung des dir genannten Prinzips? In meinen Augen ist das alles Logik.


    block_

  • Ich habe da wohl die HashMap mit der anonymen inneren Klasse missgedeutet, du hast in der Klasse ja ausschließlich Daten.
    Dann war mein Kommentar natürlich Blödsinn.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!