【问题标题】:Good Coding Practices [closed]良好的编码实践[关闭]
【发布时间】:2012-05-07 15:51:25
【问题描述】:

我正在使用 Entity Framework 进行我的第二个项目,我想阅读一些关于代码是否低于其良好编码实践的意见。

我建议的架构是这样的:

因此,网站调用业务逻辑,在那里评估业务规则。 然后它调用了DALFacade,只是不管我们是访问db2还是sql server,它对于上层都是不可见的。

EF DAL,它负责与数据库对话,CODE FIRST Approach。 实体类库是带有 poco 类的项目。 实用程序是不言自明的,我可能会放一些代码,比如从活动目录中读取属性。

这是我的代码,我尽可能地简化了它

单页:

protected void BtnSubmitRequestClick(object sender, EventArgs e)
    {
        var ecoBonusWorkflow = new EcoBonusWorkflow
                                   {
                                       IsOnHold = true
                                   };

        BusinessLogic.EcoBonusRequestSave(ecoBonusWorkflow);
    }

业务逻辑:

public static class BusinessLogic
    {
        public static void EcoBonusRequestSave(EcoBonusWorkflow ecoBonusWorkflow)
        {
            if (true)
            {
                DalFacade.EcoBonusRequestSave(ecoBonusWorkflow);
            }
        }
    }

DALFacade:

 public static class DalFacade
    {
        private  static readonly UnitOfWork UnitOfWork = new UnitOfWork();

        public static void EcoBonusRequestSave(EcoBonusWorkflow ecoBonusWorkFlow)
        {
            UnitOfWork.EcoBonusWorkflowRepository.InsertEcoBonusWorkflow(ecoBonusWorkFlow);
        }
    }

然后在 EF Dal 类库中,我使用传统的 EF 4.1 代码优先方法。 我还使用了存储库模式和工作单元。

欢迎任何意见

【问题讨论】:

  • 你真的打算让你的业务逻辑类和你的 Facades 是静态的,还是只是对 Stack 的过度简化?
  • 不,这就是为什么我提出这个问题来查看这类问题,我认为静态类更容易,因为您实际上不需要这些类的实例,对吧?

标签: c# entity-framework entity-framework-4


【解决方案1】:

包含“实用程序”对我来说似乎很奇怪。其他所有东西的名字都很好,并有一个非常具体的设置来说明它应该做什么,然后你就有了这个命名模糊的“实用程序”块。

这不是任何特定的编码标准,但我会尽可能避免将“实用程序”合并到您的顶级架构中。每个项目都有一些名为“helpers”或“utilities”的文件夹,最终成为大量杂项代码的转储,这些代码似乎无法立即适用于其他任何地方。这正是技术债务和意大利面条代码开始的方式。

除非你是项目中唯一的开发者,否则无论你呈现什么,它都可能最终会发生,但我还是会避免将其合法化。

此外,在你的快速和肮脏中包含静态类让我感到震惊。除了静态代码会损害可测试性这一事实之外,Entity 框架不是线程安全的。以线程安全的方式使用它取决于您,所以如果您有任何多线程或协同处理,您的 DALFacade 会随机抛出大量错误并令人头疼。

我也没有在您的设计中看到任何依赖注入的余地,这又涉及到代码的可测试性。

编辑:好的,这些不是对 Stack 的让步,所以是时候介绍dependency injection 的想法了。

基本上,任何时候你直接依赖于其他东西,比如当你调用一个静态类时,你就是将这两个东西联系在一起。如果不修改或更换另一部分,则一个部分不再可更换。这是一件坏事,因为它使重构和更改成为一个非常大的问题。相反,您想要做的是“松散耦合”这些依赖项,以便您可以在不破坏所有内容的情况下更改部分。在 C#/.NET 中,您主要使用接口来执行此操作。

因此,与其使用“DALFacade”并直接传递它,不如使用以下效果:

interface IDalFacade
{
    int DoAThing();

    bool DoAnotherThing();
}

class DalFacade : IDalFacade
{
    public int DoAThing()
    {
        return 0;
    }

    public bool DoAnotherThing()
    {
        return false;
    }
}

然后您可以像这样在业务逻辑中使用它:

class BusinessLogic : IBusinessLogic
{
    public IDalFacade DalFacade { get; private set; }

    public BusinessLogic() : this(new DalFacade())
    {}

    public BusinessLogic(IDalFacade dalFacade)
    {
        this.DalFacade = dalFacade;
    }

    public void LogicTheThings()
    {
        this.DalFacade.DoAThing();
    }
}

现在,如果 DalFacade 完全被破坏,或者突然之间您需要其中两个来做不同的事情,现在都不再重要了。甚至,真的,如果一个 DalFacade 被传入。只要它履行 IDalFacade 合同,它就完全没问题。你仍然可以不带参数调用它(它只是假设一个特定的实现),但即使这样也不理想。理想情况下,您会希望使用依赖注入库,例如 NinjectStructureMap,这样您就可以更轻松地进行任何特定的更改。

这在尝试对代码进行单元测试时也很有用,因为正如我所说,您甚至不需要真正的 DalFacade 来做事。您可以简单地模拟出符合 IDalFacade 合同的内容(使用类似 RhinoMocks 的内容),然后您可以完全独立于项目中的任何其他代码来测试您的所有代码。

【讨论】:

  • 所以 BL 和 dalcfacade 应该是可实例化的类?也许使用单例模式?
  • 我会避免单身,因为正如伟大的圣人 Hevery 曾经说过的那样,they are pathological liars。如果它们代表一个独立的工具,必须启动大量信息才能完成其工作,那么它们是有争议的,但对于业务逻辑和数据访问层之类的东西,它们是非常不合适的。我将更新我的答案,扩展我提到的一些事情。
  • 感谢您的评论,最后,您说 Utilities 类库是一个坏主意,但我知道我会有一些不适合其他地方的方法,所以您的想法是创建一个 Helper 文件夹每个项目都有对应的方法?我是这样画的,因为也许有些方法会跨层通用。
  • 没有一个正确的答案,甚至我对实用程序文件夹的反感也并不总是常见的。有些人认为他们很好。在出现行业惯例之前,最好的办法是每周或每两周严格重新检查你的“垃圾抽屉”项目,看看你是否可以打破具有共同主题的事物。在你这样做十几次之后,你自己的风格就会发展起来,而且我认为没有一个你可以期待的最好的行业建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多