类设计:允许类既用作对象又提供公共静态方法
我有一个愚蠢的小类“FileSystemSize”,它既可以用作对象,也可以通过公共静态方法使用。每种情况下的输出相似,但并不相同。
该类最初是静态的,但我添加了将其初始化为对象的可能性,以便允许在未来版本中使用新的“便捷方法”进行扩展,而不需要太多的参数解析。例如,我有 GetKBString()、GetMBString() 等...方法可以按照我想要的方式方便地格式化文件大小(作为字符串)。该类在内部将文件字节大小存储为双精度。
我有点困惑这是否有道理。看来我应该将其分为静态版本和对象版本,就像 Microsoft 对 Directory 和 DirectoryInfo 所做的那样。然而,对我来说,将所有这些都放在一个地方并使用一个不会弄错的名称似乎更容易 - 应该清楚 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");
I have a silly, little class "FileSystemSize" which can be used both as an object and also via public, static methods. The output is similar, but not identical in each case.
The class was intially static, but I added the possibility to initialize it as an object to allow extending with new "convenience methods" in future versions, without the need for a lot of parameter parsing. For example I have GetKBString(), GetMBString(), etc...methods to allow getting the file size conveniently formatted the way I want it (as a string). Internally the class stores the file byte size as a double.
I am a bit confused if this makes sense at all. It seems like I should perhaps split this into a static version and an object version like Microsoft does for Directory and DirectoryInfo. However it just seems easier to me to have this all in one place with a name that can't be mistaken - it should be clear what FileSystemSize does? Are there any implications for maintenance that I am not anticipating? What's that smell?
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");
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
从另一个角度来看:为什么要将 String/Number/UI 格式化方法放入 FileSystemSize 方法中?
虽然它可以用于文件,但这是一项通用功能,恕我直言,应该在组织良好的库中的其他地方找到它 - 就像路径函数不是 .net 中的文件或目录类的一部分一样,我将把字符串或数学实用程序类中的“格式化数字”方法。
将对象的职责分开,您可能会发现在这种情况下不需要混合静态和非静态成员。
Look at it another way: Why are you putting String/Number/UI formatting methods in your FileSystemSize method?
While it can be used in respect of files, this is a general piece of functionality that IMHO should be found elsewhere in a well organised library - just as Path functions are not part of the File or Directory classes in .net, I would put the "format a number" methods in a string or maths utils class.
Separate the responsibilities of your objects and you may find there is no need to mix static and non-static members in cases like this.
一个很好的测试:如果您问自己和我们是否可以,那么很可能不行。
对于类的用户来说,通过类访问某些方法而通过对象访问其他方法可能并不自然,特别是当第二个方法实际上并不需要类的实例属性时。他们很可能会感到困惑,并会说:“WTF 这个程序员这么做了?!”。
如果您喜欢使用扩展方法或通过子类化来扩展类的可能性,我建议使用所有实例方法。
A good test: if you're asking yourself and us whether it is okay, there is a chance it is not.
It may not be natural for users of the class to have some methods accessible via class and others via object, especially when the second do not really require the instance properties of the class. Chances are they will be confused and will be referring to like: "WTF this programmer did that?!".
I suggest going with all instance methods if you like the possibility to extend the class, either with extension methods or via subclassing.
由于 FileSystemSize 中没有太多状态,这不是扩展方法的完美候选者吗?
我个人会提供扩展来将数字格式化为文件大小字符串,并使用
enum
来指定如何格式化文件大小:Since you're not having a lot of state in FileSystemSize, isn't this the perfect candidate for extension methods?
I'd personally provide extensions to format numbers as file size strings and use an
enum
to specify how to format the file sizes:如果您使用 C# 3.0,则使用扩展方法和 IFormatProvider 可能会更好地表达您的意图。在代码中,这可能是 FileInfo 和 DirectoryInfo ToString 方法的扩展方法,因此它们会读取如下内容:
对于您尝试执行的操作,上面的代码感觉更自然。
看看以下内容如何为您服务。其中一些需要进行测试(我想到了递归方法 DirectoryInfoExtender.GetDirectorySize)。如果您需要能够编写诸如
Console.WriteLine("{0:GB}", fileInfo)
之类的语句,您也可以考虑编写 IFormatProvider。另请注意,我故意省略了这些可公开访问的方法的空检查和异常处理。
If you're using C# 3.0, your intentions may be better expressed with extension methods and IFormatProviders. In code, this could be an extension method on the FileInfo and DirectoryInfo ToString methods, so they would read something like this:
The above code feels more natural for what you are trying to do.
See how the following works for you. Some of it will need to be tested (the recursive method DirectoryInfoExtender.GetDirectorySize comes to mind). If you need to be able to write statements like
Console.WriteLine("{0:GB}", fileInfo)
, you might also consider writing an IFormatProvider as well.Also note that I have intentionally skimped on null checks and exception handling for these publically accessible methods.
标准气味是静态方法的使用 - 如果您在代码中使用这些方法,这使得维护变得困难。
恕我直言,另一个味道是:类名不清楚它实际的作用。根据您的描述,它旨在格式化数据,在这种情况下,我会在类名称中提及它。
Standard smell is the usage of static methods - this makes it hard to maintain in case you use those methods all over your code.
Another smell imho is: class name is not clear about what it actually does. From your description it is meant to format data in which case I would mention it in the class name.