这是一个正确实施n层架构? [英] Is this a proper implementation of n-layer architecture?

查看:256
本文介绍了这是一个正确实施n层架构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在学习C#在过去一年左右的时间,并试图将最佳实践沿途。计算器和其他网络资源之间,我以为我是在正确的轨道上正常分离我的顾虑,但现在我有一些疑虑和希望确保我会沿着正确的道路之前,我将我的整个网站在这一新架构。

I have been learning C# for the last year or so and trying to incorporate best practices along the way. Between StackOverflow and other web resources, I thought I was on the right track to properly separating my concerns, but now I am having some doubts and want to make sure I am going down the right path before I convert my entire website over to this new architecture.

目前的网站是老的ASP VBScript和有一个现有的数据库是pretty丑(无外键等),因此,至少在.NET中的第一个版本,我不想使用和学习任何ORM工具在这个时候。

The current website is old ASP VBscript and has a existing database that is pretty ugly (no foreign keys and such) so at least for the first version in .NET I do not want to use and have to learn any ORM tools at this time.

我有以下的项目,在不同的命名空间和设置,使UI层只能看到的DTO层和业务层和数据层只能从业务层看到。下面是一个简单的例子:

I have the following items that are in separate namespaces and setup so that the UI layer can only see the DTOs and Business layers, and the Data layer can only be seen from the Business layer. Here is a simple example:

productDTO.cs

productDTO.cs

public class ProductDTO
{
    public int ProductId { get; set; }
    public string Name { get; set; }

    public ProductDTO()
    {
        ProductId = 0;
        Name = String.Empty;
    }
}

productBLL.cs

productBLL.cs

public class ProductBLL
{

    public ProductDTO GetProductByProductId(int productId)
    {
        //validate the input            
        return ProductDAL.GetProductByProductId(productId);
    }

    public List<ProductDTO> GetAllProducts()
    {
        return ProductDAL.GetAllProducts();
    }

    public void Save(ProductDTO dto)
    {
        ProductDAL.Save(dto);
    }

    public bool IsValidProductId(int productId)
    {
        //domain validation stuff here
    }
}

productDAL.cs

productDAL.cs

public class ProductDAL
{
    //have some basic methods here to convert sqldatareaders to dtos


    public static ProductDTO GetProductByProductId(int productId)
    {
        ProductDTO dto = new ProductDTO();
        //db logic here using common functions 
        return dto;
    }

    public static List<ProductDTO> GetAllProducts()
    {
        List<ProductDTO> dtoList = new List<ProductDTO>();
        //db logic here using common functions 
        return dtoList;
    }

    public static void Save(ProductDTO dto)
    {
        //save stuff here
    }

}

在我的UI,我会做这样的事情:

In my UI, I would do something like this:

ProductBLL productBll = new ProductBLL();
List<ProductDTO> productList = productBll.GetAllProducts();

有关保存:

ProductDTO dto = new ProductDTO();
dto.ProductId = 5;
dto.Name = "New product name";
productBll.Save(dto);

我是完全关闭基地?我也应该有我的BLL相同的属性,而不是传回DTO的我的UI?请告诉我什么是错的,什么是正确的。请记住,我不是专家呢。

Am I completely off base? Should I also have the same properties in my BLL and not pass back DTOs to my UI? Please tell me what is wrong and what is right. Keep in mind I am not a expert yet.

我想实现的接口到我的架构,但我仍然在学习如何做到这一点。

I would like to implement interfaces to my architecture, but I am still learning how to do that.

推荐答案

贫血域是当一个产品或其他类没有真正落实不是数据的getter和setter任何东西 - 没有域的行为

Anemic domain is when a product or other class doesn't really implement anything more than data setters and getters - no domain behavior.

例如,一个产品领域对象应该有一些方法暴露,一些数据验证,一些真正的业务逻辑。

For instance, a product domain object should have some methods exposed, some data validations, some real business logic.

否则,BLL版本(域对象),几乎比DTO更好。

Otherwise, the BLL version (the domain object) is hardly better than a DTO.

http://martinfowler.com/bliki/AnemicDomainModel.html

ProductBLL productBll = new ProductBLL();
List<ProductDTO> productList = productBll.GetAllProducts();

这里的问题是,你是pre-假设你的模型是贫血,露出DTO到业务层的消费者(用户界面或其他)。

The problem here is that you are pre-supposing your model is anemic and exposing the DTO to the business layer consumers (the UI or whatever).

您的应用程序code一般要与&LT合作;产品&GT; S,没有任何BLL或DTO或什么的。这些都是实现类。他们不仅意义不大思想的应用程序员的水平,他们的意思是小领域专家谁表面上理解问题域。因此,他们只能是可见的,当你正在使用的管道,而不是当你在设计卫生间,如果你明白我的意思。

Your application code generally wants to be working with <Product>s, not any BLL or DTO or whatever. Those are implementation classes. They not only mean little to the application programmer level of thought, they mean little to domain experts who ostensibly understand the problem domain. Thus they should only be visible when you are working on the plumbing, not when you are designing the bathroom, if you see what I mean.

我的名字我BLL对象的业务领域实体的名称。而DTO是业务实体和DAL之间的内部。当域实体没有做任何事情比DTO更多 - 这是当它的贫血。

I name my BLL objects the name of the business domain entity. And the DTO is internal between the business entity and the DAL. When the domain entity doesn't do anything more than the DTO - that's when it's anemic.

另外,我要补充一点,我往往只是离开了explcit DTO类,并有域对象到一个通用的DAL与在config定义组织存储的特效,并从一个普通的老DataReader的进入其属性加载自身。随着关闭,它现在可能有非常通用的达尔斯与让你插入你的参数回调。

Also, I'll add that I often just leave out explcit DTO classes, and have the domain object go to a generic DAL with organized stored procs defined in the config and load itself from a plain old datareader into its properties. With closures, it's now possible to have very generic DALs with callbacks which let you insert your parameters.

我会坚持到可以工作,可能最简单的事:

I would stick to the simplest thing that can possibly work:

public class Product {
    // no one can "make" Products
    private Product(IDataRecord dr) {
        // Make this product from the contents of the IDataRecord
    }

    static private List<Product> GetList(string sp, Action<DbCommand> addParameters) {
        List<Product> lp = new List<Product>();
        // DAL.Retrieve yields an iEnumerable<IDataRecord> (optional addParameters callback)
        // public static IEnumerable<IDataRecord> Retrieve(string StoredProcName, Action<DbCommand> addParameters)
        foreach (var dr in DAL.Retrieve(sp, addParameters) ) {
            lp.Add(new Product(dr));
        }
        return lp;
    }

    static public List<Product> AllProducts() {
        return GetList("sp_AllProducts", null) ;
    }

    static public List<Product> AllProductsStartingWith(string str) {
        return GetList("sp_AllProductsStartingWith", cm => cm.Parameters.Add("StartsWith", str)) ;
    }

    static public List<Product> AllProductsOnOrder(Order o) {
        return GetList("sp_AllProductsOnOrder", cm => cm.Parameters.Add("OrderId", o.OrderId)) ;
    }
}

您可以再移动明显的部位伸到一个DAL。该DataRecords作为您的DTO,但他们都非常短命的 - 它们的集合,从来没有真正存在

You can then move the obvious parts out into a DAL. The DataRecords serve as your DTO, but they are very short-lived - a collection of them never really exists.

下面是SqlServer的是静态的一个DAL.Retrieve(你可以看到它足够简单的去改变它使用的CommandText);我有一个版本的这里面封装了连接字符串(所以它不是一个静态方法):

Here's a DAL.Retrieve for SqlServer which is static (you can see it's simple enough to change it to use CommandText); I have a version of this which encapsulates the connection string (and so it's not a static method):

    public static IEnumerable<IDataRecord> SqlRetrieve(string ConnectionString, string StoredProcName,
                                                       Action<SqlCommand> addParameters)
    {
        using (var cn = new SqlConnection(ConnectionString))
        using (var cmd = new SqlCommand(StoredProcName, cn))
        {
            cn.Open();
            cmd.CommandType = CommandType.StoredProcedure;

            if (addParameters != null)
            {
                addParameters(cmd);
            }

            using (var rdr = cmd.ExecuteReader())
            {
                while (rdr.Read())
                    yield return rdr;
            }
        }
    }

之后,您就可以进入完全成熟的框架。

Later you can move on to full blown frameworks.

这篇关于这是一个正确实施n层架构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆