This document is an attempt to pin down all the things you don't think about when quoting for a project, and hopefully provide a starting point for some kind of framework to make quoting, working and delivering small-medium jobs more predictable and less stressful.
This week NN Group released a video by Jakob Nielsen in which he attempts to help designers deal with the problem of customers being resistant to their new site/product redesign. The argument goes thusly:
- Humans naturally resist change
- Your change is for the better
- Customers should just get used to it and stop complaining
There's slightly more to it than that, he caveats his argument with requiring you to have of course followed their best practices on product design, and allows for a period of customers being able to elect to continue to use the old site, although he says this is obviously only a temporary solution as you don't want to support both.
The following are examples of the four types rate limiters discussed in the accompanying blog post. In the examples below I've used pseudocode-like Ruby, so if you're unfamiliar with Ruby you should be able to easily translate this approach to other languages. Complete examples in Ruby are also provided later in this gist.
In most cases you'll want all these examples to be classes, but I've used simple functions here to keep the code samples brief.
This uses a basic token bucket algorithm and relies on the fact that Redis scripts execute atomically. No other operations can run between fetching the count and writing the new count.
/** | |
* Please use this file at your own risk. I don't provide the support for it. | |
* Any suggestion or problem are welcomed to report here :) | |
*/ | |
/** | |
* Usage: | |
* 1. Log-in as an group admin in the desktop | |
* 2. Go to your group pending list like: https://www.facebook.com/groups/[group-id]/pending/ | |
* 3. Insert the following code to your browser console. See the guide: https://developer.chrome.com/devtools/docs/console |
with | |
dau as ( | |
-- This part of the query can be pretty much anything. | |
-- The only requirement is that it have three columns: | |
-- dt, user_id, inc_amt | |
-- Where dt is a date and user_id is some unique identifier for a user. | |
-- Each dt-user_id pair should be unique in this table. | |
-- inc_amt represents the amount of value that this user created on dt. | |
-- The most common case is | |
-- inc_amt = incremental revenue from the user on dt |
from django.db import models | |
class Person(models.Model): | |
name = models.CharField(max_length=200) | |
groups = models.ManyToManyField('Group', through='GroupMember', related_name='people') | |
class Meta: | |
ordering = ['name'] | |
def __unicode__(self): |