2

I am currently starting a new project with a 4-tier architecture design. The layers is set as follow.

                                          +------------------+
                         +----------------+   Presentation   |
                         |                +------------------+
                         |                         |
                         |                         |
                         |         +---------------v----------------+
                         |         |                                |
                         |         |         Services (dll)         |
                         |         |                                |
                         |   +-----+  +------+  +------+  +------+  |
                         |   |     |  | Log  <-->Print <--+Other |  |
                         |   |     |  +------+  +------+  +------+  |
                         |   |     |                                |
                         |   |     +--------------------------------+
                         |   |                     |
                         |   |                     |
                         |   |            +--------v---------+
                         |   |   +--------+  Business Logic  |
                         |   |   |        +------------------+
                         |   |   |                 |
                        +v---v---v+                |
                        |         |       +--------v---------+
                        |   DTO   <-------+   Data Access    |
                        |         |       +------------------+
                        +---------+

In service Layer, I encountered a circular referencing problem as

  1. Print Service references Log service when it need to log the print task down.
  2. Log Service references Print Servicewhen it need to get some printing detail via some method in Print Service

All of the services and other tiers/layers is existed as a csproj, so it will be compiled as a dll.

I would like to know how can I get rid of such scenario? After doing some research, the most possible solution is to create an interface project for each service. Is there any other better solution?

If I really adopt interface projects approach as a solution, Does it mean that I must go along with Dependency Injection? Dependency Injection is powerful, but it makes codes to be more difficult to trace too!

Lastly, as Presentation Layer cannot reference BLL directly. Therefore, some classes and models defined in BLL cannot be referenced. Is it a good idea to store those classes and models in DTO project so that it can be used by upper-indirectly-referenced layers? (Of course I will rename the DTO project to some more meaningful name e.g. BusinessObjects)

UPDATE 1

I know my example may not be good enough. Let me change the requirement.

CourseService and StudentService this time. The dependency is visualized as follow

                            +--------------------------------+
                            |                                |
                            |         Services (DLL)         |
                            |                                |
                            |   +-------+        +-------+   |
                            |   |Course <-------->Student|   |
                            |   +-------+        +-------+   |
                            |                                |
                            +--------------------------------+
  1. CourseService has a method GetEligibleStudent(Course crs) to list Student[] those are qualified to enroll certain Course base on some course-specific information and complex logic in StudentService.
  2. StudentService need to call PrintGrade(Course crs, Student stu) to retrieve certain course grade of the a student.

Seems this example is better. I know someone may challenge that GetEligibleStudent(Course crs) should be placed in StudentService or PrintGrade(Course crs, Student stu) should be placed in CourseService. However, circular dependency may exist anytime in development. An appropriate solution should be took, not just in my example.

  • why would log service need printing details? to do formatting? if yes, it shouldn't, that's the print service's job. if for the call in 1 - pass all necessary data, or pass a reference to the print service object, so the log service can question it. but I don't see for what it would need that. – Aganju Nov 17 '18 at 21:58
  • Thanks for your attention. I get your point. Maybe this example is not good enough. I just want to bring out how do I handle such circular dependency case. I try to use a better example instead. – mannok Nov 17 '18 at 22:02
  • 2
    The most simple solution seems to have an interface. – Konrads Nov 17 '18 at 23:48
  • 1
    I think solution would be remove Print dependency from the Log service. Print service required Log and will provide all details to the Log, without Log service knowing about Print – Fabio Nov 18 '18 at 0:37
  • 2
    Another approach is to follow "rule" that when you have circular dependency you will introduce third separated library which will combine two others. – Fabio Nov 18 '18 at 1:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.