When I hear someone say “I don’t care” regarding a decision in a meeting, it raises the hair on the back of my neck. It causes the following things come to mind:
- I have no vested interest in the outcome one way or the other.
- I don’t value whatever resources are involved in the decision being made.
- I would rather be doing other things with my time.
- Your suffering (or anyone else’s suffering) doesn’t matter to me.
- I’m fine with making short-term gains in exchange for long-term pains because I’m not concerned about the long-term impact of this decision.
There’s often a better, more specific way of getting your point across:
- “I’m not sure this decision has any impact on me, so I’m fine either way.”
- “You choose whichever option you think is best.”
- “I’m not sure I could recommend one option or the other… they both seem [good/bad].”
- “Do what you need to do in order to make [the goal] happen. I’ll support you in doing this.”
- “Let’s go with the best long-term option.”
I just saw a comment like this in a piece of code written long ago:
“Do this particular thing because it behaves like this. Not sure why.”
That, to me, is a code smell. If you aren’t sure why a particular piece of code is behaving the way it is, it’s best to take the time to understand why it is behaving the way it is, rather than compensating for it in other places. Compensating for unknown behaviour leads to messy code and unexpected bugs. It makes maintenance harder, because you then have to update code in more than one place. Duplicate code = duplicate bugs = more maintenance = it takes you longer to get new features in.
If you aren’t sure why – learn why! An hour spent now saves ten hours spent later.
At some point in time, you will be given a task like “What happened to X? Why can I no longer see it?” or “Why does the date on X say ‘Dec. 31’ when it previously said ‘Jan. 1’?” With any sort of complex system, these kinds of questions are inevitable. A user changes something without telling another user, or a weird process messes with data, or worse yet, a bug happens (which is almost inevitable).
With if you are properly logging an audit trail, these kinds of questions become really easy to solve. Want to know who deleted X? Check the logs. The logs don’t even need to contain all the detail – just a general idea. For example “User ‘Gordon Freeman’ deleted X on Aug. 1, 2012” is detailed enough to tell you who did it, and when it happened. It’s so much easier to add some basic logging in at the start, then to spend time trying to track theses kind of things down after the fact.
Save yourself some time. Add logging/auditing right now.
Have you ever been browsing a website, viewing a list of items, and had it display 20 out of 21 items? Don’t you just love clicking the “next” button to see one more item? I don’t.
Pagination – the idea of breaking up data into pages of a set length – is often necessary. When querying data, and not knowing exactly how much data is going to come back, you need to put a limit on things. Imagine searching Google, and it loading up a web page with all 550,000+ results for “discount Koala meat”. I’m pretty sure that would crash any browser – especially on a memory/CPU limited mobile device. So rather than returning all results, it breaks the search results into pages of a reasonable size. But what is a reasonable size?
One frustration I have with sites like Amazon.com is that they will display page sizes of 20 items or so. But what if my query returns 21 items? Do I really want to make the user click the “next” button to see a single item? What if they want to see items on both pages at the same time?
Situations like this make me want to implement some form of fuzzy pagination. If n is the page being requested, we examine page n+1 (if it exists). If page n+1 does exist and is the last page, and the number of results on page n+1 is <= 50% of the page size, we return the results as part of the request. If any of the above conditions fail (there is no next page, or the next page is >50% the size of a regular page), we don’t do anything special – we just return the regular sized page.
It’s features like this that are almost completely transparent to the end user, but make it that much better of a user experience.
Sometimes, when working on something, you start digging into a particular technical issue. The more you dig into it, the more it leads you away from your original goal. I like to call this “chasing the rabbit”. If you chase a rabbit through the woods, and only keep your eyes on the rabbit, you’ll eventually find yourself lost in the woods.
It’s easy to lose sight of the big picture when you are “chasing the rabbit”.
I hope I never grow tired of learning new things.
In some respects, this is great. I never grow bored of life. There’s far too many interesting things out there. The world is filled with interesting problems, and even more interesting solutions.
In other respects, it is a bit of a curse. Because of this, I have far too many interests. As the saying goes, “jack of all trades, master of none”. I sometimes feel like I don’t have the depth of knowledge that I’d like in particular subjects.
It’s amazing how deep you can go down the rabbit hole. Let’s just take programming as an example. For my day job I work with Python and Django, and in my spare time at home I occasionally play around with C# and ASP.Net. There’s a ton of interesting technologies out there. For example, suppose you are shooting for more performance for a web app, so you start digging into caching. So you start learning about Redis, and other key-value stores. That leads you down the path of learning about cache misses, specific implementations of hash tables, and fast hashing algorithms. That area of computer science alone has claimed many a PhD student. 😛
I think my ultimate dream job would be where I get paid to learn, and on occasion, get to apply/unleash that knowledge on an interesting problem.
The rope bridge philosophy is something that I discovered over at GameDev.Net a long time ago, so I can’t take total credit for it. It goes something like this:
When you need to cross a river, you first build a rope bridge. You don’t start with a concrete and steel bridge, because you don’t know if you will be crossing over that same river again. By starting with just a rope bridge, you’ve spent minimal resources on a problem that you aren’t guaranteed to encounter again. If you find yourself needing to cross that same bridge multiple times, then you can go and revise/rebuild the bridge with something stronger. Yes, it means you’ve built the same bridge twice, but you’ve also saved yourself resources by only building what is necessary.
This is totally applicable in programming – especially something like game development. There is often no clear “best” solution, and you face a huge number of unknown problems. You don’t know if the game you have designed is going to be fun without getting something working first. You only want to spend resources where they are going to matter.
Eventually, as you gain more experience, you learn when to preemptively built a bigger bridge. Like anything else, a bit of that intuition comes from experience. But even then, you still risk the danger of spending resources where they won’t be needed.
Something that I often tell my team is the following:
1. Make it.
2. Make it work.
3. Make it work right.
4. Make it work right fast.
Building a bigger bridge before you’ve gotten to your destination is making something work right/fast before the entire thing works. Learning when to build something bigger than a rope bridge at start is a bit of an art. It takes experience – but experience only comes at the cost of making mistakes. You also need the freedom to go back and revise/refactor things once everything is working. This is something that you often have to push for, and something that management needs to understand.