Un altro episodio della serie “cose che solo io trovo utili”
Conosco almeno un altro sviluppatore che lo avrebbe trovato utile HINT
HINT
Fino a poco tempo fa lavoravo su una code base Rails 3 composta per un
terzo di rescue nil, perché il capo si lamentava che c’erano troppi
errori… una tortura.
Insomma, questa è roba da professionisti, i niubbi non provino a rifarla
a casa!
Inviato da iPhone
Più che da professionisti, è una cosa da fuori di testa xD fin quando si
scherza si scherza, ma exceptions as control flow… brividi!
Il giorno gio 6 ago 2015 14:05 Luca P. [email protected]
ha
scritto:
Mi permetto di correggere, perché qui stiamo parlato di missed exception
control to keep the flow ◕ ◡ ◔
Giusto, ascrivibili al gruppo “usare le eccezioni per far altro che non
sia
gestire eccezioni”
Il giorno gio 6 ago 2015 14:14 Elia S. [email protected] ha scritto:
class NilClass
def method_missing(*)
self
end
end
Ecco, monkey patch di questo tipo mi fanno davvero paura
Preferisco un approccio meno invasivo
2015-08-06 14:26 GMT+02:00 Elia S. [email protected]:
Mah, sono abbastanza serio
Il caso d’uso è ben circoscritto e sarei ben lieto di usare soluzioni
altrettanto concise anche se ad ora non ne vedo.
La try chain è scomoda e poco leggibile quando si gestiscono accessi ad
Hash:
params.try(:[], :profile).try(:[], :resume).try(:tempfile).try(:path)
Così come la boolean chain:
if params[:profile] && params[:profile][:resume] &&
params[:profile][:resume].try(:tempfile).try(:path)
Come affronteresti questo specifico caso?
@luca: da maneggiare con attenzione, ovviamente Un uso ad-minchiam è
potenzialmente letale.
2015-08-06 14:10 GMT+02:00 Maurizio De Santis
[email protected]:
Ok, allora rispondo seriamente
Usare le eccezioni per controllare il flusso è un noto antipattern:
Ho avuto a che fare con questo tipo di approccio con un collega a cui
piaceva, e l’aveva usato un bel po’ in giro nel codice di un progetto.
Dopo
averne parlato siamo giunti alla conclusione che crea più problemi che
altro, per i seguenti motivi:
- viola il principio di minima sorpresa: le eccezioni sono fatte per
gestire errori, non per gestire un flusso previsto - la logica ha la priorità sulla concisione: se del codice richiede
della
complessità logica in sé, non puoi sacrificarla per amor di concisione - ti perdi le eccezioni rescuate: questo è un grande problema, perché se
la
parte di codice wrappata genera un’eccezione che non pensavi potesse
spuntare fuori te la perdi, non viene loggata e cominciano a verificarsi
i
tanto classici quanto temuti fenomeni paranormali informatici
Inoltre, nel codice postato usi rescue Exception, che rescua anche da
eccezioni di sistema:
Nel caso da te citato userei una delle soluzioni che hai scritto, magari
estraendola a metodo privato. Sarà meno elegante, ma è più logica e
manutenibile.
Il giorno gio 6 ago 2015 14:29 maurizio de magnis <
[email protected]> ha scritto:
+1 per StandardError al posto di Error (ho aggiornato il post) e +1
anche
per il fatto di non usare le eccezioni come strumento di gestione del
flusso di codice.
Ora, nel caso menzionato gestisco solo questi fallimenti:
- NoMethodError: undefined method `[]’ for nil:NilClass
- NoMethodError: undefined method `XXX’ for “YYY”:String
L’obiettivo che mi sono posto, limitando volontariamente lo scope di
Brave.be, è ottenere una syntactic sugar per recuperare un valore
nestato
in una struttura dati. Di fatto, a parte l’essere più o meno bello da
vedere, non comporta le stesse sorprese della magia nera da
Metaprogrammazione.
2015-08-06 15:13 GMT+02:00 Maurizio De Santis
[email protected]:
FY(possible?)I: Tom Stuart - Refactoring Ruby with Monads - YouTube
–
:: Andrea P.
:: email: [email protected]
:: mobile: +44 747 3090534
On 6 August 2015 at 14:13:46, Maurizio De Santis
([email protected]) wrote:
Ok, allora rispondo seriamente
Usare le eccezioni per controllare il flusso è un noto antipattern:
Ho avuto a che fare con questo tipo di approccio con un collega a cui
piaceva, e l’aveva usato un bel po’ in giro nel codice di un progetto.
Dopo
averne parlato siamo giunti alla conclusione che crea più problemi che
altro, per i seguenti motivi:
- viola il principio di minima sorpresa: le eccezioni sono fatte per
gestire errori, non per gestire un flusso previsto - la logica ha la priorità sulla concisione: se del codice richiede
della
complessità logica in sé, non puoi sacrificarla per amor di concisione - ti perdi le eccezioni rescuate: questo è un grande problema, perché se
la
parte di codice wrappata genera un’eccezione che non pensavi potesse
spuntare fuori te la perdi, non viene loggata e cominciano a verificarsi
i
tanto classici quanto temuti fenomeni paranormali informatici
Inoltre, nel codice postato usi rescue Exception, che rescua anche da
eccezioni di sistema:
Nel caso da te citato userei una delle soluzioni che hai scritto, magari
estraendola a metodo privato. Sarà meno elegante, ma è più logica e
manutenibile.
Il giorno gio 6 ago 2015 14:29 maurizio de magnis <
[email protected]> ha scritto:
params.try(:[], :profile).try(:[], :resume).try(:tempfile).try(:path)
potenzialmente letale.casa!
Conosco almeno un altro sviluppatore che lo avrebbe trovato utile
Maurizio ಠ_ಠ My profile
Ml mailing list
[email protected]
[email protected]
http://lists.ruby-it.org/mailman/listinfo/ml
Ml mailing list
[email protected]
http://lists.ruby-it.org/mailman/listinfo/ml
Ecco, questa è una soluzione molto, molto elegante
Nonostante non sia un patito di method_missing, lo preferisco ad un
begin/rescue
+1
2015-08-06 15:26 GMT+02:00 Andrea P. [email protected]:
La mancanza di Optional/Maybe nel 2015 in un linguaggio come Ruby è
piuttosto preoccupante.
2015-08-06 15:59 GMT+02:00 maurizio de magnis
[email protected]:
@maurizio: Revolution! XD
ecco il repository con l’implementazione di Tom S. delle monad
Optional, Many ed Eventually:
2015-08-06 16:09 GMT+02:00 Maurizio De Santis
[email protected]:
O se vuoi solo un wrapper per quei due casi… fai un wrapper!
comunque +1 per Tom S.
PS. il tuo post oramai è una wiki
Comics time: The Philosophy of the Science of Poker - Existential Comics
Il giorno gio 6 ago 2015 16:03 Stefano P.
[email protected]
ha scritto:
Piccola nota: dovrei convertire params in una OpenStruct (o similare)
per
poter gestire la chain tramite Optional.
2015-08-06 16:59 GMT+02:00 Elia S. [email protected]:
O se vuoi solo un wrapper per quei due casi… fai un wrapper!
Mmh, espandi un po’. Cosa intendi?
comunque +1 per Tom S.
Già, tanta roba.
PS. il tuo post oramai è una wiki
ghgh, lo prendo come un complimento
class InfiniteHash
def initialize(hash = nil)
@hash = hash
end
def value
@hash
end
def [] key
value = @hash[key]
return Value.new(value) unless value.nil? or value.is_a?(Hash)
InfiniteHash.new(value)
end
class Value < Struct.new(:value)
def [] key
self
end
end
end
hash = {a: 1, b: {c: 2}}
p InfiniteHash.new(hash)[:a].value
p InfiniteHash.new(hash)[:b][:c].value
p InfiniteHash.new(hash)[:b][:c][:d][:e][:f].value
>> 1
>> 2
>> 2
Ma tutto sommato mi sa che una specializzazione di quello che fa TS