Struct, Static Class oppure Extension Method?

di il
8 risposte

Struct, Static Class oppure Extension Method?

Buongiorno a tutti,

mi ritrovo con l'esigenza di gestire dei numeri interi in base 36. In pratica vorrei assegnare dei numeri di lotto alla produzione di articoli facendo in modo che siano i più corti possibili da scrivere (devono essere gestiti anche manualmente ed un lotto 1679615 è improponibile - già storcono il naso perché il lotto, figurarsi una roba così lunga). Estendere l'esadecimale mi è sembrata la soluzione più "semplice".

Il problema nasce nel momento in cui questi numeri devono gestiti. Nel senso: è facile codificarli e decodificarli in stringa per le visualizzazioni, ma il dato reale come deve essere? Facendomi portare dall'entusiasmo del neofita smanettone, ho subito pensato ad una struct. In fin dei conti anche gli Int16/32/64/128 sono struct, quindi... Ma mi son reso conto che è un po' farlocca la cosa. Io rappresento un intero (long è sufficiente per le mie necessità) e le struct per gli interi ci sono già. Quel che serve a me è solo rappresentarlo in modo diverso.

Ho valutato quindi una classe statica. Ci infilo i due metodi che facciano long<->string e via andare. Ma così facendo mi complico la vita nel momento in cui devo maneggiarli, dato che dovrò sempre: leggere la stringa, fare confronti e/o somme, riformare la stringa. Questo ogni volta che incontro un numero di lotto. E son parecchie volte in tutto il codice.

Dato che il tipo long non si può ereditare, imposto i due metodi come Extension method di long e rifattorizzo tutto. Ora il confronto e/o somma è facile e son però fregato come prima perché dovrò sempre "convertirlo" prima da stringa a numero.

L'idea della struct è quella che mi solletica di più, facendo creare le varie istanze con due costruttori distinti, ma poi tra overload e overrride, li gestisco direttamente nel codice. Eppure continua a sembrarmi una corbelleria.

C'è una ratio che io possa seguire? O mi sto facendo una secchiata di voli pindarici per nulla? Qualcosa (quasi poco o nulla) in giro per la rete l'ho trovato, ma segue la via della struct o della static class, e quindi son punto e a capo.

Grazie in anticipo per qualsiasi spunto riuscirete a darmi.

8 Risposte

  • Re: Struct, Static Class oppure Extension Method?

    21/01/2025 - Sgrubak ha scritto:

    mi ritrovo con l'esigenza di gestire dei numeri interi in base 36. In pratica vorrei assegnare dei numeri di lotto alla produzione di articoli facendo in modo che siano i più corti possibili da scrivere (devono essere gestiti anche manualmente ed un lotto 1679615 è improponibile - già storcono il naso perché il lotto, figurarsi una roba così lunga). Estendere l'esadecimale mi è sembrata la soluzione più "semplice".

    Ciao, non ho capito bene se devi lavorare o no con le linee guida per attribuire lotti di produzione come da standard previsti e che a breve entreranno in vigore per legge.

    Potresti essere più chiaro in merito ?  Grazie

  • Re: Struct, Static Class oppure Extension Method?

    21/01/2025 - Sgrubak ha scritto:

    C'è una ratio che io possa seguire? O mi sto facendo una secchiata di voli pindarici per nulla?

    Tenderei a propendere per la seconda, perché onestamente non ho ben capito quale sia il tipo di problema (magari potresti esemplificare).

    Se ho ben compreso, stai gestendo un intero lungo, ma in fase di rappresentazione sottoforma di testo - quindi in visualizzazione - lo stai convertendo per rappresentarlo in una forma più corta. E' così? Se sì, da cosa derivano queste elucubrazioni su struct, classi statiche e quant'altro?

  • Re: Struct, Static Class oppure Extension Method?

    Anch'io ho le stesse perplessità.

    Tu devi memorizzare sul DB e nel codice un dato intero a 32 o 64 bit, quello che vuoi.

    Solo per l'input e per l'output gestire le conversioni da e verso il formato che vuoi

  • Re: Struct, Static Class oppure Extension Method?

    21/01/2025 - Sgrubak ha scritto:

    un lotto 1679615 è improponibile

    mah... 

    220221-7F;   410321-10; 2401873006; 240425LB;

    Sono alcuni esempi reali di lotti che carico con gli acquisti di materia prima...

    in produzione puoi mettere un prefisso, un numero e un suffisso.

    non esiste una regola.

    il banco taglio mi da le pesate con in uscita e stampa un numero di pesata progressivo (mica pretendo che la ditta produttrice mi crei un lotto per come lo vorrei io)..

    in linea generale il numero che scegli non dice nulla.

    il latte xbc125669pp ha una sua codifica con sito di produzione, ciclo di lavorazione ecc...

    quando assegni un lotto, nel caso di alimenti, quel numero che ti porti in etichetta è l'id del foglio di lavorazione.

    lotto abc123 è formato dai seguenti componenti o materie prime:

     moca: 

    - cartone ditta xy lotto m

    - vassoio carta ditta yz lotto 233

    ecc...

    materia prima:

    - farina marca pippo lotto 345 provenienza italia

    - lievito marca pluto lotto bb provenienza cina

    ecc...

    ogni singolo componente o materia prima è tracciato dalla bolla di acquisto.

    ogni prodotto finito è tracciato dalla distinta base di lavorazione (ergo potrebbe essere il lotto).

    se la pizza lotto 12345 ha problemi con il lievito cinese lotto bb devi trovare tutti (ripeto tutti) i prodotti finiti che hanno usato quel lievito.

    se la pizza margherita col lievito alla diossina fa male, anche la pizza napoli con quel lievito fa male.

    sono parti meccaniche? idem.

    se la lega per il perno dell'ala del boing è difettosa lo stesso difetto lo ritrovi nel jet militare... va ritirato e sostituito.

    io non mi preoccuperei del numero, puoi sempre usare un lettore barcode o qrcode o rfid... margine di errore "prossimo" allo zero (se il lettore non è un giocattolo).

    anche la catena di montaggio automobilistica usa codici lunghi... cambiamo nr. telaio alla macchina?

  • Re: Struct, Static Class oppure Extension Method?

    21/01/2025 - By65Franco ha scritto:

    non ho capito bene se devi lavorare o no con le linee guida

    Ciao By65Franco, non ho nessuna linea guida. Tutta roba interna mia, per fortuna. Posso spaziare come meglio credo con la creatività.

    21/01/2025 - Alka ha scritto:

    stai gestendo un intero lungo, ma in fase di rappresentazione sottoforma di testo - quindi in visualizzazione - lo stai convertendo per rappresentarlo in una forma più corta.

    Ciao Alka, esattamente. Purtroppo quando distribuivano la sintesi ero distratto. XD Le elucubrazioni nascono dalla ricerca del modo "giusto", ammesso ne esista in assoluto uno, di uniformare questa conversione da numero intero a testo e viceversa. L'istinto mi ha portato a scrivere una classe, per poi rendermi conto che probabilmente non era scelta più corretta visto che io voglio rappresentare un "dato semplice" e non un oggetto complesso. Ho virato quindi verso l'uso della struct e l'ho abbozzata così:

        public struct Base36 : IEquatable<Base36>, IComparable<Base36>
        {
            private static readonly char[] chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
    
            private long _value;
            public Base36(long value) { _value = value; }
            public Base36(string value) { _value = ToLong(value); }
    
            public static long ToLong(string base36Number)
            {
                bool isNegative = base36Number.ElementAt(0) == '-';
                if (isNegative)
                    base36Number = base36Number.Substring(1);
                long res = 0;
                for (int i = base36Number.Length-1; i >= 0; i--)
                {
                    res += Array.IndexOf(chars, base36Number.ElementAt(i)) * (long)Math.Pow(36, base36Number.Length - 1 - i);
                }
                if (isNegative)
                    res *= -1;
                return res;
            }
            public static string ToBase36String(long value)
            {
                bool isNegative = false;
                if (value < 0)
                {
                    isNegative = true;
                    value = Math.Abs(value);
                }
                var res = new StringBuilder();
                while (value != 0)
                {
                    value = Math.DivRem(value, 36L, out long reminder);
                    res.Append(chars[reminder]);
                }
                if (isNegative)
                    res.Append('-');
                var temp = res.ToString().ToCharArray();
                Array.Reverse(temp);
                return new string(temp);
            }
            public override string ToString()
            {
                return ToBase36String(_value);
            }
            bool IEquatable<Base36>.Equals(Base36 other)
            {
                return _value == other._value;
            }
            public override bool Equals(object obj)
            {
                return obj is Base36 b &&
                       _value == b._value;
            }
            public override int GetHashCode()
            {
                return -1939223833 + _value.GetHashCode();
            }
            int IComparable<Base36>.CompareTo(Base36 other)
            {
                return _value.CompareTo(other._value);
            }
    
            public static Base36 operator +(Base36 value1, Base36 value2)
            {
                return new Base36(value1._value + value2._value);
            }
            public static Base36 operator -(Base36 value1, Base36 value2)
            {
                return new Base36(value1._value - value2._value);
            }
            public static Base36 operator *(Base36 value1, Base36 value2)
            {
                return new Base36(value1._value * value2._value);
            }
            public static bool operator == (Base36 value1, Base36 value2)
            {
                return value1._value == value2._value;
            }
            public static bool operator !=(Base36 value1, Base36 value2)
            {
                return value1._value != value2._value;
            }
            public static bool operator >(Base36 value1, Base36 value2)
            {
                return value1._value > value2._value;
            }
            public static bool operator <(Base36 value1, Base36 value2)
            {
                return value1._value < value2._value;
            }
            public static bool operator >=(Base36 value1, Base36 value2)
            {
                return value1._value >= value2._value;
            }
            public static bool operator <=(Base36 value1, Base36 value2)
            {
                return value1._value <= value2._value;
            }
    
        }
    

    Arrivato a questo punto, mi sono reso conto che ho sprecato caratteri: tutto quello sproloquio è un long a tutti gli effetti, solo che fa meno cose. E li m'è venuto il dubbio: ma mi serve davvero un struct/class che sia? Dopo che l'ho vista scritta, mi son detto di no. E allora ho pensato agli extension method. A me, al minimo, serve trovare il max in una lista che arriva da DB ed incrementarlo, quindi cose che con un long si fanno facilmente. Però ridurre tutto a

            var lotto = (Base36)sqlDataReader.GetString(0);
            lotto++;
            //... bla ...
            lotto.ToString();

    mi affascina. 

    21/01/2025 - oregon ha scritto:

    Tu devi memorizzare sul DB e nel codice un dato intero a 32 o 64 bit, quello che vuoi.

    Ciao oregon, qui nasce la mia fregatura. La colonna del DB è un varchar(20). Il fatto che ad oggi io abbia usato un numero è fondamentalmente un caso. M'è venuto naturale, diciamo. Ho il vincolo di unicità sulla coppia di colonne [codice articolo] e [codice lotto] quindi non possono essere inseriti due codici articolo con lo stesso lotto, ma non ho limiti a quanti articoli hanno lo stesso lotto. Con la logica della progressione numerica tutti gli articoli avranno codice di lotto "1", "2", ..., "n" e questa cosa mi crea problemi in fase di scarico dei materiali perché i codici di lotto vengono scambiati tra gli articoli ed il gestionale non intercetta l'errore. Invece che complicare le procedure ai dipendenti, volevo escogitare un qualcosa che, a parità di flusso di lavoro, minimizzasse l'errore umano facendo in modo che ad ogni codice di lotto corrisponda un solo codice articolo. IN questo caso, qualora il codice di lotto non fosse presente, il gestionale blocca l'inserimento del dato ed io ho intercettato l'errore. Io nel DB salverò sempre una stringa, ma nel codice vorrei gestirlo come un numero. È questo fatto che mi crea confusione.

    Spero di aver risposto alle vostre domande, ma come vedete l'inferno che ho in testa urla abbastanza. 

  • Re: Struct, Static Class oppure Extension Method?

    21/01/2025 - Sgrubak ha scritto:

    Ciao By65Franco, non ho nessuna linea guida. Tutta roba interna mia, per fortuna. Posso spaziare come meglio credo con la creatività.

    Capito... e ho letto le successive risposte che hai dato, allora devi escogitare un metodo sicuro e controllato nei limiti che hai. hmmmmm....

  • Re: Struct, Static Class oppure Extension Method?

    21/01/2025 - sihsandrea ha scritto:

    io non mi preoccuperei del numero

    Ed infatti non è il numero a preoccuparmi. Io l'idea ce l'ho chiara. Quel che mi sfugge è come gestirla lato codice, e per "come" intendo a livello di rappresentazione perché quella che può essere la successiva implementazione in testa già ce l'ho.

    21/01/2025 - By65Franco ha scritto:

    allora devi escogitare un metodo sicuro e controllato nei limiti che hai

    E si purtroppo. La questione preponderante è che il fattore umano attualmente incide parecchio. Al momento la procedura prevede: leggi il lotto dall'etichetta -> riscrivilo su un foglio -> riporta quanto scritto sul foglio a PC. Il tutto coinvolge minimo 2 persone, se non 3. La confusione che si può creare è tanta, ma per fortuna i miei colleghi son in gamba e riusciamo a contenere abbastanza gli errori. Volevo dar loro uno strumento, ad implementazione rapida (per loro, meno per me a quanto pare XD) per non cambiargli la metodologia di lavoro ed al contempo non arrivare a gestire manualmente codici con tanti caratteri. Quando poi riuscirò ad informatizzare i reparti produttivi, allora il problema sarà ancora più attenuato.

  • Re: Struct, Static Class oppure Extension Method?

    AAMMGG123MI

    Data-nrcicloproduttivo-stabilimento

    Non penso sia lunghissimo...

    Per il.resto non capisco che codice stai cercando di creare...

    21/01/2025 - Sgrubak ha scritto:

    Con la logica della progressione numerica tutti gli articoli avranno codice di lotto "1", "2", ..., "n" e questa

    Quindi?

    Hai una descrizione dell'articolo in anagrafica

    In lotti avrai

    Idarticolo lotto produttore quantità 

    Mi capita spesso di trovare quella materia prima prodotta da A e venduta dai rivenditori Z e Y che mi forniscono l'articolo M lotto 123

    Anche in questo caso devi distinguere il produttore

    La ditta Z ha subito una contaminazione la ditta Y no.

    Non capisco che problemi riscontri...

    Selezioni l'articolo e prelevi il lotto disponibile (giacenza >0 e non bloccato).

    Fai finta che il lotto sia la taglia e il colore del prodotto pantaloni...

    Selezioni pantaloni e visualizzi quanti sono M e rossi...

    Questo lato carico e gestione lotti per rivendita

    Lato produzione compili la distinta base con articoli usati (componenti) e lotto utilizzati. La distinta sarà:

    Sitoproduzione, dataproduzione, nrdistinta o commessa

    Hai i tre elementi

    La data il sito e il ciclo

    Aammgg-mi-001

    Non sembra lungo ed è parlante

    Caso mai aggiungi l'articolo

    Pchp-aaggmm-mi-001

    E lo codifichi barcode 128

Devi accedere o registrarti per scrivere nel forum
8 risposte