How DRY is too DRY?

I'm working on fixing up the code in my first Rails application and
have come around to DRYing up the views and partials. For the most
part, I'm satisfied with the DRYness of the application, but I have
5-6 partials that display nearly identical XHTML, just with different
content, link_to paths, and images.

I know this question is entirely subjective, but would finding a way
to further DRY the 5-6 partials into one partial with plugs for
different fillers be too much? If so, how would I go about doing
this?

2 examples...

http://pastie.org/402754
http://pastie.org/402756

Here's how it could look like -> http://pastie.org/402767

And having five pages with almost the same markup is always wrong, you
don't even need to be looking for DRYing up your code.

Thanks, I'll work through your example.

I'm not sure that I follow your second comment. I understand that
having duplicate markup is not desirable, but is there another way I
should be approaching this?

And what about cases where I need the model attribute names to be
different? For instance, in one case I might print item.name, but in
the other, item.title. And since this markup will be similar to the
front-end display (non-admin), is there a good way to set the link_to
to be either :admin or :root?

And what about cases where I need the model attribute names to be
different? For instance, in one case I might print item.name, but in
the other, item.title.

Make all models that are going to be used by that template respond to
the same message. If at your template, you're calling "item.title",
all models that are going to be used in there should have a "title"
method. In your case, you can just alias the "name" method to "title".
A better approach would be to implement the "to_s" method in your
active record models by returning these "name" properties.

If you have a user model, you could implement it's to_s like the following:

class User < ActiveRecord::Base

  def to_s
    login
  end

end

So you don't even care about what that model is, you just expect it's
to_s method to yield a correct "label".

And since this markup will be similar to the
front-end display (non-admin), is there a good way to set the link_to
to be either :admin or :root?

You can just add another parameter at the render :partial call.

Ok, I follow having all models respond to "title", but why would
implementing the model's "to_s" method be a better approach? Is it
just for consistency, always expecting to_s to return what the partial
should display? How is that any different that expecting all models
to answer to title?

Thanks. This has been really helpful. I used your example to create
the following. Thoughts?

http://pastie.org/402843

ericindc wrote:

I'm working on fixing up the code in my first Rails application and
have come around to DRYing up the views and partials. For the most
part, I'm satisfied with the DRYness of the application, but I have
5-6 partials that display nearly identical XHTML, just with different
content, link_to paths, and images.

This supplements your other answers, which are doubtless technically correct.

The DRY is primarily about the behaviors of methods in an OO design. Having two methods that do the exact same thing, but with different labels or a different algorithm, is the greatest violation of DRY. (Start by seeing if you can make the two methods look more similar, before merging them. If you can't, at least find a way to put them right next to each other!)

Similarly, your metadata should be DRY. This is why (and how) Rails obeys "convention before configuration". Don't write an XML file saying "our unit tests are in the test/ folder". That repeats the information stored in the name of the folder.

Now we come to the heart of the matter. HTML, by itself, is not behavior, and it's almost not structure. It is mostly art. DRYing two similar stretches of HTML is the moral equivalent of DRYing all your #fff and "white" CSS directives. It's okay if they say the same thing, when they don't use logical statements to say them, and when you might not frequently need to change them all at the same time.

So that is the answer to "too DRY". Keep DRYing your project until you reach a local maximum of convenience, and then don't DRY any more.

* ericindc <ericmilford@gmail.com> [2009-02-27 18:20:27 -0800]:

I'm working on fixing up the code in my first Rails application and
have come around to DRYing up the views and partials. For the most
part, I'm satisfied with the DRYness of the application, but I have
5-6 partials that display nearly identical XHTML, just with different
content, link_to paths, and images.

I know this question is entirely subjective, but would finding a way
to further DRY the 5-6 partials into one partial with plugs for
different fillers be too much? If so, how would I go about doing
this?

My criteria for *repeat* detection is, what you want when you need
to change them. When you DRY up two similar parts, you lose the ability
to modify one without affect the other one. So I think if the similar
parts are likely to change in the same way in future, they should be
DRYed; otherwise I prefer to keep them seperate although they looks
simliar to each other.

my $0.02
Jan

Ok, I follow having all models respond to "title", but why would
implementing the model's "to_s" method be a better approach? Is it
just for consistency, always expecting to_s to return what the partial
should display? How is that any different that expecting all models
to answer to title?

First it's for the sake of consistency, but it's also 'cos the to_s
method is defined to return a "string representation of the object",
so if you already have a method that does what you want, why create
another one or why care about creating another method that "returns a
string representation of the object"?

This way you don't need to add extra virtual methods at your models,
you just expect them to have a good to_s implementation.

Thanks. This has been really helpful. I used your example to create
the following. Thoughts?

http://pastie.org/402843

It's good, but that's how I'd do it -> http://pastie.org/403009

The more conventions you have, the easier it is to keep things
consistent in your pages.

Thanks for both posts regarding DRY and too DRY. Some very good
points.

> Ok, I follow having all models respond to "title", but why would
> implementing the model's "to_s" method be a better approach? Is it
> just for consistency, always expecting to_s to return what the partial
> should display? How is that any different that expecting all models
> to answer to title?

First it's for the sake of consistency, but it's also 'cos the to_s
method is defined to return a "string representation of the object",
so if you already have a method that does what you want, why create
another one or why care about creating another method that "returns a
string representation of the object"?

Thanks, you've been a huge help.

Makes sense for consistency's sake. My initial concern is about
overriding a core method. What if I needed to_s elsewhere? Plus,
wouldn't I be writing more code given that every model must now have a
custom defined to_s method? Unless adding extra virtual attributes is
bad, would it be less work (given that I'd have to change two models
at this point) to just add a "title" method for those that doesn't
respond to title?

This way you don't need to add extra virtual methods at your models,
you just expect them to have a good to_s implementation.

> Thanks. This has been really helpful. I used your example to create
> the following. Thoughts?

>http://pastie.org/402843

It's good, but that's how I'd do it ->http://pastie.org/403009

The more conventions you have, the easier it is to keep things
consistent in your pages.

I picked up a few good points, but I decided on my implementation
because there are other types of those sidebar boxes. For instance,
they won't all say "Create New XYZ". Some will say "My Comments", or
"Add Member". The images, etc. will change too.

It made sense to me to keep the structure of the box DRY since that
will never change and just plug in my values as needed. And the only
way I found to do that was what I pastied too. I'll keep looking at
it though.

Makes sense for consistency's sake. My initial concern is about
overriding a core method. What if I needed to_s elsewhere?

Usually, you shouldn't need it unless what you need is a "string
representation of your object" (yes, i'm sounding like a broken vinyl
now ;D), and receiving a user_name or a title would probably be what
you're looking for.

Also, if it's something for debugging purposes in Ruby we use "inspect".

Plus, wouldn't I be writing more code given that every model must now have a
custom defined to_s method? Unless adding extra virtual attributes is
bad, would it be less work (given that I'd have to change two models
at this point) to just add a "title" method for those that doesn't
respond to title?

Yes and no. When you say that it's "title", it has to be a method
called title, so you're stuck with this "title" thing, if a model has
a title and you don't want to use it, you're about to have a problem.
Using to_s or a to_label (this one feels clumsy) means your view code
don't need to know which method is going to be called, which
simplifies changes in the future. Imagine that today, when presenting
a user, you show it's full name, but later on there's a request to,
instead of showing the full name, show only the login, if you had a
full_name call at every user show, you'd have to change them all to
login, but if you had oveeriden the to_s method you would just have to
change it in one place.

Also, when you override the to_s method you don't need to call it at
the view, as you need to call the "title" method:

<%= link_to user, user %>

The link_to helper will automatically call "to_s" at your object, so
you don't have to call it by yourself.

Ok, I'm sold. I'll update each model's to_s method to respond with
the "title" that I want displayed in the partial. Thanks again for
your input.