0

Wir haben eine Spring MVC-Anwendung, die meisten REST-Operationen sind die einzige GET-Operation pro Ressource. Zurzeit haben wir viele Controller mit der einzigen GET-Methode, die sich nicht voneinander unterscheiden (selbst in URLs, Inhaltstypen, Parametern usw.).Pro und Kontra mit einem Controller für mehrere Ressourcen

Um eine solche Duplizierung zu entfernen, bietet unser Teamkollege an, einen Controller mit der einzigen GET-Operation und einer Karte mit Service (Ressourcenname -> Ressourcenservice) zu erstellen.

Aber wir sehen solche Nachteile wie kompliziertere Spring Injection tuning, keine Möglichkeiten, einige Einschränkungen für Inhaltstypen, Parameter hinzuzufügen - Anpassung der Operation in einem Wort. Darüber hinaus gibt es mehrere Ressourcen, die sich in einem separaten Controller befinden. Ich erwarte auch nicht, dass es zumindest einen einfachen Weg gibt, die einzige Methode in Swagger auf verschiedene Arten zu dokumentieren (unterschiedliche Beschreibung).

Also für mich auf der einen Seite ist weniger Code, aber auf der anderen Seite sind die Möglichkeiten der Operation Anpassung, Mischung von Architekturen, Mangel an ordnungsgemäße Dokumentation oder zumindest komplizierte Konfiguration eingeschränkt. Ich halte es nicht für eine gute Methode, eine Methode zu entwickeln.

Bin ich richtig? Wenn ja, wie kann ich es beweisen? Wenn nicht warum? Vielen Dank für Ihre Zeit und Ideen!

Antwort

2

Ja, Sie haben Recht. Kurz gesagt, gemäß single responsibility principle sollte jeder Controller nur einen Job ausführen (nur eine URL verarbeiten).

Sie beschreiben perfekt die Probleme, die der generische Controller behandeln würde. Denken Sie auch darüber nach, ob ein Controller im Moment perfekt zur generischen Regel passt, aber nächsten Monat bestimmte Dinge benötigt? Sie müssen Code kopieren und einfügen und dann neu hinzufügen. So nach einiger Zeit bekommen Sie Chaos mit riesigen und komplexen generischen Controller und doppelten Code. Niemand konnte vorhersagen, wie schnell es sein könnte, da die Geschäftsanforderungen unerwartet für das Entwicklerteam hinzugefügt werden konnten.

Auf der anderen Seite ist Ihr Teamkollege richtig in seinem Wunsch, doppelten Code zu reduzieren. Zumindest nicht alle Entwickler wollen ihre Zeit damit verbringen, Code sauberer zu machen. Und die meisten Menschen müssen Anerkennung erlangen (stellen Sie sicher, dass ihre Meinung den Wert hat). So schicken Sie ihn nicht weg :)

Was könnte ich empfehlen: Einführung abstrakt Eltern und verwendet Vererbung und Template Muster für Ähnliche Controller

/** Interface mainly works as a marker. 
    At first look, interface isn't necessary but it'll improve maintainability. 
    Next year you say 'thank you' to yourself */ 
interface IController { 
    //some methods which will implement EACH controller even the most specific 
    public void doGet(params) 
} 
abstract class AbstractController implements IController { 
/** Class implements default behavior for controllers. 
    Implementation written so child classes could adopt behaviour easily*/ 
    @Override 
    public void doGet(params) { 
    // use Template pattern 
    doLog(params); 
    prepareStuff(); 
    process(); 
    } 
    // common stuff which should be done at first 
    protected void doLog(params) { // your favorite logger here} 
    // extension point for inherited classes 
    abstract protected void prepareStuff(); 
    // here is the real processing for default controller 
    public void process() { 
    //implement common processing for GET request 
    } 
    // Prefer to use protected method instead of field 
    protected String getURL() { return DEFAULT_URL;} 
} 
// usual controller has nothing special 
class Controller1 extends AbstractController { 
    @Override 
    protected String getURL() { return "url1";} 
    @Override 
    protected prepareStuff() {// do nothing} 
} 
// do some specific preparation/checks 
class Controller2 extends AbstractController { 
    @Override 
    protected prepareStuff() {//preparation/checks here } 
    /** Note I 'forget' to override getURL() so it'll process DEFAULT_URL. 
    It could be useful if AbstractController calculates url dynamically and 
    you don't want to write boilerplate strings "/myApp/section7". 
    Also you could write abstract getURL() 
    */ 
} 
/** custom controller but you want to re-use some common code. 
In fact I would not recommend this way as usual approach */ 
class Controller3 extends AbstractController { 
    /** Overriding this method totally discards the Template pattern. 
     It could (and will) lead to confusing and errors*/ 
    @Override 
    public void doGet(params) { // new implementation } 
    @Override 
    protected prepareStuff() { 
    // you don't need it but you have to override since it abstract 
    } 
} 
// totally custom controller. Implements interface just as a marker 
class SpecificController implements Controller { 
    // In order to support legacy code just call method wich has been already written. You even no need to rename it. 
    @Override 
    public void doGet(params) { specificMethod();} 
    // lagacy method which probably is used somewhere else 
    public void specificMethod() { // the actual logic here} 
} 

In der Tat habe ich ähnliche Lösung in einem Projekt sollte. Mit IDE-Funktionen wie "Methode einführen" und "zum Elternteil wechseln" habe ich Dutzende von Klassen an einem einzigen Tag refaktoriert.

Hoffnung, die Sie oder Ihre Mitspieler könnte eine solche Idee in wenigen Tagen

+0

Danke implementieren und vergleichen, ich schätze Sie wirklich Zeit, um die Antwort zu machen gefunden! Aber ich sehe keinen architektonischen Unterschied zwischen Vanilla Servlets dann: C dieser Fall scheint der Verwendung von Befehlsmuster ähnlich zu sein –

+0

1. Du reduzierst duplizierten Code, indem du ihn in Eltern AbstractController einführst und 2. du hast Erweiterungspunkte, um behavior zu ändern (der Unterschied Ihr Teamkollege vorschlagen: Single-Controller, die schwer zu erweitern) – ADS

+0

und was ist als Alternative haben einen Controller mit mehreren GET-Methoden? –

Verwandte Themen