0

Nous avons une application Spring MVC, la plupart des opérations REST étant la seule opération GET par ressource. Donc actuellement nous avons beaucoup de contrôleurs avec la seule méthode GET qui ne diffère pas les uns des autres (même dans les urls, les types de contenu, les paramètres et etc). Afin de supprimer une telle duplication, notre équipier propose de faire un contrôleur avec la seule opération GET et une carte avec service (nom de la ressource -> service de ressources). Mais nous voyons des inconvénients tels que le réglage de l'injection de printemps plus compliqué, aucune possibilité d'ajouter des restrictions sur les types de contenu, les paramètres - personnaliser le fonctionnement en un mot. En outre, plusieurs ressources doivent résider dans un contrôleur distinct. Aussi, je ne m'attends pas à ce qu'il y ait au moins moyen de documenter la seule méthode dans Swagger de plusieurs façons (avoir une description différente). Pour moi, d'un côté, il y a moins de code mais de l'autre, il y a des possibilités réduites de personnalisation des opérations, mélange d'architectures, manque de documentation appropriée ou au moins une configuration compliquée. Je ne pense pas que ce soit une bonne approche ici pour faire une méthode.Avantages et inconvénients d'avoir un contrôleur pour plusieurs ressources

Ai-je raison? Si oui, comment puis-je le prouver. Si non pourquoi? Merci pour votre temps et vos idées!

Répondre

2

Oui, vous avez raison. En bref, selon single responsibility principle chaque contrôleur devrait faire un seul travail (traiter une seule URL).

Vous décrivez parfaitement les problèmes rencontrés par le contrôleur générique. Pensez aussi à ce qui se passe si un contrôleur s'adapte parfaitement à la règle générique en ce moment mais nécessite des choses spécifiques le mois prochain? Vous devez copier-coller le code, puis ajouter de nouveaux. Donc, après un certain temps, vous obtenez mess avec le contrôleur générique énorme et complexe et dupliquer le code. Personne ne pouvait prédire à quelle vitesse cela pourrait être puisque les besoins de l'entreprise pourraient être ajoutés de manière inattendue pour l'équipe de développeurs. D'autre part, votre coéquipier a raison de réduire le code en double. Au moins, tous les développeurs ne veulent pas passer leur temps à rendre le code plus propre. Et la plupart des gens doivent être reconnus (s'assurer que leur opinion a la valeur). Alors, ne lui envoyez pas loin :)

Ce que je pourrais recommander: Présentez-parent abstrait et utiliser l'héritage et Template modèle pour les contrôleurs similaires

/** 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} 
} 

En fait, je supposais solution similaire dans un projet. En utilisant les fonctions de l'EDI comme 'introduire la méthode' et 'passer au parent' j'ai refaçonné des dizaines de classes en une seule journée.

vous espérez ou votre coéquipier pourrait mettre en œuvre et de comparer cette idée dans quelques jours

+0

Merci, je vous apprécie vraiment trouvé le temps de faire la réponse! Mais je ne vois pas de différence architecturale entre servlets vanilla alors: C ce cas semble être similaire à l'utilisation du modèle de commande –

+0

1. Vous réduisez le code dupliqué en l'introduisant au parent AbstractController et 2. vous avez des points d'extension pour modifier behaivor (le différence que votre coéquipier suggère: contrôleur unique qui est difficile à étendre) – ADS

+0

et qu'en est-il comme alternative avoir un contrôleur avec plusieurs méthodes GET? –