Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #14620 > unrolled thread
| Started by | markspace <-@.> |
|---|---|
| First post | 2012-05-18 08:29 -0700 |
| Last post | 2012-05-19 22:29 -0400 |
| Articles | 6 — 4 participants |
Back to article view | Back to comp.lang.java.programmer
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: How is this "pattern" called? markspace <-@.> - 2012-05-18 08:29 -0700
Re: How is this "pattern" called? markspace <-@.> - 2012-05-18 08:37 -0700
Re: How is this "pattern" called? markspace <-@.> - 2012-05-18 10:35 -0700
Re: How is this "pattern" called? Wanja Gayk <brixomatic@yahoo.com> - 2012-05-30 14:32 +0200
Re: How is this "pattern" called? "John B. Matthews" <nospam@nospam.invalid> - 2012-05-18 15:35 -0400
Re: How is this "pattern" called? Arne Vajhøj <arne@vajhoej.dk> - 2012-05-19 22:29 -0400
| From | markspace <-@.> |
|---|---|
| Date | 2012-05-18 08:29 -0700 |
| Subject | Re: How is this "pattern" called? |
| Message-ID | <jp5ptm$jp9$1@dont-email.me> |
On 5/18/2012 1:53 AM, Stefan Ram wrote: > In the MVC pattern, I think, M, V, and C should be at least > one non-innner class each? > > I often have seen (possibly, especially in beginner code) a > coding pattern, where there is only one single non-inner class: > the model. "Especially in beginner code" seems to say to me that they might be copying from beginner examples, especially of the sort that appear in Oracle's Java tutorial. These example are designed to be shorter to read on a web page or book page, and don't show best practice or correct pattern. The examples simply show how to use the API. Also, MVC is not MVC. That is, most languages and frameworks use a modified MVC that really isn't MVC. Java itself uses a "split model" design pattern. Model-Presenter-Controller is currently a popular design pattern which can be used in Java. <http://www.martinfowler.com/eaaDev/uiArchs.html> > > The listeners and the view then are embedded into this > model, possibly, as inner classes. It's not really MVC > as the observer pattern is not used for decoupling. "Close coupling" is an anti-pattern in most cases. Do you have an example we could look at?
[toc] | [next] | [standalone]
| From | markspace <-@.> |
|---|---|
| Date | 2012-05-18 08:37 -0700 |
| Message-ID | <jp5qc2$n26$1@dont-email.me> |
| In reply to | #14620 |
On 5/18/2012 8:29 AM, markspace wrote: > design pattern. Model-Presenter-Controller is currently a popular design Argh. Model-View-Presenter. How did I mix those up?
[toc] | [prev] | [next] | [standalone]
| From | markspace <-@.> |
|---|---|
| Date | 2012-05-18 10:35 -0700 |
| Message-ID | <jp619l$5ms$1@dont-email.me> |
| In reply to | #14620 |
On 5/18/2012 9:59 AM, Stefan Ram wrote: > I do not see a real problem with this style, assuming that > the assignment at hand was just to write such a simple dot > paint program. Right, though the style doesn't particularly teach best practice either. I think I'd call this the "monolithic example" pattern. 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.
[toc] | [prev] | [next] | [standalone]
| From | Wanja Gayk <brixomatic@yahoo.com> |
|---|---|
| Date | 2012-05-30 14:32 +0200 |
| Message-ID | <MPG.2a30200c52428337989702@202.177.16.121> |
| In reply to | #14624 |
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 news@netfront.net ---
[toc] | [prev] | [next] | [standalone]
| From | "John B. Matthews" <nospam@nospam.invalid> |
|---|---|
| Date | 2012-05-18 15:35 -0400 |
| Message-ID | <nospam-0A319A.15355218052012@news.aioe.org> |
| In reply to | #14620 |
In article <MVC-20120518183901@ram.dialup.fu-berlin.de>,
ram@zedat.fu-berlin.de (Stefan Ram) wrote:
> I do not see a real problem with this style, assuming that the
> assignment at hand was just to write such a simple dot paint program.
>
> The inner classes can easily share a common model and identifier
> scope, while at the same time there is some reasonable separation
> between the different concerns of the inner classes.
>
> Should it be required later to decouple one of these inner classes
> more than now, this is also possible using a refactor that will make
> it become an outer class or will introduce an observer relationship.
> But should it not be required later, no time is wasted now to
> implement a decoupling and separation not needed.
I sometimes strive to make nested classes static in order to facilitate
re-factoring, as suggested in the example below. Static also keeps me
honest on inadvertent coupling. I also use the somewhat dated Observer
and Observable classes to stress the observer pattern, even implementing
Observer despite leaking `this`.
Here's my understanding of the basic architecture:
<http://stackoverflow.com/a/2687871/230513>
Here's a more elaborate example that mentions other ways to implement
the observer pattern:
<http://stackoverflow.com/a/3072979/230513>
And I frequently refer to this article on Swing & MVC
<http://java.sun.com/products/jfc/tsc/articles/architecture/>
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MVCMain {
public static void main(String args[]) {
new MVCMain().buildGui();
}
public void buildGui() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Model model = new Model();
View view = new View(model);
Control control = new Control(model, view);
JFrame f = new JFrame();
f.add(view);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
private static final class Model extends Observable {
private List<Point> points = new ArrayList<Point>();
public void next(Point p) {
points.add(p);
setChanged();
notifyObservers();
}
public List<Point> getPoints() {
return points;
}
}
private static final class View extends JPanel implements Observer {
private Model model;
public View(Model model) {
this.model = model;
this.model.addObserver(this);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.blue);
for (Point p : model.getPoints()) {
g.fillRect(p.x, p.y, 8, 8);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
@Override
public void update(Observable o, Object arg) {
repaint();
}
}
private static final class Control {
private Model model;
private View view;
public Control(final Model model, View view) {
this.model = model;
this.view = view;
this.view.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
model.next(e.getPoint());
}
});
}
}
}
--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2012-05-19 22:29 -0400 |
| Message-ID | <4fb85727$0$295$14726298@news.sunsite.dk> |
| In reply to | #14620 |
On 5/18/2012 12:59 PM, Stefan Ram wrote:
> final class Main
> {
> /* model */
>
> final private java.util.Collection<java.awt.Point> collection
> = new java.util.ArrayList<>();
>
> /* view */
>
> Panel panel;
> final private class Panel extends javax.swing.JPanel
> { public Panel()
> { this.setPreferredSize( new java.awt.Dimension( 300, 300 ));
> this.addMouseListener( new MouseListener() ); }
> final @java.lang.Override public void paintComponent
> ( final java.awt.Graphics graphics )
> { super.paintComponent( graphics );
> for( final java.awt.Point point : Main.this.collection )
> graphics.fillRect( point.x, point.y, 4, 4 ); }}
>
> final private class Frame extends javax.swing.JFrame
> { Frame()
> { Main.this.panel = new Panel(); this.add( Main.this.panel );
> this.setDefaultCloseOperation
> ( javax.swing.WindowConstants.DISPOSE_ON_CLOSE );
> this.pack(); this.setVisible( true ); }
> final @java.lang.Override public void dispose(){ super.dispose(); }}
>
> /* controller */
>
> final private class MouseListener extends java.awt.event.MouseAdapter
> { public final void mousePressed
> ( final java.awt.event.MouseEvent mouseEvent )
> { Main.this.collection.add
> ( new java.awt.Point( mouseEvent.getX(), mouseEvent.getY() ));
> Main.this.panel.repaint(); }}
>
> public final java.lang.Runnable buildGui = new java.lang.Runnable()
> { @java.lang.Override public final void run(){ new Frame(); }};
>
> public final void buildGui()
> { java.awt.EventQueue.invokeLater( this.buildGui ); }
>
> public static void main( final java.lang.String args[] )
> { new Main().buildGui(); }}
>
> I do not see a real problem with this style, assuming that
> the assignment at hand was just to write such a simple dot
> paint program.
>
> The inner classes can easily share a common model and
> identifier scope, while at the same time there is some
> reasonable separation between the different concerns
> of the inner classes.
>
> Should it be required later to decouple one of these inner
> classes more than now, this is also possible using a
> refactor that will make it become an outer class or will
> introduce an observer relationship. But should it not
> be required later, no time is wasted now to implement a
> decoupling and separation not needed.
From a theoretical point of view V and C are not part of M.
From the practical point of view the pattern (combined with
your non standard formatting) ensures that it takes 10
times longer to read and understand the code.
Arne
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web