struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mike Menzies <glo...@gmail.com>
Subject Re: JspHelper concept to improve MVC separation
Date Mon, 07 Oct 2013 21:22:07 GMT
Ya, kinda... for how we use model driven we probably should be using the
scoped version, but that's not the case. We have an abstract action that
handles the validation/refreshing/storing of the model in the session. It's
overkill, but it's heavily unit tested and robust, so we continue using it.


On Mon, Oct 7, 2013 at 4:12 PM, Dave Newton <davelnewton@gmail.com> wrote:

> You mean like ScopedModelDriven?
>
> I'm a big fan of presenters/decorators most of the time, although I'll
> admit I'm also lazy a lot and just use a "real" model and tags :/
>
> Dave
>
>
>
> On Mon, Oct 7, 2013 at 5:08 PM, Mike Menzies <glopal@gmail.com> wrote:
>
> > Hmm.. ya, that makes a lot of sense. I think I will try this approach
> going
> > forward. We sort of bastardize model-driven a little bit by having a
> layer
> > that stores and retrieves the model in the session on every request
> (among
> > other things)... which in most cases is not needed.
> >
> > You've given me some things to think about. Thanks Dave.
> >
> >
> > On Mon, Oct 7, 2013 at 4:00 PM, Dave Newton <davelnewton@gmail.com>
> wrote:
> >
> > > "The" model? "The" model is whatever you want exposed to the view
> layer;
> > > there's nothing that states it has to be the lowest-level domain object
> > > available--it's just "that which you wish exposed to your rendering".
> > >
> > > I don't usually use the built-in validations (for a variety of reasons)
> > so
> > > I'd have to experiment with that to find what I liked.
> > >
> > > Dave
> > >
> > >
> > > On Mon, Oct 7, 2013 at 4:56 PM, Mike Menzies <glopal@gmail.com> wrote:
> > >
> > > > I can see that approach working well. You don't feel that it's
> misusing
> > > > ModelDriven... by not directly returning the model?  Also, if you are
> > > > validating your model, would adding @VisitorFieldValidator to the
> > domain
> > > > getter within the decorator work the same?
> > > >
> > > >
> > > > On Mon, Oct 7, 2013 at 3:43 PM, Dave Newton <davelnewton@gmail.com>
> > > wrote:
> > > >
> > > > > Then I'm not sure I see the point; `ModelDriven` would do the same,
> > but
> > > > > you'd expose the decorator, not the underlying domain object. I
> tend
> > > > > towards the same pattern, but delegate directly to a domain model,
> > so I
> > > > can
> > > > > precisely control access (and document) at the view level.
> > > > >
> > > > > Dave
> > > > >
> > > > >
> > > > >
> > > > > On Mon, Oct 7, 2013 at 4:38 PM, Mike Menzies <glopal@gmail.com>
> > wrote:
> > > > >
> > > > > > Yes. That's pretty much exactly what it is.
> > > > > >
> > > > > >
> > > > > > On Mon, Oct 7, 2013 at 3:35 PM, Dave Newton <
> davelnewton@gmail.com
> > >
> > > > > wrote:
> > > > > >
> > > > > > > So it's a presenter/decorator?
> > > > > > >
> > > > > > > Dave
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On Mon, Oct 7, 2013 at 4:26 PM, Mike Menzies <glopal@gmail.com
> >
> > > > wrote:
> > > > > > >
> > > > > > > > Hello,
> > > > > > > >
> > > > > > > > My name is Mike, and I work for a fairly large company
that
> > uses
> > > > > > Struts 2
> > > > > > > > for most of its web apps. Some of these web apps are
quite
> > large,
> > > > and
> > > > > > one
> > > > > > > > in particular has grown into a monster. In my ongoing
efforts
> > to
> > > > > clean
> > > > > > up
> > > > > > > > this project, I have developed what I like to call
a
> JspHelper.
> > > > > Before
> > > > > > I
> > > > > > > > explain exactly what that is, I'd like to provide
you with
> some
> > > > > > examples
> > > > > > > of
> > > > > > > > the problems that I set out to fix.
> > > > > > > >
> > > > > > > > *Problem 1 - Monster JSPs*
> > > > > > > > During early development of this project, struts tags
were
> > highly
> > > > > > > > leveraged. I was not involved with the early phases
of this
> > > > project,
> > > > > > so I
> > > > > > > > can't speak to why they were used so extensively..
but they
> > were.
> > > > > Tons
> > > > > > of
> > > > > > > > nested if tags that read var tags that were set in
the JSP.
> > Some
> > > of
> > > > > > these
> > > > > > > > JSPs were very hard to follow.
> > > > > > > >
> > > > > > > > Even though I am a fan of struts tags, I've come to
realize
> > that
> > > > they
> > > > > > > > should not be overused. JSPs cannot be unit tested
and JSPs
> are
> > > > hard
> > > > > to
> > > > > > > > debug.
> > > > > > > >
> > > > > > > > So cleaning up a JSP means shifting logic out, in
most cases
> > into
> > > > the
> > > > > > > > action. An easy clean up could be something like this:
> > > > > > > >
> > > > > > > > <s:if test="articles != null && articles.size
> 0 &&
> > > > > > > user.canViewArticles">
> > > > > > > >
> > > > > > > > into
> > > > > > > >
> > > > > > > > <s:if test="showArticleSection()">
> > > > > > > >
> > > > > > > > It's instantly more readable, and the logic is in
a testable
> > Java
> > > > > > class.
> > > > > > > > Following this approach creates a lot of methods in
the
> action,
> > > > which
> > > > > > can
> > > > > > > > be a problem if you already have...
> > > > > > > >
> > > > > > > > *Problem 2 - Bloated Action Classes*
> > > > > > > >
> > > > > > > > When the project was small, it made a lot of sense
to create
> > > > > > > > abstract/parent action classes to share code between
actions.
> > As
> > > > time
> > > > > > > > passed, we just continued shoving any shared code
in one of
> two
> > > > > > > "abstract"
> > > > > > > > classes... even if the code was only being shared
between two
> > out
> > > > of
> > > > > > the
> > > > > > > 20
> > > > > > > > actions.
> > > > > > > >
> > > > > > > > The fix for this trend is to moved shared code into
services,
> > so
> > > we
> > > > > > began
> > > > > > > > enforcing that practice. But this approach had its
> limitations.
> > > We
> > > > > use
> > > > > > > > Spring injection for all of our services, and some
times a
> > > > particular
> > > > > > > piece
> > > > > > > > of logic just required too much stateful input...
it just
> made
> > > more
> > > > > > sense
> > > > > > > > to leave it on the action where it had easy access
to
> > everything
> > > it
> > > > > > > needed,
> > > > > > > > as opposed to shoving it in a stateless service and
having to
> > > pass
> > > > > in a
> > > > > > > ton
> > > > > > > > of arguments.
> > > > > > > >
> > > > > > > > What we really needed was some best practices put
in place
> for
> > > the
> > > > > > > creation
> > > > > > > > of stateful, non-Spring services.
> > > > > > > >
> > > > > > > > *Enter JspHelperInceptor
> > > > > > > >
> > > > > > > > *
> > > > > > > > It wasn't until after I created this inceptor that
I realized
> > it
> > > is
> > > > > > > almost
> > > > > > > > identical to the ModelDrivenInceptor. At which point,
I
> > wondered
> > > if
> > > > > > that
> > > > > > > is
> > > > > > > > what I should actually be using.. but more on that
later.
> > > > > > > >
> > > > > > > > All this interceptor does is push an object onto the
value
> > stack.
> > > > > > That's
> > > > > > > > it. Your action implements JspHelperAware which provides
> Object
> > > > > > > > getJspHelper(), and the intercept code reads almost
line for
> > line
> > > > > with
> > > > > > > the
> > > > > > > > ModelDrivenInterceptor.
> > > > > > > >
> > > > > > > > The idea behind this JspHelper, which is just a POJO
that you
> > > > define,
> > > > > > is
> > > > > > > to
> > > > > > > > provide a place where all (or most) of the data your
JSP
> needs
> > > can
> > > > be
> > > > > > > > found. This means that OGNL can find any public members
or
> > > > operations
> > > > > > > > faster, and also developers can trace back any OGNL
> expressions
> > > in
> > > > > the
> > > > > > > JSP
> > > > > > > > to it's corresponding Java code.
> > > > > > > >
> > > > > > > > This approach places code in a shareable component.
You can
> > > easily
> > > > > > > > aggregate one JSPHelper into another one, and then
either
> > provide
> > > > > > wrapper
> > > > > > > > methods or simply push the aggregate helper onto the
stack
> > using
> > > > the
> > > > > > > s:push
> > > > > > > > tag for direct access to it's members.
> > > > > > > >
> > > > > > > > This approach makes the actions leaner, and provides
a very
> > clear
> > > > cut
> > > > > > > view.
> > > > > > > > I find at times that the action tends to be both controller
> and
> > > > view,
> > > > > > > when
> > > > > > > > really it should only act as the controller (IMO).
> > > > > > > >
> > > > > > > > This technique is functionally very similar to ModelDriven,
> but
> > > > it's
> > > > > > used
> > > > > > > > slightly differently. I've used a JspHelper in combination
> with
> > > > > > > > ModelDriven, and I've found the JspHelper to be a
good place
> to
> > > > store
> > > > > > > > logic.. and leave the Model strictly as a business
object.
> > > > > > > >
> > > > > > > > *Conclusion
> > > > > > > > *
> > > > > > > > I have personally found this technique incredibly
useful in
> > > > cleaning
> > > > > up
> > > > > > > > code. You can shift all of the JSP exclusive logic
and
> > properties
> > > > to
> > > > > > the
> > > > > > > > helper without touching the JSP (the OGNL expressions
remain
> > the
> > > > > same).
> > > > > > > > Then after that initial step, you have a real handle
on the
> > exact
> > > > > input
> > > > > > > > your JSP needs, and the actual clean up process progresses
> > faster
> > > > and
> > > > > > > with
> > > > > > > > less errors. I'm still in the process of establishing
some
> best
> > > > > > > practices,
> > > > > > > > but so far this approach is working for us.
> > > > > > > >
> > > > > > > > I would like some honest feedback
> > > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > --
> > > > > > > e: davelnewton@gmail.com
> > > > > > > m: 908-380-8699
> > > > > > > s: davelnewton_skype
> > > > > > > t: @dave_newton <https://twitter.com/dave_newton>
> > > > > > > b: Bucky Bits <http://buckybits.blogspot.com/>
> > > > > > > g: davelnewton <https://github.com/davelnewton>
> > > > > > > so: Dave Newton <
> > http://stackoverflow.com/users/438992/dave-newton
> > > >
> > > > > > >
> > > > > >
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > e: davelnewton@gmail.com
> > > > > m: 908-380-8699
> > > > > s: davelnewton_skype
> > > > > t: @dave_newton <https://twitter.com/dave_newton>
> > > > > b: Bucky Bits <http://buckybits.blogspot.com/>
> > > > > g: davelnewton <https://github.com/davelnewton>
> > > > > so: Dave Newton <http://stackoverflow.com/users/438992/dave-newton
> >
> > > > >
> > > >
> > >
> > >
> > >
> > > --
> > > e: davelnewton@gmail.com
> > > m: 908-380-8699
> > > s: davelnewton_skype
> > > t: @dave_newton <https://twitter.com/dave_newton>
> > > b: Bucky Bits <http://buckybits.blogspot.com/>
> > > g: davelnewton <https://github.com/davelnewton>
> > > so: Dave Newton <http://stackoverflow.com/users/438992/dave-newton>
> > >
> >
>
>
>
> --
> e: davelnewton@gmail.com
> m: 908-380-8699
> s: davelnewton_skype
> t: @dave_newton <https://twitter.com/dave_newton>
> b: Bucky Bits <http://buckybits.blogspot.com/>
> g: davelnewton <https://github.com/davelnewton>
> so: Dave Newton <http://stackoverflow.com/users/438992/dave-newton>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message