Ci sono degli svantaggi reali nel concatenamento di metodi autoreferenziali?


14

Di recente ho suggerito di implementare un metodo di concatenamento per una determinata classe in un determinato progetto in modo da migliorare la leggibilità del codice. Ho ottenuto una risposta "le interfacce fluide non devono essere implementate solo per comodità, ma per la semantica" e il mio suggerimento è stato respinto. Risposi che non stavo suggerendo un'interfaccia fluida, ma il metodo che si concatenava (entrambi possono essere confusi tra loro, letti in fondo) per migliorare la leggibilità e il comfort di programmazione, il suggerimento è stato abbattuto di nuovo.

Comunque, questo mi ha fatto pensare che forse potrei essere incorso in una cattiva pratica restituendo sempre "questo" in metodi che non dovrebbero restituire nulla (ad esempio setter).

La mia domanda è: l'applicazione della precedente convenzione può essere considerata una cattiva pratica o un abuso? Perché? Non penso che ci siano degli svantaggi prestazionali o ci sono?


2
Guarda questa domanda per una bella discussione programmers.stackexchange.com/questions/48419/…
KeesDijk,

@KeesDijk Grazie, ho modificato un po 'la mia domanda in modo che non sia simile a quella, poiché sono più interessato al caso di metodi concatenati della stessa classe
dukeofgaming

1
a SO, mi hanno detto che il concatenamento non è per C ++ - stackoverflow.com/questions/5760551/… - cosa ne pensi?
Kagali-san,

1
@mhambra Sembra che dovresti solo fare attenzione quando applichi il concatenamento dei metodi e definisci standard chiari per questo.
dukeofgaming

Risposte:


10

No

Come sottolinea Kent Beck , il codice viene letto molto più spesso di quanto non sia scritto.

Se il concatenamento dei metodi rende più leggibile il codice, utilizzare il concatenamento dei metodi.


1
Ottimo libro .. +1
Rein Henrichs,

5
MA , cosa succede se sei l'unico metodo di ricerca concatenamento più leggibile? Se questa è una questione di problemi stilistici, dovrai attenersi a una serie di convenzioni di codifica: ciò significa, scrivendo nello stesso modo del codice esistente, per coerenza.
coredump,

@coredump Sembra che gli OP abbiano già detto di farlo, ma penso che Steven lo stesse dicendo solo se il concatenamento dei metodi lo rende più leggibile.
Panzercrisis,

1
@Panzercrisis OP è stato invitato ad astenersi dall'usare il concatenamento del metodo per convenienza rispetto alla semantica. La risposta di Steven dice sostanzialmente "fallo comunque" e considera solo la leggibilità del codice OP da solo, senza considerare l'opinione o la coerenza del team. Cosa succederebbe se OP volesse riscrivere ogni classe esistente nel progetto in modo che si adatti ai suoi gusti riguardo alla leggibilità del codice? Ecco come capisco l'argomento convenienza / semantica: dovrebbe esserci un motivo "tecnico" per avere il concatenamento del metodo (tra l'altro, tale argomento sembra anche che l'altra persona stia inventando una scusa per le sue preferenze)
coredump

9

Sì, ci sono degli svantaggi

Il codice facile da leggere è buono, ma fai attenzione anche a ciò che comunica . Quando i metodi di un oggetto restituiscono sempre l'oggetto, comunica un paio di cose:

  1. Ho bisogno di una configurazione avanzata che non sia necessariamente ovvia nell'ordine in cui le cose dovrebbero essere impostate o configurate
  2. Ogni chiamata di metodo successiva si basa sull'ultima

Caso d'uso valido: query su database ad hoc

Le librerie di classi esistono in quasi tutte le lingue che consentono di interrogare un database senza ricorrere a codice SQL codificato. Prendi l'Entity Framework per .NET come esempio:

DBContext db = new DBContext();
List<Post> posts = db.Posts
    .Where(post => post.Title.Contains("Test"))
    .OrderBy(post => post.DateCreated)
    .ToList();

Questa è un'interfaccia fluida in cui ogni successiva chiamata di metodo si basa su quella precedente. Leggere logicamente queste chiamate ha senso nel contesto dell'interrogazione di un database.

Caso d'uso non valido: zucchero sintetico per l'impostazione delle proprietà

Ora usiamo lo stesso modello con la Postclasse:

public class Post
{
    public string Title { get; set; }
    public DateTime DateCreated { get; set; }
    public string Body { get; set; }

    public Post SetTitle(string title)
    {
        Title = title;

        return this;
    }

    public Post SetDateCreated(DateTime created)
    {
        DateCreated = created;

        return this;
    }

    public Post SetBody(string body)
    {
        Body = body;

        return this;
    }
}

Ora diamo un'occhiata a come useresti questa classe:

Post post = new Post()
    .SetTitle("Test")
    .SetDateCreated(DateTime.Now)
    .SetBody("Just a test");

Quando vedo questo codice, faccio immediatamente questa domanda: "Dopo aver chiamato SetBody, interroga il database? Devo chiamare un altro metodo per dire 'Ho finito?'"

Cosa comunicano le chiamate del metodo concatenato al codice usando la Postclasse?

  1. Ho una configurazione complicata
  2. Ogni chiamata di metodo si basa su quella precedente

È davvero vero? No. La Postclasse non ha una configurazione complicata. Impostare il titolo, la data di creazione e il corpo non si basano l'uno sull'altro verso un obiettivo finale più complicato. Hai schiacciato un piolo quadrato in un foro rotondo.

Lo svantaggio del concatenamento di metodi autoreferenziali è che si comunica che sono necessarie più chiamate di metodo per fare qualcosa e che ciascuna chiamata crea l'ultimo. Se ciò non è vero, il concatenamento dei metodi potrebbe comunicare la cosa sbagliata ad altri programmatori.

Quando i tuoi colleghi hanno detto:

Le interfacce fluide non dovrebbero essere implementate solo per comodità, ma per la semantica

Erano assolutamente corretti. Un'interfaccia fluida, o metodo concatenato, comunica qualcosa in sé e per sé che potrebbe non essere vero.


Ciò presuppone che il concatenamento dei metodi e la configurazione complessa vadano sempre di pari passo. Sono entità distinte e la presenza dell'una non dovrebbe farti assumere l'altro.
Jack,

Non è solo "configurazione complessa", ma anche "successive chiamate di metodo costruiscono la precedente". Il concatenamento di metodi ha una meta-comunicazione al riguardo che non è sempre fedele allo scopo di una classe.
Greg Burghardt,

1
Anche le successive chiamate di metodi che si basano su quelle precedenti sono distinte dal concatenamento di metodi, e non credo che trattare la sintassi del concatenamento di metodi come comunicazione forte per la semantica delle serie di operazioni secondarie dipendenti dall'ordine sia affidabile o utile. È una scorciatoia sintattica, niente di più. Usalo dove rende le cose più brevi e più leggibili.
Jack,

1
Capisco si pensa metodo di concatenamento è separata, ma sto dicendo che altri programmatori che non erano dentro la tua testa e utilizzare altre librerie di classi che non implementano il metodo di concatenamento per queste ragioni potrebbe finire per fare ipotesi circa il codice che sono vere. Tieni presente che il concatenamento dei metodi potrebbe implicare qualcosa che tu, l'autore del codice, non intendevi. Il codice che comunica chiaramente è importante tanto quanto il codice che è facile da leggere. Non sacrificare l'uno per l'altro.
Greg Burghardt,

1
When an object's methods always return the object, it communicates a couple of things- Penso che questa sia un'opinione personale; è difficile affermare che chiunque guardi ai metodi concatenati assumerà le stesse cose.
Sam Dufel,

1

Lo svantaggio principale è una perdita di chiarezza. Per esempio:

x.foo();
x.bar();
x.baz();

Poiché nessuna di queste affermazioni restituisce un valore (o se lo fanno, è stata ignorata), possono essere utili solo se producono effetti collaterali. Contrasto che a:

x.foo()
 .bar()
 .baz();

Innanzitutto, non è chiaro bare bazoperare su oggetti dello stesso tipo di x, a meno che non si sappia per certo che xla classe è l'unica classe con quei metodi. Anche se questo è il caso, non è chiaro su quali metodi operare xo su nuovi oggetti.

È utile evidenziare le parti del codice che presentano effetti collaterali, poiché è necessario tenere traccia di tali effetti collaterali per ragionare sul programma. Devi soppesare la potenziale perdita di chiarezza rispetto al potenziale guadagno nella facilità di scrittura del codice, ma considera anche che il codice viene letto più di quanto sia scritto.


0

Considera tutti gli elementi stilistici dei linguaggi di programmazione (al contrario del linguaggio macchina di codifica manuale) e indebolisce l'argomento "semantica non convenienza".

Gran parte di ciò che facciamo come ingegneri è fornire praticità sulla semantica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.