创建松散耦合/可扩展的软件架构

时间:2010-09-17 18:12:48

标签: c# .net design-patterns architecture

我一直在研究这个问题。我目前正在使用n层(3层)方法和工厂设计方法设计松散耦合架构设计。我的目标是将每个客户端的业务逻辑(ClientA.DLL,ClientB.DLL)放在单独的命名空间中,以便项目扩展,这意味着我可以修改/删除/添加特定客户端的业务逻辑而不会影响其他客户端,因为它们是不依赖于彼此。然后,我使用客户端的唯一标识符(在数据库中维护的字符串值)通过Factory命名空间调用客户端的名称空间/类。 Factory.DLL 隐藏每个客户端逻辑,而 BusinessAbstract.DLL 用作每个客户端的布局或模板课程将使用。

以下是项目解决方案:

alt text

以下是实际代码:

BusinessAbstract.DLL

namespace BusinessAbstract
{
   // the entity / data transfer object
   public class MemberDTO
   {
      public string MemberID { get; set; }
      public string MemberName { get; set; }
    }

   // the interface
   public interface IMaintainable
   {
      void Add();
      void Edit();
      void Delete();
   }

  // the base abstract class, implements the Entity and the Interface
  public abstract class Member : MemberDTO, IMaintainable
  {
    // Implement IMaintanable but change it to abstract
    public abstract void Add();
    public abstract void Edit();
    public abstract void Delete();

    // a method with Database access, get from DAL
    public virtual MemberDTO GetMemberDetails(params object[] args)
    {
        return DAL.MemberDAL.FetchMemberDetails(args);
    }

    public virtual string GetClientBLL()
    {
        return "base's method";
    }
   }
 }

AbstractAusinessRule的ClientA实现

ClientA.DLL

 namespace ClientA
 {
    public class _Member : BusinessAbstract.Member
   {
       public override void Add()
      {
        throw new NotImplementedException();
      }

      public override void Edit()
      {
        throw new NotImplementedException();
      }

      public override void Delete()
      {
        throw new NotImplementedException();
      }

      public override string GetClientBLL()
      {
        return "ClientA Method";
      }
    }
 }

工厂

Factory.DLL

 public static class Invoker
 { 
     public static T GetMemberInstance<T>(string clientCode)
        where T : Member, IMaintainable
      {
        Type objType = Type.GetType(clientCode + "._Member," + clientCode);
        return (T)Activator.CreateInstance(objType);
      } 
  }

Presentation Tier上的示例实现

网站

 protected void Page_Load(object sender, EventArgs e)
 {

    // invoke Member class using String hardcode
    Member obj = Invoker.GetMemberInstance<Member>("ClientA");
    Response.Write(obj.GetClientBLL()); //prints clientA method

    obj = Invoker.GetMemberInstance<Member>("ClientB");
    Response.Write(obj.GetClientBLL()); //prints clientB method

 }

你还会注意到我在每个客户端DLL和AbstractBusinessRule DLL中都有一个DAL文件夹,因为我还想缩放DAL层并使用层结构“UI-BLL-DAL”。

欢迎任何有关此设计的意见/建议。我希望能得到关于如何改进这种结构的意见。提前谢谢。

4 个答案:

答案 0 :(得分:1)

我唯一能看到的东西,我只是在查看你的帖子时忽略了这一点,但是我没有看到一个DAL接口定义或抽象层将BL从你的BL中抽象出来的方式从你的BL中分离出来介绍

这很重要,因为它为您提供了使用相同数据创建新业务层的灵活性,而无需重写DAL,或者在单元测试/第三方维护中使用平面CSV文件/模拟替换您的数据库soap Web服务响应,或者将来可能是更好的数据存储机制。

答案 1 :(得分:0)

您基本违反了关注点分离/单一责任原则:您的业务对象了解其存储空间。

3层体系结构的数据层应该负责CRUD操作,并且应该查询消费者需要的对象的实例。像这样:

Presentation Layer ------- Data Layer
                              ||
                              ||
                       Business Layer

这允许业务层专注于实现,并保持持久性问题。如果表示层需要一个新的业务对象(用于创建),它会向数据层询问它。

答案 2 :(得分:0)

我的第一个评论是你的名字需要更具描述性。通过查看解决方案大纲,您的程序实际上做了什么并不明显。如果您为客户端类和工作区提供有意义的名称,那么这将是朝着正确方向迈出的一步。

答案 3 :(得分:0)

这个问题过于宽泛,没有一个最适合所有方法。

在添加类和继承时,个人基础上的扩展点没有真正受益于它的真实案例,这是我所看到的一切都非常复杂。

很难说明提供的信息量,但考虑使用更基于配置的方法的替代方法/并不意味着配置文件,只是传递到系统中的配置。

您可以拥有一组基本规则,以及将一组规则应用于客户端的默认配置。如果您在代码中执行此操作,则在添加客户端配置时,您可以只说.AddClient(“ClientA”),它将仅使用默认规则。

或者,您可以在添加客户端时指定适用于客户端进程的规则,这可能涉及为这些规则设置不同的规则甚至不同的配置值。

ClientA可能需要未包含在基本规则中,然后可以将自定义/代码业务规则应用于客户端进程。

我不会尝试一直跳到这样的通用框架。相反,我会将上述内容集中在特定流程上,并为这些流程公开扩展点。当你在解决方案中工作时,应该出现常见的模式,然后在适当的时候(看到真正的好处)你可以将它重构为更通用的东西。