这是三层应用程序设计的良好实现吗?

时间:2013-11-27 23:36:43

标签: c# asp.net oop n-tier-architecture

我试图围绕分层应用程序架构,在经过相当多的阅读后,我想出了一些试图实现数据访问层/业务逻辑层/表示层的代码做法。代码完成了我的期望,但我希望得到一些关于我是否成功实现了这个想法的反馈,或者我的思考过程是否有任何问题。

这是我将数据存储在自定义对象中:

public class SalesOrderMetaData
{
    private bool isValid;
    public bool IsValid
    {
        get { return isValid; }
        set { isValid = value; }
    }
}

演示层:

protected void Page_Load(object sender, EventArgs e)
{
    // instatiate the BLL object
    SalesOrderBLL salesOrderBLL = new SalesOrderBLL();

    // reuest the custom object from the BLL
    SalesOrderMetaData salesOrderMetaData = salesOrderBLL.GetSalesOrderMetaData("23447");

    // present a value from the custom object to the user
    Label1.Text = salesOrderMetaData.IsValid.ToString();
}

业务逻辑层:

public class SalesOrderBLL
{
    public SalesOrderMetaData GetSalesOrderMetaData(string csono)
    {
        // instantiate the DAL object
        SalesOrderDAL salesOrderDAL = new SalesOrderDAL();

        // request the custom object from the DAL
        SalesOrderMetaData salesOrderMetaData = salesOrderDAL.GetSalesOrderMetaData(csono);

        // return the custom object to the PL
        return salesOrderMetaData;
    }
}

数据访问层:

public class SalesOrderDAL
{
    public SalesOrderMetaData GetSalesOrderMetaData(string csono)
    {
        // instantiate the custom object 
        SalesOrderMetaData salesOrderMetaData = new SalesOrderMetaData();

        // retrieve the data from the data source
        string sql = "IF EXISTS (SELECT * FROM sosord WHERE csono = @csono) SELECT 1 ELSE SELECT 0;";
        SqlParameter param = new SqlParameter("csono", csono);

        // set the custom object property based on the retrieved data
        // SQLUtilities.GetScalar() is a custom method that returns a SqlCommand.ExecuteScalar() object 
        salesOrderMetaData.IsValid = Convert.ToBoolean(SQLUtilities.GetScalar(sql,param)); 

        // return the custom object to the BLL
        return salesOrderMetaData;
    }
}

3 个答案:

答案 0 :(得分:6)

这是一个好的开始。我会指出一些事情(知道你只是在学习......所以在你去的时候调查这些):

1)每个层当前紧密耦合到它下面的层的实现。通常,在这种情况下,您将“对接口进行编码”。这意味着您的代码与合同相关联而不是实现。不是因为你正在学习而破坏交易...但要记住这一点很好。

2)您的数据层都是非常自定义的。通过调查ORM的使用,你可以在这里省去很多麻烦。他们花了一些时间学习..但是他们值得维护麻烦。

3)通常,您拥有代表域对象的域模型。很多时候这些直接对应于数据库表。然后在您的UI中,您有ViewModel,它表示正在呈现的视图中的当前实体。这使您可以灵活地在ViewModel中添加基于UI的自定义逻辑(验证,格式化等),而Domain Models不需要在其中包含这些特定的UI问题。

如果你真的想开始考虑设计和架构(这太棒了!开始考虑那些东西的荣誉),那么你一定要查看以下内容:

SOLID Principles

ORMs

IoC/Dependency Injection Frameworks

等。我再次赞扬你采取了实际考虑你的应用程序结构的步骤:)

答案 1 :(得分:3)

您不应允许调用者将您的域对象设置为有效。这是你的代码:

public class SalesOrderMetaData
{
    private bool isValid;
    public bool IsValid
    {
        get { return isValid; }
        set { isValid = value; }
    }
}

任何图层都可以将IsValid属性设置为true,然后当另一个图层询问对象是否有效时,它会错误地报告它是有效的。

我建议您将IsValid属性设置为只读(仅get)。内部isValid变量的更新应通过类似Validate()的方法完成,如下所示:

public class SalesOrderMetaData
{
    private bool isValid;
    public bool IsValid
    {
        get { return isValid; }
    }
}

public void Validate()
{
    // Check business rules here and then set isValid value to true or false
}

现在其他图层不能对域对象撒谎,并且说它可能没有,但是可以通过Validate方法请求验证域对象。

使用Validate方法不是解决此问题的唯一方法,只是想让您了解如何处理它。

层之间的交互代码看起来不错。

答案 2 :(得分:0)

到目前为止,你所展示的是基本的n层方法,这是一个良好的开端。通过首先用实体框架代码替换您的数据访问层,从此处构建它可能更容易。另请参阅Unity等控件容器的反转,以此作为进一步分离功能/关注点的方法

Unity在这里:http://msdn.microsoft.com/en-us/library/dn170416.aspx

此处的实体框架:http://msdn.microsoft.com/en-us/data/ee712907