diseño de la clase: permitir que una clase para ser utilizado tanto como un objeto y también la oferta métodos estáticos públicos

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

Pregunta

Tengo un, poco de clase tonto " FileSystemSize ", que puede ser utilizado tanto como un objeto y también a través de públicos, métodos estáticos. La salida es similar, pero no idéntico en cada caso.

La clase era inicialmente estática , pero añadí la posibilidad de inicializar como un objeto para permitir que se extiende con nuevos "métodos conveniencia " en futuras versiones, sin la necesidad para una gran cantidad de parámetros de análisis. Por ejemplo, tengo GetKBString () , GetMBString () , etc ... métodos que permitan conseguir el tamaño de archivo convenientemente formatea la forma que yo quiero (como una cadena). Internamente las tiendas de clase El tamaño de byte de archivo como un doble.

Estoy un poco confundido si esto tiene sentido en absoluto. Parece que tal vez debería dividir esto en una versión estática y una versión objeto como Microsoft hace para Directory y DirectoryInfo. Sin embargo, apenas se parece más fácil para mí tener todo esto en un lugar con un nombre que no se puede confundir - debe quedar claro lo que hace FileSystemSize? ¿Hay implicaciones para el mantenimiento que no estoy anticipando? ¿Qué es ese olor?

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");
¿Fue útil?

Solución

visto de otra manera: ¿Por qué estás poniendo cuerdas / Número / UI formato a métodos en su método de FileSystemSize

A pesar de que se puede utilizar en relación con los archivos, se trata de una pieza general de la funcionalidad que en mi humilde opinión se debería encontrar en otro lugar en una biblioteca bien organizada - al igual que las funciones de trayectoria no son parte del archivo o directorio en clases .NET, me pondría el "Formato de un número" métodos en una cadena o una clase de matemáticas utils.

Separar las responsabilidades de los objetos y puede que no hay necesidad de mezclar los miembros estáticos y no estáticos en casos como este.

Otros consejos

Una prueba buena:. Si usted se está preguntando y nos si está bien, hay una posibilidad de que no es

No puede ser natural para los usuarios de la clase a tener algunos métodos accesibles a través de clases y otros a través de objetos, especialmente cuando el segundo no requieren realmente las propiedades de la instancia de la clase. Lo más probable es que se confundan y se refieren a como: "WTF este programador hizo eso?!"

.

Yo sugeriría ir con todos los métodos de instancia si te gusta la posibilidad de extender la clase, ya sea con los métodos de extensión o por medio de subclases.

Ya que no está teniendo una gran cantidad de estado en FileSystemSize, este no es el candidato perfecto para los métodos de extensión?

Yo personalmente había proporcionar extensiones a formato a los números como cadenas de tamaño de archivo y utilizar un enum para especificar cómo dar formato a los tamaños de archivo:

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,
}

Si estás usando C # 3.0, sus intenciones pueden expresarse mejor con los métodos de extensión y IFormatProviders. En el código, esto podría ser un método de extensión de los métodos FileInfo y DirectoryInfo ToString, por lo que se lee algo como esto:

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

El código anterior se siente más natural para lo que está tratando de hacer.

Vea cómo las siguientes obras para usted. Algunos de los que tendrá que ser probado (el DirectoryInfoExtender.GetDirectorySize método recursivo viene a la mente). Si tiene que ser capaz de escribir frases como Console.WriteLine("{0:GB}", fileInfo), también puede ser que no escribe una IFormatProvider también.

también en cuenta que he skimped intencionalmente en los cheques nulos y excepción de manipulación para estos métodos públicamente accesibles.

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);
    }
}

olor estándar es el uso de métodos estáticos -. Esto hace que sea difícil de mantener en caso de que utilice estos métodos en todo su código

Otra en mi humilde opinión olor es: nombre de la clase no es clara acerca de lo que realmente hace. Por la descripción que está destinado a datos de formato en cuyo caso me gustaría mencionar que en el nombre de la clase.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top