views:

35

answers:

3

I'm writing a web application (in Python, not that it matters). One of the features is that people can leave comments on things. I have a class for comments, basically like so:

class Comment:
    user = ...
    # other stuff

where user is an instance of another class,

class User:
    name = ...
    # other stuff

And of course in my template, I have

<div>${comment.user.name}</div>

Problem: Let's say I allow people to post comments anonymously. In that case comment.user is None (undefined), and of course accessing comment.user.name is going to raise an error. What's the best way to deal with that? I see three possibilities:

  • Use a conditional in the template to test for that case and display something different. This is the most versatile solution, since I can change the way anonymous comments are displayed to, say, "Posted anonymously" (instead of "Posted by ..."), but I've often been told that templates should be mindless display machines and not include logic like that. Also, other people might wind up writing alternate templates for the same application, and I feel like I should be making things as easy as possible for the template writer.
  • Implement an accessor method for the user property of a Comment that returns a dummy user object when the real user is undefined. This dummy object would have user.name = 'Anonymous' or something like that and so the template could access it and print its name with no error.
  • Put an actual record in my database corresponding to a user with user.name = Anonymous (or something like that), and just assign that user to any comment posted when nobody's logged in. I know I've seen some real-world systems that operate this way. (phpBB?)

Is there a prevailing wisdom among people who write these sorts of systems about which of these (or some other solution) is the best? Any pitfalls I should watch out for if I go one way vs. another? Whoever gives the best explanation gets the checkmark.

+1  A: 

I'd go with the first option, using an if switch in the template.

Consider the case of localization: You'll possibly have different templates for each language. You can easily localize the "anonymous" case in the template itself.

Also, the data model should have nothing to do with the output side. What would you do in the rest of the code if you wanted to test whether a user has a name or not? Check for == 'Anonymous' each time?

The template should indeed only be concerned with outputting data, but that doesn't mean it has to consist solely of output statements. You usually have some sort of if user is logged in, display "Logout", otherwise display "Register" and "Login" case in the templates. It's almost impossible to avoid these.

deceze
Good point with the localization, I hadn't thought of that
David Zaslavsky
+1  A: 

Personally, I like for clean code, and agree that templates should not have major logic. So in my implementations I make sure that all values have "safe" default values, typically a blank string, pointer to a base class or equivalent. That allows for two major improvements to the code, first that you don't have to constantly test for null or missing values, and you can output default values without too much logic in your display templates.

So in your situation, making a default pointer to a base value sounds like the best solution.

LarryN
A: 

Your 3rd option: Create a regular User entity that represents an anonymous user.

I'm not a fan of None for database integrity reasons.

Jen