Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to separate Business from Presentation Logic?

I want to create a game that will work both locally and online.

My first thought was to create an interface that would have all the methods that will be needed by the GUI for the business logic and then have a network implementation and a local implementation.

This works fine for request-response messages. But what about messages that the server sends, where I have to update some GUI components (i.e. JLabels)?

My first solution to this was to implement listeners, where each change in the implementation will fire an event. The GUI would register and change it's components appropriately. However, calls to fire events in the business logic looks a little wrong.

Am I in the right track? Because I think I'm not. Any suggestions?

Thank you.

NOTE: The client is a simple Java Swing GUI.

like image 548
pek Avatar asked Dec 27 '08 14:12

pek


2 Answers

What you have described will serve the goal of keeping the model independent of presentation issues, which is A Good Thing. This will also help you during design, development, and maintenance of the model, because you can write unit tests on the basis that certain changes in the model should fire specific events, without worrying about what that might look like on a screen.

And, of course, it frees you up to have different GUI designs for different environments.

The key is that the events should be about changes in the state of the model, and not about intended actions/representations at the presentation level. Let the presentation layer deal with whether/how to respond to a model event.

like image 84
joel.neely Avatar answered Sep 21 '22 09:09

joel.neely


I'll admit that I do web development, so I don't have much experience with Swing.

But I've always thought that the way I'd approach it would be to break the app into packages /view, /model, and /controller. The relationships would be unidirectional: /controller would know about both /model and /view, but neither would import any classes from /controller or each other.

The /view layer components would never be JFrames; they'd always be JPanel or another suitable container that could be composed together into JFrames as needed. Each would have references to Listener interfaces, initialized in constructors, and would defer to these for event handling:

public class ExamplePanel extends JPanel implements ActionListener
{
    private JButton button;
    private ActionListener buttonListener;

    public ExamplePanel(ActionListener buttonListener)
    {    
        this.button = new JButton("Do Something");
        this.buttonListener = buttonListener;
        this.button.addListener(this.buttonListener);
    }

    public void actionPerformed(ActionEvent e)
    {
        this.buttonListener.actionPerformed(e);
    }
}

This arrangement works well with dependency injection, because now the controller can choose to use a local or remote implementation of that Listener interface, changing the behavior in a way that doesn't affect the client at all.

I'll admit that I've never followed it all the way through.

The Spring folks have a rich Swing client module, but it appears to have fallen out of favor. It looks like they've decided that a BlazeDS direction is a better choice for rich clients. But perhaps you can glean some design ideas from their approach.

like image 31
duffymo Avatar answered Sep 19 '22 09:09

duffymo