我在内部应用程序上使用.Net Reflector来尝试理解之前的Dev正在做什么以及学习。我从来没有关于如何开发应用程序的实际指令,所以我从可以的地方采取(Hooray Stack Overflow)。话虽如此,我发现了让我困惑的事情。一个名为WinConstant的类库,包含以下代码。
以下是我的实际问题:
这可能有什么用处?
存储a有什么价值 一堆常数 库中?
这被认为是“最好的 实践“?
赞赏的想法和指导!
Public Class clsConstant
Public Const cAccess As String = "Access"
Public Const cAddress As String = "Address"
Public Const cCancel As String = "Cancel"
Public Const cCity As String = "City"
Public Const cClear As String = "Clear"
Public Const cClickOnMessage As String = "Click on any row in top pane to see the detail fields in the bottom pane."
Public Const cClientID As String = "ClientID"
Public Const cColon As String = ": "
Public Const cComma As String = ","
Public Const cContactID As String = "ContactID"
Public Const cCounty As String = "County"
Public Const cDash As String = "-"
Public Const cDelete As String = "Delete"
Public Const cDepartment As String = "Department"
Public Const cError As String = "Error"
Public Const cExec As String = "Exec"
Public Const cFalse As String = "False"
Public Const cFavorite As String = "Favorite"
Public Const cFederal As String = "Federal"
Public Const cFriday As String = "Friday"
Public Const cfrmMain As String = "frmMain"
Public Const cfrmModuleLogin As String = "frmModuleLogin"
Public Const cfrmModuleSplash As String = "frmModuleSplash"
Public Const cHelp As String = "Help"
Public Const cHint As String = "Hint"
Public Const cImagePath As String = "../../image"
Public Const cIn As String = "In"
Public Const cInformation As String = "Information"
Public Const cInitialScreenID As String = "InitialScreenID"
Public Const cInsert As String = "Insert"
Public Const cJuvenileID As String = "JuvenileID"
Public Const cLetter As String = "Letter"
Public Const cManual As String = "Manual"
Public Const cMasterID As String = "MasterID"
Public Const cModuleID As String = "ModuleID"
Public Const cModuleName As String = "ModuleName"
Public Const cMonday As String = "Monday"
Public Const cName As String = "Name"
Public Const cNegative As String = "Negative"
_
Public Shared ReadOnly cNLowDate As DateTime = New DateTime(&H851055320574000)
_
Public Shared ReadOnly cNullDate As DateTime = New DateTime
Public Const cNullDateString As String = "12:00:00 AM"
Public Const cOfficeIDDefault As String = "01"
Public Const cOne As Integer = 1
Public Const cOut As String = "Out"
Public Const cPopUp As String = "PopUp"
Public Const cPositive As String = "Positive"
Public Const cProcess As String = "Process"
Public Const cProviderID As String = "ProviderID"
Public Const cQuestion As String = "Question"
Public Const cRead As String = "Read"
Public Const cReferralID As String = "ReferralID"
Public Const cReminder As String = "Reminder"
Public Const cReport As String = "Report"
Public Const cReportEngine As String = "ReportEngine"
Public Const cReportEnginePath As String = "ReportEnginePath"
Public Const cReportingServices As String = "ReportingServices"
Public Const cReportServer As String = "ReportServer"
Public Const cReportService As String = "ReportService"
Public Const cReportServiceLocal As String = "ReportServiceLocal"
Public Const cReportServiceServer As String = "ReportServiceServer"
Public Const cSaturday As String = "Saturday"
Public Const cSearch As String = "Search"
Public Const cSelect As String = "Select"
Public Const cSpace As String = " "
Public Const cSQLLoginError As String = "SQL Server login/password invalid"
Public Const cStart As String = "Select a module"
Public Const cState As String = "State"
Public Const cSubjectID As String = "SubjectID"
Public Const cSunday As String = "Sunday"
Public Const cThursday As String = "Thursday"
Public Const cTooltipCancel As String = "Reset form data values back to before all manual changes."
Public Const cTooltipClear As String = "Clears all data entry fields prior to an Insert"
Public Const cTooltipClient As String = "Display a Client popup window."
Public Const cTooltipClose As String = "Close this form"
Public Const cTooltipDelete As String = "Delete the current record being displayed, no undo possible."
Public Const cTooltipExe As String = "Initiate a batch process."
Public Const cTooltipInsert As String = "Insert a brand new record"
Public Const cTooltipSearch As String = "Perform a Search for values entered."
Public Const cTooltipSelect As String = "Perform a Select for values entered."
Public Const cTooltipUpdate As String = "Update an existing record"
Public Const cTrue As String = "True"
Public Const cTuesday As String = "Tuesday"
Public Const cUnderscore As String = "____________________________________________________________"
Public Const cUpdate As String = "Update"
Public Const cWarning As String = "Warning"
Public Const cWeb As String = "Web"
Public Const cWednesday As String = "Wednesday"
Public Const cWorkerID As String = "WorkerID"
Public Const cZero As Integer = 0
Public Shared strLongDate As String() = DateAndTime.Now.ToLongDateString.Split(New Char() { ","c })
Public Shared strModuleMainStatusStripFormID As String = Nothing
End Class
答案 0 :(得分:8)
回到用c编码windows应用程序的时代,在Windows中有类似的文件#included包含 long #defines创建常量列表。各种c应用程序在自己的文件中模拟了这种方法。 “阶级”似乎是这种“c-ism”的“音译”。面向对象设计的基本原则是将代码和数据混合到相关的功能单元:对象中。 正如jfullerton写道:
从编程的角度来看, 面向对象涉及程序 对象,封装,继承, 和多态性。概念 对象在程序中建模 码。封装保持一个对象 使用数据的数据和方法 作为对象的一部分。
很明显,这个常数列表不符合OO实践,但是回归过去。
回答你的问题:
当然,如果这是你的应用程序的一部分,你不能把它扔掉。相反,假设您使用Test Driven Development和Refactoring
的当前最佳做法,这可以随着时间的推移重构答案 1 :(得分:7)
将文字与其余代码分开是一个好主意。
奇怪的是,这些应该主要是资源而不是常量字符串。然后,如果需要,可以轻松地对其进行本地化,或者在不重新编译整个应用程序的情况下替换/更新。
其中一些甚至不是资源:cUnderscore
例如看起来像使用文本来创建视觉效果 - 通常是一个坏主意。
在你的前任的辩护中,我认为这个代码比寻找分散在整个源代码中的相同常量更为可取,因为它会使资源的重构变得更简单。
答案 2 :(得分:4)
常量永远不会改变,例如
Public Const NumberOne as Int = 1
所以这是我的第一句话:你总结的一些东西并不是真的。
另一个缺点是使用const关键字会创建二进制依赖项。这意味着您将不得不重建使用constants.dll的程序集。你不能只是替换它。这是由consts的工作方式引起的:编译器在编译时用替换名称。
此问题的解决方案是使用ReadOnly而不是Const。
我认为创建这样的库并不是一个好习惯。我不允许我的团队创建一个......
答案 3 :(得分:4)
这看起来像开发人员有一个编码标准,说:不要在代码中使用字符串文字,并尽职尽责地将每个常量分开,无论它是否有意义。
例如,可能有一些元素需要代码中的数字1,而不是使用DefaultNumberOfLineItems或其他一些描述性常量,它们使用NumberOne = 1;
最佳做法是保持常量描述并接近其使用点。静态类的相关常量没有任何问题,这些常量具有某种类型的含义并且彼此相关。
例如,有一个系统我使用了唯一键来处理标签属性。这些键收集在静态类中,在属性上具有描述性名称,实际键由自动化系统生成
public static class AttributeIDs
{
public const string Name = "UniqueGeneratedKeyForNameAttribute";
public const string Description ="UnqiueGeneratedKeyForDescriptionAttribute";
... etc.
}
在实践中,这就像
一样使用MyAccess.GetValueForAttribute(AttributeIDs.Name);
将所有相关常数放在一起。
答案 4 :(得分:2)
这类课程可能有用。通常,诸如“幻数”或“魔术字符串”之类的内容会被转换为常量并放置在静态(共享)类中。这样做的原因是将这些“魔术”值隔离到一个位置,并允许它们被有意义的名称引用。 (通常用于数值。)对于字符串值,它有助于确保每次都使用相同的值引用事物。最好的例子是你的app.config文件中的字符串键。
话虽这么说,常量应该用于不改变的东西(或者很少改变,它实际上是不变的)。在大多数情况下,可能会更改(或需要本地化)的字符串应作为资源存储在.resx文件中。
答案 5 :(得分:2)
拥有一个常量类库是没有错的。常数是一种很好的习惯。毕竟,枚举在.NET中占有一席之地,它们只是数组常量。依赖于常量程序集与任何其他依赖项没有什么不同。理解常量的目的更多的是关于应用程序的逻辑。我的猜测是这些常量可以启用详细日志记录,而无需使用一堆字符串文字填充应用程序。
答案 6 :(得分:2)
它看起来像是一个字符串表的天真实现。
这些值不是魔术字符串和“简单”的系统范围更改。我认为资源文件更容易实现和维护。
您同事的实施是最佳做法吗?我会说不。使用字符串表,特别是如果您需要在应用程序中进行国际化。
答案 7 :(得分:1)
在许多情况下,将字符串常量放入单独的类中是最佳实践,但是,这是一个糟糕的例子。更好的方法是创建一个StringConstants命名空间,然后组织字符串,以便将相关的字符串常量组织成单独的类。这只是一个好主意的糟糕实现。
如果全球化是一个问题,那么(正如其他人所指出的那样),字符串应保存在资源文件中。
答案 8 :(得分:1)
我们这样做是为了从代码库中分离出数据库特定的常量。这种解耦使我们可以在将来更新数据库(当前的MS Access)以更好地(可能是SQL Server)而不必更改大量的代码库。以下是特定于表的常量块的示例:
Public Class Equalisations
Public Const TableName As String = "Equalisations"
Public Class SPs
Public Const SelectAll As String = General.SPs.Prefix & TableName & General.SPs.SelectAll
Public Const SelectDropDownList As String = General.SPs.Prefix & TableName & General.SPs.SelectDropDownList
Public Const SelectAllChildRecords As String = General.SPs.Prefix & TableName & General.SPs.SelectAllChildRecords
Public Const SelectRecord As String = General.SPs.Prefix & TableName & General.SPs.SelectRecord
Public Const SelectMaxId As String = General.SPs.Prefix & TableName & General.SPs.SelectMaxId
Public Const InsertRecord As String = General.SPs.Prefix & TableName & General.SPs.InsertRecord
Public Const DeleteAllRecords As String = General.SPs.Prefix & TableName & "_DeleteAllRecords"
End Class
Public Class Cols
Public Const CompanyAccountID As String = "CitiAccountID"
Public Const NAVDate As String = "NAVDate"
Public Const GLCodeID As String = "GLCodeID"
Public Const Income As String = "Income"
Public Const LoadedFileID As String = "LoadedFileID"
End Class
Public Class Parms
Public Const CompanyAccountID As String = "pCitiAccountID"
Public Const NAVDate As String = "pNAVDate"
Public Const GLCodeID As String = "pGLCodeID"
Public Const Income As String = "pIncome"
Public Const LoadedFileID As String = "pLoadedFileID"
End Class
End Class
答案 9 :(得分:0)
我能想到的唯一解释是某种消息库 - 但这并不适用于90%的条目。
例如,这只是愚蠢的:
Public Const cInsert As String = "Insert"
这闻起来非常糟糕。
答案 10 :(得分:0)
c#中有两种类型的常量: 编译时常量和运行时常量。他们有不同的行为和 使用错误的将花费你的性能或正确性。 所以选择适合你的项目使用的常量类型..
http://dotnetacademy.blogspot.com/2011/09/constants-in-net.html