It turns out that when you use Google to “query the database in the constructor”, you will find that this problem, even if you emphasize the complexity, has been redefined.
I find it bad practice to query the database in constructors.
There is no direct cost when you look at it at a "low level", people's discomfort is more general. Now it’s easy to ignore such non-specific objections, in practice, when you do this, you are likely to do everything you can, and is equally good compared to dividing the database query into a fetch method. In fact, you then need to write additional code, an additional line to retrieve the data.
What you get in such cases is on a different level than your specific small project in front of you: you force yourself to use a certain style that on average will do you more good, even if you have a (tiny) flaw in the short term.
The advantage is that when you get used to splitting database queries, you get flexibility and “order”: if the code changes later because you want to reload the data throughout the entire life cycle of the object, you need to reorganize what you already they wrote (including in all places where you created such an object, and if others used your code as a module, they should do it too) or destroy / recreate the object. If the fetch function is optional from the start, it will work no matter what!
So, your first proposal is suitable for those who write their personal hobby project on the weekend once a year, if you want or want to become a professional programmer for reasons beyond the scope of any particular project, you should go for something more maintained and streamlined long-term. Long-term projects that are programmed quickly and "dirty" in the enterprise, because they must be small in the end five years later, "monsters", because for the first two years, programmers believed that such short cuts are in order, because "this just a small project. "
As I see it, this is the real purpose of such agreements, to take care of what you do not see (the future).