Note: The Model, View, Controller pattern, or “MVC”, actually comes in many flavors, but for the purposes of this article, I’m referring to MVC fo...
For further actions, you may consider blocking this person and/or reporting abuse
Model is usually (in most frameworks) connected to database with some ORM. There were some frameworks which also used models for different stuff like form models. I actually liked that.
However, if your model is connected to the database, I wouldn't put any business logic into it, other than getting even more data from the database. ORM objects are rather hard to instantiate in tests and unstable to pass around in your application. I don't ever feel safe when my object has the
->save
method.So what I've been trying to do lately instead is to create DTOs (Data Transfer Objects) for pretty much everything and repositories to save and fetch DTOs. Models are just used by the repositories. It is much easier in Perl because with Moose MOP you can skip tedious creation of DTOs and methods to translate DTO to model (usually two per model).
DTOs are easy to create, safe to pass around and in my case, they already contain all the right type constraints (with Type::Tiny). I also created a common DTO method named
->dummy
which creates a new offspring class for the DTO with all the same type constraints but with no required fields, so that I can create DTOs even if I don't technically have all the data it needs. I admit that it's not a tested solution but works pretty well where I use it, and when I talk with my coworkers about it (in PHP context) they often agree.Let me know if this is interesting to you, I can extend that to a full dev.to post with some Perl examples and such
I think seeing a dev.to article about that would be great!
Even though Python can't legibly get the terseness of a Perl or Ruby, I still aim for the shortest clearest function / method that gets the job done.
I often start sloppy, putting the logic where I think of it, then refactoring out as I see repetition or big chunky complexity that obscures the job of the current function. Pretty remarkable how often those refactored bits end up being useful for other contexts within the application.
I can understand that point of view and I used to be there. Over time, I discovered that when I knew that a particular place was bad for my code, leaving it there would cause issues in the long run. Refactoring a large, working application is hard work.
That being said, just because I know where something doesn't belong doesn't always mean I know where it does belong. Software is still hard 😃
Well, yeah. There is that. "Where I think of it" isn't quite as random as it was for me say ten or twenty years ago. Plus, the "refactor" flags start waving about five to ten lines in. The river follows the path of least resistance, but often enough it follows the path that already worked.
OTOH it's not uncommon for me to wake up to an ugly chunk of code I added last night at 2am that urgently needs to be cleaned up for my own sanity.
How can we change the fact that people who implement those bad practices sometimes just follow the recommendations of doing the work the fastest and cheapest way, imposed by decision makers who don't know what they are doing, without thinking of the future, that will surely be a mess if done that way? 😭
We'll never fully eliminate that because sometimes, doing things the fastest, cheapest way is what's needed to stretch the budget towards hitting that MVP. It's not an either/or proposition.
However, it can be mitigated by strong hiring practices up front. Hiring is one of the things tech companies are worst at (they're getting better a hard skills, but not soft skills). But if you get the right devvelopers, their default position is doing good work and cutting corners as needed. When the default is cutting corners, doing good work becomes much more expensive and much less obvious.
Thanks for putting into words what I've had in mind for months!
In the same line of thought, I once had a senior dev tell us
and as a dev whose work for the past years has basically been connecting web UIs to databases I took it very personally because I was like "so, what's left? :'("
Only with experience I later realised how important it was to have a Model that is agnostic to what happens outside of the business logic, that doesn't do database calls, and that doesn't generate any HTML
It's a sad problem that for many companies today, a "senior" dev is decided by years of experience, not ability. Thus, technical ability is sometimes dismissed by the business side.
That being said, "years of experience" often means "business knowledge" and that's something which is sometimes dismissed by the technical side.
I've given talks before about how to bridge this divide, but it's hard to do. So many have chosen which side of the management/technology divide they're on and they're happy to stay there.
In general, tutorials are broken, at least from the student point of view. They show a single solution to a problem that may have different trade-offs, which are swept under the rug. They put the student into the mentality of "this is how it's done". That's rarely the case in a complex business environment.
Not to mention the speed with which they become obsolete, or how they introduce bad practices on the emitting side, and cargo cult programming on the receiving side.
Separation of concerns is such a key aspect that many dont get
My brief way of saying this is "if your tests are hard (or impossible) to write, you probably need a refactoring or two or three..."
Absolutely! I should write a post about that: tests that are hard to write are often a code smell.