Va bene usare le classi statiche mentre si crea un wrapper per l'API REST?

6

Sto consumando un servizio web in C # usando le API REST. Quindi, ho creato una classe wrapper per ogni endpoint. Sembra una buona idea implementare il wrapper usando la statistica. Questo rende il codice molto più pulito. Ad esempio, il consumo di un metodo su Albums endpoint si presenta come segue.

List<Album> albums = AlbumsEndpoint.GetAllAlbums();
Album myAlbum = AlbumsEndpoint.GetAlbum("myAlbumId");

D'altro canto consumare questa API usando un'istanza apparirebbe scomoda.

List<Album> albums = new AlbumsEndpoint().GetAllAlbums();
Album myAlbum = new AlbumsEndpoint().GetAlbum("myAlbumId");

Tuttavia, vedo molti SDK che usano questo modello. ( Ecco un esempio ). Qual è il punto di creare un'istanza qui? Non sarebbe un singleton? Questo non aggiunge un sovraccarico nel mantenere viva quell'istanza?
Quindi, va bene usare la statistica ovunque? Cosa mi manca non usando le classi di istanza?

    
posta akshay2000 21.07.2016 - 14:44
fonte

3 risposte

10

I metodi di classe statici sono fondamentalmente funzioni globali e sono considerati una cattiva idea nella progettazione OO. Il motivo per cui sono considerati negativi è difficile da vedere in un semplice esempio di codice in cui stai solo confrontando la differenza tra chiamare lo stesso metodo su un'istanza o sulla classe stessa.

Ma quando si entra in un progetto un po 'più complicato, le funzioni globali diventano un vero problema.

Prendi ad esempio il codice

albums = new AlbumsEndpoint().GetAllAlbums();

vs

albums = AlbumsEndpoint.GetAllAlbums();

Potrebbero sembrare molto simili ma nella parte superiore hai un oggetto e nel secondo hai una funzione globale ( AlbumsEndpoint.GetAllAlbums() è una funzione globale, in realtà non ha nulla a che fare con una classe, GetAllAlbums() potrebbe appendere qualsiasi classe non sarebbe importante)

Il codice oggetto può essere sostituito con una riga come questa

albums = myEndpointInstance.GetAllAlbums();

E questo funzionerà ancora. Cos'è myEndpointInstance ? È qualsiasi oggetto che soddisfa il contatto che fornisce un metodo GetAllAlbums . Questo oggetto può provenire da qualcos'altro, non deve essere istanziato qui nel codice (vedi Iniezione di dipendenza). Questo ti dà flessibilità, perché il codice non interessa quale tipo di oggetto myEndpointInstance è solo finché fornisce l'interfaccia prevista.

Potresti venire domani e scrivere un oggetto Endpoint completamente nuovo che funziona in modo completamente diverso e passare quell'oggetto qui dentro in questo codice. Il codice di cui sopra non gli interessa perché non gli interessa come l'oggetto endpoint funziona, a lui importa solo che funzioni. E tu non tocchi nessun altro che stava usando il diverso oggetto più vecchio. Tutto funziona perfettamente.

Ora vedi cosa succede quando invece di usare un oggetto usi una funzione globale. Hai legato questo codice alla funzione globale AlbumsEndpoint.GetAllAlbums() . Domani vuoi cambiare il modo in cui funziona il codice qui, ma non vuoi cambiare il modo in cui funziona da nessun'altra parte. Quindi devi creare una nuova funzione globale, quindi devi modificare il codice nel tuo metodo per utilizzare la nuova funzione globale.

Non così male in un piccolo codice base che raramente cambia. Mal di testa nel codice più grande che deve essere mantenuto.

Se usi gli oggetti hai la flessibilità che gli oggetti ti danno in quegli oggetti che agiranno su qualsiasi messaggio capiscano, il codice che chiama l'oggetto non ha bisogno di sapere che cos'è esattamente l'oggetto. Se invece usi le funzioni globali, leghi la chiamata della funzione a un'implementazione molto specifica di quella funzione, e cambiandola dopo che il fatto può essere difficile e introdurre dei bug. Dopo tutto è uno dei principali vantaggi del design orientato agli oggetti, in primo luogo

    
risposta data 21.07.2016 - 15:12
fonte
4

I framework / SDK probabilmente usano metodi di instantance perché rendono possibile l'integrazione della dipendenza, il che non è il caso dei metodi statici. Tuttavia, se non si utilizza DI, un metodo statico è il modo più semplice. BACIO.

    
risposta data 21.07.2016 - 18:48
fonte
1

Ogni volta che creo un metodo statico non banale da usare, finisco sempre per rimpiangerlo a causa di quanto possa essere difficile da testare. Soprattutto se lo si utilizza in tutto il codebase.

Esempio di un metodo statico perfettamente preciso:

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

Inoltre non ha alcuna dipendenza richiesta.

Ma quando hai qualcosa di simile:

public static User getCurrentUser() {
    var auth = SecurityContextHolder.getContext().getAuthentication();
    if (!auth.isAuthenticated()) {
        throw new UserNotLoggedInException();
    }

    return ((User) auth.getPrincipal());
}

Diventa solo un incubo. Ho usato questo metodo statico in modo troppo generico e, mentre rendeva il codice "più pulito", ha reso i test molto più difficili. Se puoi, ti suggerirei di usare DI se possibile.

Disclaimer: ho poca esperienza in SWE, quindi prendi questa risposta con un pizzico di sale. Sto solo condividendo i miei due centesimi.

    
risposta data 08.11.2018 - 18:06
fonte

Leggi altre domande sui tag