Aggiungendo un nuovo metodo a una libreria di classi per la sua nuova versione ed esponendo un'opzione di versione gli utenti possono selezionare

4

È una cattiva idea aggiungere un nuovo metodo (che implementa un nuovo algoritmo) a una libreria di classi per la sua nuova versione ed esporre un'opzione di versione che gli utenti possono selezionare?

È solo per la retrocompatibilità in cui una vecchia applicazione potrebbe richiedere una sequenza costante di numeri casuali per un certo numero di seme.

Il seguente codice potrebbe parlare molto meglio della mia idea. Spero che tu abbia l'essenza.

//Class Library:
namespace MyGenerator
{
    public sealed class MyRandom
    {
        public enum Version { One, Two }// add more options in the future 
        private int current;
        private Version version;

        public MyRandom(int seed, Version version = Version.One)
        {
            current = seed;
            this.version = version;
        }

        public int Next()
        {
            switch (version)
            {
                case Version.One:
                    AlgorithmOne();
                    break;
                case Version.Two:
                    AlgorithmTwo();
                    break;
                // add more options in the future
            }
            return current;
        }

        private int AlgorithmOne()
        {
            current = (current * 1234567890 + 987654321) & 0x7FFFFFFF;
            return current;
        }

        private int AlgorithmTwo()
        {
            current = (current * current + current) & 0x7FFFFFFF;
            return current;
        }
        // add more algorithm in the future
    }
}

e

//Console Application (for testing purposes):

using MyGenerator;
using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            const int seed = 12345;
            MyRandom rnd = new MyRandom(seed, MyRandom.Version.Two);
            Console.WriteLine(rnd.Next());
            Console.ReadLine();
        }
    }
}
    
posta kiss my armpit 03.01.2014 - 04:37
fonte

4 risposte

11

No, non farlo mai. Se vuoi progettare la futura versione, quindi usa i modelli orientati agli oggetti specificamente progettati per questo . Ad esempio, ecco come risolverei il tuo problema:

abstract class MyRandom
{
    // Ensure that a third party cannot extend the base
    // class by making the ctor private.
    private MyRandom() {}

    public abstract int Next();

    private class First : MyRandom
    {
        // whatever
    } 

    private class Second : MyRandom
    {
        // whatever
    } 

    // Chef's choice:
    public static MyRandom MakeRandom() { return new Second(); }

    // Diner's choice:
    public static MyRandom MakeFirst() { return new First(); }
    public static MyRandom MakeSecond() { return new Second(); }
}

Quando vuoi aggiungere una nuova versione, questo è un dettaglio dell'implementazione privata della classe , e poi aggiungi un nuovo metodo factory static . Se il chiamante vuole che tu scelga la versione migliore, chiamano il metodo che ti permette di decidere. Se hanno una versione specifica che vogliono, chiamano un metodo che li fornisce.

Altre indicazioni:

  • Se credi che aggiungerai più membri a un enum in futuro, probabilmente stai facendo qualcosa di sbagliato. L'insieme di elementi in una enumerazione dovrebbe essere identico per sempre.

  • Se stai prendendo un enum non-flags con n opzioni e facendo n cose diverse come risultato allora scrivi solo n metodi .

risposta data 03.01.2014 - 18:27
fonte
10

Avere un parametro di versione sarebbe sporco.

È una sfacciata mescolanza di preoccupazioni. La prima preoccupazione è che è previsto che il metodo faccia. Il secondo riguarda come gestire più versioni in conflitto di un'enorme API. I due sono completamente indipendenti e dovrebbero rimanere il più separati possibile.

Come sviluppatore, mi interessa solo la prima preoccupazione ( cosa il metodo dovrebbe fare). Se provo a chiamare Math.Random e improvvisamente c'è un parametro per la versione ... beh, sarò confuso. Che cosa ha il versioning con la casualità?

In altre parole, l'aggiunta di un parametro di versione costringerebbe lo sviluppatore a prendere coscienza dell'implementazione di Math.Random (e della sua cronologia) invece di sapere solo cosa è previsto che faccia. A mio parere, ciò renderebbe una pessima API.

    
risposta data 03.01.2014 - 12:24
fonte
4

La risposta probabile è ... perché non vogliono.

Sembra che stiano lasciando aperta la loro opzione per passare a un algoritmo PRNG diverso se ne vuole uno nuovo che preferiscono. C'è anche la possibilità che i futuri runtime di .NET per piattaforme completamente nuove possano richiedere qualcosa di diverso in termini di un algoritmo PRNG, quindi non vogliono bloccarsi in un determinato algoritmo.

Non hanno bisogno di fornire versioni precedenti dei loro generatori perché sono ostili a dicendo di non fare affidamento su di esso per risultati prevedibili. Lo scopo è restituire un numero psuedo-random. Non una sequenza riproducibile di numeri. Non c'è motivo di preoccuparsi di quale versione dell'algoritmo stanno usando, perché la stai chiamando per ottenere un numero casuale.

Se hai bisogno di risultati prevedibili, devi implementare il tuo generatore di numeri casuali (preferibilmente utilizzando uno degli algoritmi meglio testati e noti).

    
risposta data 03.01.2014 - 05:29
fonte
2

È un'idea interessante. Tuttavia, probabilmente proverei a maledire lo sviluppatore della libreria quando provo a usare un metodo come questo. Dal punto di vista dell'utente, rende la libreria molto più complicata da comprendere.

In questo caso specifico, farò il modello Metodo modello . Creerò una classe astratta "Random" e renderò l'esistente "MyRandom" la sua sottoclasse.

Dopo questo, posso implementare l'algoritmo B in un'altra nuova sottoclasse ("YourRandom", "HisRandom" :)) Il codice esistente non si romperà, il nuovo utilizzo può selezionare l'algoritmo in modo casuale.

    
risposta data 03.01.2014 - 16:20
fonte

Leggi altre domande sui tag