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
Print Service
referencesLog service
when it need to log the print task down.Log Service
referencesPrint Service
when it need to get some printing detail via some method inPrint 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| |
| +-------+ +-------+ |
| |
+--------------------------------+
CourseService
has a methodGetEligibleStudent(Course crs)
to listStudent[]
those are qualified to enroll certainCourse
base on some course-specific information and complex logic inStudentService
.StudentService
need to callPrintGrade(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.
Print
dependency from theLog
service.Print
service requiredLog
and will provide all details to theLog
, withoutLog
service knowing aboutPrint