Visualizza post

Questa sezione ti permette di visualizzare tutti i post inviati da questo utente. N.B: puoi vedere solo i post relativi alle aree dove hai l'accesso.


Post - riko

Pagine: [1] 2 3 ... 571
1
Cavolo, il necroposting ti ha preso la mano eh?

Macche' necro... la risposta e' stata scritta alla massima velocita' che potevo...

> Cominciamo a metterci d'accordo sul fatto che esistono vari livelli di esperienza e/o necessità a cui corrispondono diversi problemi che si scoprono. E magari si risolvono. Se quando sviluppi sistemi complessi in team grandi vien fuori che i named arguments sono una rogna (e non stento a crederlo da quel poco che ho visto/capito), allora a quel livello non userai i named arguments. Ma non me la sento di dare la colpa a Python perché ha i named arguments.

Non sono stato chiaro. In molti linguaggi comuni il *nome* degli argomenti non e' parte della signature del metodo (e in Python stesso e' irrilevante quando usati in modo posizionale).
Il problema e' che *tutti* gli argomenti possono essere chiamati per nome il che vuole dire che in Python il *nome* degli argomenti e' *sempre* parte della signature del metodo.
Quindi un cambiamento apparentemente innocuo come copy(src, dst) nel piu' esteso (a volte, coding guidelines etcc etc etc) copy(source, destination) andrebbe trattato come un braking api change ma *non appare* come tale.

Io credo che anche molti sviluppatori che sono perfettamente consci che le loro funzioni possono venire chiamate con parametri per nome o per posizione non realizzino che quello in realta' e' un breaking change.
Se invece ogni argomento potesse essere chiamato *solo* per nome o per posizione il problema non sussisterebbe.

Ora non e' un dramma (ma ora rifletti che invece quando scrivi in C questo comportamento dipende se usi PyArg_ParseTupleAndKeywords oppure solo PyArg_ParseTuple).

Il mio punto e' che tutta la parte intorno ai named arguments ha un po' di problemi di suo e che sembra un'idea molto buona finche' uno non si ferma a riflettere.

> . Cioè sì, *potrei* fare un ulteriore layer solo per astrarre questa necessità. Ma andiamo, dai: un OrderedDict va benone per questo. Tutto il resto mi sembrerebbe una inutile complicazione.

Oh, ma figurati, certo. Ci sono usi occasionali per OrderedDict. Ora, detto fra noi... sarebbe sempre il mestiere di un sorted dict, a volerla dire tutta. Poi vabbe' ti hanno dato OrderedDict e lo fai con quello.
Io pero' avevo tanto in mente tutta sta storia delle serializzazioni...

E poi prendiamo il caso dei named arguments ordinati. Certo, *io* non ne ho mai sentito la necessità. E però non sono d'accordo con te:
>  il punto e' che quando si parla di named argument
> quello che vuoi fare e' proprio "ignorare" l'ordine.

> Già, a meno che io non sia l'autore di un'estensione per un editor come questa https://packagecontrol.io/packages/AutoDocstring che ispeziona i parametri della funzione e produce automaticamente uno stub per la docstring, ecco ALLORA forse mi piacerebbe presentare anche i kwargs nell'ordine giusto, no? Eh. (Questa è anche una risposta alla tua domanda "ma ci fate qualcosa con python?, il problema è stampare gli argomenti?": di tanto in tanto...)

E ovviamente, visto che stai scrivendo un editor di testo, cosa cavolo ti impedisce di andare a parsarti il sorgente e mettere gli argomenti nell'ordine giusto?
E scusami... vorrei vederci chiaro. Tipo il parser builtin con Python *ovviamente* conserva l'ordine degli argomenti della funzione.

In [3]: ast.parse('foo(bar="bar", baz="baz")')
Out[3]: <_ast.Module at 0x106864278>

In [4]: t = _

In [5]: ast.dump(t)
Out[5]: "Module(body=[Expr(value=Call(func=Name(id='foo', ctx=Load()), args=[], keywords=[keyword(arg='bar', value=Str(s='bar')), keyword(arg='baz', value=Str(s='baz'))]))])"

In [6]: ast.dump(ast.parse('foo(baz="bar", bar="baz")'))
Out[6]: "Module(body=[Expr(value=Call(func=Name(id='foo', ctx=Load()), args=[], keywords=[keyword(arg='baz', value=Str(s='bar')), keyword(arg='bar', value=Str(s='baz'))]))])"
[/quote]

Poi per ovvi motivi non vuoi usare quella li, e infatti il tizio secondo me se l'e' scritta. E allora se la scriva giusta? :)


> https://stackoverflow.com/questions/4459531/how-to-read-class-attributes-in-the-same-order-as-declared Nota che questo è proprio un esempio di "cosa che si rompe" (e si è sempre allegramente rotta, dall'alba dei tempi delle mataclassi) se *non* usi OrderedDict (cioè, se non ci sbatti il muso e poi impari a usare OrderedDict).

E ancora una volta, tutta questa roba si fa con un sorted dict, se vuoi. Un treemap, come lo chiamavamo prima.

[quote]
> Un problemino dei named parameters?
> se qualcuno cambia copy(a, b) in copy(src=a, dst=b)
> il mock si rompe potenzialemente

Uh, che cosa vuol dire? Che se cambi la signature di una funzione potrebbe rompersi il suo mock? Beh sì, credo che sia vero *in generale*. Stai cambiano la signature di una funzione, caspita. Che tutto il resto intorno si rompa, beh un po' me lo aspetto.
[/quote]

Ah, pensavo fosse piu' chiaro. No, quello e' il call site. Ovvero, se in un punto interno del mio codice cambio il modo in cui chiamo copy, mock si rompe. Ora voglio essere chiaro, non e' che il fatto che mock si rompa e' un problema di Python. Il problema e' che questa cosa dei named parameter introduce *tante* piccole ambiguita'. Quindi se stai usando mock devi stare attento a come fai le asserzioni. Mock decide di essere esplicito (correttamnte secondo zen), ma il punto e' proprio che sotto molti punti di vista le chiamate copy(a,b) e copy(src=a, dst=b) sono la stessa cosa. Ma non sono *davvero* la stessa cosa. E' un dramma? No. E' una cosa che ti fa perdere un po' di tempo di tanto in tanto.

[pythoncode]In [8]: m = mock.MagicMock()

In [9]: m(a=1, b=1)
Out[9]: <MagicMock name='mock()' id='4404144336'>

In [10]: m.assert_called_once_with(1, 2)[/pythoncode]

> Poi certo, se intendi dire: "non sembra che sto cambiando la signature, ma in python è così e questo causa confusione e fa perdere tempo", allora sì certo. La soluzione è non usare named arguments, hai ragione.

E sfortunatamente non e' cosi'. Perche' l'uso (o no) dipende da chi mi chiama, non da me. Che io sappia l'unico modo in pure python di impedire che ti chiamino con named argument e' fare qualcosa come (o varianti sul tema) -- ma ti perdi tanto:

In [11]: def f(*args):
    ...:     a, b = args


> Maddai... davvero io non ne capisco molto, ma ultimamente vedo (per esempio) tutta questa ansia di produrre build deterministiche...

Non capisco di cosa parli... ma potrebbbe essere che semplicemente tanti dei niubbi che prima finivano in altri lidi ora arrivano qui?

> Ora, il punto è che tutto quello che origina da un dizionario e finisce in qualche modo in un... file di testo (per dire... un output serializzato), non è deterministico.

Boh... se mi serve un certo ordine usero' quell'ordine. Se non mi serve, non lo usero'.

> Non è bello, in certi casi, avere un dizionario ordinato? E non ci pensi più.

Non ci pensi piu'? Abbiamo deciso che l'ordine di output e' importante (se no non lo stiamo facendo).
Per cui ... o speriamo che il dizionario prodotto in un altro punto del codice, magari giorni prima, abbia ancora l'ordine che vogliamo in output oppure lo dobbiamo... riordinare. Non vogliamo farlo? Bene: abbiamo fatto si che un vincolo su uno specifico caso di serializzazione si propaghi fino alla creazione dell'oggetto. E preghiamo forte che non dobbiamo serializzarlo con un altro ordine da un'altra parte. Se no siamo fottuti (oh, certo, possiamo deciedere che uno dei due e' di prima classe... poi i tiZi che scrivono gli altri use-case si chiedono perche' a loro e' andata male).

Ah... oppure ce ne fottiamo e riordiniamo il dizionario ordinato (o ne creiamo uno nuovo con l'ordine giusto). E allora chissene frega dell'ordine del dizionario: ordinero' le chiavi mano mano che le tiro fuori, no?

Il punto e' che se per te e' ok che un vincolo su come devi serializzare una struttura determina come la devo creare, abbiamo visioni su quello che sia un buon design non compatibili. E per me e' talmente ovvio che e' una cattiva idea  he non riesco nemmeno a spiegarti perche' (cioe', posso nominare principi, pattern... ma e' tutta roba nota che sono sicuro tu sappia: se non ti hanno convinto quegli autori, non ho l'arroganza di riuscirti).

Non e' che mi dia fastidio il dizionario ordinato. Sono sicuro che troviamo use case in cui davvero e' la cosa comoda (magari perche' quello che ci interessa e' appunto l'ordine di inserimento). Il problema e' che la maggior parte degli use-case che sento per lui sono use-case in cui viene abusato e di fatto quello che interessa e' che abbia un certo ordine.
In particolare, crei una dipendenza fra come costruisci l'oggetto e come lo visiti (perche' stai spingendo questa logica nel concetto, di per se agnostico, di mappa).

> Oppure più banalmente (e in un altro campo), se faccio i test con doctest, che per forza di cose non può far altro che confrontare stringhe, mi piacerebbe eccome avere dei dizionari order-preserving, o no?

Ok. Dimmi quando questa cosa ha fine. Perche' qui il pattern e' giustifichiamo cattive idee mostrando che se ho altre cattive idee queste diventano piu' semplici. Poi mi si chiede perche' gradualmente mi allontano da Python. :)

Cioe' doctest grandioso. Il suo scopo principe per cui e' davvero grandioso e' che risolve brillantemente il problema in cui ho del codice nella documentazione e lo devo tenere valido. E' egregio e se non ci fosse il mondo sarebbe piu' complicato. Ovviamente *puoi* pensare di usarlo per i test. Tipo se hai una funzione di 10 righe con un happy path e due failure mode. E lo fai quando l'alternativa sarebbe "no test".

Ma ancora uan volta... a me non capita di scrivere funzioni di 10 righe che vivono in isolamento (tipo prendono due interi e una stringa). Insomma... nella maggior parte dei casi voglio pytest. E grazie: contestalo. Tutti stronzi quelli che hanno scritto pytest perche' tanto basta doctest, no? Ma oggettivamente, basta un file pieno di assert una dietro l'altro, no? "basta".

E ora vogliamo ordinare i dizionari per rende piu' facile un'anti-pattern: quello di verificare le strutture dati transformandole in stringhe e poi contollando che sono uguali. Di questo stiamo parlando alla fine... :)

[quote]
E poi ci sono delle volte in cui proprio non ho capito se sono io scemo o cosa:

> Io trovo il discorso: ho implementato gli argomenti
> delle funzioni con un dizionario, ma il dizionario
> non va bene, quindi modifico tutti i dizionari
> completamente delirante. Se per te questa linea di
> ragionamento e' sensata, non c'e' spazio per discutere.
> Abbiamo una visione di software engineering drammaticamente diversa

> Ma no, dai. (Ok, qui potrei dirti che se i core devs di python - Guido compreso - hanno preso questa decisione, proprio deliranti magari non sono... ma sarebbe un falso argomento, si capisce).
[/quote]

Puoi perfino prendere una decisione giusta per motivi deliranti. O prendere una decisione sbagliata per ottimi motivi.
Specificamente ha senso ottimizzare i dizionari? Si, sempre. O meglio: ha senso ottimizzare le cose sul path delle chiamate dei metodi? Certo.
In certi contesti ci si pone perfino il problema di non avere metodi virtuali perche' sono lenti (e.g., C++, Rust). Java minimizza il problema per via del JIT. Python paga tutto. Vogliamo fargli pagare un po' meno. Buona idea. "Tutti" chiamano metodi. Non e' sempre critico, ma e' un buon posto dove ottimizzare

> A parte che non hanno modificato i dizionari *per* ordinare i named arguments... diciamo che è stato un concorso di ragioni... ma anche se fosse così: non c'è qualcosa di sbagliato in quello che scrivi?

Boh, forse. Ovviamente se pensassi di si, non lo farei. ;)
E no, penso che forzare tutti i dizionari di Python ad essere ordered dict per questa cosa non e' una buona idea.

> Non è "modifico tutti i dizionari"... ma è "estendo" i dizionari, o no? Stiamo violando il principio di sostituzione qui? Tutto quel che potevi fare con i vecchi dizionari puoi farlo anche con i nuovi, o no? C'è un problema che non vedo?

Il mio problema non e' che scelgano un comportamento fra i tanti implementation defined. Il mio problema e' che questo diventi un vincolo. E capisco: nel momento in cui per alcuni anni tutti sono abituati che i dizionari sono ordinati (e la gente ci farebbe affidamento), non sarebbe comunque possibile tornare indietro facilmente, anche senza renderlo ufficiale.

Forse verrebbe da dire che il fatto che tutto il macchinario di OOP di Python si fondi sulla stessa struttura dati user-facing che usiamo in 27 altri modi e posti non e' la migliore idea (diverso pattern d'uso?). E ovviamente poi siccome questa cosa del dizionario e' molto leaky come abstraction questa cosa potrebbe essere inevitabile.

Diciamo che arriviamo al punto critico: ho scritto Python per piu' di 15 anni. Quello che si fa con un computer pero' cambia. Anche le cose in cui una piattaforma e' forte e debole cambiano con gli anni (e.g., il GIL non era davvero un problema su macchine con 2 core, adesso e' un dramma e si s

[quote]
Beh, no. Ci sono due aspetti separati qui: primo, i named arguments. Su questi, il vincolo implementativo non è stato introdotto adesso, ma proprio dall'inizio. Se li implementi con un dizionario, ti porti dietro i difettucci dei dizionari, e sei destinato a cambiare la loro semantica tutte le volte che cambi i dizionari. E' un peccato, certo, ma un peccato antico non recente. E da un punto di vista di design, ci sono pochi dubbi che i named arguments *dovrebbero* essere ordinati: a parte le applicazioni pratiche (metaclassi, etc), averli non-ordinati è un attrito cognitivo inutilmente crudele (e già il sistema dei parametri delle funzioni in Python non è proprio una perla di chiarezza, diciamolo). Quindi ben venga la patch tardiva.
[/quote]

E anche qui... il problema in effetti sono i named arguments. Perche' mentre viene istintivo considerarne l'ordine quando si definisce la funzione (anche perche' e' sempre possibile chiamarla senza i nomi), invece nei punti di chiamata l'ordinamento non e' rilevante (e meno male, visto che e' uno dei "vantaggi" che i named arguments portano).

Secondo, i dizionari. Certo, adesso è stato introdotto un vincolo implementativo: se in futuro, per dire, qualcuno dovesse fare un dizionario ancora più performante *ma* non order-preserving, non potrebbe più inserirlo dentro python. Occhei, sono d'accordo.

>  Ma d'altra parte, l'evoluzione verso un dizionario order-preserving è nella natura delle cose,

No. Non e' nella natura delle cose. E' una scelta come un'altra. Quella che fa Ruby, per esempio. Go prende la scelta opposta: *randomizza* l'ordine di enumerazione. A me pare un po' estremo, ma certamente evita il problema che qualcuno possa pensare per piu' di 10 nanosecondi che una mappa e' una struttura ordinata.

> Ora so che adesso ti metti a smattare, ma a un certo punto un linguaggio vale anche perché è usato, e se la gente si aspetta i dizionari order-preserving, vuol dire che è una soluzione comoda in un certo numero di casi d'uso.

Tutt'altro. Questo e' il punto chiave (non sono d'accordo sul "vale se e' usato", da persona che pensava che python valesse quando non era usato). E non sono d'accordo nemmeno che sia una soluzione comoda. Tutti i casi d'uso presentati si risolvono con un sorted dict. Il punto e' che questo e' un testamento. Si sono accorti che con l'utenza odierna di Python l'attrito cognitivo era troppo. E *fanno* bene a farlo, se la situazione e' questa. Pero' sarebbe anche molto triste. O forse nemmeno. E' triste perche' dopo tutto sapere qualcosa di strutture dati non serve ad una mazza. Cioe', serve di tanto in tanto, figurati. Ma non particolarmente piu' di altre cose.

E si, mi sono amminchiato su questa cosa. Python 3.7 e' davvero meglio di 2.7.  E oggettivamente nella pratica non mi cambia *nulla*. Mi avrebbe fatto piu' piacere un sorted dict che mi avrebbee dato cose che dict non mi da? Si. Certo. Me lo posso sempre scrivere, voglio dire. :)

[quote]
Guarda javascript (ecco, adesso smatti: te l'avevo detto). Per anni la gente ha ciclato su Object aspettandosi che fosse order-preserving. Adesso finalmente hanno Map: il risultato è che tutti usano Map nello stesso modo in cui (speravano di) usare Object. Per anni quelli di Chrome sono andati avanti a litigare con gli sviluppatori su questo (https://bugs.chromium.org/p/v8/issues/detail?id=164#c83 ma tutto il thread...), mentre mettevano patch per sistemare piccoli bachetti, cose da nulla capisci... tipo che *il feed di Facebook* su Chrome non veniva ordinato giusto... Ma se alla fine pure i devs di Facebook sono dei niubbi che non sanno usare le strutture-dati corrette, non so, qualcosa di sbagliato ci sarà. Alla fine, devi leggere l'ultimo commento del thread: "Previously, our customized JSON parser generated a separated array of the properties on the insertion order on a Object. Now, we switched to Map everywhere". Ecco fatto, tanto ci voleva, problema risolto, passiamo ad altro.
[/quote]

Stiamo sempre parlando di cambiare l'implementazione per fixare i bachi alla gente. Perche' i bachi sono bachi. E' una buona idea? Boh. Nel breve tempo sembra una buona idea. Io ho paura delle ripercussioni a medio termine. Ci sta anche che sia davvero il trend dei linguaggi con tipizzazione dinamica... per i quali oggettivamente il concectto di array associativo ha similiarita' notevoli con alcune proprieta' core del concetto di oggetto. Forse e' davvero una buona idea.  Pero' c'e' il caso he si sposti solo il problema.

Hai sicuramente reso complicata la vita a tutti quelli che devono supportare Python < 3.5. Ovviamente se hanno best practice no, non gli hai creato un gran problema. Se pero' non e' cosi'....
E va bene. Potrebbe anche essere un trade off accettabile.

2
Web framework / Re:Risorse varie!
« il: Novembre 03, 2018, 12:22 »
> Sto pensando di comprare un libro, diciamo da beginner/intermedio...avete suggerimenti?

Guarda, per quanto possa piacermi l'idea di un libro... i libri su una tecnologia specifica tendono ad essere vecchi ancora prima di essere pubblicati.
Insisti con la documentazIone :)

Se vuoi libri, prendi libri sui *concetti*.

3
Python-it.org cafè / Re:Delle domande prima di cominciare
« il: Ottobre 14, 2018, 10:34 »
Ok ... info sufficienti, mi cascano le braccia

Come mai ti cascano le braccia?

Citazione
ma nel fine settimana proverò a sottoporre alla Vostra attenzione la mia prima avventura con python, deliberatamente progettata da me e perfettamente funzionante ... senza aver minimamente pensato in python, e poi un quesito da esso derivante, magari non li guarderà nessuno ma sai mai, magari qualcuno si degna di gettare uno sguardo sul codice (1.600 righe) e poi spiegarmi perché s'è messo a ridere :D

Ti anticipo che *non* potrai contare sul mio parere. *Non* ho nessuna intenzione di leggere 1600 righe di codice postate in un forum (a meno che non trovi davvero interessante il problema). Tra l'altro, buona parte delle cose che si avrebbero da dire sono molto probabilmente state gia' dette (e.g., PEP8, code style guides) e basterebbe applicarle [sto pensando alla menzione sulle "abitudini implementative" di cui parli...].

Sicuramente non mi metto a scaricare zip di codice dai forum. Se hai bisogno di condividere codice, github e simili. Fine.

Ma poi davvero quale e' il punto? Se hai un baco, riproducilo con un esempio minimale e di quello si parla. Di cosa si puo' parlare su 1600 righe di codice? Cioe' cosa ti aspetti? Che qualcuno *leggendo* trovi bachi? A volte sono evidenti, vero. Ma... perche'? Che ti si dica: leggi qui e leggi li? Gia' fatto, senza nemmeno postare. ;)
Tanto sappiamo tutti, oggettivamente, che non interessa. Il codice che scrivi lo leggi e usi solo tu. Non ci deve mettere le mani nessuno e sono sicuro che hai cose piu' divertenti che stare a rispettare guide di stile che sono utili quando invece qualcun altro deve mettere mano al tuo codice. Certo, sarebbero anche utili quando vuoi condividere un esempio minimale perche' hai un problema. Ma veramente ti metterai un po' di fine settimana a riadattare il codice a modo senza avere nessun vantaggio immediato?

Ah, e poi ci sono i classici errori di "non conosco o non ho capito come si fa OOP". Interessa? Ma interessa *davvero*? Perche' sono cose che si imparano lentamente e prendono *anni*. Verrebbe da dire che prendono "sempre", visto e considerato che rispetto a 10 anni fa, per esempio, scrivo diversamente (e mi aspetto che fra 10 anni trovero' cose che non mi piacciono nel codice che scrivo oggi). Anche perche' le convenzioni cambiano.

Poi qualcuno ti suggerira' di scrivere i test. Altra cosa che di solito non interessa fare (e che ovvimaente e' un requisito se davvero vuoi mettere in giro questa cosa), ma probabilmente a te non cambia troppo. Avrai meno problemi e perderai ore non particolarmente divertenti a scrivere sti test, su un progetto scritto senza riguardo per i test, con il risultato che molto probablmente faresti prima a riscrivere daccapo.

Per darti un'idea, 1600 righe di cui fare review a lavoro (con uno standard adeguato) sono alcune ore di lavoro. E si e' un po' nell'ambito dei favori: sono davvero tante da guardare tutte insieme. Di piu' se il collega e' junior.  E in questo caso non e' nemmeno banale dare feedback comprensibile (quindi c'e' il rischio che sia lavoro buttato); c'e' un motivo per cui ci sono tool per fare code review e non si scrive tutto via email. ;)

4
Aggiungo: il problema e' che praticamente *tutti* i linguaggi fanno cacate quando vengono progettate le librerie di collections.
E se fai una cosa fatta *davvero* bene (ammesso che il linguaggio sia abbastanza espressivo) ti trovi con una cosa che potrebbe essere troppo complicata da usare (bene) dal grande pubblico. E piu' il linguaggio e' espressivo e piu' ti trovi con edge case che e' difficile da incastrare. E hai *sempre* il problema se rendere possibile una cosa poco efficiente (che e' un problema perche' porta a problemi inaspettati di performance) oppure dovere pagare overhead di sviluppo quando invece le performance non sono un problema.

Nel caso specifico di Python il problema e' che sono nate prima le implementazioni delle interfacce astratte (types, collections). Che e' anche uno dei problemi alla radice di quando hanno introdotto collections in Java (che ha portato a fare errori). In particolare, quello che hanno cazzato e' stato non avere fin da subito interfacce immutabili e interfacce mutabili. E *ovviamente* quando cominci a progettare la roba in questo modo e hai in giro un sacco di thread, scopri che anche questo porta problemi che puoi evitare solo introducendo struttura ben progettata, che e' complicato e non intuitivo. Oppure facendo quello che fa Rust (che porta in compenso una quantita' di complessita' che spesso mette in difficolta' *me*, per cui finisce che le cose sono anche progettate bene, ma piccoli errori da parte mia hanno un costo elevato, a meno di non essere *massimamente* generici, che porta i suoi problemi). Go lang ha evitato il problema della complicazione, e tutti a lamentarsi che e' troppo semplicistico (verissimo su certe cose).

Purtroppo il problema e' che non esiste una soluzione universale (a me nota) che abbia complessita' (di sviluppo, non algoritmica) che scali con i requisiti. Di solito ti trovi una piattaforma che e' troppo semplice per quando le cose si complicano o troppo complicata per quando le cose sono semplici. E se anche si riesce a tenere semplici le cose semplici, in genere mi sono accorto che progettare il codice intorno in modo che sia semplice finche' le cose sono semplici e poi si complica *gradualmente* quando i requisiti si complicano *non* e' banale. Specie se inserisci nell'equazione ingegneri esperti, ma con esperienza in *altre* tecnologie.


5
>  in Python il vuoto cosmico
Sì, per il caso d'uso "chiavi ordinate alfabeticamente". D'altro canto, Python ha OrderedDict (e adesso semplicemente dict), che non mi sembra che ci sia in Java out-of-the-box. Pari e patta, direi.

No, davvero. Senti, siamo oggettivi. Faccio questo mestiere da tempo. HashMap/dizionari? Tutti i giorni. "TreeMap" e simili? Si usano. Ovviamente avendo un briciolo di familiarita' in algoritmi, e' anche ovvio quando. Tra l'altro, l'ordered dict standard e' implementato esattamente come farei se avessi 10 minuti di tempo per farlo. E' un dict cui hanno ficcato dentrro una lista per tenere traccia di quando hai messo le chiavi.

Nient'altro. Se il tuo tipo di chiave si presta a sort invece che a hash (si, esistono...), non ti aiuta (che invece e' uno dei motivi per avere treemap). Oggettivamente (l'unica cosa che fa e' ... beh. La faccenda e' che qualcuno lo ha implementato e che PHP e RUBY (esatto...) avevano questa "feature". Ora fare l'ordereddict e' cheap. Specie perche' ha nel contratto limiti che vengono da come e' implementato.

Ovvero tiene in memoria l'ordine in cui le chiavi vengono inserite *la prima volta* (quindi per esempio non va nemmeno bene boh, per tenere traccia delle scritture). E' semplicemente la cosa piu' semplice che ti da l'illusione di avere ordine. Questo perche' la gente non conosce ASG e si sorprende sull'iterazione. Che non dovrebbe manco essere quello che fai con i dizionari: cioe' comodo e'... ma se davvero quello che devi fare e' iterare, sei piu' efficiente con una lista di tuple. Gia'. Quindi entra OrderedDict.

E tu vuoi paragonare questo con l'immensa libreria di strutture dati che e' in Java collections? No, mi dispiace. L'offerta di Python nell'area e' estremamente limitata. Poi che a chi non sa cosa si perde vada bene e' un conto. Anche che con un po' di magheggi ce ne si esce e' vero (e poi saltano fuori quarantasette implementazioni parzialmente buggate di priority queue costruite su heapq).

E io capisco che a te sia simpatico ordered dict. Ma e' davvero una pezza. La meta' delle volte la gente lo usa creando da 0 un dizionario ogni volta inserendo le chiavi nell'ordine che vogliono, sicche' poi "siano ordinate". Cioe' stanno facendo hacking del fatto che l'ordine di inseriemento e' l'ordine di uscita (invece che l'ordinamento naturale o richiesto delle chiavi) e tanti saluti. E in generale in questi casi non vogliono *davvero* un dizionario: vogliono una sequenza di chiave valore. E no, quello non e' un dizionario. Sebbene un dizionario ti dia l'illusione di esserlo. E qui bisognerebbe parlare di gerarchie astratte e di un livello di complicazione che potrebbe davvero essere eccessivo.

Ci si vive? Certo. E' ideale? No. E' la pezza ad una carenza. Oggettivamente inadeguata. Meno e' presente in roba come PHP (e forse nemmeno), C (che si fa come vanto di essere minimale nella stdlib -- e cinquantamila implementazioni di linked list piu' tardi forse si sono accorti che non era una buona idea). E Golang. Cioe', Golang e' confrontabile con Python ( e considerato largamente inadeguato nell'area ).

Ogni volta che mi trovo a scrivere codice algoritmico in Python, mi sento come un carpentiere che ha solo martello e chiodi. E poi figuriamoci... ci so costruire tutto. Solo che e' appunto, una pezza su una pezza. Ah, certo... posso prendere dipendenze. E bella questa su ActiveState (ma voglio veramente prendere una ricetta da li e metterla in produzione?) oppure ci sono 27 librerie (di cui 20 scritte da studentelli alle prime armi, 5 dai loro docenti -- che non hanno mai messo in produzione nulla -- e una e' quella buona). Ora, si scheza... ma davvero, se sai quello che fai, sai anche come uscirne... ma sai anche che se ce l'avessi preconfezionato faresti prima.

> Uhm, sì e no. Cioè, sì, Raymond ha progettato un dizionario più veloce. Ma *non* è stato introdotto in Python perchè era più veloce, ma appunto per l'effetto collaterale di essere order-preserving, e questo proprio fin dall'inizio... La storia è interessante e fa capire un po' di problemi.

E questo e' il dramma. D'altra parte ormai Python non lo considero nemmeno piu' per le robe semplici. Dal mio punto di vista, e' debito tecnico allo stato puro. E' qualcosa che so che dovro' buttare e riscrivere. MA a tutti i livelli... faccio spesso tuning per avere performance. Bene, in Python e' per non fare finire tutto a rotoli. In Java e' perche' posso fare di piu' con meno. E Java e' un linguaggio *terribile*. E la JVM non mi piace. Ma alla fine, con un po' di buon senso se ne ha ragione.

Ora che ci penso, tutti i pezzi di codice che ho visto in giro che andavano a rotoli per memory leak, performance issues, vacca boia e compagnia hanno un comun denominatore. Python. (Non che Ruby o PHP siano diversi in questo... Perl lo e': di solito li il problema e' mantenere il codice, ma una volta scritto e limato un po' le performance non sono un problema... i bachetti si -- anche perche' credo che si incontra un limite di complessita' di gestione prima che in Python, e quindi e' in media software piu' semplice).

> Il punto qui è che tu puoi dire e ripetere che un dizionario non è order-preserving, e la gente può sicuramente abituarsi all'idea... finché quello che vede è un dizionario.

Non e' che la gente "si abitua" all'idea. Non piu' di quanto la gente si "abitui all'idea di avere un intestino e di usarlo per cacare". E' semplicemente cosi' che funziona.

Citazione
Ma poi ci sono casi dove il dizionario sta dietro le quinte, e tu non lo vedi... e magari ti aspetti delle cose che il dizionario dietro non può darti. Case-in-point, gli argomenti di una funzione: tu ti aspetti che l'ordine degli argomenti sia significativo..., *tranne* che invece per i kwargs l'ordine improvvisamente *non* è significativo (perché sono implementati con un dizionario... naturalmente!).

Io trovo il discorso: ho implementato gli argomenti delle funzioni con un dizionario, ma il dizionario non va bene, quindi modifico tutti i dizionari completamente delirante.
Se per te questa linea di ragionamento e' sensata, non c'e' spazio per discutere. Abbiamo una visione di software engineering drammaticamente diversa e non c'e' nulla che nessuno possa dire o fare per convincermi che infilare un dettaglio implementativo in un'interfaccia di alto livello per via di alcuni use-case dell'implementazione sia una buona idea. Tutti i principi di software engineering che ho studiato, interiorizzato e applicato per mettere in piedi roba che appunto in piedi ci sta... bene, *tutti* (quelli rilevanti) dicono che e' una buona idea.

> Ora, ci sono alcuni corner-case dove questo potrebbe darti fastidio, da sempre... ma ovviamente il problema esplode letteralmente e diventa visibile a tutti nel momento in cui tu introduci una cosa come collections.OrderedDict, con l'idea di fare un favore alla gente... salvo che poi di colpo la gente si aspetta che OrderedDict(a=1, b=2) preservi le chiavi nell'ordine in cui ha inserito gli argomenti... solo che gli argomenti sono ancora un dict vecchio stile, non un OrderedDict a loro volta!

Questo e' un classico di esempio di quello che succede facendo piling di hack. OrderedDict e' una cosa apparentemente innocua, ma crea piu' problemi di quello che risolve.
Per intenderci, uno dei motivi per cui i named parameters sono considerati una feature (I disagree, sono un'altra idea apparentemente buona che quando fai sul serio di si ritorce contro) e' perche' riducono il costo cognitivo di ricordarci l'ordine (e.g., il classico copy(a, b) chi e' la destinazione? vs. copy(src=a, dst=b) che e' piu' facile da ricordare e da leggere). Quindi forse il punto e' che quando si parla di named argument quello che vuoi fare e' proprio "ignorare" l'ordine.

Un problemino dei named parameters? Lo vedi quando hai large code base e per esempio usi dei mock. E il problema e' che se qualcuno cambia copy(a, b) in copy(src=a, dst=b) il mock si rompe potenzialemente (sono curioso di sapere cosa succede adesso che abbiamo gli ordered dict --  spero che non abbiano fatto sta cazzata). E ancora una volta, finche' ti leggi e ti scrivi il codice non e' un problema.

Pero' *se* hai named arguments nel linguaggio, allora *anche* il nome dei parametri di una funzione (che normalmente non e' parte della signature -- solo il loro tipo lo e' -- ), beh, anche il nome e' parte della signature. E sai quanto tempo ho visto perdere su sta roba?

Come dicevo, questo non lo vedi se scrivi e leggi il tuo codice o lavori con due o tre persone. Quando lavori in contesti un po' piu' ampli, lo diventa. Oh, e' inevitabile eh... non dico nemmeno che i named arguments siano il male assoluto. Ci sono casi in cui mi sono stati comodi, figurati. Sono esempi di implicazioni non banali che derivano da scelte di design apparemente innocue. Perche' il problema non e' davvero che sia cosi': il problema e' che la maggior parte della gente non realizza immediatamente l'implicazione "qualcuno mi puo' chiamare per nome, quindi il nome e' ora intoccabile" -- vincolo che non ci sarebbe stato in altri contesti).

E non e' il peggio: appena cominci a mischiare "named arguments", "default arguments" e **kwargs, scopri che una serie di problemi che sarebbero potuti essere risolti direttamente dal compilatore, ora invece sono piu' complicati da individuare e debuggare.

Poi ovviamente, quando scrivo uno script di 500 righe... appunto in 500 righe faccio un *sacco* di cose. Pero' io avevo capito che
- Explicit is better than implicit.
- Complex is better than complicated.
- Flat is better than nested.
- Errors should never pass silently.
...

> E come si implementa, dietro le quinte, questa cosa? Ma semplicissimo: introducendo il nuovo dict di Raymond, che oltre a essere più veloce ha anche questo bellissimo side-effect di preservare l'ordine delle chiavi, che adesso ci viene proprio comodo.

Si ecco... e il fatto e' che per te questa e' una cosa buona. Per me e' delirio allo stato puro. Se a un meeting un'idea del genere venisse fuori, gli mangerebbero la faccia.

> Questa è una cattiva idea? E' una buona idea? Boh. Tanto ormai è andata.

Diciamo cosi'... credo semplicemente di avere outgrown python. Io ho in mente un mondo dove fa fatica e la gente che lo scrive ha in mente un altro mondo. Sono sicuro che Python vada benissimo per tanti la fuori. Sono convinto che per chi fa webapp con Django queste idee siano *davvero* comode. A me fa *davvero*  paura che nessuno si sia reso conto che questo modo di ragionare e' *pericoloso*.

Mi diverte scrivere in Python? Sempre. Ma mi fido sempre meno a farci roba seria.

Tra l'altro Python era il linguaggio con la macchina del tempo. Features apparentemente slegate che in modo emergente portavano qualcosa di elegante, semplice e potente. Adesso siamo arrivati a ficcare vincoli implementativi nelle strutture dati core perche' la gente non sa usare OrderedDict. Dal mio punto di vista non mi stupirei se fra qualche anno ci saranno __builtin__._COOKIE e __builtin__._POST.

> Ovviamente non c'è solo il caso di OrderedDict... per esempio, quando devi stampare gli argomenti di una funzione per l'utente, ti dà fastidio che non siano stampati nell'ordine "giusto".

Ma ci fate qualcosa di utile con sto Python? Cioe' il problema e' *stampare* gli argomenti o scrivere una funzione che faccia qualcosa di utile?

> Ma poi, in generale, oltre ai dizionari di kwargs, ci sono altri casi in cui un dizionario non-order preserving è una bella scocciatura. Caso tipico, la serializzazione, tutte le volte che hai bisogno di ottenere risultati riproducibili evitando diff spuri.

Si, tipo la serializzazione *se* uno non ha capito come organizzare  un layer di persistenza, non ha capito che l'uguaglianza non e' una proprieta' intrinseca, etc etc etc.
In altre parole: se stai scrivendo scriptoni tutto questo e' un problema. Se stai scrivendo roba piu' complicata... beh, no. Non lo e'. Quello che ci vorrebbe sarebbero buone API e buona separazione.

> Per questi casi il modulo json da sempre offre l'opzione di ordinare alfabeticamente le chiavi nell'output, ma ci sono casi in cui questo comunque non basta (per esempio quando lavori cross-locale e l'ordine di collazione potrebbe variare).

E questo e' un problema specifico dell'interfaccia troppo semplicistica dei vari moduli di serializzazione. E

Citazione
Ora, nella mia modesta esperienza, quando qualcuno produce un output in json, prima o poi a qualcun altro verrà in mente di usarlo, al di là degli scopi e dell'ambito in cui era stato concepito inizialmente. Quindi l'OP dovrebbe restare acutamente consapevole di stare introducento una semantica (l'ordine significativo delle chiavi del suo dizionario) che ha perfettamente senso nell'ambito Python (3.6+) del suo programma, ma che invece non trova corrispondenza nell'ambito del suo output json. Come minimo, dovrebbe documentare molto chiaramente la cosa. Come minimo.

Ovviamente.

6
Base / Re:Aiuto per principiante
« il: Ottobre 11, 2018, 22:00 »
Uhm, sì con qualche punta di no.
Intanto conviene tenere separati i concetti di "cli" e "cli interattiva". In questo thread di parlava di cli interattiva, in realtà. La "cli pura, unix-style" non è uno strumento per utenti finali, e quando ne fai il design non devi tener conto di una marea di problemi di user interaction. Per dire, se sbagli un flag, se il parametro non è del tipo giusto... si pianta e muore lì. Una cli "pura" è questa roba qui, per capirci: https://xkcd.com/1168/.

Ohibo'. Guarda tutte ste definizioni sono piuttosto arbitrarie, le mie in primis. Basta intendersi. Anche cose come "utenti finali" possiamo discuterne per ore e scopriamo che abbiamo dato al termine un senso leggermente diverso.
Mi concentro dove siamo in non accordo.

> python myscript.py 12 18

Ma suvvia, ovvio. Ma oggettivamente fintanto che il programma piu' complicato che si scrive e' sommare due interi c'e' poco da fare. E si, sono d'accordo, per una roba cosi' va benissimo qualunque REPL python.
Pero' di solito ad un certo punto si vuole fare un programma che faccia qualcosa di utile. Per ognuno e' qualcosa di diverso.

Un esempio? la classica todo-list. Classica applicazione da principianti. E ovviamente utile fin li (visto che ce ne sono di prefatte).
Ma intendiamoci... ci sono anche todo-list prefatte da linea di comando. E le ho viste usare *davvero*.
Alla fine, se buona parte del tuo lavoro e' un terminale aperto (e si lo so che il *tuo* lavoro non e' cosi', ma e' una condizione normale per tanta gente che fa il sysadmin e tanti software engineer).
Che so... io sono patologico, ma nel senso... dove lavoro e' gente come me (e in tante startup e FANG e compagnia).

Ora non discutiamo se sia piu' o meno comodo. :) Per alcuni *e'* comodo. Io personalmente il TODO da linea di comando non lo uso -- sebbene spesso sviluppi su una macchina remota che ha un numero di core che non ci stanno in un laptop :) --
Ma li ho visti usare. :) E se ci pensi, dati i constraint, non e' peregrino.

Da cui il mio discorso che alla fine, anche considerando l'estrema semplicita' del tutto, e' un buon modo per scrivere programmi relativamente comodi e utili. E si, magari la gui fighettosa sarebbe anche piu' comoda, pero' andiamo per gradi con sti principianti. Insomma, lo trovo un buon target per potersi scrivere programmetti che hanno anche qualche utilita'.

Oppure pensa al fatto che uno probabilmente si puo' automatizzare qualcosa che gli rompe le palle fare. O meglio, a uno viene in mente che potrebbe automatizzare e ci prova. E va bene. Ci siamo passati tutti. Quello che dico e' che si fanno un favore a fare una cli stile unix (che poi che cavolo vuole dire... tutti i sistemi a linea di comando, incluso DOS, hanno quel tipo di programmi).

> Quindi no, non credo che la minore esposizione a unix sia una seria aggravante per il problema in questione.

Non so quale sia il problema che hai tu. Insisto: se hai fatto qualcosa con unix (cli), e' piu' probabile che ti renda conto che fare

catalogue_pictures holidays

e' piu' comodo che fare il coso che chiami e poi gli fai type-in della directory... perche' tipo sei abituato ad avere la history di bash e quindi il comando lo richiami... mentre farti la history nel tuo coso e' complicato e non lo fai. Dai, roba ovvia.
Se invece hai usato "solo GUI", per te essere nel terminale con Python e' un mondo relativamente alieno e non si ha sviluppato una preferenza.

> Vero è comunque che se il principiante non riesce a "vedere" oltre le gui, allora abbiamo un problema.

Il desiderio di molti principianti e' di fare cose da "non sono piu' principiante". Quindi vedi il desiderio del creare l'exe (anche per darlo in giro), il desiderio per fare le GUI (come i programmi "professionali") oppure il sito web viene quasi subito.
Io personalemente da professionista se mi devo scrivere un programma spero tanto che mi basti una cli perche' faccio una cosa usabile (come interfaccia) in meno tempo e oggettivamente UI piu' complicate prendono tempo prima di raggiungere quel tipo di usabilita'.
Oggettivamente l'ultima volta che mi sono scritto una GUI mi sono sfracellato prima di finire la maschera. Sono anche anni he non scrivo una cosa "GUI" (web si... poi non ti dico l'interaction design da persona che trova vim comodo...). Ma ca**o quanto ho goduto quando *ero* un principiante quando mi sono scritto la GUI.

ca**o, ricordo ancora il primo coso "utile" che mi scrissi per linux con una GUI. Era un coso in C che usava qualche versione preistorica delle GTK (e non ti dico quanto mi sono sentito provessionista quando mi sono scritto il Makefile -- che ovviamente aveva hardcodato i path delle librerie e al primo update ho capito perche' la gente si prendeva la briga di usare configure -- della cui esistenza avevo nel frattempo preso conoscenza --. Questo coso essenzialmente era un runner di programmi (e vacca boia, ci avevo pure messo la history ad un certo punto). E ovviamente ce ne erano 620, ma quello che era successo e' che ero abituato ad usare sti runner con il mio desktop environment (che ovviamente *non* poteva essere KDE o GNOME perche' quelli fichi usavano roba piu' primitiva a cui mancava un sacco di roba *ma* occupavano meno RAM e quindi ... boh, minchia non ho idea di cosa avessi in testa all'epoca. Poi ero passato ad un altro desktop environement che pero' non aveva sto runner -- ovviamente avrei potuto trovare il modo di semplicemente fargliene usare uno esistente... ma per qualche motivo mi sembrava una buona idea scrivermelo da 0 invece. La qual cosa mi ha anche imparato a capire che quando un programma viene linkato (dinamicamente, che gli hard disk erano piccoli) ci sono tutta una serie di complicazioni stupide e tediose (che deve essere la stessa ccosa che hanno pensato quelli che hanno fatto Go e Rust, visto che ora gli hard disk piccoli non sono).

Quante cose che imparai.... e ovviamente non ero "principiante" come quelli che hai in mente tu (quelli che stanno scrivendo somma_due_numeri e poi si piantano a scrivere il coso che li illude di calcolare il codice fiscale).



Sulle cli interattive, quindi. Per cominciare, è chiaro che qui stiamo parlando dal punto di vista della *didattica* di Python.
> Ora, quello che io vorrei che il principiante capisse, è sostanzialmente questo: non ti *serve* una cli interattiva. Lascia perdere. Non usare "input", punto.

E su questo mi pare siamo in accordo. ;)

> Quando vuoi provarlo con dei parametri diversi, apri lo script e cambia i valori. E così via. Tutto qua. Se il tuo script *non* ha un utente (perché è un esercizio, perché è una prova, perché sei un principiante), allora *non* preoccuparti dell'interfaccia utente.

Ma pensa all'aspetto umano. :)
Il principiante vuole fare la cosa che pensa essere piu' "seria" per le sue conoscenze.
E il programma indipendente con un loop interattivo ti sembra davvero professionale per quello che sai fare. :)

E ovviamente e' tempo "buttato" didatticamente. Ma hei... bisogna anche motivarsi. :)

> Nel mio manuale ideale, "print" è introdotto dopo una cinquantina di pagine, e "input" è un argomento avanzato che non compare prima di pagina 200.

O mai... :) oggettivamente l'unica volta in vita mia che ho usato raw_input in un programma di produzione e' stato per aggiungere un nagger ad una utility (Are you really really sure that you want to turn off the power grid for the whole continent? -- e no, ovviamente e' un esempio... non e' che posso dire cosa faceva davvero il programma... no, non spegneva S3 ;) ). Che oggettivamente e' una cazzata, ma vabbe', quando ci si mette piu' a discutere che a fare, tanto vale. :) Per dire quanto e' inutile.



7
Base / Re:Aiuto per principiante
« il: Settembre 23, 2018, 22:21 »
Poi intendiamoci, il design di una CLI interattiva è Difficile. Francamente, per queste cose è meglio usare una gui. Però certo, ci sono situazioni in cui può aver senso anche la cli interattiva.
Detto questo, va bene anche scrivere cose del genere, purché sia chiaro che sono delle scorciatoie fragili e che non ci stiamo ponendo i problemi che una cli interattiva "seria" dovrebbe porsi.

Sono in vena di necro-posting... per qualche motivo il forum mi ha indicato questo post e ci ho trovato questa gemma (come spunto).

Quello che succede e' che i principianti vogliono scrivere un programma. E sono semplicemente contenti di vederlo girare. Non si pongono il problema che sia "piacevole". Non si pongono nemmeno il problema che sia robusto o corretto: sono gia' contenti di vedere qualcosa scritto da loro che funziona (per la loro definizione di funziona).

Ovviamente scrivere una cli con parametri sensati e' piu' facile e c'e' rischio che sia piu' comodo. In realta' tante classi di programmi "seri" funzionano cosi'. Perche' e' una cosa che, anche nel 2018, ha senso fare.
Non va bene per tutto, non prova ad andare bene per tutto e non ti illude che vada bene per tutto. Pero' e' qualcosa. E' piu' semplice e piu' longevo.

Pero' i principianti odierni tipicamente non hanno una lunga esposizione a unix (che presenta numerosi esempi di programmi usati tutti i giorni che funzionano cosi'), perche' ovviamente se anche usano Linux non usano quotidianamente quella parte. Non usano tanto il terminale (che avrebbero anche su Windows, anche se in qualche modo meno prominentemente -- le features adesso ci sono quasi tutte eh...). Il che vuole dire che l'unico esempio di interfaccia che conoscono e' quella "grafica" e siccome non hanno ancora un toolkit fanno una cosa interattiva ma testuale (che guarda caso e' strettamente piu' scomoda di una GUI e di una cli vera, e, in un certo senso, piu' complicata di entrambe).

Poi ovviamente si arriva al nocciolo della questione: per assurdo oggi ci sono piu' tool e piu' documentazione. Ma "entrare" in un sistema e' piu' complicato. Gli home computer degli anni 80 avevano in generale solo un merdoso basic, ma era estremamente immediato. E dava accesso a quasi tutto quasi immediatamente. E per il resto c'era tipicamente il codice macchina (che a volte si poteva quasi embeddare nel basic). Le GUI complicano tutto: la learning curve e' strettamente piu' ripida e in effetti richiedono piu' concetti avanzati. In particolare, senza un po' di OOP si fa *fatica* a comprendere certe cose. Sono anche programmi intrinsecamente piu' complicati ("eventi", "gestione dell'errore") e quindi tutte le tecniche di software engineering per semplificare la vita diventano preziose quasi subito.

E noi cerchiamo di "insegnare a sviluppare software" a persone che invece mirano a vedere un programma che stampa "hello world". Noi "sappiamo" che appena oltre l'hello world questo detour fa risparmiare tempo. Ma viviamo ai tempi della 1 hour delivery (in certi posti). Io ero contento quando un libro mi arrivava in una settimana.

8
Base / Re:Numpy più lento della nativa random?
« il: Settembre 20, 2018, 12:05 »
La gente che fa sta roba tipicamente usa massicciamente numpy.
Come ti hanno fatto notare, devi progettare il codice sulla computazione matriciale, perche' e' molto piu' veloce (non solo i numeri random).

Se non sai/vuoi/puoi farlo, probabilmente numpy non e' per te.

Detto fra noi... quando mi parli di "computazione" e "python" nella stessa frase e non vuoi usare uno dei pochi strumenti che hai per non andare piano, mi verrebbe da dirti di cambiare linguaggio.

9
Scusa, ma non capisco. E' tutto piuttosto razionale. Vorrei capire quali cose ti sembrano anomale. Tra l'altro io ti dico come *io* faccio code review. Non tutti usano lo stesso stile. Ma non ho capito se stavi parlando del processo di code review nell'insieme o nel day to day della code review.
Anche perche' tipicamente non e' che le CR siano il punto focale della baracca. Sono uno dei tanti strumenti per mantenere la code quality.
In molti casi anche auto-organizzarsi in un modo che funziona, appunto funziona. Se ci sono problemi poi uno degli strumenti puo' essere fare tuning del processo di code review.

10
> Siamo d'accordo. A volte pero' mi capita di fare domande per evitare un linguaggio piu' assertivo, e ho notato che su certe persone funziona meglio che su altre: alcuni preferiscono un linguaggio piu' diretto e chiaro, altri no, per cui, va bene cosi'.

Si, certo. A me spesso capita di fare domande perche' ci sono cose che puzzano. Il che vuole dire che manca un commento sul *perche'*, oppure c'e' effettivamente un errore.
Quello intendo: se devo farlo "troppo" (nella stessa CR), vuole dire che non ho abbastanza contesto e non dovrei essere io a fare la review (oppure l'altro non ha abbastanza contesto e non dovrebbe fare la modifica). Se invece capita un paio di volte c'e' che sia solo una questione che a quello che fa la modifica sono ovvie cose che non sono ovvie a chi quel codice lo mantiene.

Riguardo allo stile, sono sempre terso. Dai, ci leggiamo da anni... sai come scrivo. :)
Ovviamente e' piu' facile quando si puo' essere precisi. Please use strategy. Terso, rapido, non ambiguo, non te la puoi neanche prendere.
Sappiamo *tutti* che spesso si prendono scorciatoie. E' anche la filosofia di Go. L'idea e' che se il codice e' chiaro e sul pezzo e' piu' facile fare refactoring se e quando si deve piuttosto che (sovra)ingegnerizzare ogni manopola per rendere tutto configurabile. E' il compito del reviewer, a mente fredda, considerare che le scorciatoie non devono essere troppe e non devono essere miopi.

11
Che dire... mi sa che devo andare contro corrente. ;)

Personalmente trovo che le code review siano davvero efficaci solo nel caso in cui in qualche modo una persona "esterna" vuole contribuire ad un progetto.
E nota che, in questo caso, sono proprio code review, ma non davvero peer review. In un qualche modo la persona che fa la review *non* e' un peer (per lo meno, non nel contesto del progetto).

Quando si lavora tutti sulla stessa code base... come dire. Le code review fanno venire fuori dinamiche interessanti. Parliamo di fare design in fase code review? Cosa e' questo? Questo e' un abuso di fiducia. Le scelte di design che faccio, le prendo io. Punto. Se e' una scelta sufficientemente grossa da coinvolgere il team, deve essere una decisione di team (o di un sotto-gruppo del team). Fare design in code review vuole dire che un ingegnere a caso (il primo che arriva sulla cr) puo' abusare il fatto di essere in posizione di dovere "approvare" per influenzare decisioni che non dovrebbbe influenzare. Nel senso che se potesse influenzare il design con altri canali, non userebbe la code review, no?

Poi bisognerebbe capire cosa si intende design. Sebbene io venda sempre il fatto che "fai design ogni volta che scrivi un metodo", adesso... l'architettura e' una cosa interessante, poi sai se c'e' TMP o Strategy... come dire, i progetti non falliscono per quello, il software non e' che smette di funzionare per quello. Si tratta piu' che altro di essere un po' piu' o meno comodo da mantenere. Ora, se ci si mette *davvero* a parlare di architettura in CR, forse qualcosa a monte e' andato storto.

Il secondo peccato mortale delle CR (che secondo me e' il primo), e' il bike-shedding. Questo fattore toglie da solo ogni potenziale utilita' alla CR quando si manifesta. Ci dovrebbe essere un comitato che in presenza di bike-shedding da ship-it blanket e mette direttamente tutto in produzione e la prossima volta fai le cose seriamente ca**o.

In generale sono uno strumento che non possiamo davvero togliere, perche' non abbiamo alternativa. Ma a seconda dei contesti possono essere completamente inutili. Oggettivamente credo di avere evitato tanti problemi facendo CR agli altri. Indietro di solito prendo "hey, hai invertito due lettere nel commento del test su quella parte di codice che hai detto che deprecherai nella prossima cr". Gia'... cosi' critico...

Ma davvero non puoi toglierle.

Ah... commenti? Se cominci a fare "classi" dove c'e' chi le CR le fa e chi le riceve, crei un botto di friction nel team. Non solo, vai a fare overload della gente piu' senior (che sarebbe il caso che si interessasse di cose piu' rilevanti) e togli responsabilita' a chi sta venendo su. Brutta brutta immagine. Io ti confesso che da un team del genere me ne andrei il giorno stesso. Potrebbe essere diverso nel caso in cui si stanno introducendo, per cui al momento ci sono davvero 2 persone che sanno come funzionano. Ma oggettivamente... se sentissi che si sta "parlando di introdurre le CR nel 2018", forse scapperei a gambe levate dalla compagnia.

> Al perché è stato utilizzato un tipo di struttura dati, o al perché sono state creati dei metodi piuttosto che altri, eccetera.

Su questo sono parzialmente in disaccordo. Usare una struttura dati invece che un altra e' chiaramente una scelta implementativa, non di design.
Ovviamente ci sono edge cases, ma in generale e' una scelta implementativa. Allo stesso modo, suggerire un refactoring in un certo senso o qualcosa di simile non e' una scelta di design.

No, mettersi a scrivere lavagnate di UML per accordarsi e poi fare il codice (che evita il problema di discutere i metodi in CR) non e' time-effective.

> Il tutto purtroppo in tempi abbastanza stretti perché non c'è una grande finestra (ahimé) per la code review.

Non vuoi un processo lungo. Deve essere abbastanza per arrivare ad essere "piu' o meno ok".  I dettagli si possono aggiustare sempre in seguito.

> Io generalmente guardo al codice, cerco di capire cosa fa (magari testo sulla mia macchina), pongo domande piu' che affermazioni, e a meno che non ci siano vistosi errori di programmazione, solitamente non chiedo granche'.

Capisco il concetto di fare domande, spesso mi capita. Ma tento di limitarlo. Generalemnte se sento che debbo fare troppe domande, vuole dire che non sono la persona giusta per fare la CR perche' non ho abbastanza contesto. Una piccola quantita' di domande e' normale.

Io *traccio* le CR perche' l'expectation e' che la maggior parte delle CR passino al primo colpo, con nessun o pochi commenti di poca importanza. Se non si e' qui, bisogna arrivarci. E' importante arrivare al punto in cui "normalmente" quando si manda il codice per review questo passi e basta. Se non succede (frequentemente) bisogna cercare di capire quale e' il problema.

12
@riko
Manno, figurati... sarà il solito caso di autocommit regolato male...

Anche. Resta il fatto che trovo 5 giorni per un problema di ingestion parecchio. Ci vogliono *davvero* quantita' di dati davvero violente (e non e' facile trovarsi con dataset del genere) perche' sia "giustificabile". A me viene davvero da dire che il problema sia come viene fatta l'ingestion.

Per intenderci, stavo leggendo un articolo di un ingegnere che facendo le cose per bene (architetturalmente) stava facendo ingestion di 1M di rows al secondo su un MySQL da un certo cloud provider (e' un esempio: e' probabilmente molto piu' che necessario). Facciamo due conti? 1M al secondo, 3.6K secondi per ora, 24 ore al giorno, 5 giorni. Sono 400 miliardi di record.

Ora questo viene da un benchmark, per comparare bisognerebbe capire di che dati si tratta (nel benchmark) e nell'applicazione di OP.  Ma rendiamoci conto che twitter fa 90M post al giorno (e i post sono piccoli e poco relazionali). Quindi, per dare un ordine di grandezza, se twitter forsse stato costante nel tempo come dimensione (invece che crescente) staremmo parlando di fare l'onboarding degli ultimi *17* anni di Twitter (che esiste solo da 12).

Insomma, quei tempi sono sensati se stai facendo quel tipo di cose. Ah, sempre secondo il benchmark, togliendo il loro componente custom (che di fatto distribuisce su 15 nodi), un normale nodo di un certo cloud provider citato nel benchmark fa circa 150.000 (invece che 1M). Con un normale nodo su un cloud provider (uno a caso... ;) ) in 5 giorni butti dentro il dataset degli ultimi 2 anni di Twitter.  Considerando crescita e tutto, verosimilmente stiamo parlando che in poco piu' di 5 giorni butti dentro i post dal day 1 (gli anni vecchi costano una frazione di quelli nuovi).

Ora, se non hai questo tipo di dati, vuole dire che stai sbagliando ad usare il db, stai sbagliando nel codice che fa l'ingestion oppure stai sbagliando nell'hw. Ovviamente la domanda non e' stata posta, ma se stai facendo ingestion su un raspberry pie, grazie tante che lo sdrai.

Evito di linkare l'articolo perche' non ti spiega davvero come fare (ti da solo un'idea di quello che si puo' fare facendo le cose per bene, ma non ti spiega come farlo). E ovviamente menziona chiaramente il cloud provider che ha usato. In tutto questo non credo che ci sia nulla di magico (ovvero uno specifico cloud provider). Le parti chiave sono la capacita' di rendere i dati accessibili con una latenza decorosa (che vuole dire molto probabilmente che il provider abbia un qualche sistema di storage su cui puoi parcheggiare i dati) o che i dati siano su qualcosa che abbia un buon bocchettone verso il cloud provider. E sinceramente non credo che sia nemmeno una questione di "cloud". Il punto e' che il cloud ti consente di avere rapidamente accesso a macchine con capacita' di calcolo decisamente fuori dal budget della gente, che possono venire usate solo per il tempo necessario, e ti consente di avere *cluster* di queste macchine, se serve.

Addizionalmente, verrebbe da chiedersi se per caso questi dati non stanno meglio in qualche altro formato... penso ad una qualunque delle soluzioni "big data" che vanno di moda ora.

Ma ovviamente non e' chiaro quale sia il reale problema dell'ingestion, non sappiamo la mole e la natura dei dati. Sappiamo solo che ci vanno 5 giorni ad essere caricati e stiamo speculando che siccome sistemi costruiti opportunamente in 5 giorni possono gestire quantita' di dati che e' complicato generare (a meno di specifiche compagnie), molto probabilmente il punto e' che le cose non sono fatte a modo. Ma ovviamente e' speculazione.

Ricordiamo poi che quando c'e' un problema che sembra insolubile (magari i dati sono veramente tanti), ci sono comunque delle semplificazioni che possono consentire di farcela. Che so... se il problema fossero che invece che tanti dati fossero record grossi, spesso conviene tenere nel db solo la parte relazionale e ficcare la ciccia dei dati da un'altra parte (per intenderci, S3 o analogo). Ma io ho il sospetto che il problema sia piu' semplice di cosi'. Potenzialmente proprio un cattivo uso delle transazioni (onestamente, non ci stavo nemmeno pensando a qualcosa di cosi' banale, ma why not).

13
Ric capisci che quando hai un DB lavorativo che sono 2/3 giorni che carica dati e che probabilmente non finirà entro i prossimi 2, preferisco la performance all'innovazione e le "cose giuste" da fare.

Senti, io capisco che qualcosa non va abbestia. "Performance"? Tu non hai un problema di performance, tu hai un problema di architettura.
5 giorni per caricare dei dati? Ma scherziamo? Vuole dire che hai l'ingestion rotta completamente e/o stai mettendo le cose nel sistema sbagliato o stai facendo le cose nel modo sbagliato.

1. ci metti cosi' tanto perche' hai troppe righe?
2. perche' hai troppi blob nelle righe?
3. perche' hai dati troppo relazionali?
4. hai per caso troppi indici inutili (o che non usi di frequente)?
5. quante macchine hai allocato per l'ingestion?
6. sei proprio sicuro che non stai usando lo strumento sbagliato? io sono quasi certo di si. o e' lo strumento sbagliato, o lo stai usando nel modo sbagliato.

Tra l'altro e' molto piu' probabile che hai codice Python (o PHP) scritto alla ca**o di cane piuttosto che sia un problema di MySQL. Nel senso che con tutti i suoi difetti, MySQL e' piuttosto veloce quando usato correttamente. E la differenza di performance fra decodare utf8 o qualcos'altro non mi aspetto sia un fattore cosi' rilevante come lo puo' essere anche una piccola inefficienza in Python. Che poi piccola non e'... ma in Python (e in Perl e in PHP e in Ruby etc etc etc) ci sono proprio tante cose molto innocue che in realta' sono costosissime.

14
Feedback / Re:Vorresti passare a phpBB?
« il: Luglio 29, 2018, 18:52 »
Massi... alla fine, il mezzo ha importanza limitata.
Aggiungo solo che SO non ha nessun senso. Non abbiamo massa critica per una roba del genere. Ci vogliono molti piu' utenti per vederne i vantaggi.
Anche perche' poi la gente si comporta come su SO (se va bene), non come in una community. Vuole dire cambiare taglio al tutto.

15
Base / Re:Aiuto per principiante
« il: Giugno 19, 2018, 21:15 »
E a nessuno e' venuto in mente che l'unica cosa sensata per la funzione fermat e' ritornare un booleano?

Pagine: [1] 2 3 ... 571