Be Brave

Un altro episodio della serie “cose che solo io trovo utili”

http://playersgonnaplay.it/be-brave-in-ruby-land

Conosco almeno un altro sviluppatore che lo avrebbe trovato utile HINT
HINT

:high-five:

2015-08-06 12:14 GMT+02:00 Elia S. [email protected]:

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! :slight_smile:

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 :smiley:
Preferisco un approccio meno invasivo :slight_smile:

2015-08-06 14:26 GMT+02:00 Elia S. [email protected]:

Mah, sono abbastanza serio :slight_smile:
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 :slight_smile: Un uso ad-minchiam è
potenzialmente letale.

2015-08-06 14:10 GMT+02:00 Maurizio De Santis
[email protected]:

Ok, allora rispondo seriamente :slight_smile:

Usare le eccezioni per controllare il flusso è un noto antipattern:
http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why

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:
http://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby

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: https://youtu.be/J1jYlPtkrqQ?t=6m57s


:: 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 :slight_smile:

Usare le eccezioni per controllare il flusso è un noto antipattern:
http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why

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:
http://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby

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! :slight_smile:

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 :slight_smile:
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:

https://github.com/tomstuart/monads

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 :stuck_out_tongue:

Comics time: http://existentialcomics.com/comic/49

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. :slight_smile:

PS. il tuo post oramai è una wiki :stuck_out_tongue:

ghgh, lo prendo come un complimento :slight_smile:

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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs