Create a loosely coupled / scalable software architecture

I researched this for several weeks. I am currently developing a poorly coupled architecture design using the n-tier (three-layer) method and factory. My goal is to put each client business logic (ClientA.DLL, ClientB.DLL) in separate namespaces so that the project is scaled, which means that I can change / delete / add specific client business logic without affecting others, because they are independent of each other. Then I call the client namespaces / class using a unique client identifier (a string value that is supported in the database) through the factory namespace. Factory.DLL also hides the logic of each client, and BusinessAbstract.DLL serves as a layout or template that classes for each client will use.

Here is the project solution:

alt text

And here is the actual code:

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 method"; } } } 

Client implementation of AbstractBusinessRule

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

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 example implementation

Web site

  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 } 

And you will also notice that I have a DAL folder in each of the client DLLs, as well as an AbstractBusinessRule DLL, because I also want to scale the DAL layer and use the "UI-BLL-DAL" layer structure.

Any comments / suggestions about this design are welcome. I hope to receive information on how I can improve this structure. Thanks in advance.

+6
c # design-patterns architecture
source share
4 answers

The only thing I see, and I'm foggy, I just skip this while looking at your message, but I don’t see the definition of the DAL interface or the abstraction layer that separates it from your BL as your BL abstracts from your presentation.

This is important because it gives you the flexibility to create a new business layer using the same data in the future without having to rewrite the DAL or replace your database with flat CSV files / mocks in unit testing / a third-party supported soap web service, or something else could be the best storage engine in the future.

+1
source share

You have a major violation of the principle of separation of responsibility / sole responsibility: your business objects are aware of their storage.

The data layer of the three-tier architecture should be responsible for CRUD operations and should be requested for object instances that need users. Something like that:

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

This allows the business layer to focus on implementation and does not allow it to remain persistent. If a new business object is required for the presentation level (to create), it requests a data layer for it.

0
source share

My first comment will be that your names should be more descriptive. It is not at all obvious what your program actually does by looking at the outline of the solution. If you give your client classes and meaningful workspace names, this will be a step in the right direction.

0
source share

this question came out too broadly, there is not one better approach for the whole.

Personally based extension points when adding classes and inheritance without a real case that is very profitable from this, I see that it all ends in great complexity.

It is very difficult to say with the amount of information provided, but consider the alternative of using a more configuration-based approach / does not mean configuration files, but simply configurations that are transferred to the system.

You may have a set of basic rules and a default setting that applies the set of these rules to the client. If you do this in code, when you add the client configuration, you can simply say .AddClient ("ClientA") and it will only use the default rules.

Alternatively, you can specify the rules that apply to client processes when adding a client, which may include setting different rules or even different configuration values ​​for them.

ClientA may have a need that is not included in the basic rules, then a user / code business rule can be applied to the client process.

I would not try to make the transition to such a general structure. Instead, I would focus on specific processes and set extension points for them. When you are working in a solution, general patterns should appear, and then, if necessary (real benefit), you can reorganize it into something more general.

0
source share

All Articles