Dichiarare esplicitamente la proprietà in Java

4

Mi chiedo se esiste un buon modo per dichiarare esplicitamente (non necessariamente imporre) il trasferimento di proprietà delle risorse in Java.

Il mio problema è fondamentalmente questo: ci sono risorse che devono essere ripulite (si pensi a AutoClosable ) che sono immesse dalla dipendenza in un'istanza dal suo creatore. Voglio comunicare al creatore che l'istanza si assume la piena proprietà e responsabilità per detta risorsa (a livello di sorgente, dato che sono abbastanza sicuro che non c'è modo di applicarlo in Java).

Attualmente sto intrattenendo l'idea di utilizzare una classe wrapper Owned<T> , che fondamentalmente si comporta come un Optional che deve sempre essere riempito.

Vale la pena? Dovrei semplicemente inserire un commento nel JavaDoc? O c'è un modo comune per gestirlo?

    
posta Kolja 22.09.2016 - 21:18
fonte

2 risposte

5

Penso che dovrebbe essere possibile implementarlo utilizzando le annotazioni @Owned per i parametri di funzione e return . Chiunque chiama new possiede inizialmente una risorsa. Se possiedi una risorsa, devi o distruggerla o darla via - sia da return come una risorsa @Owned o passandola a una funzione che ne rivendica la proprietà. Dopo aver rinunciato alla proprietà, non devi più utilizzare la risorsa. Se hai passato una risorsa come parametro non annotato come @Owned , non devi distruggerlo e non devi passarlo a funzioni che ne rivendicassero la proprietà. Per definire "distruzione", vorremmo probabilmente un'annotazione @Destroys per i metodi su una risorsa.

L'idea è fondamentalmente presa da Rust (disclaimer: non ho mai effettivamente programmato in Rust) che credo che sia strongmente ispirato al C ++. Penso che il sistema di annotazione in Java dovrebbe essere abbastanza strong da agganciare un analizzatore statico che applicherebbe la correttezza del tuo programma con zero overhead di run-time. Dal momento che non ho mai scritto un plugin per analizzatore statico per il compilatore Java, non ho idea di quanto sarebbe difficile / facile. Un problema più pratico che dovresti superare è che molte funzioni della libreria standard e di terze parti non si preoccupano delle tue annotazioni e dovresti trovare un meccanismo per informare il tuo analizzatore che sai cosa stai facendo. (Come metodi "non sicuro" @Owned T makeOwned(T t) e T makeNotOwned(@Owned T t) che "escludono" l'annotazione o supporto per un file di annotazioni esterno per caricare le annotazioni per gli intrefaces di terze parti.)

Penso che questo sarebbe un progetto accademico molto interessante ma temo che quasi certamente si trasformerà in un gigantesco crollo temporaneo se applicato a qualsiasi progetto pratico.

    
risposta data 22.09.2016 - 23:17
fonte
2

Non sono sicuro che ci sia un modo comune per gestirlo, perché ci vuole un sacco di lavoro e disciplina per farlo bene, e la maggior parte delle persone preferisce lasciare aperta la possibilità di errore piuttosto che disciplinare se stessi.

Mi piace sperimentare, specialmente con metodi per ridurre la possibilità di errore, quindi di tanto in tanto ho utilizzato varie tecniche.

Una tecnica è il modello "hand-off": ogni volta che una risorsa chiudibile viene passata dall'oggetto A all'oggetto B, viene anche passato un flag booleano "handoff", che dice all'oggetto B se deve disporre della risorsa quando è fatto con esso. Non ne sono molto soddisfatto, perché non è affatto applicabile: il detentore della risorsa può fare esattamente l'opposto di ciò che suggerisce il parametro "handoff".

Un'altra tecnica che è attuabile a metà strada sta usando il sistema di tipi nella sua massima estensione: se ti viene data una risorsa usa e getta, devi sempre eliminarla. Se non hai intenzione di smaltirlo, allora non dovrebbe essere usa e getta. In altre parole, se non è usa e getta, non puoi eliminarlo.

Sfortunatamente, JRE non è stato progettato con questo in mente, quindi devi rifare un sacco di classi e interfacce per farlo funzionare. Ad esempio, InputStream è una classe che implementa Closeable . Quindi, se dovessi usare la tecnica del tipo system con questa classe così com'è, significherebbe che ogni volta che passassi un InputStream a qualcuno dovresti baciarlo ciao ciao.

Quindi, classi come InputStream dovrebbero essere rielaborate come segue:

Viene introdotta una classe InputStreamResource , che incapsula completamente la classe InputStream originale di JRE; Viene introdotta una nuova interfaccia InputStream , contenente tutti i metodi della classe originale InputStream , ad eccezione di Close() ; quindi, InputStreamResource viene creato per implementare la nuova interfaccia InputStream e l'interfaccia Closeable . Pertanto, chiunque accetti un InputStreamResource promette di chiuderlo, mentre chiunque accetti un'interfaccia InputStream non può semplicemente chiuderlo, perché non è Closeable .

    
risposta data 22.09.2016 - 22:28
fonte

Leggi altre domande sui tag