0

オブジェクトとしてもパブリックな静的メソッドを介しても使用できる、ばかげた小さなクラス「FileSystemSize 」があります。出力は似ていますが、いずれの場合も同一ではありません。

このクラスは最初はstaticでしたが、多くのパラメーター解析を必要とせずに、将来のバージョンで新しい「便利なメソッド」で拡張できるように、オブジェクトとして初期化する可能性を追加しました。たとえば、 GetKBString ()GetMBString()など...メソッドを使用して、必要な方法で(文字列として)フォーマットされたファイルサイズを便利に取得できるようにします。内部的に、このクラスはファイルのバイト サイズを double として格納します。

これがまったく理にかなっている場合、私は少し混乱しています。Microsoft が Directory と DirectoryInfo に対して行っているように、これを静的バージョンとオブジェクト バージョンに分割する必要があるようです。ただし、これをすべて1か所にまとめて、間違いのない名前にする方が簡単に思えます.FileSystemSizeが何をするのかは明らかです。予想外のメンテナンスへの影響はありますか? あの匂いは何?

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");
4

5 に答える 5

2

別の見方をすると、FileSystemSize メソッドに文字列/数値/UI の書式設定メソッドを入れているのはなぜですか?

ファイルに関して使用することはできますが、これはよく整理されたライブラリの別の場所に配置する必要がある一般的な機能です。文字列または数学ユーティリティ クラスの「数値をフォーマットする」メソッド。

オブジェクトの責任を分離すると、このような場合に静的メンバーと非静的メンバーを混在させる必要がないことがわかる場合があります。

于 2009-09-05T20:22:01.270 に答える
1

良いテスト:あなたが自分自身と私たちにそれが大丈夫かどうか尋ねているなら、そうでない可能性があります。

クラスのユーザーが、クラスを介して一部のメソッドにアクセスし、オブジェクトを介して他のメソッドにアクセスできるようにするのは自然ではない場合があります。特に、2番目のメソッドがクラスのインスタンスプロパティを実際に必要としない場合はそうです。彼らは混乱し、「このプログラマーがそれをしたのはWTF?!」のように言及する可能性があります。

拡張メソッドまたはサブクラス化のいずれかを使用してクラスを拡張する可能性が必要な場合は、すべてのインスタンスメソッドを使用することをお勧めします。

于 2009-09-05T19:55:26.183 に答える
1

FileSystemSizeには多くの状態がないので、これは拡張メソッドの完璧な候補ではありませんか?

個人的に、数値をファイルサイズの文字列としてフォーマットするための拡張機能を提供し、を使用しenumてファイルサイズのフォーマット方法を指定します。

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,
}
于 2009-09-05T19:56:44.777 に答える
1

C# 3.0 を使用している場合は、拡張メソッドと IFormatProvider を使用して意図をより適切に表現できます。コードでは、これは FileInfo および DirectoryInfo ToString メソッドの拡張メソッドである可能性があるため、次のようになります。

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

上記のコードは、あなたがやろうとしていることに対してより自然に感じられます。

以下がどのように機能するかを確認してください。一部はテストする必要があります (再帰メソッド DirectoryInfoExtender.GetDirectorySize が思い浮かびます)。のようなステートメントを記述できるようにする必要がある場合はConsole.WriteLine("{0:GB}", fileInfo)、IFormatProvider も記述することを検討してください。

また、パブリックにアクセス可能なこれらのメソッドの null チェックと例外処理を意図的に省略していることにも注意してください。

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);
    }
}
于 2009-09-05T20:21:27.217 に答える
0

標準的な臭いは、静的メソッドの使用です。これにより、コード全体でこれらのメソッドを使用する場合に保守が難しくなります。

別の匂いの私見は次のとおりです。クラス名は、実際に何をするかについて明確ではありません。あなたの説明から、データをフォーマットすることを意図しています。その場合、クラス名で言及します。

于 2009-09-05T20:21:04.877 に答える