At the beginning there was chaos, probably the very first big ball of mud :).
When I started programming, the only thing that used to matter to me was the effect of it. It was fine, as it got the job done and delivered business gain. But as the software I worked on became more complicated, I’ve started to see the downsides of not pre thinking the structure of code and overall software architecture.
When you start learning new framework at the beginning of your software development journey, you don’t think of consequences of coupling anything with anything. You just throw anything you need, anywhere you need. Well, when your app is just a simple CRUD with not complicated (or even none) business logic, it’s fine. But when you are creating an application with a more complicated domain which is something more than just an interface for a database, you should be more concerned about what you are using in which layers. It’s a good practice (for me, at least) to create some structure. Something like this:
Application\ is like a person in the company that you encounter when you want something from the company. All interaction with your application go into this namespace. There should be one entry point for every use case. I like to call them Actions. They are a thin layer orchestrating all of the components needed for the use case, just like a customer service person in a company.
Domain\ is describing the business of the company. It’s a knowledge held by your company experts trarnslated into code. There should be no implementation details inside this area, just plain business logic so you can even discuss with experts in the domain. Create interfaces defining contracts that will have to be fulfilled to deliver implementation by an Application Layer. You shouldn’t use there language that will not be understood by a business person (not familiar with programming terms).
Infrastructure\ is a good place for tools that your application does not use directly. If you are using Symfony Framework, you could put there some CompilerPasses, ParamConverters, yaml files. Anything your framework uses but not your application directly will be a good fit there. So, using some analogy — it’s an external supplier that gives your company tools to help you with your Use Cases.
Now the most important part. Application knows about the Domain. But Domain does not know about the Application. Application and Domain do not know about the Infrastructure.
The best way to write good software is to structure it around a problem it solves, not around the software engineering terms like Entity, Controller, etc. That is what Domain Driven Design is all about. For me, personally, getting to know DDD was the biggest game changer in my software engineering career. I hope that this article got your curiosity and you will put some of your attention towards DDD!