7

I've been trying to adhere to a strict interpretation of MVC in rebuilding a personal web application at home, but I'm having some issues.

The application is a financial tracking application. I'm stuck at the first page, which is just a list of the bank account transactions for the month. The transaction list is my Model. The Controller and View are easy enough to envision at this point.

However, I also have two buttons at the top of the page. They are arrows, one corresponding to the previous month, and the other corresponding to the next month's transaction list. I don't want these buttons enabled if there are no transactions for the previous/next month, so I need to talk to the database to figure out whether each button should actually link somewhere.

From most of what I've read, to the largest extent possible database access should be encapsulated in models, with little to no database access in Controllers and Views.

However, these buttons essentially need to ask the database, "Are there any transactions for the next/previous months?" The answer will determine whether or not their links are disabled, as well as where to send the user.

Strictly speaking, putting their logic into the Transaction List model does not seem appropriate, as whether or not transactions exist outside the requested range is beyond the concern of the Transaction List Model.

I guess I could also make another Model that would correspond to all Year-Month combinations where transactions exist. I could then pass this Model and the Transaction List on to the proper View.

Or should I deviate from the no-database-access-outside-the-model paradigm, and just throw some quick DB querying into the View (since the result is essentially a UI concern, making navigation easier)?

What do you guys think about this conceptual issue?

BTW, I am not using any framework. This is pet project designed to get me more familiar with the nuts and bolts of the MVC pattern.

Clayton Roth
  • 95
  • 2
  • 6

2 Answers2

2

... should I deviate from the no-database-access-outside-the-model paradigm, and just throw some quick DB querying into the View ...

The short answer is: no. If you're truly interested in learning MVC and better coding in general, taking shortcuts "just because" is a very bad idea. Domain logic separation is a fundamental concept of MVC, and to violate it would essentially be moving out of MVC into territory that is dominated by terrible code and "MVC Frameworks." If you want to learn "the nuts and bolts of MVC," you'll have to understand that the nuts and bolts are things like separation of concerns, and they are very important.

A lot of the text in your question suggest a few mixed ideas about what a model should be, so I'm going to redirect you to the most linked-to answer regarding MVC models. That answer encompasses everything you'll want to know about the concept of models. To summarize the most important concept from it, a model is not a class, it's a layer. The model layer has many components that all do their own thing, which leaves you with a testable, extensible, semantic, and logical domain logic layer.

Just remember to be careful: There is way more mis-information out there about MVC than there is reliable information. The worst thing you can do to learn proper MVC is look inside of a framework that claims to be MVC.

edit: I assumed the language was PHP while responding, so some of my answer might reflect that assumption. However the concepts are applicable across nearly all languages

Community
  • 1
  • 1
orourkek
  • 2,091
  • 15
  • 22
  • I took a look at the link you gave (which was fantastic, btw), but I'm still left wondering: once the "Service" has done its thing of associating a Domain Object with one or more Data Mappers, what does the Service return? Is it okay if the Service returns the fully fleshed-out Domain Object, or should it return something else? – Clayton Roth Aug 27 '12 at 20:34
  • @ClaytonRoth That's somewhat debatable. Returning a domain object out of the model layer would be very convenient, but you would be purposefully leaking domain logic out of the model layer. The ideal solution, although quite involved initially, is to translate those domain objects into something like [Data Transfer Objects](http://martinfowler.com/eaaCatalog/dataTransferObject.html), which can be used throughout the application. The issue is that you'd then have two container classes to maintain, which can develop into a more significant problem if the codebase is large enough. – orourkek Aug 27 '12 at 20:44
  • I did some looking at Data Transfer Objects, and it looks like everyone agrees that DTO's do indeed multiply container classes. Do you believe that an acceptable middle-ground would be to use a generic Transformation class which would create an XML representation of a serialized object? Using Reflection, you would only need to create a single class, with maybe a few methods to tweak the output, and you could still have Service Layer isolation. – Clayton Roth Aug 27 '12 at 23:37
  • If you want to avoid writing specific DTOs altogether, then either a generic DTO or a DTO automapper would be the way to go. Both solutions are a bit of a shortcut around maintaining DTOs **and** DOs, But the anonymous/generic DTO is one (small) logical step above an array, so you'll have to assess whether or not it's intelligent to add another generic data structure into the application. Personally I prefer to write the specific DTOs, just to be 100000% sure that everything comes out on the other side exactly as planned. – orourkek Aug 27 '12 at 23:43
1

The application is a financial tracking application. I'm stuck at the first page, which is just a list of the bank account transactions for the month. The transaction list is my Model. The Controller and View are easy enough to envision at this point.

Everything on your web page, is categorised in the View domain. A "list" is a visual object.

For a web application/page, The model exists on your server, within your database. Everything that exists on the web page, (Buttons, Forms, List boxes etc) is you View domain.

From most of what I've read, to the largest extent possible database access should be encapsulated in models, with little to no database access in Controllers and Views.

The View objects traditionally talk directly to your Model objects. Which means you have to provide a way for your View objects to talk to your database.

An example,

  • http//server/transactions (Get all transactions)
  • http//server/transactions?from=x (Get transactions from x)
  • http//server/transactions?from=x&to=y (Get transactions from x to y)

Could be your interface to your Model by your View.

Michael Brown
  • 498
  • 4
  • 13