10 Aug 2017 c.e.
Trying to Fit a Tonka in a Minivan

One of my biggest weaknesses in software for a long time was the absolute belief in my ability to shoehorn a Tonka truck into a Minivan object.

In other words, I believed that I could take something that looks nothing like a Minivan, and fudge the data structure just enough to fit a Tonka truck in it.

This causes problems. Always. Usually those problems radiate outwards from the data storage place to all the places that have to come in contact with the data. Suddenly you need functions to know how to tell the difference between a Tonka and a Minivan, since what you're handing them could very easily be either.

You need the ability to tell the difference between a Minivan and a Tonka truck everywhere that that data object ends up. The chance for forgetting to check for Tonka vs Minivan-ism becomes higher the longer it's been since you stuck a Tonka truck in the Minivan parking spot. It also becomes higher the more code that you write that has to deal with that parking spot (so to speak).

I find that this is a problem that tends to crop up in non-typed codebases most of all. Because there's no type checking system to make sure that you've kept the Tonka out of the Minivan object, you just shoehorn it in.

It is possible to shoehorn Tonka trucks into Minivans in typed languages; sometimes they give this ability a special name like 'generics'. In generic land, you're only in marginally better territory than non-typed language territory -- the consequences of having to check the label on the object you get remains valid.

I wouldn't care about this so much if I wasn't currently attempting to get the Tonka truck out of the Minivan parking spot at the moment.

If only everyone learned lessons at the same time that I do.

#refactoring #architecture
11 Jul 2017 c.e.
The Art of Differentiation

tl;dr: one of the skills software development requires can make you into a pedantic asshole

This post fits into the category of 'allegorical comparison piece on an abstract idea about software as a concept'. It won't make you better at writing software, but it might help you better talk about and identify certain aspects of the job that is writing software.

Now that I've done the work of setting expectations, let's talk about expertise.

Expertise, Kinds of

Roughly speaking, there are five types of 'expertise' that a person can develop. These expertises are as follows:

  • physiological: feats of strength. Usain Bolt's speed or Simone Biles' graceful, aerial contortions
  • muscular manipulation: muscle memory type things that require a certain amount of practice and movement, usually only developed through practice. Carpentry, knitting, playing a musical instruments, vocal production and acting
  • memory: learning new languages, rote recitation, math
  • social: I tend to think of Machievellian Frank Underwoods, but there's also your friend that likes organizing parties
  • differentiation: a skill based on your ability to tell things apart; typically built through exposure over time, ie experience

These aren't 'pure' categories; learning a foreign language is part differentiation, part memory and part physical skill (muscluar manipulation). Being adept at math requires knowing what kinds of equations are good for solving a particular problem (differentiation). It's also highly likely that I've left some categories out. If you think of any, I'd love to hear about them.[1]

On Differentiation

Of all these skills, differentiation is the skill of erudition.

Consider the case of a sommelier, a wine expert often hired by restaurants to field questions of wine pairings from patrons and offer suggestions to the less knowledgeable. Becoming a sommelier requires you to gain the skill of differentiation in the domain of wine tasting -- if someone asks you to recommend a wine similar to another one that they like, you'd better know of other kinds of wine that are similar to it. Or at the very least, what won't be similar, lest you recommend the wrong thing.

Writing good software also requires a taste for differentiation. Put another way, a software developer needs to be able to know when a thing is different enough from another. Given another requirement or feature, is it a new case statement, or is it something that you can shoehorn into an existing structure? Or once a bug has been found, what type of a change is required? Do you need a separate class or will just an if statement do? Maybe the bug forces a complete rearchitecting of a given structure.

Unlike wine, however, software lines are more difficult to draw. Wine can be categorized based on growing region, grape type, year of harvest, knowledge of the weather that the the grapes were grown in, how long the wine was casked for, what kind of casking process the wine underwent, who's selling it, etc. You can compare the flavor of a wine just by tasting it -- the set of different categories of wine are set. The only wines that need to be categorized are the ones that have been produced; the boundaries are with what exists, concretely.

Software is arbitrary. The space and delineations of software classes are the made up lines that the creator has seen and defined. Yes, the definitions and categories are sometimes derived from the problem domain in which you're working -- enterprises call this the business logic layer of an application because the domain is defined in part by the business needs. But it's not always clear cut whether you should build a factory factory in order to best iterate through the variable typed list or if there's a better abstraction or generic solution that would more concretely capture the difference between the things. Often times, I've found that the solution is subjective, depending largely on both the preferred tools of the developer and the differentiations that they've discerned.

Good Software Developers, Then

Good software developers then, become excellent at the skill of differentiation.

They also become pedantic assholes who want nothing but to get to the root of how or what exactly is the essence of a thing. Because without that root, there is no way to differentiate, no way to tell, exactly, how this thing that you're talking about is different from the other. Whether it's a new feature or something else entirely.

And that is why all of your software writing friends tend, over time, to converge into pendantic assholery.

[1] I would love to know how to classify writing

#art #apis #skills
29 Apr 2017 c.e.
Women In Tech

tl;dr Women in Tech Are Problem Solvers

I'm at a tech conference for women today, listening to a woman talk about her experience getting a board seat at a Fortune 500 company. It's inspiring; it's also devastating that this is a thing we hold strategy sessions on.

That's right. This whole conference is a strategy session.

I want to let you in on a little secret. Women in tech want to make the industry a better place. When women in the industry get together and talk, we talk about what sucks but we also talk about how we can make it better. Lady back channels are problem solving working groups. We complain, we share, and we strategize.

Women pay money for conference fees out of their already discounted salaries to hear other women talk about how to solve the same disparate problems.

Subtle discrimination and inability to be recognized for contributions at work is a problem that we are trying, desperately, to solve. We're trying to fix our micro environments and the things in them that are holding us back from the recognition and promotions that we get passed over for or overlooked for or where the goalposts keep moving just out of reach. We're trying to be better at our jobs, to have our voices and concerns heard and recognized and considered, not ignored and shrugged off. We're tired of feeling like Cassandra, like Hestor, like Mata Hari.

Women in tech are trying and have been trying and if you think they aren't what do you think women in tech fucking talk about. We are problem solvers by trade, what makes you think we would approach professional problems any different?

The fact that we haven't solved the problem yet says something, I think, about the enormity of the challenge.

We're working to fix it. We've been brainstorming and talking and working to fix it.

Why aren't you?

#women #in #tech
27 Apr 2017 c.e.
Roadblocks on the Way to Refactoring

tl;dr how good is your mental map of the territory?

My three month 'anniversary' at Pluot Communications is quickly approaching. In the time since I've started, I've worked on a dizzying number of projects, most of which has been getting up to speed on how WebRTC and React/Redux works. Recently, a lot of our software contractors rolled off the project (and hopefully onto something else equally squishy). Anyway, with their rolling, I've since more or less acquired responsibility for a large React / Redux project. Part of the work we've been doing at Pluot lately is a big re-skinning job, getting ready for some soon to come feature that I'm not allowed to tell you about yet.

Reskinning is like refactoring the view parts of a website. It seems logical to me then that refactoring the code parts would rightly follow. And they usually do, depending on what, exactly has changed about the spec.

Refactoring a project that is A) large, B) mostly unfamiliar, C) untested, D) written in a dynamic, non-self documenting language (JavaScript) is not one of those things that anyone would largely recommend that you do. I'm here to tell you that you can and you should do it. Here's why.

What should Refactoring accomplish?

I'm going to be honest, I don't know why other people re-write things. A lot of times when I've observed teammates embark on refactorings (which honestly never seems to be as often as I feel like I'm hauling off on them, but I digress) sometimes the code comes out cleaner. Most times it comes out far more confusing and complicated and they claim that they've just saved ... something.

I don't buy white knight refactoring. When I refactor shit I'm usually multiplying code. I refactor things so that I can read them, so that the chance of me breaking something in the future in considerably lessened, so that it's easier to make changes to one part of the code without having to necessarily consider other parts. When I 'refactor' I pull out components, try and keep all of the logic for a thing into a single, canonical, topically or functionally organized place.

I try as hard as possible to decouple view code. View code is notorious for being an arena for subtle bugs. You change a padding in one place and it looks good everywhere except the checkout page where it completely hides the Buy button for certain languages. Of course you checked everywhere, except there, and it took an analyst three days of pondering why the sales numbers in Turkey had taken a plunge in order for someone to figure out what had happened.

As far as I know, I've never done anything like this. But that just shows what I know.

You mentioned earlier that refacotring large, unknown, untested, untyped projects is a good idea. Can you expand on this more?

Sure. When you're faced with changing a codebase that you don't understand, the probability for changes you make introducing bugs is very high. There's a whole taxonomy of where bugs originate from that I won't get into right now, but a large, a very large class of them, fall under the category of problems introduced because you did not understand how the code worked. The root of these bugs then is Your incomplete mental model of the codebase.

So how do you pre-emptively fix this class of bugs, bugs caused because there are incorrect assumptions that you have drawn about how the code works? It may seem obvious, but the easiest way to not make bugs based on bad assumptions is to not hold bad assumptions. How do you know what quality of assumptions you hold? Like any good scientist does, by testing them.

How do you test assumptions about code? There are two ways. One is by closely reading the source document. This is a bit of a pro-level move. The other is by changing things and seeing what breaks and how.

Sometimes I rename variables just so I can see where all it's used. That way I have to touch every single last place that that particular variable appears. It also makes grep a viable tool to help you check when you're finished with a particular task -- when all mentions of the old variable are gone you're done. Grep is a particularly important tool for non-static or non-compiled languages. Back in the day when I did Java codes, IntelliJ or Eclipse would automatically reneame a variable with a few strums of the keyboard. Without that compiler guarantee, it's basically up to you to manually check that every instance of a variable has been updated or changed or whatever. Grep's a good tool for this. If you're new to the grep game, check out git grep -- it only parses files that are checked into git. The only flag I really use for grep is the occasional -n which shows the line number that a particular match was found at. Between grep and vim, I can crank through a number of renamings pretty quickly.

What's the use of knowing every place that a variable is used? It gives you an idea of the scope of that object. If you know every place that a variable is used, your assumptions about that variable are probably more accurate, which reduces the chance of introducing bugs. More than anything, you'll find out really quickly how good your naming scheme is. If you're having trouble figuring out which 'versions' of a variable name are related to each other, maybe you should use more explicit or unique names for things. Asking someone to use a project unique name for every variable is a bit of a tall order, but hey no harm in considering it. After all, you are programming in a language with a shitty toolset -- hacks are expected.

When to Refactor?

You should refactor any time that you encounter code that you do not understand and the person who wrote the code is no longer available to explain it to you. The goal of the refactoring should be simple -- to make it such that you do understand the code.

What if you break the code and can't get it work the way that it originally did?

Let's go back to assumptions. If you're unable to re-write code such that A) you understand it and B) it functions as it previously did, then clearly you don't understand what that code is doing.

In this situation, my advice is to either A) start over or B) give up. If you give up, you better not change anything else related to how that code works as you've just irrevocably proven that you have no idea how it works. Clearly the person who wrote it is a madman who sucks at programming and you should celebrate your defeat by posting the offending code-bit to the code shaming website of your choice. I recommend StackOverflow.

What if you need to make a change to that code but you don't understand how it works?

I'm sorry to say it, but your odds don't look very good here. Making changes to code you don't understand is not something I'd put money on. You really shouldn't either, but this all depends on what you consider an acceptable level of risk.

Have you tried asking for help? I hear StackOverflow is a good place for that.

What does Refactoring accomplish?

Ok so you've totally refactored large swaths of your project and managed to wrangle the three-way merge hell into a single large commit.

Congratulations! You are now the only person who, supposedly, understands how the code works. As the only person who understands how the new code works, you have implicitly become its maintainer into perpetuity.

Isn't that exciting?

#refactoring #maps #wtf
26 March 2017 c.e.
Bugs of Projects Past

tl;dr: there is no such thing as a 'worst' bug

A question was put to me last week that I didn't have a ready answer for: what's been the worst bug you've encountered?

I've enocuntered plenty of bugs in 7 years of software development, but when asked directly have trouble bringing a memorable one to mind. Once they're solved they're hard to remember as being difficult. Or maybe I'm too used to things crashing, or to dealing with those once in a Samsung release kinds of problems, that none of it seems re-telling. You deal with Android long enough and crashes on specific systems due to differences of opinion on how an API should be implemented and function become mundane. Once you have an explanation for a bug it seems far less mysterious or interesting. And the tenth time you're blaming Samsung, the previous nine bugs are marginally less memorable.

International Incidents

That being said, I do have a story that, with much prompting, I'll often drag out. It comes from the Android eco-system, from a logging framework that I wrote as one of my first projects as a Professional Developer.

In the first version of the library, I sent back logs with localized datetime strings. This works really well in every language that I tested it in; it works less well in Arabic, whose alphabet uses its own number glyphs. The Arabic number timestamps were incomprehensible by our log ingestor, which meant every Arabic language Android phone was successfully avoiding our attempts to log information about their system.

Arabic numbers are quite beautiful. For a while thereafter, Arabic became my go to language for testing RTL layouts (right to left), even after I discovered there was a debug RTL language setting that was in English but backwards. Dear lord, I even made sure that the Electric Objects app looked decent RTL. I'm a sucker for weird corner case testing.


You can also ask me anything about that one time that I spent a weekend hacking a currency selector into the Etsy Android app and introduced a bug that crashed the app on open for users on phones that had a non-existent locale set as default. Lucky for me this wasn't a lot of users, but coding around it was hard as heck -- deciding on a fallback locale felt fraught with hegemonic implications.

Much later, a co-worker re-wrote one of our navigation drawers in such a way that made it blank for users with their language settings set to Persian. His mistake made me feel a bit better about my own international failures.

A fascination for corner cases would explain my strange fetish for internationalization. While working on the currency selector, I spent a lot of time on the formatting function for prices. There are a lot fun, semi-arcane things to know about price formatting. For example, in some countries (like Sweden) you put the monetary symbol after the price. In America we write $10; in Sweden they'd write it as 10$. A lot of currencies have their own symbol for currency, like the pound or euro sign. In other currencies they use the same symbol as the US, the $, but annotate after the amount to denote which version of dollars they're talking about. A Hong Kong price would be $10HK[1]. Japanese don't use decimals for their prices, you just truncate it at the whole yen. The Swiss franc doesn't have a currency symbol, it's usually only annotated with the letters CHF after the value.

If you really want to get trippy, decimal annotation changes between languages too. Canadian French put spaces between their thousands and use the "," as a decimal separator (1 000 000,34), whereas English Canadians do it like the Brits do (1,000,000.34). Colonialism lives on.[2]

The Java libraries on Android had a fairly complete API for figuring out how many decimal places to show, and what punctuation marks to use, but the before and after split for prices wasn't exactly correct or necessarily nice to look at. Not to mention that the code itself was rather verbose. Of course, after I had figured most of this out, someone on the team (most likely my engineering lead) mentioned that it's best to let the server have all the logic for what to show people instead of embedding it in the client as it's easier to track down and fix bugs that originate with the server. Which would have been all well and good if the server's price formatting logic had been anywhere near as complete as the Java + custom logic we wrote for the app. One nice thing about phones is that they provide a locale and language preference for a user, which you can use to figure out whether to display fonts in British or French Canadian. The server side location preferences were good but not French vs British Canadian good.

Time Bugs

Timing errors led to some pretty memorable bugs. One of the first ones I ran into was while I was at Etsy, working on developing a feature using an emulator. For those of you unfamiliar with mobile development, an emulator is like having a fake phone that you run inside of your computer. It's basically a virtual machine that runs all the same code that runs on a cell phone. The only difference (in theory) is that you don't need the phone hardware. And you can load up & run programs on the same machine you're developing them on.

The old school Android emulators were slow, especially when compared to the Apple iPhone simulators. Simulators use the host computer's chip architecture and do a rough approximation of the same program on top of a different instruction set; emulators have virtual chips that they run the actual program against. Emulators run hella slow because there's more layers of software involved, but in theory are more accurate as far as exposing bugs. Once you started up an emulator, you tended to keep it up as they often took 3-4 minutes to launch.

Anyway, I was working on a new feature for the Etsy Android app, and kept running into a problem with the API requests I was making. The errors didn't make much sense though -- they seemed to indicate that there was something wrong with the certificate on my app, which had nothing to do with what I had changed or was building.

I didn't have a very good understanding of how network security worked at the time -- I knew how to set up a proxy with a man in the middle to read my network traffic (/me pours one out for Charles) but that was just me following a very simple wiki page. It turned out that something about ssl and/or our pinned certificate could only work if the server time was within 2 hours of the phone's clock time. Which is all well and good on a normal cellphone that gets its time from cell phone towers on the regular. However, the emulator that I had been working on, while it had started off with a clocktime that matched that of my laptop, when I suspended my computer overnight the emulator was also suspended. The difference being that it didn't have a separate battery to keep track of the time like my laptop does (more about these later). The clock fell behind by exactly the number of minutes the laptop slept for. Which meant that network requests were failing because the SSL handshake timestamps fell outside of the 2 hour window. Once I knew the problem it was easy to just restart the emulator. I had to start restarting the emulator on the regular and eventually ended up just using real devices for testing because it was faster and easier than dealing with the slow pile of morass that was the Android emulator situation in 2013.

Timing issues came back for some fun when I worked at another job, where we were building proprietary Android devices. Basically someone forgot to put batteries on the bill of materials for parts that we'd need for manufacturing. You need batteries to keep the clocks in sync while the unit is powered off. Most electronics have a battery powering the clock, round the clock. One of our engineering leads had to go find a couple hundred batteries in Arizona while they were attempting to get the devices manufactured the first time around. I believed they got them all in before they were shipped, thank goodness.

One of the hardest bugs I ever had to track down was a race condition (time again!) over a super slow, very spotty network. The problem was in the OAuth renegotiation from a client to a server. Normally OAuth tokens expire after a few hours and the application asks the server for a new one but there were a bunch of reasons why this check would sometimes randomly fail in my app, most of which could be traced to a lack of good locks around the refresh token sequence in the client app.

I did a lot of work to lock the refresh token down to a single thread and moved our network requests to a queue rather than the firehose structure they had been using before, thereby completely erasing the race, but we still would get reports from the field of devices that were randomly logging themselves out due to an expired token. Finally, I managed to replicate a condition where a device on a bad network could send off a request to the server, successfully generate a new token server side (thus invalidating the current token), and then never actually receive the packet with the new token on the client side. At this point your client application is basically hosed -- there's no way to recover without the user logging in again since as far as the server knows it sent you good information. We knew that a surprisingly large majority of devices we had manufactured had less than stellar wifi chips in them so we did what any self respecting software engineering team would do and gave up.

This problem, unique as it is, does highlight an interesting property of network requests -- that they're largely assumed to be successful. I've worked with a lot of server teams, but i've never heard of anyone writing rollback protocols that are triggered by failed TCP deliveries. If you know of one, I'd love to hear about it.

Send Me Your Bugs

I also love hearing about bugs. I also love helping solve bugs, though I'm not great at it. If you've got a particularly juicy one that you'd like to tell me about, tweet it over to me @basicbitchsoftw.

[1] Big thanks to my Canadian co-worker for writing this into our library, I wouldn't have known about it otherwise.

[2] Another front of formatting differences between languages: quotation marks. I've never seen a library that accurately translates quotation marks between languages. I feel like I've seen Google Translate do this elegantly, but a quick check shows that to be mistaken.

#bugs #reflections #race-conditions #internationalization
12 Mar 2017 c.e.
*Redaxted*

tl;dr: Learning a new framework sucks, especially if that framework is written in JavaScript.

Dear god there is something absolutely screwed up about the JavaScript code ecosystem, I'll tell you what. If I had to put a finger on a root cause, naively I'd assume that few of the people writing code for JavaScript packages have written or worked in any large system not in JavaScript. Well, actually, I can imagine that they have worked in Ruby land. I'll amend that lemma to be "not in a compiled language, at any rate".

I've spent the majority of this week learning the React/Redux workflow as it's what we use on our webapp at Pluot. Generally speaking, the idea behind the architecture is pretty solid and can summed up thusly: keep all your state in one place, you filthy animal, and pub/sub/observe/notify any updates.

There. You now understand Redaxt.

Have you ever programmed anything in JavaScript? The language is so flexible as to be practically incoherent. Prototypes mean that any and everything is up for grabs at runtime which leads to some amazing flexibility and beautiful abstractions but also chaos and mayhem. There is good cause to complain about the release of a new 'JavaScript' framework -- the number of guarantees you have about the conceptual idioms of that framework are very limited. One side-effect of this is that JavaScript developers have the most finely tuned vocabulary for model-presenter-view you'll find anywhere, I guarantee it.

I'd like to recount for you the suffering I have been subjected to at the hands of the JavaScript ecosystem, as I've been learning how to Redaxt things this week.

Npm

I really have nothing much to say about npm as if you've ever used it you'll understand intuitively my point, but for those of you who have never used it, I will briefly explain the horror.

npm is a package manager for node, the JavaScript runtime that unleashed the horrors of mutability onto server side programming. It is as flakey as all fuck. The common advice for fixing weirdness with your program dependencies is to forcibly remove the entire cache of libraries and redownload them from the Internet whence they came. npm builds have a zero guarantee of repeatability, as the version of your dependencies is updated as published. Isn't that nice.

Webpack

JavaScript is great because it doesn't have a compiler but, sometimes, it's really nice to have a compiler. Also the JavaScript language cabal recently underwent a coup from the Ruby department, known more widely as ES6, and they needed a tool to patch over the ensuing chaos. Yes, more chaos than the normal amount of chaos that comes from an untyped, uncompiled, prototypical, dynamically functional language.

Webpack is the everyman's tool for transpiling your sugary, Ruby-ified JavaScript into something that average Joe Browser can understand. Yes, that is correct. State of the art JavaScript requires translation in order to be practically understood. Webpack does a lot of other things, like serving your pages locally, from memory while you're developing, re-writing output paths, copying your files into weird hard to find places, obfuscation in the most literal of senses, and more.

Given the correct flag, webpack will re"compile" your files when they're changed but I have yet to figure out what heuristic it's using to trigger a rebuild, given how randomly it actually works as intended. Your mileage may vary, but if you figure this out please someone let me know how it's supposed to work. To add insult to injury, the build output doesn't include anything so useful as a timestamp so that you can easily tell when the last time it deigned to run was.

Typos

You would think my shitty typing skills would be something I can't blame JavaScript for, but you'd be wrong. JavaScript has the incredibly dubious distinction of being one of those programming languages that you can make a typo in and not find out about it until you've "compiled" the project, refreshed the page and then attempted to click a button. You can mangle a variable name and nothing will happen, that nothingness being precisely the problem. Silent failures are the worst kind of failure. JavaScript has a fancy transpiler and really great[1] syntax but it can't tell when I've made a really obvious keymash. JavaScript is clearly the language of the futur.

Functional Programming Cargo Culted Fanfic, aka The Redux Docs

Here are a few curated selections:

  • "It's very important that the reducer stays pure." like a virgin, until you touch it for the very first time. Or actually no, don't ever touch it because then it will not be pure and how could you do that to a function?

  • "No surprises. No side effects. No API calls. No mutations. Just a calculation." asking for a boy to love him.

  • "let's start writing our reducer by gradually teaching it to understand the actions we defined earlier", oh noble Pygmalion.

  • "Redux will call our reducer ... for the first time. This is our chance...", your once in a lifetime opportunity!

  • "Here is our code so far. It is rather verbose:" This statement was followed by the least verbose code I've seen. I do not understand what the word 'verbose' means to anyone in this universe.

  • "we can split the reducers into separate files and keep them completely independent" as separate files are a recognized talismic barrier for keeping code from becoming logically entangled.

To be fair, once you get past the many rough edges, JavaScript is an entirely delightful language to write your own universe in. Redux/React is a fairly well thought out system for updating views and maintaining a centralized state mechanism, and I'll probably consider using it on my next JavaScript project.

Or maybe I'll just try Elm. I hear its compiler is very nice.

This post is dedicated to my friend Myk who can't remember the last time he did something that wasn't JavaScript.

[1] Great if you like syntactic sugar bullshit that is the opposite of readable.

#javascript #react #redux
20 Jan 2017 c.e.
The Type of Problem that is an Algorithm

Wherein I Rant About Being Interviewed

I had an in-person interview recently where the day was split up by 'type' of skill that, I, as a 'generic' softwawre engineer (typically this means web) am expected to have acquired by this point: front-end knowledge (JS & CSS), architecture, databases, algorithms, 'culture', a tour of the code-base, and lunch with a few other engineers. Without question, I bombed the algorithm portion, fumbled quite a bit on the front-end piece (in my defense, it has been 5 years since I last made a web UI), and revealed a large knowledge gap about how database indexing works.

Having the skills required to be a web engineer so concretely delineated and feeling like I wasn't really particularly good at any one of them, made me question what skills I had. It certainly wasn't domain specific knowledge of large databases or JavaScript or how to solve algorithms. Yet I have been writing and shipping software for half a decade. What exactly have I been doing, if it wasn't any of these things?

As a mobile dev of the Android variety, I'd say that the types of problems that I've spent a lot of time thinking about are application state[2], manual testing, code architecture, network availability, and view drawing code. I enjoy thinking about the way code fits together.[3]

I've found interviewing to be a struggle because solving algorithm problems is not something I'm good at. I've taken a single online class on them, solved a number of exercises, watched tens of other engineers solve algorithms problems, and am generally familiar with the classes of problems that algorithms fall into. But I haven't, personally, solved a large number of algorithms problems on my own, an experience that I think greatly improves your ability to do so when timed and under pressure.

In thinking through this, I found it helpful to delineate the difference between an algorithm and an architecture question, as a way to better understand what sort of work involves needing to be good at one or the other of these skills.

The Nature of an Algorithm

An algorithm is the precise set of steps that you must take in order to accomplish a task. A solution to an algorithmic problem can be judged on the number of steps that it takes to complete the task and the amount of computer memory that is occupied during the process. Solving an algorithm, then, is a matter of divining the necessary steps.

An algorithm can fail if the defined steps do not return a correct answer for a valid starting condition. Part of the process of finding a solution is identifying potential places that the steps, blindly followed, will arrive at incorrect results.

The Nature of Program Architecture

Architecture is the theater of abstraction. As a topic, it is a wider, and more nebulous category of problem, but generally speaking it is a class of problems that concerns the definition of spheres of responsibility between the various functions of your application. Usually this involves some amount of data flow. When you 'architect' a system you are naming things, assigning work, and defining relationships.

Wrapping Up

The interviews that appreciate the skills that I currently have are the ones that I've done the best at. I didn't end up getting the job at the company who put me through a litany of web-centric problems.[1] It's frustrating to be judged on what you don't know, rather than what you do, but I've been enjoying the opporutnity to better understand what different engineering organizations value in new hires.

And next time, I'll definitely spend time brushing up on algorithms.

[1] I didn't get the job, for reasons cited as "looking for someone with more web experience", at which point I seriously had to question the recruiter's reading comprehnsion skills, as you could have figured that out from my resume in about five seconds. Based on their interview process, they seem to be seeking candidates with a skillset that generally matches that of their existing team.

[2] Android developers tend to be very well versed in state-management by nature of the job.

[3] As much as I hate them, take-home coding exercises seem to be the best place to showcase this particular talent.

#algorithms #architecture #types-of-developers #skillsets
19 Jan 2017 c.e.
What to Ask When You're Being Interviewed

I've been interviewing for jobs in software development over the past few months. My friends mentioned that they liked my rubric of questions to ask founders, engineering managers, and recruiters about their companies, so I thought I'd share it a bit more widely.

What are you building?

I like knowing what I'd be working on, and in my experience, most engineers relish the opportunity to talk about what they're building. For that reason, I find that these questions make for good ice-breakers. These questions are probably no brainers, but for the sake of completeness...

  • Tell me about what you're working on right now.
  • What's the biggest challenge (technical or otherwise) that your team is looking to tackle in the next 6 - 12 weeks?
  • Who are your users?

How Are You Building It?

This is a good follow up to the previous section.

  • How many engineers are on your team?
  • Tell me about the tools you're using.

Where is the Money Coming From?

A great saying I heard once sums up the crux of what this set of questions drives at: if the service is free, you are the product. More concretely, consider Google Search: your attention and pageviews are the product that Google sells to advertisers for money. Your eyeballs are the monetization strategy.

I'm picky about what I want my time to be put towards. Even if my efforts won't be directly related to a money-making project, I like knowing that my time is spent on something I think is ultimately worthwhile (maybe for you Search is worth charging an eyeball tax!)

Ethics or personal morals around money sources aside, I also like knowing that the company has the potential to grow, and that there's a good chance I'd have job 6 months from now. In my experience, companies that do the best on these metrics tend to be B2B.

  • How do you make money?
  • How much VC funding have you taken? (Startups with a lot of VC money but no concrete money-making strategy are sometimes trouble. Consider running. Questionable counterpoint: Twitter)
  • Are you currently profitable?

Who Am I Enriching?

For a publicly traded company, this is fairly straightforward -- the answer is (almost) always the shareholders. But for private companies, which most startups are, the only way to find this out is by asking the founders. For me, it's really important that employees are rewarded for their work. I don't have any great questions that I ask about this; if you have any that you like to ask I'd love to hear them.

The Role of Women In the Org

I love asking about this. The answer is important, but not in the way that you might think. Yes, I ask about women's role in an organization because I'm interested in what a company's representatives will say about it, but, more importantly, I'm using this conversation as an opportunity to gauge how comfortable it is. Gender representation is usually something companies are slightly embarrassed about. For that reason, it's a great topic to judge how well someone handles tough conversations, which is really good information to have when trying to decide where to work.

I'd love to hear how much mileage non-women engineers get out of these questions, too.

  • How many women do you have in management roles, or are considered on the management track?
  • ...on your board, or as advisors? (This is a good question for founders or CEOs, but asking a recruiter or engineering manager will probably get you a rough answer)
  • ...working as engineers on the team that I'm interviewing for?

Interviews are Two-Ways

I really enjoy the opportunity to get to know more about how a company functions, where it sees itself growing, and how teams view their role in that growth. Interviews are a great chance to get an inside scoop on what's up with a company that you find interesting, or just better understand how they see themselves growing (or not...).

You may notice that I don't ask very many questions about their build process or particular languages that they use. I don't ask about their build pipeline, or how long it takes to compile their app (though after recent conversations around this, I'm strongly considering adding this to my list). In my experience, people who think deeply about their organization and their culture also tend to think deeply about what technologies they're using. If you really care about what ecosystem you work in, you should ask about it though.

Did I miss something? Do you have questions that you like to ask? I'd love to hear it (You can reach me on twitter).

#startups #recruiting #what-to-ask
More...