You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
8.2 KiB

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1">
  6. <link rel="icon" type="image/png" href="/favicon.ico">
  7. <link rel="canonical" href="https://www.mcmillen.dev/blog/20210721-downvotes-considered-harmful.html">
  8. <link rel="alternate" type="application/atom+xml" href="https://www.mcmillen.dev/feed.atom" title="Colin McMillen's Blog - Atom">
  9. <title>Downvotes & Dislikes Considered Harmful | Colin McMillen</title>
  10. <link rel="preconnect" href="https://fonts.gstatic.com">
  11. <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@500;700&display=block" rel="stylesheet">
  12. <link href="https://fonts.googleapis.com/css?family=Fira+Mono:500&display=block" rel="stylesheet">
  13. <link rel="stylesheet" href="/pygments.css">
  14. <link rel="stylesheet" href="/style.css">
  15. <meta name="twitter:card" content="summary">
  16. <meta name="twitter:site" content="@mcmillen">
  17. <meta name="twitter:title" content="Downvotes & Dislikes Considered Harmful | Colin McMillen">
  18. <meta name="twitter:description" content="If you’re letting users rank content, you probably don’t need and don’t want downvotes. Here’s why. (This post inspired by news that Twitter is considering adding “Dislikes” to Tweets.)">
  19. </head>
  20. <body>
  21. <div id="page-container">
  22. <div id="content-wrap">
  23. <div id="header">
  24. <div class="content">
  25. <a href="/" class="undecorated">Colin McMillen</a>
  26. <span style="float: right;"><a href="/feed.atom"><img src="/img/rss.svg" alt="Atom feed" style="width: 17px; height: 17px; margin-bottom: 1px;"></a></span>
  27. <span style="float: right;"><a href="https://twitter.com/mcmillen"><img src="/img/twitter.svg" alt="@mcmillen"></a></span>
  28. </div>
  29. </div>
  30. <div class="content">
  31. <h1 id="downvotes-dislikes-considered-harmful">Downvotes &amp; Dislikes Considered Harmful</h1>
  32. <p><em>Posted 2021-07-21.</em></p>
  33. <p>If you&rsquo;re letting users rank content, you probably <strong>don&rsquo;t need and don&rsquo;t want downvotes</strong>. Here&rsquo;s why.</p>
  34. <p>(This post inspired by news that Twitter is considering <a href="https://twitter.com/Sadcrib/status/1417913362999136257">adding &ldquo;Dislikes&rdquo; to Tweets</a>.)</p>
  35. <h2 id="background">Background</h2>
  36. <p>In my past life at Google, I was responsible for co-creating <a href="https://books.google.com/books?id=fEJ0AwAAQBAJ&amp;newbks=1&amp;newbks_redir=0&amp;lpg=PP83&amp;dq=memegen%20eric%20schmidt&amp;pg=PP83#v=onepage&amp;q=memegen%20eric%20schmidt&amp;f=false">Memegen</a>, a large &amp; influential Google-internal social network. Memegen lets Google employees create internal-only memes and allows users to upvote &amp; downvote the memes of others. Memegen&rsquo;s home page is the Popular page, which shows the most-upvoted memes of the past day.</p>
  37. <p>Adding downvotes to Memegen was my single greatest mistake.</p>
  38. <h2 id="the-problems-of-downvotes">The problems of downvotes</h2>
  39. <p>Any voting system where <em>most</em> posts mostly receive upvotes, but also allows downvotes, has a huge problem:</p>
  40. <blockquote>
  41. <p>No matter how you do the math, <strong>downvotes count more</strong> than upvotes do.</p>
  42. </blockquote>
  43. <p>Mathematically, it will always be comparatively easy for a vocal minority to bury any specific items that they don&rsquo;t want surfaced on the top-N posts page. This is true even if you&rsquo;re using a sophisticated ranking algorithm like <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score intervals</a> to rank posts (as Reddit &amp; many other sites do).</p>
  44. <p>Downvotes aim to solve the problem of filtering out low-quality <strong>content</strong>, but are too easily coopted by trolls to let them filter out <strong>people</strong> &mdash; often for bad reasons that have more to do with the identity of who&rsquo;s posting rather than the content of their posts.</p>
  45. <p>From the standpoint of attracting users, downvotes create another huge problem: someone whose first submission to a site gets downvoted to oblivion will feel bad about it and probably not come back to submit better stuff in the future.</p>
  46. <h2 id="what-does-a-downvote-actually-mean">What does a downvote actually <em>mean?</em></h2>
  47. <p>The other problem with downvotes is that it&rsquo;s unclear to everyone what they mean. Does a downvote mean that this particular post is:</p>
  48. <ol>
  49. <li>offensive or illegal and needs to be removed ASAP?</li>
  50. <li>a duplicate?</li>
  51. <li>just something you personally don&rsquo;t like?</li>
  52. <li>off-topic for the forum?</li>
  53. </ol>
  54. <p>As the creator of a social product, you need <strong>give people different buttons</strong> for these.</p>
  55. <p>Offensive or illegal posts (#1) shouldn&rsquo;t be handled by an algorithmic rating system. You need actual human moderators for that &mdash; and enough of them that they can review those reports in a timely manner. (I hope you&rsquo;re willing to train &amp; pay them well!)</p>
  56. <p>For duplicate posts (#2) it&rsquo;s nicer &amp; more informative if your software simply says &ldquo;hey, this submission is a duplicate of this other thing, why don&rsquo;t you all check out that post instead?&rdquo;</p>
  57. <p>#3 is solved by default &mdash; people can simply not vote for content they don&rsquo;t like.</p>
  58. <p>#4 is pretty much the same as #3 (but maybe a moderator should intervene if a user has a history of posting too many off-topic things, or if it&rsquo;s obviously spam).</p>
  59. <h2 id="how-to-actually-rank-posts">How to actually rank posts</h2>
  60. <p>Once you&rsquo;ve dispensed with the idea of downvotes, the main things a user cares about are: &ldquo;what are the best things that have been posted today?&rdquo; (or in the last hour / week / etc) or &ldquo;what are the best things since I last visited?&rdquo;</p>
  61. <p>On paper, the math is super simple: just count the number of upvotes for each item that was submitted in the relevant time period, and show the top N!</p>
  62. <p>It turns out that&rsquo;s it&rsquo;s actually a bit trickier to implement than something like a Wilson score interval, so here&rsquo;s some tips on how to do that.</p>
  63. <p>We need to store each vote and when it was cast, and then when it&rsquo;s time to compute the &ldquo;most popular in the last day&rdquo; page, you first select all the votes cast within the last day, and then count how many were for each post, and rank those.</p>
  64. <p>Doing this every time the user hits the homepage is clearly a terrible idea, so set up a cronjob to do it every 5 or 15 minutes or something. It&rsquo;s okay if the info is slightly out of date! Most users won&rsquo;t care or notice if it takes a few minutes for things to move around.</p>
  65. <p>How exactly to optimize this depends on the scale of your site, your storage architecture, a ton of other stuff, but for Memegen, every post had properties like <code>score_hour</code>, <code>score_day</code>, <code>score_month</code>, <code>score_alltime</code>. A mapreduce was responsible for updating these values every few minutes.</p>
  66. <p>Obviously you don&rsquo;t need to touch or compute anything for any post that got no votes since the last time you ran the updater. In the steady state, <em>most</em> of the posts in your system won&rsquo;t need any update.</p>
  67. <h2 id="conclusion">Conclusion</h2>
  68. <p>Downvotes are a blunt instrument for users to say &ldquo;I don&rsquo;t like this content&rdquo;.</p>
  69. <p>It&rsquo;s easy for small groups of trolls to misuse downvotes as a vehicle for harassing &amp; silencing groups of (often marginalized) people.</p>
  70. <p>Downvotes reduce engagement by scaring off first-time posters.</p>
  71. <p>Instead of adding downvotes to your site, build <em>specific</em> tools that handle specific kinds of unwanted posts.</p>
  72. <p>(This post is a distillation &amp; refinement of some thoughts originally posted in <a href="https://twitter.com/mcmillen/status/1310998579184574465?s=20">a Twitter thread</a> in September 2020.)</p>
  73. <h2 id="comments">Comments?</h2>
  74. <p>Feel free to reply to <a href="https://twitter.com/mcmillen/status/1418010991913230336">my post on Twitter</a> about this article. Thanks!</p>
  75. </div>
  76. </div>
  77. <div id="footer">
  78. <div class="content">
  79. &copy; 2021 <a href="/" class="undecorated">Colin McMillen</a>. No cookies, no tracking.
  80. </div>
  81. </div>
  82. </div>
  83. </body>
  84. </html>