0

While dividing my C# application in layers, I have solved the problem of circular dependency among layers in the following way:

using System;
using System.Collections.Generic;
using System.Text;

using SolvingCircularDependency.Common;
using SolvingCircularDependency.DA;

namespace SolvingCircularDependency.BO
{
    public class MyClass : IPersistent
    {
        private string _message;
        public string Message
        {
            get { return _message; }
            set { _message = value; }
        }

        public bool Save()
        {
             return MyClassDA.Save(this);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Text;

namespace SolvingCircularDependency.Common
{
    public interface IPersistent
    {        
        bool Save();
        string Message { get;}
    }
}

using System;
using System.Collections.Generic;
using System.Text;

using SolvingCircularDependency.Common;

namespace SolvingCircularDependency.DA
{
    public class MyClassDA
    {
        public static bool Save(IPersistent obj)
        {
            Console.WriteLine(obj.Message);

            return true;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Text;

using SolvingCircularDependency.BO;

namespace SolvingCircularDependency.UI
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myobj = new MyClass();
            myobj.Message = "Goodbye Circular Dependency!";
            myobj.Save();

            Console.ReadLine();
        }
    }
}

Can anyone suggest me any better solution as the "Common" project in the sln is looking redundant to me?

3 Answers 3

2

It's up to you to decide if IPersistent should be declared in Common or Service assembly. The best practice (usually) is to declare interfaces in a separate assembly for better layer separation. You need to take into account things like how often developers will create implementations of IPersistent, is it really need to be loose coupled, etc.

Sign up to request clarification or add additional context in comments.

2 Comments

What do u mean by Service Assembly?
Sorry again, i think my prev answer can be non-obvious. I think Common is an assembly that has no dependencies to other assemblies (your own). If it's true that means the assembly is a good candidate to host IPersistent interface.
1

Point your attention to Dependency Inversion Principle.

5 Comments

Yes, DI is a common case when we're dealing with service/interface issue.
How can I rewrite this program using DI?
No, please don't. I mean, if you ask the question this way. DI means 'loose coupling' which is rarely required in real life (when used improper it adds incredible configuration hell).
@frogbot What? 'loose coupling' is a good design principle that should always, I repeat, always be aspired towards. Not trying to achieve loose coupling will result in highly duplicated code that is dependent on large numbers of things. This means every change you make to the system will now effect more and more classes, resulting in more and more bugs. It becomes a maintenance nightmare and quickly.
I think you have a mix in your IPersistent interface. It seems it has at least two consumers - DA classes access data properties (like Message) and someone (which isn't shown here if it exists) consumes IPersistent.Save() because it seems no sense to consume it from DA classes. So once you separate those to responsibilities you can move on to refactoring your solution. Next you need to identify which part your are going to reuse and thus make its dependencies weak - put IPersistent interface in a separate assembly (Separated Interface principle) or put it into assembly with reusable classes.
0

IPersistence is a concern for you DA and a means for your BO to communicate through it. That relationship should end there. Your UI should only know your BO and if you need to define a new interface to support "coding to contracts" define a new one in your BO. Your UI and BO should have separate concerns for what they do within the system.

For example, the IPersistence interface is going to define specific tasks for persisting the record to the database. You don't want that in your UI because it would be bypassing your BO. So unless you want an anemic BO, which really doesn't do anything and shouldn't be there at all, define something new at that level that relates to supporting your business logic.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.