【问题标题】:Class Library of Constants--Best Practice?常量类库——最佳实践?
【发布时间】:2010-10-04 13:40:23
【问题描述】:

我在一个内部应用程序上使用 .Net Reflector 来尝试了解以前的开发人员在做什么并学习。我从来没有关于如何开发应用程序的实际说明,所以我从我能做到的地方(万岁堆栈溢出)。话虽如此,我发现了一些让我感到困惑的东西。一个名为 WinConstant 的类库,包含以下代码。

这是我的实际问题:

  1. 这可能有什么用途?

  2. 存储一个 一堆常量在一个类中 图书馆?

  3. 这是否被认为是“最佳 练习”?

感谢您的想法和指导!


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

【问题讨论】:

    标签: .net


    【解决方案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
    

    【讨论】:

      【解决方案2】:

      c# 中有两种类型的常量可用: 编译时常量和运行时常量。他们有不同的行为和 使用错误的会降低您的性能或正确性。 所以选择你正在为你的项目使用的正确的常量类型..

      http://dotnetacademy.blogspot.com/2011/09/constants-in-net.html

      【讨论】:

        【解决方案3】:

        在许多情况下,将字符串常量放入单独的类中是一种最佳实践,但是,这是一个糟糕的例子。更好的方法是创建一个 StringConstants 命名空间,然后组织字符串,以便将相关的字符串常量组织到单独的类中。这只是一个好主意的糟糕实现。

        如果全球化是一个问题,那么(正如其他人所指出的),字符串应该保存在资源文件中。

        【讨论】:

          【解决方案4】:

          它看起来真的是一个简单的字符串表实现。

          这些值不是魔术字符串和“简单”的系统范围更改。我认为资源文件更容易实现和维护。

          您同事的实施是最佳实践吗?我会说不。使用字符串表,尤其是当您需要在应用程序中进行国际化时。

          【讨论】:

            【解决方案5】:

            在用 c 编写 windows 应用程序的日子里,windows 中有类似的文件#included,其中包含 long 个创建常量的#defines 列表。各种 c 应用程序在自己的文件中模拟了这种方法。 “阶级”似乎是这种“c-ism”的“音译”。面向对象设计的基本原则是将代码和数据混合成相关的功能单元:对象。 正如jfullerton 所写:

            从编程的角度来看, 面向对象涉及程序 对象、封装、继承、 和多态性。概念性的 对象在程序中建模 代码。封装保持对象的 数据和使用数据的方法 一起作为对象的一部分。

            很明显,这个常量列表不符合 OO 实践,而是回归旧时代。

            回答您的问题:

            1. -- 这个类包含常量,就是这样
            2. -- 老开发者这样做可能是因为他习惯这样做
            3. -- 这不是当前 最佳实践。

            当然,如果这是您的应用程序的一部分,您不能就这样扔掉它。相反,如果您使用Test Driven DevelopmentRefactoring

            当前 最佳实践,随着时间的推移,这是需要重构的东西

            【讨论】:

            • 仍然有非常正当的理由使用由常量组成的类。并非编程世界中的所有东西都能/将符合纯粹的 OO 理念。有关更多解释,请参阅其他一些回复。这不一定是应该重构的东西。
            • 当您处理大量数据集/数据表并需要引用应用程序许多部分的列或表时,这种列表非常适合。
            • @stingyJack- 你能详细说明一下吗,因为这就是我们所拥有的。怎么样?或者那是第二个帖子吗.. :)
            【解决方案6】:

            拥有一个常量类库并没有错。一般来说,常量是一种很好的做法。毕竟,枚举在 .NET 中无处不在,它们只是分组的数字常量。对常量程序集的依赖与任何其他依赖没有什么不同。理解常量的目的更多的是关于应用程序的逻辑。我的猜测是,这些常量可以启用详细日志记录,而无需使用一堆字符串文字填充应用程序。

            【讨论】:

              【解决方案7】:

              文字与其余代码分开是个好主意。

              奇怪的是,这些应该主要是资源而不是常量字符串。然后,如果需要,它们可以很容易地本地化,或者在不重新编译整个应用程序的情况下替换/更新它们。

              其中一些甚至不应该是资源:例如,cUnderscore 看起来像是在使用文本来创建视觉效果 - 通常是个坏主意。

              为您的前任辩护,我认为这段代码比在整个源代码中查找相同的常量更可取,因为它会使资源重构变得更简单一些。

              【讨论】:

                【解决方案8】:

                例如,常数是永远不会改变的东西

                Public Const NumberOne as Int = 1
                

                所以这是我的第一句话:你总结的一些东西并不是真正的 const。

                另一个缺点是使用 const 关键字会产生二进制依赖性。这意味着您将不得不重建使用您的 constants.dll 的程序集。你不能只是更换它。这是由 const 的工作方式引起的:编译器将名称替换为 在编译时的值。

                解决这个问题的方法是使用 ReadOnly 代替 Const。

                我真的不认为创建这样一个库是一个好习惯。无论如何,我不会让我的团队创建一个...

                【讨论】:

                  【解决方案9】:

                  这样的类可能有一些有用的场景。通常,诸如“幻数”或“幻字符串”之类的东西会变成常量并放在静态(共享)类中。这样做的原因是将这些“神奇”值隔离到一个位置,并允许它们被有意义的名称引用。 (通常用于数值。)对于字符串值,它有助于确保每次都由相同的值引用。最好的例子是 app.config 文件中的字符串键。

                  话虽如此,常量应该用于不改变的东西(或者很少改变以至于它实际上是常量)。在大多数情况下,可能会更改(或需要本地化)的字符串应作为资源存储在 .resx 文件中。

                  【讨论】:

                  • resources > 常量,如果有更简单的方法
                  • @Joel Coehoorn:我认为这取决于它们的使用方式。例如,确保一堆 DllImport 属性的名称一致。我不能使用资源作为 DLL 的名称,但我可以使用常量。
                  【解决方案10】:

                  这看起来就像一个开发人员有一个编码标准:不要在代码中使用字符串文字,并且尽职尽责地分离出每个常量,无论它是否有意义。

                  例如,其中可能有一些元素在代码中需要数字 1,而不是使用 DefaultNumberOfLineItems 或其他描述性常量,而是使用 NumberOne = 1;

                  最佳做法是使常量保持描述性并接近其使用点。具有某种含义并且彼此相关的相关常量的静态类没有任何问题。

                  例如,我曾在一个系统上使用唯一键标记属性。这些键被收集在一个静态类中,属性上带有描述性名称,实际上键是由自动化系统生成的

                  public static class AttributeIDs
                  {
                     public const string Name = "UniqueGeneratedKeyForNameAttribute";
                     public const string Description ="UnqiueGeneratedKeyForDescriptionAttribute";
                     ... etc.
                  }
                  

                  在实践中这样使用

                  MyAccess.GetValueForAttribute(AttributeIDs.Name);
                  

                  它将所有相关的常量放在一起。

                  【讨论】:

                    【解决方案11】:

                    我能想到的唯一解释是某种消息库——但这并不适用于 90% 的条目。

                    例如,这很愚蠢:

                     Public Const cInsert As String = "Insert"
                    

                    这闻起来非常难闻。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2011-12-16
                      • 2012-03-27
                      • 2011-03-06
                      • 1970-01-01
                      • 2013-08-03
                      • 1970-01-01
                      • 2017-11-30
                      相关资源
                      最近更新 更多