Hah, I just finished my response... perfect timing :D
This is a pretty hefty subject so I'll break my answer into three parts: a
bit of history, my opinion, and then why my opinion doesn't matter :)
tldr - Noir is meant to build websites of any size. While I provide some
guidance on a starting point, how you choose to write sites in Noir is
largely up to you.
I've been building sites professionally for just shy of 8 years and I was
around for the beginning of the "web MVC" movement (I actually wrote one of
those frameworks too :D). One thing most people who start out on the web
don't know though, is that what we call MVC is actually something quite
different than the original concept. In the early days of web MVC,
controllers often took on the brunt of the business logic, while models
were mostly data-access oriented - essentially nothing more than
representations of the tables in the database. Controllers then asked the
models for information, did whatever was necessary and passed objects to
the views so they could render themselves. If you look up MVC on wikipedia,
though, you'll find a different description: views ask the models directly
for information and controllers exist solely to handle input and trigger
events. If you apply that architecture to a web server, it would be
something like this: views would ask the models directly for processed data
and render HTML from it. The controller would be responsible for handling
the HTTP request, as that's really the only trigger/input for a
server-based site (there are a couple others, but they don't change the
overall point). When you think about it though, almost everything about an
HTTP request is already handled for you in most modern web frameworks. All
you really need to do is declare what should happen for specific requests.
What this means is that a properly factored controller is incredibly tiny,
essentially it's nothing more than a function triggered per request that
sometimes has an extra two or three lines to handle a little branching or
setting session vars. After building these out for several years, I asked
myself what's the value of this separation? The web framework is already
essentially acting as the controller.
By the true definition of MVC, Noir *doesn't* mix domain logic and
presentation. Domain logic should (regardless of what you're using) reside
in the models, and the controller should simply pass around whatever bits
come from HTTP. Throughout all the websites I've built I've never needed a
heavy controller, and I've found over time that it was significantly
cleaner to just phase them out of my code. Why do I need a middleman that
offers me nothing other than another layer of indirection? Truth was, I
didn't - not for huge websites or tiny ones. Instead of trying to follow
the strict definitions of models, views, and controllers that web MVC tried
to create, I've found it much better to organize my code into pieces that
more closely map with the way I think about the app (which, thanks to
frameworks, has little to do with http). Even for the sites that I've built
that were in the 100's of thousands of lines, controllers didn't really add
any value. And that's why they don't show up in Noir.
This brings me to my next point, Noir isn't trying to be anything we've
seen before. As it stands, it looks a fair bit like Sinatra, though I
actually hadn't thought about that til someone mentioned it on Twitter when
I first released. I didn't intentionally mimic anyone, instead I focused on
making something that fits well with all of the experiences I've had
building sites from scratch. Clojure itself is a very different context
than Ruby, Python, or whatever other language people are coming from and I
think its better to use terms that fit conceptually than to try to avoid
contextual overlap. The use of "view" in this case, is very conceptually
fitting - when someone accesses a url, we notify the models and return a
view of the data (whether it be HTML, JSON, Clojure or some other transport
format). Models then handle data-access (which boils down more or less to
state) and business logic. Very simple, very easy, and incredibly flexible.
Now for the most important part: it doesn't matter what I think. Noir is
written in such a way that you can organize your site however you want.
With 1.2.2-SNAPSHOT you can define a huge list of route strings in some
file, use defpage with those in a "controller" and then use whatever
templating you want. Don't like that either? Try something else then :) I
give people a starting point, based on a decent amount of experience, but
that doesn't mean it's the best way or the "right" way. It's just a
starting point, if you grow out of it and find something better, Noir
should be able to handle it. If it can't, then you should let me know :)
Lastly, you bring up the idea of using Noir as a base to build an even
higher level framework. My question is what would such a thing look like?
I'm not sure you can go much higher level and still maintain the generality
necessary to build whatever website you come up with. Certainly you can
create some nice abstractions over *parts* of the web. For example, you can
use frameworks that abstract creating RESTFUL services or XML-RPC (like
ring-finger or necessary-evil). In the end, though, you often need
something more than just that. The nice thing is that Noir is written in
such a way that you can use those, while still having the flexibility to do
things that may not fit cleanly into such solutions. That being said, if
you have ideas on how to make Noir better, or thoughts on how the
abstraction could be raised even more, I'm definitely all ears! I want Noir
to fit the needs of the Clojure web community. But right now, I actually
think it's pretty close to the sweet spot between simple, easy, and
flexible.
Cheers,
Chris.
On Sat, Nov 26, 2011 at 7:56 PM, Radford Smith <radsm
...@gmail.com> wrote:
> This was originally posted as a GitHub issue:
>
https://github.com/ibdknox/noir/issues/49 > ---
> If we look at things from the MVC perspective, Noir's views are
> actually controllers and views coupled together, a mixture of domain
> and presentation logic. In contrast to other frameworks in the same
> space, such as Sinatra, a view is strictly presentation code. Noir
> seems to be the outlier here.
> I'm not criticizing Noir's decision to couple the traditional MVC
> controller and view logic. This works well for small sites, which
> seems to be Noir's primary use case right now. The problem is the
> simply the name. If your site grows bigger, you'll probably move
> toward the MVC architecture, and you'll have to juggle the concept of
> a Noir view and and MVC view during the transition. Any reference to a
> view in the Noir documentation is a mental switch from what most
> people already know as a view.
> This raises a question: what is Noir's intended place in the world of
> web frameworks? Is it like Sinatra, where you build a small site and
> eventually grow out of it, or is it something you can continue to
> build on top of as your site gets more complex? As the author has
> mentioned in the discussion group, decoupling Noir's components is
> trivial. I think large sites and frameworks could use Noir as another
> layer in the onion (as someone in #clojure IRC put it), similar to
> Ring's use case.
> We could make this happen and still support smaller sites. The
> controller and view can still be coupled by default, but these
> functions should not be called views. I haven't thought about a better
> name too much (actions? pages, as in defpage?), but I wanted to raise
> the issue, as I think it could confuse new users, especially those
> coming from traditional MVC frameworks.
> Here's an example: if you prefer to put your controller logic in
> separate files, you're going to get something like this in your
> server.clj as of Noir 1.2.1:
> (server/load-views "src/my-app/controllers/")
> If you're not familiar with Noir, this is nonsense.