Lil' Jay
&& [ birds ] && 0 comments
There is a Scrub Jay that likes to hang around our feeder we named Little Jay. Lots of birds hang around our feeder, and most of them don’t get names. But Little Jay is challenged, which makes him endearing. It also makes him easy to recognize.
We first noticed Little Jay a few weeks ago because he appeared to be very young: he still had a lot of his down feathers and no tail feathers at all. He was super awkward around the feeder and the surrounding perches. That’s when we noticed he had a bum leg, probably broken. He never uses it, which makes it difficult to move around sometimes.
Most of the time he shows up to the bird feeder alone (which is not unusual for a Scrub Jay) but he does come by often, much more often than any other Jays. If another Jay shows up to the feeder while he is there, he let’s them eat first. Even if he’s not at the feeder we can usually spot him sitting on power line or perch somewhere close by.
We hope he has not become dependent on our feeder, but it is in our minds as a possibility. We are hopeful for him though, as his down seems to slowly disappearing and there is a hint of a tail feather starting to show. Maybe his leg will eventually heal.
While I had always intellectually known that many species of bird stick to a single territory including the California Towhees, House Finches and Morning Doves that often visit us, Little Jay made the idea instinctual. He is a reminder that we may live in this place and pay the rent, but it is not our home alone.
Dear 2019, From 2020
&& [ other ] && 0 comments
Why do years only last for 12 months? Can’t they last a little longer?
Dear 2019,
You really should have stuck around. Which is funny, because the people living during my time didn’t seem to think you were very pleasant back then. Your news was full of dire circumstance, conflict and uncertainty. People were getting hurt, they were angry and scared. But as your successor, let me tell you, you had it easy.
You were the third year of power for a man who was very obsessed about building his wall. Does he even remember it now? I don’t think he does. Instead he’s moved on to focusing his hatred towards people living inside his own country as opposed to those trying to get in. But there are people that still remember, and won’t forget.
During your time planes started falling out of the sky causing many people to be scared around the world. But now people can’t fly anyway. And they have other things to be scared of. However, Boeing made some serious mistakes with the 737 Max. Was I a well timed break for them? Probably. But does their screw up deserve to be forgotten?
You gave rise to some serious protests in Hong Kong. The people there showed the world that they take issue with China’s quickly tightening grip on their free society. This wasn’t a problem isolated to you. In fact their plight has only gotten worse in in my year. It’s been hard for people in the US at least to keep paying attention when they have their own massive protests going on. They told me to tell you that they still remember you but that they have some stuff going on at home that they have to deal with right now.
2019, you are a perfect example of how no matter how bad things might seem, they can always get worse. Yes, I’m afraid I won’t be remembered very fondly. Bad timing I guess.
Yours truly,
-2020
Be Careful with Object.assign in Javascript
&& [ code, javascript ] && 0 comments
Immutability is important say the React docs. And of course this is correct, especially in the context of React, Vue.js and the like that depend on immutability to work correctly. It’s also a core facet of functional programming which is becoming more and more popular by the hour. But can you over do it?
Object.assign for the win?
One of the most popular tools for writing immutable code in Javascript is Object.assign().
Instead of mutating an object:
x = { baz: 'boo'}
x.foo = 'bar'
// x is now:
{foo: 'bar', baz: 'boo'}
We can use Object.assign to create a new object as a copy of an existing
object but with new values(s):
x = { baz: 'boo'}
y = Object.assign({}, {foo: 'bar'}, x)
//y is now:
{foo: 'bar', baz: 'boo'}
//x is still:
{ baz: 'boo'}
So why not just use Object.assign or the spread
operator
all the time thus removing mutability, side effects, and all that stuff that
functional programming teaches us is bad? Well, because performance can be
abysmal.
Take the following test suite using benchmark.js:
var Benchmark = require('benchmark')
const suite = new Benchmark.Suite;
const obj = { foo: 1, bar: 2 };
let mutObj = { foo: 1, bar: 2};
suite.
add('Object spread', function() {
({ baz: 3, ...obj});
}).
add('Object.assign()', function() {
Object.assign({}, { baz: 3 }, obj);
}).
add('Mutation', function() {
mutObj.baz = 3
}).
on('cycle', function(event) {
console.log(String(event.target));
}).
on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').map('name'));
}).
run();
The results are telling:
Object spread x 18,041,542 ops/sec ±0.81% (85 runs sampled)\ Object.assign() x 12,785,551 ops/sec ±0.87% (89 runs sampled)\ Mutation x 780,033,935 ops/sec ±1.86% (84 runs sampled)\ Fastest is Mutation
We can see here that mutating an object is 65x faster than using Object.assign.
Which makes sense because Object.assign is creating an entire new object.
The difference is even more pronounced when using larger, nested objects:
const obj = {
foo: 1,
bar: 2,
lorem: 'ipsum, dolor, amet...',
nested: {
bird: 'yes',
mammal: 'no',
platypus: 'maybe',
}
}
Object spread x 7,612,732 ops/sec ±1.14% (85 runs sampled)\ Object.assign() x 7,264,250 ops/sec ±1.16% (87 runs sampled)\ Mutation x 769,863,543 ops/sec ±1.50% (82 runs sampled)\ Fastest is Mutation
Again, it makes intuitive sense that using Object.assign would be slower.
So is it a big deal? Probably not, as you’ll usually be using these slower, immutable patterns to work with React/Vue data in which the performance impact is not only negligible but necessary.
A real world example
I was recently asked to take a look at some very poorly performing pages in a Vue.js app. When I took a look I found some code that looked like this:
trackpoints[i] = new Object()
track.trackpoints.forEach(t => {
const temp = trackpoints[i]
const key = someFunction(t)
trackpoints[i] = Object.assign({}, temp, {
[key]: [t.foo, t.bar, t.baz]
})
})
return trackpoints
Let’s ignore the fact that this code could be replaced succinctly with reduce()
(and be more FP too). The problem is that track.trackpoints consists of 10s to
100s of thousands of objects. While the above code is technically immutable, it is
also creating a new Object per loop. Once the usage of Object.assign() was
removed, the performance issues went away.
To me this is a good lesson of why it’s not a good idea to be too dogmatic in programming. Programming languages are just tools to do a job and to a certain extent the way you write your code is as well.
Flask or Django? Which to Choose for your Project
&& [ code, django, flask, python ] && 0 comments
Often I get asked by fellow python developers why I chose Django/Flask for a particular project (usually by someone who prefers the framework I didn’t choose 😉). I think both frameworks are excellent and are well suited for a variety of use cases.
So how do I decide which to use for a new project? I found a simple heuristic to get 90% of the way to a final decision, and it’s pretty easy to follow:
Decide what features your project needs:
- User accounts
- An Object Relational Manager (ORM)
- Database Migrations
- User registration/social authentication
- An admin site
Does your project require 2 or more of these features?
If Yes => Choose Django
If No => Choose Flask
Flask is great for small, focused projects. Think microservices, APIs, or very small websites. But once you have to start hunting down and installing extensions like Flask Sqlalchemy and Flask User you quickly enter a situation where the “batteries included” approach of Django makes more sense. You are basically spending time re-implementing stuff that larger frameworks like Django ship with out the box, and that are very well integrated.
On the other hand, Django can be a huge overkill for some projects. Think of an API that accepts image uploads and returns thumbnails. You could use Django for such a task, but the amount of boilerplate and setup required would be ridiculous. One of the great things about Flask is the fact that an entire webapp can be written in a single file.
Of course like I said this heuristic only gets you 90% of the way. Every project has unique use cases and design constraints that must be taken into account before making a large decision like which tech stack to use.
Essential Django Apps for Every Project
&& [ code, django, python ] && 0 comments
Django projects have the ability to install apps, which are analogous to plugins in other frameworks.
Some of these apps provide simple functionality: django-gravatar installs a template tag for displaying a user’s gravatar in a template. Other apps are large, like Mezzanine which provides an entire CMS framework to your project.
No matter what you are building, you should consider the following apps. I use them in almost all of my projects.
1. Django Extensions
django-extensions is a collection of custom extensions for Django, most in the form of extra management commands. Importantly by installing django-extensions you incur no functional changes so it should be safe to add to almost any project. Here are some of it’s best features:
./manage.py shell_plus: Like the reugular shell management command, but uses
ipython instead of the standard python shell. So much more
powerful and easy to use. Essential.
./manage.py show_urls: Display the full list of URL routes. Honestly I’m surprised
Django doesn’t have a built in command for this, frameworks like Ruby on Rails
have had it for years in the form of rails routes.
./manage.py runserver_plus: Launches a development server using
Werkzeug instead of the built in one.
Werkzeug has some very cool features, like the ability to interactively debug
stack traces directly in the browser.
./manage.py generate_secret_key: Does what it says.
These are just a few of the many features django-extensions brings to your project. Check out the full documentation for more.
2. Django Filter
django-filter allows you to declaratively add dynamic QuerySet filtering from URL parameters. If you want your users to be able to order, search or filter results on a page, Django Filter is going to be a huge help. You write Filter classes which define how objects can be filtered then add them to your views where they will automatically modify your queryset for you. They even generate their own forms that you can use if you want.
This might sound a little confusing, so let’s use an example. Suppose you have a
Widget model defined in your project:
class Widget(models.Model):
price = models.IntegerField()
description = models.CharField(max_length=2000)
listed = models.DateTimeField()
You have a view where you list these widgets:
class WidgetList(ListView):
model = Widget
And now you want users on that page to be able to sort by price, search by description, or view all widgets newer than a certain date. You would write a filter that looks like this:
class WidgetFilter(fitlers.FilterSet):
order = filters.OrderingFilter(fields=['price'])
description = filters.CharFilter()
newer_than = filters.DateTimeFilter(field_name='listed', lookup_expr='gt')
Now edit your view to take advantage of your filter:
class WidgetList(FilterView):
model = Widget
filterset_class = WidgetFilter
If you want, you can now use the generated form in your template:
<p>Filter results:</p>
{{ filter.form.as_p }}
Regardless, if your view is passed url parameters like this:
http://localhost:8080/widgets/?order=-price&newer_than=2019-03-01&description=foo
The queryset will be filtered accordingly and your user will see the results they expect.
This is just a taste of what you can do with Django Filter. See the full documentation for more features.
3. Django AllAuth
Not every project requires user registration and social authentication capabilities, but many do. django-allauth is an extremely comprehensive package that provides a project with the functions that most users would expect:
- User sign up flow, including using OAuth providers like Google or Facebook
- Login/Logout
- Email confirmation
- Forgotten password resets
- “Remember me” session control
This is not stuff most of us want to be hand rolling in our projects. Thankfully Django AllAuth exists and is high quality so we don’t have to.
Notable mentions
django-rest-framework If you’re writing an API, look no further than Rest Framework.
django-storages For projects that need to store static files and media on cloud providers like Amazon S3. Django Storages makes it easy.
Redefining Productivity
&& [ life ] && 0 comments
After nearly 5 years I’ve left my position at Las Cumbres Observatory. During my time there I got to work with scientists on interesting problems in Astronomy. I wrote a lot of code, most of it open source. Without going into too much detail, it was most everything I wanted in a job and probably the best one I’ve ever had.
I can go into details about why I left and my thoughts on full-time vs part-time employment in another post.
For now I’d like to start the new month, and my new “career” by laying out some goals and how I’d like to achieve them. This is for my own benefit: a soft of self evaluation to nobody in particular except myself.
Redefining productivity
When I worked at LCO (or at any of my previous full-time jobs) the majority of my prime waking hours were devoted to a singular purpose: increase the value of the company that hired me.
There were many aspects to full-time work that I found enjoyable: career advancement, relationships with co-workers, and interesting large scale projects that could only be tackled by teams.
I could say that I never stopped being productive in the traditional sense: adding value and making money.
My personal feelings on what it means to be productive in life have changed, however. I feel like I can do more. Now that I’m not employed at a full-time job, I’d like to see if I’m capable and disciplined enough to rise to the challenge.
What I hope to achieve and how
In no particular order:
Still gotta make a living!
I need to maintain a positive income/expense ratio. I hope to achieve this with freelance work as necessary. Eventually, I’d like to launch my own sass that can turn a profit. But more on that later.
Improve my relationships
This means improving my existing relationships as well as cultivating new ones. I’d like to spend more quality time with my wife. Now that I’m more free to travel, I can visit distant family and fiends. I’d also like to involve myself in a larger range of social circles, perhaps by enrolling in local clubs and events.
Intellectual stimulation
I’d like to return to learning every day, both outside and inside my profession. This means tinkering on side projects and trying out new technologies. I’ve taken classes pass/no pass at community college before, which I very much enjoyed and would like to do again. Also, reading and writing.
Maintain my baseline fitness
Exercise is super important to me. I feel better both physically and mentally the more I get. The usual 30min/day rule has never been enough for me. My goal is 9 hours of activity a week. Activities include cycling (obviously), running, surfing and walking. I use Strava to try and track my time. Though that hasn’t worked very well for the surfing…
Create my own source of income
The most difficult goal on this list. I’ve kicked around (and started) many ideas for sass products/businesses over the years. I’ve yet to turn a profit on any of them. Now would be a good time to really focus and see if I can make it happen.
Get better at fixing stuff
This may seem silly, but I usually never spent too much time on home or auto maintenance. I always wanted to use my weekends for other things, so I’d usually pay someone else to do it. I had more money than time, which is a good problem to have. However, there is something innately satisfying about doing it yourself. And it makes you more helpful to others.
What I achieved this week
I’ve only been “on my own” for a week so far. But I feel like I’ve done a pretty good job at working towards my goals:
- I’ve continued to work on the current freelance projects I already have.
- I’ve sent in an estimate for another project.
- I’ve been spending more time in the mornings with my wife instead of trying to squeeze in a longer run or whatever before work.
- I’ve surfed a lot during the day when nobody else is out! 🏄♂️
- I attended a tech dinner with other freelancers.
- I started a mailing list sbfreelance for freelancers in the Santa Barbara area. I hope this will help us all network.
- I signed up for YNAB to help track income/expenses and to budget.
- I fixed a malfunctioning faucet which had been bugging me for months.
- I wrote this.
Things I could have done better:
- I still need to do better about finances: get taxes in order for this year, figure out retirement accounts, etc.
- I could have spent more time looking for additional work in case my current contracts fall through.
- I could probably have a little less anxiety, it’s only been a week.
My goals for next month:
- Keep up with current jobs.
- Generate at least one more solid job lead in case I need it.
- Visit a family member.
- Visit a distant friend.
- Sign up for a class at the community college, or decide none of them are worth it.
- Generate at list of 3 sass products and seriously consider if any of them could make a profit.
Badly Designed Bike Racks
&& [ cycling ] && 0 comments
Yesterday I came across what is quite possibly the most badly designed bike rack I have ever seen. May I present to you: the Capitol Bike Rack by Forms+Surfaces.
Image credit
https://www.forms-surfaces.com/capitol-bike-rack
There were two of these side by side and at first it wasn’t even clear to me that they were supposed to be bike racks (none of them were occupied, of course). Luckily they have a nice bike symbol stamped on them that eased my uncertainty, but not my doubts. Indeed, I found it impossible to lock my bike to one of these using my standard sized U-lock.
I ended up locking my bike to a bench, also designed by Forms + Surfaces, which functioned much better as a bike rack.
These were so bad, that I decided to look them up. I found a spec sheet which claimed that the racks “Meet Association of Pedestrian and Bicycle Professionals (APBP) guidelines.”
Curious, what are these APBP guidelines and how bad do they have to be for this rack to meet them?
It turns out the Association of Pedestrian and Bicycle Professionals do have a pretty good set of guidelines for designing and installing bicycle parking in their Essentials of Bike Parking document.
The following table lists the guidelines and whether the Capitol Bike Rack, the typical “inverted U” rack style, and a sign post meet them:
| Guidline | Capitol Bike Rack | Inverted U | Sign Post |
|---|---|---|---|
| The rack should provide two points of contact with the frame. | No | Yes | No |
| Accommodates a variety of bicycles. | No | Yes | Yes |
| Allows locking of frame and at least one wheel with a U-lock. Rack tubes with a cross section larger than 2” can complicate the use of smaller U-locks.. | No (cross section is 4” according to spec sheet) | Yes | Yes |
| Provides security and longevity features. | Yes (if you can lock to it) | Yes | Yes |
| Rack is intuitive. | No | Yes | Yes |
The Capitol Bike Rack fails to completely meet a single guidline provided by the APBP. A no parking sign post meets more. I’m not sure how they can claim that they meet these standards, but it is a blatant lie.
Please, if you are considering installing bicycle parking for your business or development, install racks that actually work. The typical “inverted U” may be boring, but they function.
Cycling in the US: A Dutch perspective.
&& [ cycling ] && 0 comments
Check out this video of a Dutch person’s perspective of cycling in the US:
A few of his observations that I found particularly interesting:
-
Cyclists in the US appear to be racing all the time. He attributes this to the need to keep of with other traffic since cyclists are rarely able to ride on dedicated paths and it would be dangerous to move too slowly.
-
People casually riding comfortable bikes, in normal clothing, going from A to B is a sign of a healthy cycling culture. He also uses this as an argument against helmets: they only encourage the image of cycling as a dangerous activity.
He of course makes a few observations that should be obvious to any cyclists in the US.
-
Cycling is seen as an activity for children.
-
Our bike infrastructure really sucks.
It’s great to hear an outside perspective from someone who lives in a place where cycling is so much different than it is here.
Password-store (pass) extremely slow on OSX
&& [ code ] && 0 comments
password-store (installed via homebrew) on OSX is very slow.
Austins-MacBook% time pass testpass
thisisatestpass
pass testpass 0.55s user 0.25s system 83% cpu 0.969 total
Over half a second to print out a password. Pass is just a bash script. This would not do.
After doing some sleuthing, it turns out it is this line in the platform specific code for OSX that is causing the problem:
{{< highlight shell >}} GETOPT=”$(brew –prefix gnu-getopt 2>/dev/null || { which port &>/dev/null && echo /opt/local; } || echo /usr/local)/bin/getopt” {{< / highlight >}}
Every time pass is run on OSX, it first has to run homebrew to find out where gnu-getopt is installed.
It seems silly to default to such a heavy handed approach. It would make sense to first test a well known location (perhaps, the default location where homebrew installs gnu-getopt?) first, and then resort to the other methods after:
{{< highlight shell >}} GETOPT=”$({ [ -x /usr/local/opt/gnu-getopt ] && echo /usr/local/opt/gnu-getopt; } || brew –prefix gnu-getopt 2>/dev/null || { which port &>/dev/null && echo /opt/local; } || echo /usr/local)/bin/getopt” {{< / highlight >}}
Using that method, things are improved considerably:
Austins-MacBook% time pass testpass
thisisatestpass
pass testpass 0.02s user 0.01s system 19% cpu 0.177 total
There have been patches submitted upstream in the past for this issue, but none have been merged. So I forked the upstream repo and applied the fix. You can install this version of pass using homebrew:
Uninstall pass if you already have it installed via brew:
brew uninstall pass
Then “tap” the repo:
brew tap Fingel/pass-osx
Finally, install the formula:
brew install fingel/pass-osx/pass
Enjoy a properly fast pass. This should be helpful for anyone using pass on OSX, who doesn’t mind installing their password manager via some random guy’s fork on Github… 🤔
Does Strava Encourage Illegal Trail Riding?
&& [ cycling ] && 1 comments
I recently received the following email in my Trail Care inbox (names and locations removed):
Hi, I am a long time mtb rider. I am also on the Board of Directors for the local open space advocacy/trails stewardship group. The actual owner of the surrounding open space is the county. Like other areas, we have a ton illegal trails. Many of the authorities see Strava as a negative in that riders publicly post their illegal trail rides which leads others to follow. There is also the perception that Strava motivates riders to break speed limits to get KOMs. Have you run into this anywhere else and how do you get around this?
This is a controversial subject within the mountain biking community, especially within the advocacy circles. Pretty much everyone has an opinion about Strava. Some people love it, some hate it, any everyone has their theories.
What nobody has is any data to back up their arguments. None.
Nobody can prove that Strava encourages illegal trail riding. You’d have to hang at the bottom of an illegal trail for months and ask every rider where they found out about it, compare it to months of data prior to Strava coming into existence, and even then you’d only (maybe) be able to come to a conclusion for that one trail.
You can’t prove that Strava doesn’t encourage illegal trail riding either - but not being able to prove a negative does not prove a positive.
When people say that Strava encourages illegal riding what they might really be saying is that the narrative makes sense to them. It is also very easy to blame a scapegoat, Especially when it’s a phone app coming out of Silicon Valley. I get it: I have sympathy for people that feel like phone apps have no business out on the trails. But to each their own, right?
Unfortunately telling people that they can’t prove Strava is a problem doesn’t really win any arguments. - people much prefer anecdotal and circumstantial evidence. So I’ll give you some of my personal theories:
I (as I hope I made clear) have no idea if Strava contributes to illegal trail riding. What it surely does is make it more visible to non mountain bikers. Illegal mountain bike trails have existed since people first started riding bikes off road, but maybe not too many people knew that it was happening. Trust me, it has been. You would especially think that land managers/owners might prefer to think that Strava is contributing to more people riding illegal trails when in reality they have been all along, right under their noses!
As for speed, I have to think that’s most likely bullocks. Mountain bikers love to go fast, otherwise they’d be hikers. Mountain bikes have gotten a lot faster in the last decade, at the same time the sport has become much more accessible and popular. This will of course result in occasional conflicts on multi use trails.
So in short: while I have no idea, I highly doubt Strava contributes significantly to increased use of illegal trails. Southern California especially, with it’s very few and overcrowded trails, faces huge challenges in land and recreational management. Blaming a scapegoat doesn’t actually solve any problems. Land managers and other trail users need to work with mountain bikers to come up with real solutions, not blame some silly app.