Si dovrebbe sempre sapere cosa sta facendo un'API semplicemente guardando il codice?

20

Recentemente ho sviluppato la mia API e con questo interesse investito nel design dell'API sono stato strongmente interessato a migliorare la mia progettazione dell'API.

Un aspetto che è emerso un paio di volte è (non dagli utenti della mia API ma nella mia discussione sull'argomento): si dovrebbe sapere solo guardando il codice che chiama l'API che cosa sta facendo .

Per esempio vedi questa discussione su GitHub per il discorso repo, va qualcosa come:

foo.update_pinned(true, true);

Solo guardando il codice (senza conoscere i nomi dei parametri, la documentazione, ecc.) non si può indovinare cosa farà - cosa significa il secondo argomento? Il miglioramento suggerito è di avere qualcosa come:

foo.pin()
foo.unpin()
foo.pin_globally()

E ciò chiarisce le cose (il secondo argomento era decidere se pin foo globalmente, sto indovinando), e sono d'accordo in questo caso il più tardi sarebbe sicuramente un miglioramento.

Tuttavia, credo che possano esserci casi in cui i metodi per impostare uno stato diverso ma logicamente correlato potrebbero essere meglio esposti come una chiamata al metodo piuttosto che separata, anche se non si saprebbe cosa sta facendo semplicemente guardando il codice . (Quindi dovresti ricorrere ai nomi dei parametri e alla documentazione per scoprirlo - cosa che personalmente farei sempre, non importa se non ho familiarità con un'API).

Ad esempio espongo un metodo SetVisibility(bool, string, bool) su un FalconPeer e riconosco solo guardando la linea:

falconPeer.SetVisibility(true, "aerw3", true);

Non avresti idea di cosa stia facendo. Sta impostando 3 valori diversi che controllano la "visibilità" di falconPeer in senso logico: accetta richieste di join, solo con password e rispondi alle richieste di scoperta. Dividere questo in 3 chiamate al metodo potrebbe portare un utente dell'API a impostare un aspetto della "visibilità" dimenticando di impostare altri che li costringono a riflettere solo esponendo l'unico metodo per impostare tutti gli aspetti della "visibilità" ". Inoltre, quando l'utente vuole cambiare un aspetto, quasi sempre vorrebbe cambiare un altro aspetto e ora può farlo in una sola chiamata.

    
posta markmnl 03.06.2014 - 06:27
fonte

2 risposte

27

Il tuo desiderio di non dividerlo in tre chiamate di metodo è completamente comprensibile, ma hai altre opzioni oltre ai parametri booleani.

Potresti usare le enumerazioni:

falconPeer.SetVisibility(JoinRequestOptions.Accept, "aerw3", DiscoveryRequestOptions.Reply);

O anche un enumerazione di bandiere (se la tua lingua lo supporta):

falconPeer.SetVisibility(VisibilityOptions.AcceptJoinRequests | VisibilityOptions.ReplyToDiscoveryRequests, "aerw3");

Oppure potresti utilizzare un Oggetto Parametro :

var options = new VisibilityOptions();
options.AcceptJoinRequests = true;
options.ReplyToDiscoveryRequest = true;
options.Password="aerw3";
falconPeer.SetVisibility(options);

Il pattern Oggetto Parametro ti offre alcuni altri vantaggi che potresti trovare utili. Rende facile il passaggio e la serializzazione di un set di parametri e puoi facilmente assegnare valori "predefiniti" ai parametri non specificati.

O potresti semplicemente usare i parametri booleani. Microsoft sembra fare tutto il tempo con l'API di .NET Framework, quindi potresti semplicemente scrollare le spalle e dire "se è abbastanza buono per loro, è abbastanza buono per me".

    
risposta data 03.06.2014 - 07:07
fonte
6

Ovviamente, ci sono sempre delle eccezioni alla regola, ma come hai spiegato bene da solo, ci sono alcuni vantaggi nell'avere un'API leggibile. Gli argomenti booleani sono particolarmente fastidiosi, in quanto 1) non rivelano un intento e 2) implicano che tu chiami una funzione, in cui dovresti effettivamente averne due, perché succederanno cose diverse a seconda della bandiera booleana.

La domanda principale è piuttosto: quanto impegno vuoi investire per rendere la tua API più leggibile? Più è rivolto verso l'esterno, più lo sforzo può essere facilmente giustificato. Se si tratta di un'API che viene utilizzata solo da un'altra unità, allora non è un grosso problema. Se stai parlando di un'API REST in cui prevedi di lasciare che tutto il mondo perda su di essa, allora puoi anche investire qualche sforzo in più per renderlo più comprensibile.

Per quanto riguarda il tuo esempio, c'è una soluzione semplice: a quanto pare, nel tuo caso la visibilità non è solo una cosa vera o falsa. Invece, hai un intero insieme di cose che consideri "visibilità". Una soluzione potrebbe essere quella di introdurre qualcosa come una classe Visibility , che copre tutti questi diversi tipi di visibilità. Se si applica ulteriormente il modello Builder per la creazione di questi, si può finire con il codice come il seguente:

Visibility visibility = Visibility.builder()
  .acceptJoinRequests()
  .withPassword("aerw3")
  .replyToDiscoveryRequests()
  .build();
falconPeer.setVisibility(visibility);
    
risposta data 03.06.2014 - 06:54
fonte

Leggi altre domande sui tag