L'uso di classi parziali nasconde la complessità del controllore

7

Sono un programmatore abbastanza giovane, ma felice di imparare! :) Ho creato un'applicazione basata su WebApi e l'ho inviata per essere esaminata dal mio collega. L'ho recuperato con l'opinione che il modo in cui utilizzo le classi parziali nascondono la complessità e le dimensioni del controller. Sono davvero felice di sentire la sua opinione (è stato uno sviluppatore per più di 15 anni) perché lo rispetto. Ma mi piace sottoporre a controllo le opinioni, i punti di vista per vedere il maggior numero possibile di aspetti di un caso.

Puoi trovare esempi e schermate qui sotto sul codice.

I motivi per cui organizzo le mie cose sono i seguenti:

  • facile trovare il metodo del controller in solution explorer
  • un file (una classe parziale) contiene solo un singolo metodo e i suoi metodi di utilità interni (se ce n'è uno). Se un metodo di utilità viene utilizzato da più metodi di controller, li organizzo in un luogo comune
  • un controller è responsabile di un singolo endpoint (nell'esempio è possibile vedere il controller dell'ambiente responsabile del sottodominio dell'ambiente)
  • un metodo non è mai più lungo di una dimensione dello schermo comune per due motivi: a, odio scorrere verso l'alto e verso il basso, b, la logica di business del controller viene estratta in una libreria separata chiamata Application, il controller responsabile solo per chiamare il metodo dell'applicazione e restituire il risultato.

Il mio collega ha detto che, le classi parziali sono fantastiche quando una classe implementa più interfacce e puoi separare le implementazioni dell'interfaccia in classi parziali.

Le mie domande :

  • sono sufficienti informazioni e esempi di codice che ho fornito?
  • è un buon approccio che ho?
  • se non allora dove sono i punti deboli e perché?
  • qual è lo schema comune in queste aree, tuttavia, la revisione del codice è piuttosto un insieme comune di opinioni e cultura di un team / azienda
  • dove si trova il salutare trade-off tra leggibilità / gestibilità (in base al risultato della revisione del codice ho spinto un po 'questa parte) e nascondendo la complessità, violando le regole di responsabilità

File EnvironmentController.cs: è responsabile (contiene solo) per l'impostazione relativa alla dipendenza da dipendenza (iniezione costruttore), elenca i campi e ha il valore RoutePath.

[RoutePrefix("Environment/Environments")]
    public partial class EnvironmentController : ApiController
    {
        private IEnvironmentApplication environmentApplication;

        public EnvironmentController(IEnvironmentApplication environmentApplication)
        {
            this.environmentApplication = environmentApplication;
        }
    }

EnvironmentController.AddNewEnvironment.cs: responsabile solo del metodo AddNewEnvironment e dei possibili metodi di utilità interni, se disponibile

public partial class EnvironmentController
    {
        [HttpPost]
        [Route("AddNewEnvironment")]
        public HttpResponseMessage AddNewEnvironment([FromBody] string environmentViewModelString)
        {
            try
            {
                EnvironmentViewModel model = JsonConvert.DeserializeObject<EnvironmentViewModel>(
                    environmentViewModelString,
                    new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

                EnvironmentContract result = this.environmentApplication.AddNewEnvironment(model);
                return this.Request.CreateResponse(HttpStatusCode.Accepted, result);
            }
            catch (Exception e)
            {
                return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, e);
            }
        }
    }

Come appare in solution explorer.

    
posta SayusiAndo 02.06.2017 - 14:51
fonte

4 risposte

4

Il tuo approccio non è una pratica comune e potrebbe sollevare alcuni problemi, dal momento che Visual Studio è ottimizzato per funzionare in modo diverso.

easy to find the controller method in solution explorer one file ( one partial class ) contains only a single method and its internal utility methods (if there is any).

Visual Studio ha fornito i menu a discesa nella parte superiore del riquadro del codice che consentono di trovare rapidamente un metodo. Inoltre, VS supporta regioni che possono essere nominate, nidificate, nascoste e mostrate secondo necessità.

If a utility method is used by multiple controller methods, then I organize them in a common place

Che dire di un metodo di utilità precedentemente definito in uno dei tuoi file di metodo, ma in seguito scoprirai che devi chiamarlo da un nuovo metodo? Dovresti spostarlo. Non solo è un PITA, ma romperà la cronologia nel tuo repository di codice.

a method is never longer than a common screen size for two reasons

Nessun motivo necessario; i metodi brevi sono una buona pratica in generale. Un modo per mantenere i metodi brevi è di suddividerli in metodi più piccoli. Ma, usando il tuo approccio, c'è in realtà un disincentivo per suddividere metodi più lunghi, perché lo sviluppatore dovrà aggiungere un nuovo file ogni volta. Dio aiuta uno sviluppatore che sta ristrutturando il codice e vuole essere in grado di aggiungere / rimuovere / ristrutturare un sacco di metodi contemporaneamente.

L'unico vantaggio che posso pensare è questo: nell'approccio "un file", se uno sviluppatore decide di spostare un metodo (ad esempio spostandolo dal basso verso l'alto) può causare confusione tra le unioni di codice. Se esiste un solo metodo per file, questo è un non-problema. Ma, d'altra parte, se un nome di metodo cambia, sotto il tuo sistema cambierebbe anche il nome del file, e le unioni potrebbero essere saltate del tutto.

    
risposta data 03.06.2017 - 02:36
fonte
4

Sento che inizieremo una guerra religiosa per questo, ma dirò le mie opinioni sull'argomento.

Quello che stai facendo è ridurre sostanzialmente la complessità di una singola classe (in questo caso l'EnvironmentController) aumentando la complessità della gestione del progetto, generando diversi file in una singola cartella.

Se hai pochi controller, non vedo alcun aspetto negativo. Se si dispone di più controller su tale applicazione, questo può diventare rapidamente disordinato.

Ho alcuni progetti con oltre 25 controller, alcuni dei quali con oltre 10 metodi. Utilizzando il tuo approccio, sono oltre 250 i file da gestire, dove oggi ne gestisco solo 25 e la modifica dei metodi nell'IDE (VS.2015) non è affatto difficile, poiché la maggior parte dei metodi sono piccoli come i tuoi (meno di uno pagina).

Una cosa in più che mi rende un po 'a disagio con l'approccio di classe parziale è il fatto che mi piace sapere tutto ciò che il codice fa in un unico sguardo. Mi piace codice per la lettura e avere tutto in un unico file mi semplifica la vita.

Alla fine, potrebbe essere una preferenza personale. Se tu e il tuo team siete a vostro agio con l'approccio di classe parziale, quindi con tutti i mezzi per farlo.

Prova solo a con un unico approccio sulla base di codice . Sarà difficile per un nuovo arrivato abituarsi a diversi modelli di strutture di codice solo perché uno sviluppatore ha un capriccio diverso dall'altro. Mantenere un unico stile aiuta tutti i membri del team a comunicare.

Ricorda che ho detto che ho qualche progetto con oltre 25 controller? Ciò è stato fatto da un team di 6 sviluppatori, 2 anziani, 2 junior e 2 nel mezzo. All'inizio eravamo tutti d'accordo su un formato per organizzare il codice, dividere controllori, viste, modelli, DAL, ecc ... e ora tutti possono facilmente correggere ed estendere le funzionalità degli altri codici senza problemi, anche con stili di codifica diversi.

Nota a margine: dopo quasi 5 anni di collaborazione, è abbastanza chiaro per noi come interpretare il codice guardando semplicemente lo stile di ciascuno. Ogni sviluppatore ha mantenuto il proprio stile e personalità durante la codifica, ma la manutenzione non è un peso per nessuno nel team, perché le cose (metodi, azioni, regole aziendali, ecc.) Sono facili da trovare.

    
risposta data 02.06.2017 - 17:56
fonte
2

Questo potrebbe non essere un grosso problema, ma ciò che il tuo revisore ti ha detto è corretto: potresti nascondere la complessità del controller facendo ciò (e forse alcune cattive pratiche). E ciò che è stato già menzionato qui:

  • Questo non è pratico per i grandi controllori (1 classe con 10 metodi, contro 10 classi parziali)
  • Non è una pratica comune.

La maggior parte delle volte vorrai che il tuo codice sia facilmente comprensibile agli altri. E se hai un controller che ha troppi metodi, forse l'idea migliore sarebbe quella di rivedere e verificare se stai mettendo troppe responsabilità in un unico posto.

Un controller non è una classe "normale", in quanto (idealmente) non conterrà alcuna logica di business effettiva della tua applicazione (molto probabilmente chiamerà altre interfacce) e ciò significa che i tuoi metodi non saranno grandi. Con il tuo approccio finirai con un gruppo di 5 o 6 lezioni di linea.

Un modo migliore per farlo potrebbe essere quello di dividere per tipi di responsabilità, mettere tutto ciò che inserisce / aggiunge / aggiorna in un posto e tutto ciò che Ottiene / seleziona in un altro. Non è un approccio negativo, ma se stai facendo le cose bene in altre aree, e i tuoi metodi sono concisi e piccoli, non dovrai separarti.

    
risposta data 02.06.2017 - 18:42
fonte
1

Questo è simile a una domanda sull'uso di # region nel tuo codice per nascondere le cose. Il problema reale che il tuo collega suggerisce potrebbe essere correlato al fatto che il controller sta facendo troppo. Se un metodo di azione richiede un sacco di metodi di utilità per fare il suo lavoro, e quei metodi non sono correlati alla gestione della richiesta HTTP, allora ti mancano le classi - siano esse classi "di servizio" o "dominio" o qualsiasi cosa tu voglia chiamare loro.

Fondamentalmente il tuo collega sta dicendo che potresti violare uno o più dei principi SOLID della programmazione orientata agli oggetti.

Riempire troppo in una classe, e quindi frantumare quella logica in più file, renderà una reflex notturna a refactoring.

Le classi parziali erano un modo per separare il codice generato automaticamente dal codice scritto umano. Non è mai stato pensato per "sistemare" una classe che è diventata troppo grande e fa troppo.

    
risposta data 04.06.2017 - 21:47
fonte

Leggi altre domande sui tag