Is
it just me or does this example seem incredibly forced? To start with,
although I know this isn't the code about which the questions are being
asked, why does the Content object require these "atoms" for it's
properties? Mebbe I'm missing something, but when I see getName() (and
hasName really is just getName in disguise), it immediately implies
there is a private access name variable encapsulated in the class and
the only relevant pattern at play here is retrieval of it's value.
Tom, those examples are not forced - they're actual code. I don't know
if this makes me proud or not, but it's the code I'm writing... sorry
if your eyes hurt, but bear with me, there are some interesting things
we can get out from this mess :)
Having an empty Content class, for example, stuffed with the "atoms"
(related properties and methods encapsulated into the smallest unit of
work possible) gives me a lot more flexibility than plain OOP
techniques. To name a few:
AspectWerkz does transparent persistence for introductions and
advices, so I don't need to worry about persistence for now. Jon Tirsen
pointed out that this leads to performance problems, as AspectWerkz
creates a new transaction for every field modification, and thus
Prevayler has a lot of work to do. Actually, I'm not really concerned
about this, because I can change my persistence mechanism later, if
performance becomes a problem. I don't think it will, because, like
most web applications, this one will have a lot more reads than writes
to the object model.
I'm happily reusing a *lot* of code, by making related
properties, methods and fields as "atoms" that I simply "glue" to any
business object I want. So name, owner, permissions, creation and
modification dates and meta-data in general are reusable little
components I slap into my objects. This has a great side effect: if
business requirements change, I can simply add or remove these atoms
from the objects by changing AspectWerkz' XML definition.
Having all the object and atoms definitions on the AspectWerkz
XML configuration allows me have a central place to look at in order to
understand my object model, and to create pretty XSLTs so I can explain
what's going on at any given time.
Mebbe
this is bad naming, but the hasText and hasHtmlText seem to be to be
even worse. What's wrong with polymorphism, here? How are you supposed
to test this outside of the live container? How do you do static
analysis on this code? What prevents some empty class from having so
many introductions and advices that it's unmanageable?
Nothing wrong with polymorphism - in fact, I'm using a lot more of it
on my system. Now, when I need to call the getName() method, I actually
need to use the HasName interface, and not a reference to the Content
object:
public void displayName(HasName obj) { System.out.println("The object " + obj.getClass().getName() + " is called '" + obj.getName() + "'."); }
You're probably thinking: "shit, Carlos! Can't you see you're
hard-coding your atoms in the objects when you start typecasting
stuff?". Yes, I see it, and I don't like it either, but every idea I
tried to get away with that typecast ended up bringing more trouble
than it's worth. If you have any comments on this, please tell me :)
Regarding testing, you can test 4 different parts of the system independently:
The atoms themselves - they're just regular java classes, so that's pretty easy
"Stuffed" business objects - requires running the test system
through AspectWerkz, and thank god JUnit weird classloaders work nice
with it :)
Business logic - also, regular java classes
WebWork actions - not a problem, after you create some mock objects for scoped data (request, session, application)
As for the question
itself, while I am not so sure about using ThreadLocal variables as Jon
Lipsky suggests, I agree with his approach of abstracting away via a
SecurityContext and hiding some system-level interaction with the
container. Why re-invent the wheel? Carlos admits he's using WebWork,
isn't he using a container that offers some security management service
already? If not, why not? If there's a valid reason, what's the harm in
making securable objects implement a Securable interface that AOP
advice implementations can use to get the authentication token, via
some of the suggestions in the article's comments, and meeting the AOP
injection halfway?
These are really good suggestions, and I stil have to try them out,
which I'll probably do this week. One point that you missed thouhgh, is
that I'm not reinventing the wheel here - there's no wheel to use,
actually. I tried using Tomcat's security management, and after messing
around a lot with the SecurityManagers I ended up not liking the idea
very much - it somewhat ties the application to Tomcat, and one of my
requirements is to be the most appserver independent as possible.
Is this just using AOP to being using AOP? How does this make the code
simpler and easier to understand? That is why we are all using the
tools and techniques we use, right? To help tame the complexity
inherent in software development? Don't mistake me, although I have yet
to use it, I have sufficiently read up on AOP to understand what it is
and does. I could be wrong, but Carlos' circumstances don't seem to
indicate that AOP is the way to go, here; at least not for everything
he seems to be using it for.
I'm sorry, but I really can't agree with you here. Even if it's just
using AOP for the sake of AOP, even if this grows to be a monstruous
piece of code that runs around the town blowing up buildings, stepping
on cars and throwing fireballs at the army helicopters, I think at
least I have done something important, that is living through the mess
AOP can get anyone in.
Problem is, the OOP purists today will tell you that your system must
be made exclusively of objects, and the AOP purists will tell you that
AOP should be used sparingly, just to add a little flavour, a little
spice, to your recipe, but they don't help us much when we need to know
where we draw the line, where to use aspects and where to use objects.
So, I'm pushing the whole thing and trying to do everything with
aspects. So far, it's being an entertaining (and, for what you can see,
somewhat troubled) experience. But it's being fun, nonetheless.