design di classe: permettono una classe per essere utilizzato sia come un oggetto e fornire anche metodi statici pubblici

StackOverflow https://stackoverflow.com/questions/1384100

Domanda

Ho un po 'di classe' sciocco, " FileSystemSize " metodi statici che possono essere utilizzati sia come un oggetto e anche via pubblica,. L'output è simile, ma non identico in ogni caso.

La classe è stata intially static , ma ho aggiunto la possibilità di inizializzare come oggetto di permettere l'estensione con la nuova "modalità di convenienza " in future versioni, senza la necessità per un sacco di parametri di analisi. Per esempio io ho GetKBString () , GetMBString () , ecc ... metodi per consentire di ottenere la dimensione del file comodamente formattato il modo in cui voglio che (come una stringa). Internamente la classe memorizza la dimensione del file di byte come un doppio.

Sono un po 'confuso, se questo ha un senso a tutti. Sembra che dovrei forse dividere questo in una versione statica e una versione oggetto come Microsoft fa per Directory e DirectoryInfo. Tuttavia sembra solo più facile per me avere tutto questo in un unico luogo, con un nome che non può essere scambiato - dovrebbe essere chiaro che cosa fa FileSystemSize? Ci sono delle implicazioni per la manutenzione che non sto anticipando? Cos'è questo odore?

var mypath = @"C:\mypath";

var filesystemsize = new FileSystemSize(mypath);
string kilobytes = filesystemsize.GetKBString();
string megabytes = filesystemsize.GetMBString();
double bytes = filesystemsize.ByteSize;

double staticbytes = FileSystemSize.GetDirectoryBytesSize(new DirectoryInfo(mypath));
double statickilobytes = FileSystemSize.ConvertSize(staticbytes, "KB");
È stato utile?

Soluzione

Guarda un altro modo: Perché si sta mettendo metodi / Numero / formattazione UI String nel metodo FileSystemSize

Mentre può essere utilizzato nei confronti di file, questo è un pezzo generale di funzionalità che secondo me dovrebbe essere trovato altrove in una biblioteca ben organizzata - proprio come funzioni Path non fanno parte delle classi file o directory in .net, ho metterebbe i metodi di "formattare un numero" in una classe di stringa o di matematica utils.

Separare le responsabilità degli oggetti e si possono trovare non c'è bisogno di mescolare membri statici e non statici in casi come questo.

Altri suggerimenti

Un buon test:. Se stai chiedendo se stessi e noi se va bene, c'è una possibilità che non è

Non può essere naturale per gli utenti della classe di avere alcuni metodi accessibili tramite classe e altri tramite oggetto, in particolare quando il secondo in realtà non richiedono le proprietà della classe istanza. Le probabilità sono che saranno confusi e si riferirà a come: "?! WTF questo programmatore fatto che"

Io suggerisco di andare con tutti i metodi di istanza, se vi piace la possibilità di estendere la classe, sia con metodi di estensione o tramite la creazione di sottoclassi.

Dal momento che non stai avendo un sacco di Stato in FileSystemSize, non è questo il candidato perfetto per i metodi di estensione?

io personalmente fornire estensioni per formattare i numeri come stringhe di dimensione del file e utilizzare un enum per specificare come formattare le dimensioni dei file:

public static class FileSystemSize
{
    public static long GetDirectoryBytesSize(string path);
}

public static class NumberExtensions
{
    public static string FormatAsFileSize(
        this long fileSize, FileSizeStringFormat format);
}

public enum FileSizeStringFormat
{
    KiloByte,
    MegaByte,
}

Se stai usando C # 3.0, le vostre intenzioni possono essere meglio espresso con i metodi di estensione e IFormatProviders. In codice, questo potrebbe essere un metodo di estensione sui metodi ToString FileInfo e DirectoryInfo, in modo che avrebbe letto qualcosa di simile:

var directorySize = myDirectory.ToString("GB");
var fileSize = myFile.ToString("MB");

Il codice di cui sopra si sente più naturale per quello che stai cercando di fare.

vedere come i seguenti lavori per voi. Alcuni di essi dovrà essere testato (il metodo ricorsivo DirectoryInfoExtender.GetDirectorySize viene in mente). Se avete bisogno di essere in grado di scrivere dichiarazioni come Console.WriteLine("{0:GB}", fileInfo), si potrebbe anche prendere in considerazione la scrittura di un IFormatProvider pure.

Si noti inoltre che ho volutamente lesinato sui controlli nulli e gestione delle eccezioni per questi metodi pubblicamente accessibili.

public static class DirectoryInfoExtender
{
    public static string ToString(this DirectoryInfo d, string format, int fractionalDigits)
    {
        double fileSize = GetDirectorySize(d);
        return FileSizeConverter.GetFileSizeString(fileSize, format, fractionalDigits);
    }

    public static double GetDirectorySize(DirectoryInfo d)
    {    
        var files = d.GetFiles();
        var directories = d.GetDirectories();

        if(files.Length == 0 && directories.Length == 0)
        {
            return 0;
        }
        else
        {
            double size = 0;

            foreach(var file in files)
            {
                size += file.Length;
            }

            foreach(var directory in directories)
            {
                size += GetDirectorySize(directory);
            }
        }

        return size;
    }
}


public static class FileInfoExtender
{
    public static string ToString(this FileInfo f, string format, int fractionalDigits)
    {
        return FileSizeConverter.GetFileSizeString(f.Length, format, fractionalDigits);
    }
}

public class FileSizeConverter
{
    public static string GetFileSizeString(double fileSize, string format, int fractionalDigits)
    {
        long divisor;
        string sizeIndicator;

        switch(format.ToLower().Trim())
        {
            case "gb":
                divisor = (long)Math.Pow(2, 30);
                sizeIndicator = "gigabytes";
                break;
            case "mb":
                divisor = (long) Math.Pow(2, 20);
                sizeIndicator = "megabytes";
                break;
            case "kb":
                divisor = (long)Math.Pow(2, 10);
                sizeIndicator = "kilobytes";
                break;
            default:
                divisor = 1;
                sizeIndicator = "bytes";
                break;
        }

        return String.Format("{0:N" + fractionalDigits +"} {1}", fileSize / divisor, sizeIndicator);
    }
}

odore standard è l'utilizzo di metodi statici -. Questo rende difficile da mantenere in caso si utilizzano questi metodi su tutto il codice

Un altro IMHO odore è: nome della classe non è chiaro su ciò che realmente fa. Dalla tua descrizione è destinato a formattare i dati in questo caso vorrei ricordare che nel nome della classe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top