Quando sei veramente costretto a utilizzare l'UUID come parte del design?


123

Non vedo davvero il punto di UUID . So che la probabilità di una collisione è effettivamente nulla , ma effettivamente nulla non è nemmeno quasi impossibile.

Qualcuno può fornire un esempio in cui non hai altra scelta che utilizzare l'UUID? Da tutti gli usi che ho visto, posso vedere un design alternativo senza UUID. Sicuramente il design potrebbe essere leggermente più complicato, ma almeno non ha una probabilità di fallimento diversa da zero.

L'UUID odora di variabili globali per me. Ci sono molti modi in cui le variabili globali rendono il design più semplice, ma è solo un design pigro.


23
Tutto ha una possibilità di fallimento diversa da zero. Mi concentrerei su problemi molto più probabili (cioè quasi tutto ciò a cui puoi pensare) rispetto alla collisione di UUID
DanSingerman

16
In realtà, "effettivamente nullo" è molto vicino all'impossibile.
mqp

21
No, in realtà è infinitamente lontano dall'impossibile
Pyrolistical

32
@Pyrolistical quando inizi a lanciare parole come "infinito", hai lasciato il mondo dello sviluppo del software. La teoria dell'informatica è una discussione completamente diversa dalla scrittura di software reale.
Rex M

Risposte:


617

Ho scritto il generatore / parser di UUID per Ruby, quindi mi considero ragionevolmente ben informato sull'argomento. Esistono quattro versioni principali di UUID:

Gli UUID della versione 4 sono essenzialmente solo 16 byte di casualità estratti da un generatore di numeri casuali crittograficamente sicuro, con alcuni bit-twiddling per identificare la versione e la variante dell'UUID. È estremamente improbabile che si scontrino, ma potrebbe accadere se viene utilizzato un PRNG o se ti capita di avere davvero, davvero, davvero, davvero, davvero sfortuna.

Gli UUID della versione 5 e della versione 3 utilizzano rispettivamente le funzioni hash SHA1 e MD5 per combinare uno spazio dei nomi con una parte di dati già univoci per generare un UUID. Ciò, ad esempio, ti consentirà di produrre un UUID da un URL. Le collisioni qui sono possibili solo se anche la funzione hash sottostante ha una collisione.

Gli UUID della versione 1 sono i più comuni. Usano l'indirizzo MAC della scheda di rete (che a meno che non sia falsificato, dovrebbe essere univoco), più un timestamp, più il solito bit-twiddling per generare l'UUID. Nel caso di una macchina che non dispone di un indirizzo MAC, i 6 byte del nodo vengono generati con un generatore di numeri casuali crittograficamente sicuro. Se due UUID vengono generati in sequenza abbastanza velocemente da far corrispondere il timestamp all'UUID precedente, il timestamp viene incrementato di 1. Le collisioni non dovrebbero verificarsi a meno che non si verifichi una delle seguenti condizioni: L'indirizzo MAC è falsificato; Una macchina che esegue due diverse applicazioni che generano UUID produce UUID nello stesso identico momento; A due macchine senza una scheda di rete o senza accesso a livello utente all'indirizzo MAC viene assegnata la stessa sequenza di nodi casuali e generano gli UUID nello stesso momento esatto;

Realisticamente, nessuno di questi eventi si verifica accidentalmente nello spazio ID di una singola applicazione. A meno che tu non accetti ID, ad esempio, su scala Internet o con un ambiente non attendibile in cui individui malintenzionati potrebbero essere in grado di fare qualcosa di male in caso di collisione di ID, non è qualcosa di cui dovresti preoccuparti. È fondamentale capire che se ti capita di generare lo stesso UUID di versione 4 come me, nella maggior parte dei casi, non importa. Ho generato l'ID in uno spazio ID completamente diverso dal tuo. La mia applicazione non saprà mai della collisione, quindi la collisione non ha importanza. Francamente, in un unico spazio applicativo senza attori malintenzionati, l'estinzione di tutta la vita sulla terra avverrà molto prima che tu abbia una collisione, anche su un UUID versione 4, anche se tu '

Inoltre, 2 ^ 64 * 16 corrisponde a 256 exabyte. Come in, dovresti memorizzare 256 exabyte di ID prima di avere il 50% di possibilità di una collisione di ID in un singolo spazio dell'applicazione.


8
Questa è di gran lunga la migliore spiegazione. Non so perché questo non sia stato votato al top. Complimenti a te Sporkmonger.
Brad Barker

1
@Chamnap ho scritto UUIDTools. Gli UUID possono essere convertiti in un numero intero o nella loro forma in byte non elaborati e sarebbero sostanzialmente più piccoli come binari.
Bob Aman

1
@Chamnap uuid.rawti darà la stringa di byte. Il hashmetodo non ti è utile. Viene utilizzato per le tabelle hash e le operazioni di confronto all'interno di Ruby. Tutti i metodi per la conversione da e verso varie rappresentazioni UUID sono definiti come metodi di classe e dovrebbero essere preceduti da "parse".
Bob Aman,

3
@BobAman nel 1990 ho avuto 12 collisioni UUID su un sistema Aegis, si è rivelato essere un FPU difettoso, ma ho pensato di farti sapere che può succedere (non è successo a parte quello negli ultimi 30 anni di programmazione) . Bella spiegazione, anche a proposito, questo è ora il mio post di riferimento UUID da dare alle persone :)
GMasucci

2
@kqr Hai perfettamente ragione che è il problema del compleanno, tuttavia per un codice n-bit, il problema del paradosso del compleanno si riduce a 2 ^ (n / 2), che in questo caso è 2 ^ 64, come affermato nella mia risposta .
Bob Aman

69

La cosa che gli UUID ti acquistano che è molto difficile da fare altrimenti è ottenere un identificatore univoco senza dover consultare o coordinarsi con un'autorità centrale . Il problema generale di essere in grado di ottenere una cosa del genere senza una sorta di infrastruttura gestita è il problema risolto dagli UUID.

Ho letto che, secondo il paradosso del compleanno, la possibilità che si verifichi una collisione UUID è del 50% una volta che sono stati generati 2 ^ 64 UUID. Ora 2 ^ 64 è un numero piuttosto grande, ma una probabilità del 50% di collisione sembra troppo rischiosa (ad esempio, quanti UUID devono esistere prima che ci sia una probabilità del 5% di collisione, anche se sembra una probabilità troppo grande) .

Il problema con quell'analisi è duplice:

  1. Gli UUID non sono del tutto casuali: ci sono componenti principali dell'UUID che sono basati sul tempo e / o sulla posizione. Quindi, per avere una reale possibilità di una collisione, gli UUID in collisione devono essere generati esattamente nello stesso momento da diversi generatori di UUID. Direi che sebbene ci sia una ragionevole possibilità che diversi UUID possano essere generati contemporaneamente, ci sono abbastanza altri gunk (comprese informazioni sulla posizione o bit casuali) per rendere quasi impossibile la parvenza di una collisione tra questo set molto piccolo di UUID .

  2. in senso stretto, gli UUID devono essere univoci tra l'insieme di altri UUID con cui potrebbero essere confrontati. Se stai generando un UUID da utilizzare come chiave del database, non importa se da qualche altra parte in un universo alternativo malvagio viene utilizzato lo stesso UUID per identificare un'interfaccia COM. Proprio come non creerà confusione se c'è qualcuno (o qualcos'altro) chiamato "Michael Burr" su Alpha-Centauri.


1
Esempio concreto? UUID COM / DCE: non esiste l'autorità per assegnarli e nessuno voleva assumersi la responsabilità e / o nessuno voleva che ci fosse un'autorità. Database distribuiti che non hanno collegamenti affidabili e nessun master.
Michael Burr

3
Esempio più concreto: un'applicazione bancaria. Sono installati più data center, uno per ogni paese, con ogni data center dotato di un DB. Le molteplici installazioni sono lì per obbedire a diverse normative. Può esserci un solo record cliente nell'intero set per ogni cliente .....
Vineet Reynolds

(Continuazione del commento precedente) È necessario disporre di un server centrale per generare l'ID cliente per scopi di reporting e tracciamento generale (su tutte le installazioni) o fare in modo che le singole installazioni generino UUID che fungano da ID cliente (ovviamente gli UUID non possono essere utilizzati come in nei rapporti).
Vineet Reynolds

Quando hai il 50% di possibilità di duplicazione, stai già annegando. Qualcuno indichi il volume necessario per arrivare allo 0,0000001% di probabilità. Più database a incremento automatico che iniziano da 1 an e aumentando di n ogni volta risolvono lo stesso problema in modo efficace.
Gordon

2
Le probabilità di ottenere un duplicato sono MOLTO, MOLTO inferiori alle probabilità che l'autorità centrale fallisca in qualche modo mission-critical
std''OrgnlDave

33

Tutto ha una possibilità di fallimento diversa da zero. Mi concentrerei su problemi molto più probabili (cioè quasi tutto ciò a cui puoi pensare) rispetto alla collisione di UUID


Aggiunto come risposta su richiesta di
Pyrolistical

16

Un'enfasi su "ragionevolmente" o, come dici tu, "efficacemente": abbastanza buono è il modo in cui funziona il mondo reale. La quantità di lavoro computazionale necessario per coprire quel divario tra "praticamente unico" e "veramente unico" è enorme. L'unicità è una curva con rendimenti decrescenti. Ad un certo punto su quella curva, c'è una linea tra il punto in cui "abbastanza unico" è ancora accessibile, e quindi curva MOLTO ripida. Il costo per aggiungere più unicità diventa piuttosto elevato. L'unicità infinita ha un costo infinito.

UUID / GUID è, relativamente parlando, un modo semplice e veloce dal punto di vista computazionale per generare un ID che si può ragionevolmente ritenere universalmente unico. Questo è molto importante in molti sistemi che necessitano di integrare dati da sistemi precedentemente non collegati. Ad esempio: se hai un Content Management System che gira su due piattaforme diverse, ma a un certo punto devi importare il contenuto da un sistema all'altro. Non vuoi che gli ID cambino, quindi i tuoi riferimenti tra i dati del sistema A rimangono intatti, ma non vuoi che nessuna collisione con i dati creati nel sistema B. Un UUID risolva questo problema.


Soluzione. Non essere pigro e aggiorna i riferimenti. Fallo bene.
Pirolistico

8
Questo non ha nulla a che fare con la pigrizia: se la politica è che un ID per un articolo è considerato permanente e immutabile, l'ID non cambia. Quindi vuoi che gli ID siano univoci fin dall'inizio e vuoi farlo senza richiedere che tutti i sistemi siano collegati in qualche modo dall'inizio.
Michael Burr

Allora hai bisogno del contesto. Se hai due gruppi di ID univoci che potrebbero
entrare in

23
Oppure, potresti semplicemente costruire il sistema per utilizzare gli UUID e spedirlo, venderlo, fare un milione di dollari e non sentire mai un singolo reclamo che due ID si sono scontrati perché non succederà.
Rex M

16

Non è mai assolutamente necessario creare un UUID. Tuttavia, è conveniente avere uno standard offline utenti possono generare ciascuno una chiave per qualcosa con una probabilità di collisione molto bassa.

Questo può aiutare nella risoluzione della replica del database, ecc ...

Sarebbe facile per online utenti generare chiavi univoche per qualcosa senza l'overhead o la possibilità di collisione, ma non è questo lo scopo degli UUID.

Ad ogni modo, una parola sulla probabilità di collisione, tratta da Wikipedia:

Per mettere questi numeri in prospettiva, si stima che il rischio annuale di essere colpiti da un meteorite sia una possibilità su 17 miliardi, equivalente alle probabilità di creare qualche decina di trilioni di UUID in un anno e di averne uno duplicato. In altre parole, solo dopo aver generato 1 miliardo di UUID al secondo per i prossimi 100 anni, la probabilità di creare un solo duplicato sarebbe del 50% circa.


4
Semplice, non consentire agli utenti offline di generare chiavi. Avere le chiavi temporanee assegnate fino a quando il sistema non va online in modo che le chiavi reali possano essere generate.
Pirolistico

Questa è una risposta molto utile secondo me ... stava per offrire una sorta di analogia con la probabilità io stesso, poiché sembrava che l'OP non ne capisse il significato, ma sembra che tu l'abbia fatto.
Noldorin

Comprendo che la probabilità è effettivamente nulla. Per me l'uso dell'UUID è un design pigro, e volevo solo vedere se si poteva sempre evitarlo
Pyrolistical

Questo è abbastanza giusto, purché tu veda che la bassa probabilità deve essere considerata anche nelle circostanze più estreme, come ora presumo che tu faccia.
Noldorin

13

Un classico esempio è quando si replica tra due database.

DB (A) inserisce un record con ID int 10 e allo stesso tempo DB (B) crea un record con ID 10. Questa è una collisione.

Con gli UUID ciò non accadrà poiché non corrisponderanno. (quasi certamente)


1
Ok, quindi fai in modo che DB A usi ID pari e DB B usi ID dispari. Fatto, nessun UUID.
Pirolistico

2
Con tre DB, usa 3 multipli LOL
Jhonny D. Cano -Leftware-

20
Se usi i multipli 2/3 / qualunque, cosa succede quando aggiungi un nuovo server al mix in seguito? Devi coordinare uno switch in modo da utilizzare n + 1 multipli sul nuovo server e spostare tutti i vecchi server sul nuovo algoritmo e devi spegnere tutto mentre lo fai per evitare collisioni durante l'interruttore dell'algoritmo. Oppure ... potresti semplicemente usare UUID come TUTTI GLI ALTRI.
Bob Aman

3
È anche peggio di così, perché come distingueresti tra multipli di 2 e multipli di 4? O multipli di 3 contro multipli di 6? In effetti, dovresti restare con multipli di numeri primi. Blech! Usa l'UUID, funziona. Microsoft, Apple e innumerevoli altri si affidano a loro e si fidano di loro.
sidewinderguy

2
@sidewinderguy, in GUID ci fidiamo! :)
Ron Klein

13

C'è anche una probabilità diversa da zero che ogni particella del tuo corpo scivoli simultaneamente attraverso la sedia su cui sei seduto e ti ritroverai improvvisamente seduto sul pavimento.

Ti preoccupi di questo?


7
Certo che no, non è qualcosa che posso controllare, ma i progetti posso.
Pirolistico

4
@Pyrolistical Is che realmente, intendo realmente la ragione per cui non ti preoccupare di questo? Allora sei piuttosto strano. E inoltre non hai ragione. È possibile controllarlo. Se guadagni qualche chilo, diminuisci notevolmente la probabilità di un tale evento. Pensi che dovresti aumentare di peso, allora? :-)
Veky

8

Ho uno schema per evitare gli UUID. Imposta un server da qualche parte e fallo in modo che ogni volta che un software desidera un identificatore univoco universale, lo contatti e ne distribuisca uno. Semplice!

Tranne che ci sono alcuni veri problemi pratici con questo, anche se ignoriamo apertamente la malizia. In particolare, quel server può fallire o diventare irraggiungibile da una parte di Internet. Affrontare un errore del server richiede la replica, ed è molto difficile da ottenere correttamente (vedere la letteratura sull'algoritmo di Paxos per sapere perché la creazione del consenso è imbarazzante) ed è anche piuttosto lenta. Inoltre, se tutti i server sono irraggiungibili da una particolare parte della 'rete, nessuno dei client connessi a quella sottorete potrà fare nulla perché saranno tutti in attesa di nuovi ID.

Quindi ... usa un semplice algoritmo probabilistico per generarli che è improbabile che fallisca durante la vita della Terra, o (finanzia e) costruisci una grande infrastruttura che sarà una distribuzione PITA e avrà frequenti guasti. So quale sceglierei.


2
In realtà, l'intero punto dell'invenzione degli UUID era evitare il tuo approccio. Se cerchi la storia degli UUID, vedrai che deriva dai primi esperimenti nella creazione di reti di computer sofisticate e significative. Sapevano che le reti sono intrinsecamente inaffidabili e complicate. Gli UUID rispondevano alla domanda su come coordinare i dati tra i computer quando si sapeva che non potevano essere in comunicazione costante.
Basil Bourque

7
@BasilBourque stavo usando il sarcasmo in quel primo paragrafo, nel caso non fosse ovvio.
Donal Fellows

5

Non capisco tutti i discorsi sulla probabilità di collisione. Non mi interessa la collisione. Però ci tengo alle prestazioni.

https://dba.stackexchange.com/a/119129/33649

Gli UUID sono un disastro delle prestazioni per tabelle di grandi dimensioni. (200.000 righe non sono "molto grandi".)

Il tuo # 3 è davvero pessimo quando il CHARCTER SET è utf8 - CHAR (36) occupa 108 byte!

Gli UUID (GUID) sono molto "casuali". Usarli come chiave UNICA o PRIMARIA su tabelle di grandi dimensioni è molto inefficiente. Ciò è dovuto al fatto di dover saltare la tabella / indice ogni volta che si INSERISCE un nuovo UUID o si SELEZIONA tramite UUID. Quando la tabella / indice è troppo grande per essere contenuta nella cache (vedere innodb_buffer_pool_size, che deve essere inferiore alla RAM, in genere il 70%), l'UUID "successivo" potrebbe non essere memorizzato nella cache, quindi un colpo lento del disco. Quando la tabella / indice è 20 volte più grande della cache, solo 1/20 (5%) degli hit viene memorizzato nella cache: sei legato all'I / O.

Quindi, non utilizzare gli UUID a meno che non sia l'uno o l'altro

hai tabelle "piccole", o ne hai davvero bisogno a causa della generazione di ID univoci da luoghi diversi (e non hai trovato un altro modo per farlo). Ulteriori informazioni sugli UUID: http://mysql.rjweb.org/doc.php/uuid (include funzioni per la conversione tra UUID standard a 36 caratteri e BINARY (16).)

Avere sia un AUTO_INCREMENT UNICO che un UUID UNICO nella stessa tabella è uno spreco.

Quando si verifica un INSERT, tutte le chiavi univoche / primarie devono essere controllate per i duplicati. Ciascuna chiave univoca è sufficiente per il requisito di InnoDB di avere una CHIAVE PRIMARIA. BINARY (16) (16 byte) è piuttosto voluminoso (un argomento contro il renderlo PK), ma non così male. L'ingombro è importante quando si hanno chiavi secondarie. InnoDB inserisce silenziosamente il PK alla fine di ogni chiave secondaria. La lezione principale qui è ridurre al minimo il numero di chiavi secondarie, specialmente per tabelle molto grandi. Per confronto: INT UNSIGNED è di 4 byte con un intervallo di 0..4 miliardi. BIGINT è di 8 byte.


4

Se guardi solo le alternative, ad esempio per una semplice applicazione di database, per dover interrogare il database ogni volta prima di creare un nuovo oggetto, scoprirai presto che l'uso dell'UUID può ridurre efficacemente la complessità del tuo sistema. Certo: se usi i tasti int, sono 32 bit, che memorizzeranno in un quarto dell'UUID a 128 bit. Certo: gli algoritmi di generazione di UUID richiedono più potenza di calcolo rispetto al semplice incremento di un numero. Ma a chi importa? Il sovraccarico della gestione di un '"autorità" per assegnare numeri altrimenti univoci supera facilmente quello per ordini di grandezza, a seconda dello spazio ID univoco previsto.


3

Su UUID == design pigro

Non sono d'accordo sulla scelta dei tuoi combattimenti. Se un UUID duplicato è statisticamente impossibile e la matematica è dimostrata, perché preoccuparsi? Trascorrere del tempo a progettare attorno al tuo piccolo sistema di generazione di N UUID non è pratico, ci sono sempre una dozzina di altri modi per migliorare il tuo sistema.


1

Durante il mio ultimo lavoro, ricevevamo oggetti da terze parti identificati in modo univoco con UUID. Ho inserito una tabella di ricerca UUID-> long integer e ho usato long integer come chiavi primarie perché era molto più veloce in quel modo.


Sì, certo, terze parti che ti costringono a utilizzare l'UUID è un altro problema in cui non voglio entrare. Supponendo che tu abbia il controllo per utilizzare l'UUID o meno.
Pirolistico

Bene, un "intero lungo" (128 bit) è in realtà ciò che è un UUID. Viene semplicemente mostrato come una stringa per il consumo umano. A volte può essere trasmesso in questo modo, ma per l'archiviazione e l'indicizzazione sarà sicuramente più veloce in forma intera come hai trovato.
Nicole

1

Utilizzando l'algoritmo della versione 1 sembra che sia impossibile la collisione sotto il vincolo che vengono generati meno di 10 UUID per millisecondo dallo stesso indirizzo MAC

Concettualmente, lo schema di generazione originale (versione 1) per gli UUID era quello di concatenare la versione dell'UUID con l'indirizzo MAC del computer che genera l'UUID e con il numero di intervalli di 100 nanosecondi dall'adozione del calendario gregoriano in Occidente . In pratica, l'algoritmo vero e proprio è più complicato. Questo schema è stato criticato in quanto non sufficientemente "opaco"; rivela sia l'identità del computer che ha generato l'UUID che l'ora in cui lo ha fatto.

Qualcuno mi corregge se ho interpretato male come funziona


Esistono molte versioni e molti sistemi software (Java ad esempio) non possono utilizzare la versione 1 poiché non dispone di un modo Java puro per accedere all'indirizzo mac.
Pirolistico

Riguardo all'impossibilità di Java di ottenere l'indirizzo MAC: non del tutto vero. Ci sono soluzioni per questo. È possibile impostare manualmente l'indirizzo MAC utilizzato dal generatore tramite un file di configurazione. Puoi anche chiamare ifconfig e analizzare l'output. Il generatore di Ruby UUID che ho scritto utilizza entrambi gli approcci.
Bob Aman

Inoltre, come menzionato nella mia risposta, se non riesci a ottenere un indirizzo MAC per un UUID versione 1, usi invece 6 byte casuali, come da sezione 4.5 di RFC 4122. Quindi, anche se non vuoi usare nessuno dei due le due soluzioni alternative per Java, è comunque possibile generare un UUID versione 1 valido.
Bob Aman

I GUID MS sono solo numeri casuali. Non hanno più alcuna parte MAC, perché ciò ha permesso di decodificare l'indirizzo MAC del server (che si è rivelato molto pericoloso).
Stefan Steiger

1

A coloro che dicono che gli UUID sono un cattivo design perché potrebbero (con una probabilità ridicolmente piccola) entrare in collisione, mentre le tue chiavi generate dal database no ... conosci la possibilità che un errore umano causi una collisione sulle chiavi generate dal database a causa di -la prima necessità è MOLTO MOLTO MOLTO superiore alla possibilità di collisione con UUID4. Si sa che se il db è ricreato inizierà ids a 1 ancora una volta, e come molti di noi hanno dovuto ricreare un tavolo quando eravamo sicuri che non avremmo mai mai bisogno di? Metterei i miei soldi sulla sicurezza degli UUID quando le cose iniziano ad andare storte con sconosciuti da un giorno all'altro.


0

A parte i casi in cui devi utilizzare l'API di qualcun altro che richiede un UUID, ovviamente c'è sempre un'altra soluzione. Ma queste alternative risolveranno tutti i problemi degli UUID? Finirai per aggiungere più livelli di hack, ciascuno per risolvere un problema diverso, quando avresti potuto risolverli tutti in una volta?

Sì, è teoricamente possibile che gli UUID entrino in collisione. Come altri hanno notato, è incredibilmente improbabile al punto che non vale la pena prenderlo in considerazione. Non è mai successo fino ad oggi e molto probabilmente non lo farà mai. Dimenticalo.

Il modo più "ovvio" per evitare collisioni è lasciare che un singolo server generi ID univoci su ogni inserimento, il che ovviamente crea seri problemi di prestazioni e non risolve affatto il problema della generazione offline. Ops.

L'altra soluzione "ovvia" è un'autorità centrale che distribuisce in anticipo blocchi di numeri univoci, che è essenzialmente ciò che l'UUID V1 fa utilizzando l'indirizzo MAC della macchina generatrice (tramite IEEE OUI). Ma gli indirizzi MAC duplicati si verificano perché ogni autorità centrale alla fine fallisce, quindi in pratica è molto più probabile di una collisione UUID V4. Ops.

Il miglior argomento contro l'utilizzo degli UUID è che sono "troppo grandi", ma uno schema (significativamente) più piccolo inevitabilmente non risolverà i problemi più interessanti; La dimensione degli UUID è un effetto collaterale intrinseco della loro utilità nel risolvere proprio questi problemi.

È possibile che il tuo problema non sia abbastanza grande da richiedere ciò che offrono gli UUID e, in tal caso, sentiti libero di usare qualcos'altro. Ma se il tuo problema cresce inaspettatamente (e la maggior parte lo fa), finirai per cambiare in seguito e prenderti a calci per non averli usati in primo luogo. Perché progettare per il fallimento quando invece è altrettanto facile progettare per il successo?


-10

Gli UUID incarnano tutte le cattive pratiche di codifica associate alle variabili globali, solo peggio, poiché sono variabili superglobali che possono essere distribuite su diversi pezzi di kit.

Recentemente ha riscontrato un problema del genere con la sostituzione di una stampante con un modello sostitutivo esatto e ha scoperto che nessuno dei software client avrebbe funzionato.


2
Sono contento di vivere in una società che si concentra ancora sui fatti anziché su opinioni casuali, altrimenti tutti noi in overflow saremmo senza lavoro. :)
Makarand
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.