C# 良好的编码实践

C# 良好的编码实践,c#,entity-framework,entity-framework-4,C#,Entity Framework,Entity Framework 4,我正在用Entity Framework进行我的第二个项目,我想阅读一些关于下面的代码是否符合其良好编码实践的意见 我提议的架构如下: 因此,网站调用业务逻辑,业务规则在那里进行评估。 然后它调用DALFacade,只是不管我们是访问db2还是sql server,它对上层都是不可见的 EF DAL负责与数据库对话,采用代码优先的方法。 实体类库是包含poco类的项目。 实用程序——这是不言自明的,我可能会在那里放一些代码,比如从active directory读取属性 这是我的代码,我尽可能

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

我提议的架构如下:

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

EF DAL负责与数据库对话,采用代码优先的方法。 实体类库是包含poco类的项目。 实用程序——这是不言自明的,我可能会在那里放一些代码,比如从active directory读取属性

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

一页:

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代码优先方法。 我还使用了存储库模式和工作单元


任何观察都是受欢迎的

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

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

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

此外,在您的quick and dirty中包含静态类也会让我大吃一惊。除了静态代码损害可测试性之外,实体框架不是线程安全的。以线程安全的方式使用它取决于您,因此,如果您有任何多线程或协同处理在进行,您的DALFacade将随机抛出大量错误,这将是一个巨大的难题

我也看不到在您的设计中有任何关于依赖注入的余量,这同样涉及到代码的可测试性

编辑:好的,这些都不是Stack的让步,所以现在是时候介绍这个想法了

基本上,任何时候当您使某个东西直接依赖于其他东西时,比如当您调用一个静态类时,您就是在将这两个东西捆绑在一起。如果不修改或更换另一个零件,一个零件将不再可更换。这是一件坏事,因为它使重构和更改成为一个非常大的问题。相反,您要做的是“松散地耦合”这些依赖项,这样您就可以在不破坏一切的情况下更改部分。在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完全被破坏,或者突然之间你需要两个它们来做不同的事情,这已经不再重要了。甚至,真的,如果真的有人进来了。只要它履行了IDalFacade合同,它就完好无损。您仍然可以不带参数地调用它(它只是假设一个特定的实现),但即使这样也不理想。理想情况下,您可能希望使用依赖项注入库,例如或,它允许您更轻松地进行任何特定更改


这在尝试对代码进行单元测试时也很有用,因为,正如我所说的,您甚至不需要实际的DALMeacade来做事情。您可以简单地模拟一些符合IDalFacade契约的东西(使用类似的东西),然后您可以完全独立于项目中的任何其他东西来测试所有代码。

您真的打算让您的业务逻辑类和外观保持静态,还是这只是对堆栈的过度简化,这就是为什么我要问这样的问题,我认为静态类更容易,因为你实际上不需要这些类的实例,对吧?那么BL和dalcfacade应该是可实例类?也许使用单身模式?我会避免单身,因为正如伟大的圣人Hevery曾经说过的那样。如果它们是一个自包含的工具,必须提供大量的信息才能完成其工作,那么就有理由支持它们,但是对于业务逻辑和数据访问层之类的东西,它们是非常不合适的。我将更新我的答案,扩展我提到的一些内容。谢谢你的评论,最后,你说实用程序类库是个坏主意,但我知道我会有一些不适合其他地方的方法,所以你的想法是在每个项目中用相应的方法创建一个助手文件夹?我是这样画的,因为也许有些方法在不同的层次上是通用的。没有一个正确的答案,甚至我对Utilities文件夹的厌恶也不总是常见的。有些人认为他们很好。在行业实践出现之前,最好的做法是每一两周严格地重新检查一下你的“垃圾抽屉”项目,看看你是否能摆脱一些共同主题。在你做了十几次之后,你自己的风格就会发展起来,我想,如果没有一个行业建议,这是你所能期望的最好的。