views:

75

answers:

2

Here is the scenario,

Let's say I have a user class like so:

public class User{
  private String firstName;
  private String lastName;
//...
// setter, getters
}

Then I have a class like so to handle user Comments:

public class Comments{
  // some fields
  public static loadComments(User user, int count){...}
}

So far very basic stuff. However, I want to add some helpers of course to make it easier load comments for user. So I could create something in User class:

final static int defaultCount = 10;
...
public Comment comments(){
  return Comments.loadComments(this, defaultCount);
}

I think this is an easy way to not have to pass around user instances around. But at this point, I am unhappy because I have coupled my user bean object with business logic that loads the comment. I have also saved the default count in user class which shouldn't belong there. So what is the best way to do this? My goal is to pass this object to a jsp so that JSTL functions can be called. I had an idea to create a UserWrapper which would look like this...

public class UserWrapper{
  private final static defaultCount = 10;
  private final User user;
  public UserWrapper(User user){
    this.user = user;
  }

  // should probably cache this but i am not going to show this for simplicity
  public Comments getComments(){return Comments.loadComments(user, 10);}
}

I hope I was clear. I don't like using useBean tag because its just not necessary for something like this. I am hoping there is a cleaner way to approach something like this! Any help would be appreciated!

Edit: One thing I forgot to mention. I want to be able to use this code in JSTL. Which means it must be a getter. The DAO model is well known but it doesn't help too much when my front-end developer needs to write a scriplet or I need load it for places that he may or may not need.

+2  A: 

From a technology independent stand-point...

Yes, you're absolutely right about that coupling being prohibitive. Look to the Layers architectural pattern to offer some guidance about structure business logic and data. For example, it might be an excellent idea to design two subsystems: One for your Logic, the other for Layers. Restrict communication between them by only allowing the Logic to pass messages to the Data Layer. Furthermore, you can use the Facade pattern to represent each subsystem, and thus decrease coupling even more. Treat each Layer as a black box.

Another pattern that might come in handy is the Data Access Object pattern. It will help you in defining a contract between the Layers to pass data around when it's necessary.

Mike
Some times having a DAO is just an overkill. Let's say I had comments, notifications, emails, status updates, etc... Creating a huge file just load these data is not so clean. Plus I couldn't call it directly from jsp. I forgot to mention, one goal is to write less code! haha. I can create facades, DAOs, and just to find a huge nightmare to manage.
Amir Raminfar
Try incremental development then. Plan it out well on paper, and see if everything checks out (get a friend to ensure that your design is sane). And you're absolutely right. A lean design is best. But make sure it does everything you want it to, and that it's loosely coupled. Easy, right? :)
Mike
+1 Mike. @Amir - the thing about architecture is to have an idea about where you want / need to go with the app; this is very different from YAGNI. I've found that (generally) once you adopt an approach like Mikes you quickly get familiar with it and the 'management' issue effectively disappears.
Adrian K
+2  A: 

I like to use Data Access Objects (DAOs) for this. Your User and Comment classes will only contain the fields for those objects and then you create separate classes to retrieve data about those objects. The DAOs are where you include the logic about how to retrieve, update, select, etc For example,

public class UserDAO {

     public UserDAO() {
        //maybe setup a Hibernate connection or JDBC connection here
     }

     public User getUser(int userId) {
        User user;
        //code to retrieve user from datasource
        return user;
     }

     //other methods for update, delete, select, etc
  }

  public class CommentsDAO {
     private static int DEFAULT_COUNT = 10;

     public CommentsDAO() {
        //maybe setup a Hibernate connection or JDBC connection here
     }

     public Collection getCommmentsForUserWithCount(User user, int count) {
        Collection comments = new Set();
        //retrieve comments from datasource limit to count

        return comments;
     }

     public Collection getCommentsForUser(User user) {
        return getCommentsForUserWithCount(user, DEFAULT_COUNT);
     }

     //other methods for update, delete, etc
  }
Owen