In Java, sacrificheresti la sicurezza del tipo per un'interfaccia di programmazione migliore

3

Quando e perché dovresti generalmente sacrificare typesafety per un'interfaccia di programmazione migliore?

Lasciatemi fare un esempio: se avessi la possibilità di scegliere tra due aggregatori di eventi, quale preferiresti e perché?

Versione riflettente:

SomeEvent.subscribe(instance, "nameOfAMethod"); //method called via reflection
SomeEvent.fire(arg1, arg2);  //the firing could actually even be statically typed

Versione tipizzata staticamente:

EventSystem.getEvent(SomeEvent.class).subscribe(new EventHandler<Payload>() {
   public void eventOccurred(Object sender, Payload payload) {
       //event handler code here
   }
});

EventSystem.getEvent(SomeEvent.class).fireEvent(payload);

Si noti che in Java, a causa della cancellazione dei tipi, non è possibile implementare un'interfaccia generica con parametri di tipi diversi più di una volta e è necessario ricorrere a classi anonime o esterne per i gestori.

Ora il sistema di eventi riflessivi ha un'interfaccia utente migliore, ma si perde la sicurezza del tipo. Quale preferiresti? Vuoi creare classi di eventi vuote solo per il gusto di avere un simbolo, come Microsoft lo fa con PRISM nel suo aggregatore di eventi?

    
posta Falcon 27.03.2013 - 21:23
fonte

6 risposte

8

When and why would you generally sacrifice typesafety for a nicer programming interface?

Raramente se mai, e poi solo se il tipo non-sicurezza è stato trattato efficacemente in un altro modo.

Interfacce di programmazione verbose / scomode producono un minor numero di bug e bug di gravità molto inferiori rispetto alle interfacce senza caratteri nel mezzo delle lingue digitate. Perché siamo onesti, l'utilizzo della ricerca di stringhe o il lancio di Object è la sua orribile interfaccia di programmazione - ora hai un'interfaccia orribile e problemi di battitura.

    
risposta data 27.03.2013 - 21:49
fonte
6

Penso che il tuo esempio non confronti realmente le cose allo stesso livello di dettaglio, mentre questo sarebbe:

  1. versione tipizzata con stringhe:

    public void subscribeTo(Event event) {
         event.substribe(this, "handleEvent");
    }
    public void handleEvent(Object sender, Payload payload) {
        //do something
    }
    
  2. Versione tipizzata staticamente:

    public void subscribeTo(Event event) {
        event.substribe(new EventHandler<Payload>() {
            public void eventOccurred(Object sender, Payload payload) {
                //do something
            }
        });
    }
    

Quindi in sostanza il secondo non è criticamente più lungo. Ma come altri hanno sottolineato, è sia più veloce che più sicuro.

Se sei davvero preoccupato del conteggio dei token, non dovresti usare Java per iniziare;)

    
risposta data 27.03.2013 - 22:08
fonte
5

Dovresti sacrificare di più della semplice sicurezza. La riflessione è almeno un ordine di grandezza più lento in Java rispetto all'utilizzo di tipi forti.

Comunque è una falsa dicotomia. È possibile avere una buona API di programmazione senza sacrificare la sicurezza del tipo. Vedi link

    
risposta data 27.03.2013 - 21:49
fonte
3

In realtà ho implementato un sistema di eventi strongmente tipizzato simile al tuo una volta (in C #). Era orribilmente troppo ingegnerizzato e orribile da usare. Quando ho scoperto quanto fosse orribile, si era diffuso nella mia applicazione come un virus. Ci sono voluti per sempre un refactoring, e si sentiva bene quando se n'era andato.

Would you create empty event classes just for the sake of having a symbol, like Microsoft does it with PRISM in its event aggregator?

Ti piace?

applicationEvents.Foo.Subscribe(myHandler)

Sì. Decisamente sì. Perchè no? È molto più semplice, facile da capire e digita sicuro. Ogni nuovo sviluppatore avrebbe tutti gli eventi disponibili in un posto e non dovrebbe andare a cercare il codice sorgente per capire quali eventi sono disponibili e come usarli.

Non ha senso sacrificare la sicurezza del tipo quando non è necessario.

EDIT:

Se sembro eccessivamente aggressivo, mi scuso. Non intendo criticare il tuo design, sto solo lamentando il mio errore che ho fatto in passato, ed è molto simile a quello che stai facendo. Fai solo attenzione a non complicare eccessivamente le cose.

    
risposta data 27.03.2013 - 23:36
fonte
1

se hai il tempo ora fallo con il controllo del tipo. se il suo codice potrebbe durare fino a dicembre 2013, rimpiangeresti il metodo 1 più tardi, a meno che non sia un piccolo progetto e tu sarai l'unico a lavorarci sopra ... nemmeno allora se hai il tempo che vorrei andare con il dattiloscritto.

Perché? più chiaro, meno errori, più verboso sì, ma aiuterà a tenere a bada alcuni bug e questa è una buona cosa

    
risposta data 27.03.2013 - 21:48
fonte
-1

Non sono sicuro al 100% di ciò che questi due esempi dovrebbero fare, ma suppongo che un'alternativa sarebbe usare un enum. Immagino che il numero di stringhe consentite come "nameOfAMethod" sia limitato e potresti inserire la roba di classe anonima in quell'enumerazione.

enum Methods {
    NAME_OF_A_METHOD {
        EventHandler get(final Object instance) {
            return new EventHandler<Payload>() {
                public void eventOccurred(Object sender, Payload payload) {
                    //do something with instance
                }
            }
        }
    };

    abstract EventHandler get(Object instance);
}

E il tuo esempio potrebbe diventare:

EventSystem.getEvent(SomeEvent.class).subscribe(NAME_OF_A_METHOD.get(instance));

Non sei sicuro se sia direttamente applicabile al tuo caso d'uso ma hai un'idea.

    
risposta data 27.03.2013 - 23:58
fonte

Leggi altre domande sui tag