In article <jp619l$5ms$
1...@dont-email.me>, -@. says...
> Right, though the style doesn't particularly teach best practice
> either.
>
> I think I'd call this the "monolithic example" pattern.
That pattern is known as "god class".
> It's similar to
> a lot of example code I see in books and the Java tutorial. It's
> monolithic because it crams everything into a single class, or at least
> into the minimum page space.
>
> And it's an example because that's what it is. A short program that
> isn't written by more than one person, and will not be maintained. It's
> fine for what it is, but it's not an example of good production style
> coding either.
As a Java/Swing developper with almost a decade of experience, having
seen a lot of code that got refactored inside out and back again, It's
not that simple to say sonmething is good or bad. It depends on the
purpose.
For the start it's a pragmatic, yet entirely easy to refactor approach
that has one goal in mind: Keep a unit/module together.
I do agree that you should tear this apart into several classes, but to
understand why, let me start to develop the idea.
It all starts with one decision: Will we ever exchange view technology
(like Swing to SWT)? You can't know, so you should be flexible, right?
Wrong! I have yet to see one big project, huge as a retail system,
migrate from one view technology to the other. People don't do it, it's
massively expensive and they rather pay to keep the old technology alive
and patched than to migrate to a new one. So don't expect insurance
companies and warehouse chains to migrate a huge in house application
from Swing to SWT, JavaFX 2.0 or a web interface anytime soon. Things
are that complex and there are so many framework specific hacks involved
that migrating is a daunting task that only very few companies are
willing to pay for. Usually there have been a lot of developers on the
project, some of them good, some of them rather bad, you will dig out
big piles of code that hurts your eyes (and your code will hurt theirs)
and you'll have to untangle some huge mess before you can even start to
think about that. Don't do it.
Do we need flexibility here? Rather not.
It needs a very good framework to separate the concerns good enough to
ease the pain (I'm glad I had the opportunity to work on one as
framework-developper and user) of switching from Swing to SWT alone,
still it is a heavy task. Basically that framework has to have an own
abstraction for every widget that talks to the original Swing-Widget,
Abstractions for teh EventQueue and so on, so the GUI technology can be
replaced rather easily. Most smaller businesses don't have that, they
simply can't afford to build and maintain a huge ass framework like
that. So what they do is buy one. Then you'll have to stick to its rules
anyway, which some developers wil happily ignore, which is where your
problem will resurface. Forget it, quite frankly.
So here we are again: Average company, no special framework involved,
time pressure is on, external developers going in and out all the time.
What you need is some kind of clear structure and everything should be
easy to find. You don't want to spread one module (like the mask for
editing an article) over a huge class hierarchy with too many small
classes cluttering up your directories, so no one finds anything.
Now here's where it starts to get intersting, because you can approach
it differently. Most of you will know the web developer world, but let
me use a usual fat client example here, as this is what the example
seemed to suggest.
What do you need in general?
* You have a view
* You have some business logic, some of that will reflect in the way the
view behaves (no mail order -> mail service combobox not editable), some
of that will not (posting an order takes something off the stock, puts
it into the delivery queue and sends a confirmation email, whatever).
* You have validation, both for the view (name must be entered) and for
the businsss logic (item is out of stock, another user just ordered it
the second you klicked to send your order).
You need to glue that together, which is what the controller does, and
you need to embed all this in some application frame.
So a pragmatic approach is to have a module class, say the "article
module", which includes some value object for what's currently
displayed/edited - and that's not necessarily what you need to give the
widget: You like to validate and store a list, not a table model / you
like to have some booleans, not a button model.
Now you need some view, a validation code block and some code to CRUD
things in the database, if you need one.
To keep the module API small, it should not feature much more than
necessary to incorporate the module in the application frame,
initialize, display and tear it down again, everything else is "internal
affairs".
Next decision: Do you want to use a GUI-Designer like JFormDesigner?
Probably yes.
So you should have an own class for the widgets and their layout.
Now you don't want to access each field individually, so you would
probably hand over a copy of the value object to the view, so it can do
with it whatever it wants without affecting anything. You need to have
some event handling to get to know that some thing has changed in the
view that you might need to validate, do you?
Now you have the option to move some validation into the view, because
it's its internal affair, but that could get you into problems with re-
generating a GUI class. And GUI-Designer code is usually huge and
verbose and you don't want to edit that class manually and you don't
want ot to hide and obscure code relevant for business. So you could
keep it in the controller. For the same reason you possibly like to have
the code for binding a widget to a property in the value object in the
value object itself.
You have now split the module into two top level classes: A presenter
and a view. The rest is inner classes.
You could be fine here, this is almost what you see above, only with
some tweaking for use with a GUI designer tool.
Next decision: Do you want ORM-mapping for your persistence?
If so, you need an entity class. And you need some code that transfers
your value object's data to the database. Or you use the entity itself
as vaue object (which is a nice idea at first, but may fall on your feet
later, especially when you encounter things like a manual undo).
So you have three top level classes: A presenter, a view and an entity.
Next decision: Do you want client/server separation and do you need some
stiffer security?
This is an important decision, and for a huge business application it
would be a clear yes most of the times.
I've also seen a domain driven design, where you actually had business
logic and validation in the entities itself, which also served as value
objects for the view, so the client was doing all the business logic and
the server was just a database with some client logon/logoff and
permission stuff. Not what you would call hard to attack for anyone who
gets access to the client, but certainly enough for in house use on an
intranet in a small company and it was very clear where to find what.
If you want to separate client/server, you need some class to host the
web services for that module on the server side.
You will need to move some validation there - the stuff that is not
directly reflected in the GUI. This is the point where you will repeat
some of the validation from the GUI to be sure no one sends some weird
data from a modified client. And you will need to push some business
logic here, because sending mail for example, and changing the stock, is
not anymore client's business.
So now you have four top level classes: Presenter, View, Web Service,
Entity.
And you will have them in two different projects:
A "server" project and a "client" project.
Now let's go and solve the DRY-Principle that you have violated when
pushing the validation into the text field:
Your view would check a number field to highlight a value out of bounds,
your webservice would check it to throw an exception.
There you can move your validation to a top level class and put it into
a "common" project that is both included in the classpath of the client
and server. Since the client and the server both have their own class
loaders, you can't just simply modify the validator on the client side,
the server would still see his version of the class, so that practice is
safe enough to go with. You will need to move the business rules there
too, because you need them for validation and you don't want to make a
web service call everytime you change a combobox value in the view.
Be aware though, that this will violate the SOA (Service Oriented
Architecture) that you have just established by introducing the web
service.
If you really need SOA at this point, you need to bite the bullet and
either live with a lot of web service calls and kill your user
experience with sluggish behavior or violate DRY.
Anyway, for your module you might have five top level classes now:
Presenter, View, Web Service, Validator, Entity.
This is not quite "model view controller", but still a reasonable
architecture.
What do you think?
Kind regards,
-Wanja-
--
..Alesi's problem was that the back of the car was jumping up and down
dangerously - and I can assure you from having been teammate to
Jean Alesi and knowing what kind of cars that he can pull up with,
when Jean Alesi says that a car is dangerous - it is. [Jonathan Palmer]
--- Posted via news://
freenews.netfront.net/ - Complaints to
ne...@netfront.net ---