【问题标题】:Best Practices on Code Duplication c#代码复制的最佳实践 c#
【发布时间】:2009-02-26 01:13:49
【问题描述】:

我正在尝试以减少/避免代码重复的方式构建我的代码,但我遇到了一个有趣的问题。每次我的代码调用存储过程时,我都需要传递一些存储过程共有的变量:例如用户名、域、server_ip 和 client_ip。这些都来自 HttpRequest 对象或 system.environment 对象。

由于这些被传递给每个存储过程,我最初的想法是创建一个实用程序类,它是一个数据库包装器,并且每次都会初始化并传递它们,所以我不必在我的代码中这样做。 问题是尽管 c# 类(在 App_Code 文件夹内)看不到 Httprequest 对象。当然,我可以将此作为参数传递给包装器,但这会破坏创建包装器的整个目的。我在这里遗漏了什么吗?

我意识到每次调用存储过程时重复 4 行代码并不是什么大问题,但我宁愿在早期阶段消除代码重复。

【问题讨论】:

    标签: c# code-duplication


    【解决方案1】:

    将您的数据层设置为从包含这些值的 4 个属性的基类继承。使公共构造函数需要这 4 个属性。

    然后在业务层做一些类似的事情——在构造函数中使用这 4 个属性的基类。

    然后 UI 执行 new BusObj( Request["username"], ... ).method()

    在数据层中,您可以有一个方法来构建具有这 4 个属性的 SQLParameter 数组,然后每个方法都可以向数组添加其他参数。

    【讨论】:

      【解决方案2】:

      作为一般规则,无论编程语言如何,如果您可以眯起眼睛并且代码看起来相同,您应该从中创建一个函数/方法/消息并传递参数。

      一旦你的方法接受了大量参数(4 是一个很好的经验法则,但它肯定是具体情况),是时候让该方法接受一个对象了作为参数而不是单个参数。 99.99999999999999999999% 的时间这样的对象应该是不可变的(没有可写的实例变量)。

      【讨论】:

        【解决方案3】:

        HttpContext.Current 与您在 HttpRequest 中找到的信息相似,更重要的是在 App_Code 中可用。

        【讨论】:

          【解决方案4】:

          这是一个你可能喜欢也可能不喜欢的奇怪想法:定义一个“配置文件”类和一个函数,该函数将配置文件扩展为采用公共参数的函数的参数。

          class P {
              readonly string name;
              readonly string domain;
              public P(string name, string domain) {
                  this.name = name; this.domain = domain;
              }
              public void inject(Action<string, string> f) {
                  f(p.arg1, p.arg2);
              }
              public T inject<T>(Func<string, string, T> f) {
                  return f(p.arg1, p.arg2);
              }
          }
          

          在您有 AddressOf 运算符的 VB.net 中,它可能会更好地工作。使用这种类型的东西我会非常谨慎,因为你很容易破坏可读性和封装性。

          【讨论】:

            【解决方案5】:

            我会按照你现在的方式保留它。它更干净,更容易扩展/修改,更容易进行单元测试。

            至于像其他人建议的那样使用 HttpContext,我会说这是一个坏主意。一旦你开始在你的域中引入对 HttpContext 的依赖,就很难把它去掉。如果以后你想在没有 HttpContext 的情况下使用你的模块怎么办?那么单元测试呢?

            【讨论】:

              【解决方案6】:

              尝试 System.Web.HttpContext.Current.Request 获取当前请求。

              【讨论】:

                【解决方案7】:

                您可能正在滑下一个滑坡。 DRY 的要点是不要在多个地方重复业务逻辑,因为需求的变化会导致需要在多个相似的地方更改代码。如果这 4 行是上下文相关的,那么您不必仅仅因为 4 行是相同的而重构。您还通过引用 httprequest 来破坏封装,因为您使用的是全局变量。作为你类的消费者,我必须知道我只能从 Web 应用程序调用你的实现细节。

                话虽如此,如果您考虑到这一点并仍想继续,这里是此类信息的另一种选择。创建包含所需属性的自定义 SecurityPrincipal(实现 IPrincipal)并将其附加到线程。在用户登录时填写它们,然后您可以在请求期间的任何地方访问它。您的调用者仍需要确保已完成此操作,但至少不是特定于平台的。

                否则,为了获得最佳封装效果,请将具有所需属性的类传递给需要使用这些属性的每个对象的构造函数。

                【讨论】:

                • 我们正在努力实现的目标之一是强制将这 4 个参数传递给每个存储的过程(审计目的),因此灵活性在这里不是一个大问题,但肯定需要考虑。
                猜你喜欢
                • 2018-08-05
                • 1970-01-01
                • 2017-10-17
                • 2011-05-02
                • 2012-01-13
                • 1970-01-01
                • 1970-01-01
                • 2011-08-02
                • 2011-03-21
                相关资源
                最近更新 更多