تصميم الفصل: اسمح لاستخدام فئة ككائن وأيضًا توفير طرق ثابتة عامة

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

سؤال

لدي فئة صغيرة سخيفة "FileSystemsize"والتي يمكن استخدامها ككائن وأيضًا عبر الأساليب العامة والثابتة. الناتج متشابه ، ولكنه غير متطابق في كل حالة.

كان الفصل ثابت بشكل كبير, ، لكنني أضفت إمكانية تهيئتها ككائن للسماح بالتمديد مع الجديد "طرق الراحة"في الإصدارات المستقبلية ، دون الحاجة إلى الكثير من تحليل المعلمات. على سبيل المثال لدي getKbstring (), getMbstring (), ، وما إلى ذلك ... طرق للسماح بحجم الملف تنسيق بشكل مريح بالطريقة التي أريدها (كسلسلة). داخليًا ، يقوم الفصل بتخزين حجم بايت الملف بمثابة مزدوج.

أنا مرتبك بعض الشيء إذا كان هذا منطقيًا على الإطلاق. يبدو أنني ربما ينبغي علي تقسيم هذا إلى إصدار ثابت وإصدار كائن مثل Microsoft do for directory و directoryinfo. ومع ذلك ، يبدو أنه من الأسهل بالنسبة لي أن أحصل على كل هذا في مكان واحد مع اسم لا يمكن أن يكون مخطئًا - يجب أن يكون واضحًا ما الذي يفعله نظام الملفات؟ هل هناك أي آثار على الصيانة التي لا أتوقعها؟ ما هذه الرائحة؟

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");
هل كانت مفيدة؟

المحلول

انظر إليها بطريقة أخرى: لماذا تضع أساليب تنسيق السلسلة/الرقم/واجهة المستخدم في طريقة نظام الملفات الخاص بك؟

على الرغم من أنه يمكن استخدامه فيما يتعلق بالملفات ، إلا أن هذه وظيفة عامة يجب العثور عليها في مكان آخر في مكتبة منظمة جيدًا - تمامًا مثلما لا تكون وظائف المسار جزءًا من فئات الملف أو الدليل في .NET ، أود أن أضع أساليب "تنسيق رقم" في فئة سلسلة أو رياضيات.

افصل مسؤوليات الكائنات الخاصة بك وقد تجد أنه لا توجد حاجة لخلط أعضاء ثابتة وغير منتظمة في مثل هذه الحالات.

نصائح أخرى

اختبار جيد: إذا كنت تسأل نفسك ولنا ما إذا كان الأمر على ما يرام ، فهناك فرصة ليست كذلك.

قد لا يكون من الطبيعي أن يتمكن مستخدمو الفصل من الوصول إلى بعض الطرق عبر الفصل والآخرين عبر كائن ، خاصةً عندما لا يتطلب الثانية خصائص مثيل الفصل. من المحتمل أن يتم الخلط بينهم وسيشيرون إلى مثل: "WTF هذا المبرمج فعل ذلك؟!".

أقترح الذهاب مع جميع أساليب المثيل إذا كنت ترغب في إمكانية تمديد الفصل ، إما مع طرق التمديد أو عبر التصنيف الفرعي.

نظرًا لأنك لا تملك الكثير من الحالة في نظام الملفات ، أليس هذا هو المرشح المثالي لطرق التمديد؟

أنا شخصياً أقدم ملحقات لتنسيق الأرقام كأسلاك لحجم الملف واستخدام 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,
}

إذا كنت تستخدم C# 3.0 ، فقد يتم التعبير عن نواياك بشكل أفضل مع طرق التمديد و Iformatproviders. في الكود ، يمكن أن تكون هذه طريقة تمديد على أساليب FileInfo و DirectoryInfo ToString ، بحيث يقرأون شيئًا كهذا:

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

يبدو الرمز أعلاه أكثر طبيعية لما تحاول القيام به.

انظر كيف يعمل لك ما يلي. سوف تحتاج إلى اختبار بعضها (تتبادر إلى الذهن طريقة العودية. إذا كنت بحاجة إلى أن تكون قادرًا على كتابة عبارات مثل Console.WriteLine("{0:GB}", fileInfo), ، قد تفكر أيضًا في كتابة iformatprovider أيضًا.

لاحظ أيضًا أنني قمت بتخزينها عن عمد على الشيكات الفارغة ومعالجة الاستثناء لهذه الأساليب التي يمكن الوصول إليها علنًا.

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

الرائحة القياسية هي استخدام الأساليب الثابتة - وهذا يجعل من الصعب الحفاظ عليها في حالة استخدام هذه الطرق في جميع أنحاء الكود الخاص بك.

رائحة أخرى IMHO هي: اسم الفصل ليس واضحا حول ما يفعله بالفعل. من وصفك ، يهدف إلى تنسيق البيانات في هذه الحالة أذكرها في اسم الفصل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top