Ask for clarifications or details on the company’s roadmap. How’s the business side of things? How is the engineering dept progressing towards meeting roadmap goals? How is the roadmap changing? What factors might cause it to change?
Keep in mind that this topic depends on your company’s size. A smaller company means your manager is more likely to have more knowledge about the company’s direction and decision-making.
Bring up any pain points. Talk about possible improvements in company processes (PTO, food, etc) or technical process (git practices, code reviews, hiring, dev environment, deployment, tech stack).
How can you improve your value to the company? Are there any upcoming training opportunities. What do you want to learn? What does the company want you to learn? What can the company help you learn via training classes and conferences?
But make try to get specific feedback. Asking “How am I doing?” is imprecise, and therefore, it could be less helpful. Unless you’re screwing up something big, most managers probably don’t have a solid response ready (they’ve got other things on their minds –like other meetings they have that day). More precise: “What skills should I focus on? How can I help more? Are there new projects in the roadmap that I can really add value to? What goals does the company has for my role?”
Anyway, one of the biggest things I focus on in my 1:1s is training/learning opportunities. For example, “What’s the company’s training budget/policy? Is there any training I could take that would benefit the company directly? What about training that I’m personally interested in? Can I go to conference A, B, and/or C? Can I attend workshop D, E, and/or F? There’s a meetup I want to attend, but I’d have to leave work early every Tuesday; is that ok?”
I also like to discuss new hotness. For example, “I’ve been interested in technology X; can I give a presentation to the team about it even if we can’t use it any time soon? Can we possibly start using it?”
And suggestions for process improvements. For example, “Here are my thoughts re: onboarding, hiring, story planning, etc”.
Sometimes, I discuss team issues (personnel or process). For example, personnel issues: “Person X tends to interrupt me a lot. I’ve tried A, B, and C. So things have gotten better, but there’s still room for improvement. Can you help?” For example, process issues: “We need a better convention for git branching/merging.”
After the first 2 or 3 1:1 meetings, a decent chunk of time is dedicated to just reflect on the topics brought up in the previous meeting.
You can also talk about a lot of initiatives outside of the day-to-day. You can express desire to: spearhead company culture stuff, organize team events, be a mentor, start an internship program, organize meetups, volunteer at recruiting events, etc.
So I guess it’s a mutual feedback session: I want to discuss ways for me to grow + ways for company/team to grow.
Less directly, it’s a good way to see if your interests are still aligned with the team. For example, through the 1:1s, if you express concerns that are never addressed or if you express desire to work on something but you never get the opportunity –then the 1:1s help you learn it’s time to switch teams or even jobs :(
Ask your manager about their experiences. How many meetings do they attend on a typical (and atypical) week? What goals do they have for themselves? What do they like/dislike about the job? What did it take for them to achieve their own career goals?
You gain a lot of insight by learning about your manager, their perspectives, and their typical day (outside of directly interacting with you and your team). You gain insight on what it’s like to be in a formal leadership role, how content/stressed your manager is (look out for burnout), etc. This insight can help you better approach your manager with new ideas and even help make sure there are no major signs that the manager might be unhappy at the company. If the manager leaves, that could have a huge impact on your job.
It’s not a status meeting, code review session, etc.
This isn’t a time for simply recapping “so what have you been working on?” If your manager doesn’t already know the answer to that question, that’s a bad sign or your organization isn’t properly structured to give your managers the time/opportunity to understand direct reports’ work.
In other words, the 1-on-1 shouldn’t just be used as a more in-depth SCRUM/status meeting.
I’ve also heard that 1-on-1s could be used for in-depth code reviews, but if your organization doesn’t do proper code reviews as part of the usual process of development, that’s another bad sign.
Go into the 1-on-1 meeting with some kind of agenda, plan, questions, etc. Don’t just go into the meeting empty handed.
Based on the conversation, take some notes. Use them as reference, but also use them to track your own progress towards meeting any goals or action items discussed in previous meetings.
]]>It’s been nearly two years since I wrote about my preferences for Sublime Text 2. In those two years, I’ve accrued more tools, and I’ve installed/configured a better web dev setup for myself. My current setup is documented in a repo, which will be kept up to date so then any time I need to set up a new machine, I have a quick guide that I can reference.
There are a few aspects of my setup worth explaining…
I’ve switched to Atom. There’s no doubt that Sublime Text is way faster. I still use it to read and edit extremely large files (e.g., large JSON). But Sublime Text always felt a bit clunky in its GUI. Most notably, the package manager for Sublime Text wasn’t very nice to use.
On Macs, Atom has a lot of great features for updating the software and packages. It has one-click installation of shell commands (e.g., atom [filename]
to open a file in Atom via terminal).
On Linux, these features are missing, but I still use Atom on my Ubuntu machine because its GUI feels more modern than Sublime Text’s GUI. Also, Atom’s built-in Markdown and Git features are pretty sweet.
That said, Microsoft’s Visual Code Studio looks enticing. The battle of free code editors is really heating up! Visual Code Studio appears to be more powerful than Atom – and I’ve got to give it a try eventually – but Atom’s community is at least 2x larger at the moment. The ecosystem of Atom packages is outstanding.
Some of my favorite Atom packages: - pigments to highlight colors (great for CSS/SCSS/LESS code that deal with colors) - file-icons to show icons specific to different file types - autocomplete-emojis because emojis can spice up any comment/documentation! 🌟
I still use Google Chrome as my main browser for development, and now I use a few Chrome extensions a whole lot: Advanced REST Client for testing REST APIs and JSONView for browsing JSON data.
For development, it can be helpful to disable the “prefetch resources” advanced setting. If it’s enabled, the network panel of your Chrome DevTools might jump the gun, confusing you in the process.
That said, I’m enjoying Mozilla Firefox Developer Edition. It’s got some fancy dev tools that I haven’t gotten a chance to use much, but the browser itself feels pretty speedy. Unlike normal Firefox, the dev edition has separate processes for each tab.
Also, I like supporting Mozilla by using their browser. It’s good to have some competition in browsers, and Mozilla has no conflict of interest with the web. They’re more likely to promote an open web as much as possible whereas Google and especially Apple have a conflict of supporting web versus supporting iOS/Android apps. Some say Safari is neglected by Apple because they care more about dedicating resources to iOS + the App Store.
There’s also a nice conspiracy theory suggesting that Apple would rather web apps not rise in popularity because that would detract from the App Store’s prominence. You could argue the same goes for Google and the Play store, but Google’s done some amazing work on “Progressive Web Apps” to make web tech (push notifications, offline support, etc) as powerful as native mobile apps.
My documentation repo has more tips & tricks, but I’ll lay out a few here. They all happen to relate to making development on a Mac even better (I guess I’ve been using my Mac way more than my Ubuntu machine lately).
The latest Mac OSX has a built-in window layout feature, but it sucks. I continue to use SizeUp. It’s free and more powerful/flexible.
I try to install as much as possible via Homebrew. It makes updating installed software a bit easier, and it can help you avoid common pitfalls (e.g., installing Node.js via Homebrew avoids permissions issues with npm install -g
that you’d normally have to fix yourself).
Do yourself a favor and go into the keyboard settings to disable Smart Quotes. Otherwise, they could eventually find their way into your code and screw you up in the most insidious way (it could take awhile for you to realize you’ve accidentally typed/copy/pasted some Smart Quotes into your code).
]]>Why the image of a water pipe with flowing water? It will all make sense soon, my dear reader.
Given a bunch of arrays kept within a JavaScript hash table (plain object), we want to extract the arrays and combine them. In other words, we’re given a collection of arrays of elements and we want a single array of elements.
This example was inspired by some code I found in the codebase where I work. The use case was different, but the overall idea (extracting elements from within arrays that are within an object) is the same. To make things slightly more complex, the arrays of the input object could possibly contain null
elements because the elements were being provided by a service that could sometimes return null
.
The output has the null
s removed. We can pretty much assume we only want to see user objects in the output array; no other kinds of elements.
The following code snippet is a slightly modified version of someone else’s work. I’ve changed the variable names and comments, but the core logic/algorithm is the same.
_.each
and Array.prototype.concat
creates one big array from all the arrays within the input object called keyedArrays
.filter
and Boolean
rids the big array of falsey values to ensure no null
elements end up in the output.Sadly, we need to create our own concatArray
because Lodash doesn’t have such a utility method (I swear it used to exist in an earlier version …maybe).
Thankfully, we can actually use Lodash’s reduce
on objects (not just arrays). I see the replacement of each
with reduce
as a win because the end result is more expressive. each
is vague whereas reduce
makes it more clear that we intend to go from a collection of things (in this case, a collection of arrays) to just a single thing (in this case, just a single array).
Now we use function composition via flow
, which uses left-to-right direction. Standard function composition via compose
would read from right-to-left, but I prefer LTR for a more familiar aesthetic. My friends who are more advanced in functional programming assure me I’ll get used to the RTL direction if I give it a shot, but for now, I protest (i.e., I’m lazy).
With flow
, we can read combineKeyedArrays
as a series of 3 steps. First, we extract values from an object via values
, then we flatten the resulting array via flatten
, then we reject any falsey elements from the array via compact
.
Notes:
values
obviates the need for the combo of reduce
+ concat
flatten
is shallow by defaultcompact
obviates the need for the combo of filter
+ Boolean
OMG WHERE DID THE INPUT/PARAMETER GO?!
–You (probably)
We can stop referring to the input as keyedArrays
. Our function combineKeyedArrays
has now been written in a pointfree (aka point-free aka tacit) style. In other words, we no longer need to name - and refer back to - any parameter variable.
Think of it like the verbs “hit” and “type” in the English language. The word “hit” is a bit vague, so you probably should include more context or references for clarity. Are you hitting a person in a fight? Are you hitting some books to study? Are you hitting the bed to sleep? Are you hitting a keyboard button to type?
The word “type” is more specific. You already can infer you’ll be dealing with a keyboard. You don’t need to mention the keyboard at all when you use the verb “type” instead of the verb “hit”.
“I’m typing UNIX commands” is more concise and direct than “I’m hitting buttons on the keyboard to issue UNIX commands”. Both are valid, but the former is easier to understand even though it’s less comprehensive.
Now, let’s translate from Lodash to Ramda, a utility library that is much more aligned with the functional programming style. I’ve covered how to get started with Ramda in an earlier blog post that one friend labeled as an “excellent summary”. I must be pretty awesome :D.
Notes:
pipe
is Ramda’s _.flow
. I appreciate the name “pipe” over “flow” because “pipe” reminds me of Bash’s |
operator.unnest
is Ramda’s shallow array-flattening method.compact
:(R.filter(Boolean)
is leveraging currying / using partial application to yield the same effect as _.compact
.We’ve gained so much:
each
is vague; the refactored versions using flow
and pipe
are far more direct and straightforward (assuming you’re familiar with the library methods). Also, the combo of _.chain
and _.value
adds unnecessary boilerplate cruft compared to the simplicity of flow
or pipe
.By the way, possible documentation for our refactored, pointfree combineKeyedArrays
involves a type signature as a comment, but admittedly, I’m still learning how to do proper, FP-style type signatures. Also, keep in mind that the names of your functions should help tell others what it does, and the fact that it’s composed of 3 easy-to-read methods is quite helpful as well.
Why don’t we say something more specific such as // {k: [user]} --> [user]
? Because combineKeyedArrays
clearly works with any type of element inside the arrays. It could even be considered as a utility function and added to an internal library of helpers. Whoooaaaaaa…
And because I appreciate you as a cool person, here’s a Gist that has all the code in one spot for your future reference.
]]>It’s true that really low-level performance optimizations often don’t feel like they’re worth learning or worrying about. You’ve got to deal with complicated business logic and juggling user data and state! You don’t have time to record CPU profiles for every new function you write!
On top of that, computers keep getting more powerful, right?
Here’s the insight*: if you’re targeting laptops/desktops, then you can probably feel safe about imperfect code in many respects. However, the trend of computers getting more powerful isn’t what it seems.
Look at the trend from a bigger picture perspective: modern tech has gone from powerful desktops to less powerful laptops (and netbooks and Chromebooks!) to even less powerful smartphones/tablets to much less powerful wearables and IoT devices. Consider that smartphone apps might not be so popular if web apps were more performant earlier in the history of iOS, Android, and web views.
*Disclaimer: I can’t take credit for the insight. I read it somewhere on the Internet, and I don’t remember where. Probably Quora though.
I’ll also add my own thought to chew on: Memory optimizations might still be important as folks browsing the web tend to leave a ton of tabs open and don’t close/reopen their browsers as often as they used to.
To be fair, browsers have come a long way. And it can be tough to care about tiny performance optimizations when browsers might end up handling them for you. For example, string concatenation used to be a no-no in JavaScript. The recommended best practice was to use Array.prototype.join
instead of string concatenation.
This “best practice” is now very outdated.
Like most decisions in reality, there will be trade-offs and ROI concerns. Like most decisions, the right answer is probably somewhere in between two extremes. Like most of my commentary on this blog, I’m dispensing info with JavaScript in mind, but some takeaways are language-agnostic.
My decision-making process for how to spend my time on performance involves a few key points:
while
loop vs for
loop, i++
vs ++i
, etc).I’ve noticed many of my “key points” really just boil down to “do your best, buddy!” Freaking brilliant.
Because JavaScript is single-threaded, the multi-core loveliness of modern CPUs doesn’t directly help your web app unless you use web workers.
That said, there will be some benefit regardless of web workers just because devices such as smartphones usually have to juggle more than just your web app (e.g., background apps, managing sensors, etc). The extra cores should help prevent the phone from stressing out from the juggling, so that tangentially helps your web app’s performance.
]]>This is not a “What is FP?” guide that uses JavaScript. If that’s what you’re looking for, you’ll love Brian Lonsdorf’s free GitHub-based guide. For this blog post, I will assume you already know currying and composition. I won’t assume you know functors, monads, and the other funky whatchamacallits that I’m still trying to learn for myself.
There are a lot of blogs and presentations that answer “What is Functional Programming?” and “Why bother with Functional Programming?”. There aren’t a lot of resources answering “How do I start using Functional Programming in REAL life?”. Most intro-to-FP resources leave you feeling like you’re supposed to just drop everything and start coding from scratch in Haskell or an FP-focused language that transpiles into JavaScript (e.g., Elm and ClosureScript).
My team at work has recently been exploring FP in JavaScript by using a library called Ramda. It’s a functional programming JavaScript library. Ramda offers some common FP utilities to help you code in the FP style or just slowly convert parts of your codebase to the FP style.
Most of the team is unfamiliar with FP, so rather than diving into massive re-writes to convert large chunks of code from Object-Oriented Programming to FP, we’ve been starting small. Along the way, we’ve learned some solid steps for introducing FP into an existing codebase at a comfy pace. The gist of it is: don’t dive into the world of endofunctors, monoids, and catamorphisms. Instead, focus on treating functions differently by cutting down on anonymous functions, subdividing functions into tiny functions, and using the simplest FP concepts such as currying and composition.
These are some signs that code is very imperative and not very FP-like:
curry
and composition
).map
, reduce
, and filter
that can perform the most common looping operations in a style that is more functional and declarative.each
, map
, filter
, reduce
, etc - Using these FP iteration functions encourage you to also write small helper functions and predicates. They will guide you towards more FP.R.curry
, R.compose
, R.composeP
, R.prop
, R.is
, R.has
, R.anyPass
/R.allPass
are all worth checking out. Set a goal to use these as much as possible. It’s a great (and reasonable!) goal to get started with the FP style without getting too overwhelmed.
curry
and compose
get you to the heart of FP’s flexibility. Your code will look significantly different once you start currying and composing functions.R.prop
or R.has
as needed).foo
changes some parent scope variables in addition to performing some calculation, then change foo
so it calls two helper functions: the parent scope manipulation is done by one helper function while the calculation is done by another helper function.What can you expect as you start writing FP code?
console.log
, you may have to add it to compositions. E.g., var processData = R.compose(calculateStuff, logFilteredData, filterData);
You can find a more detailed example of this logging tactic later in this blog post.Keep in mind that I’m using Ramda.js for these examples.
The “most functional” technique may seem unappealling because it requires so many lines of code, but it’s vital to remember that predicates serve as re-usable, easily testable utilities. Also, R.allPass([isOdd, isDivisibleBySix])
is more expressive than number % 2 || number % 6 === 0
. In the latter case, readers must remember how %
works and how the result is a number that gets coerced into a boolean value for truthiness/falsiness.
Once again, it may seem a tad painful. You’re being forced to create a special logger function. But much like in the previous example, keep in mind that you’re being forced to create specialized functions that will probably be useful enough to be part of your project’s internal library of utilities and helpers.
Let’s pretend we need to grab data about an animal. First, we query our database of animals. Second, we use our query results to get more info from a 3rd-party animal API. Third, we use some part of that info to search for relevant photos from the Flickr API.
Some programming friends think I’m crazy, but I most definitely <3 pair programming. I dig the human interaction. I appreciate enduring the horrors of debugging with a comrade. I love the anti-ego culture.
On top of all that, pairing reduces the risk of burnout for a couple of reasons. Firstly, the average level of focus stays high throughout the day so you don’t have to work as many hours. Secondly, any stress, tedium, and brain workouts are shared by two folks instead of one. Therefore, individuals are less likely to get overwhelmed or feel alone in handling responsibilities or overcoming blockers.
Admittedly, there are times when I want to get in the flow by myself without the need to constantly talk to another person, but usually, I embrace 1-on-1 talks. Why? (1) Discussion activates more of my brain. (2) I’m a big fan of communication skills. (3) Considering another individual’s perspective gives me more to think about, and I love thinking about thinking.
For nearly 2 years, I’ve been pair programming. During this time, I’ve picked up on a few tips and pet-peeves. Read on for some musings on software development in dynamic duos.
These tips are good for all communication, not just pair programming. But bad communication skills become an unavoidable problem when you pair up, so consider improving how you talk and listen to become a better paired engineer.
Another way to put it: be curious about your own assumptions, conclusions, and judgements. Unless you are 100% certain, give your partner the benefit of the doubt.
- DO: What if X? Will that affect idea Y?
- DON’T: Your idea (Y) won’t work because of X.
- DO: What are the obstacles? Let’s see if we can tackle them together.
- DON’T: I imagine what we need to do should be easy. Why don’t you think so?
The below example is more pertinent to a senior teaching a junior, but even proficient engineers get out of sync when generic words like “that one” are used instead of precise words like “the [insert object name] at [insert context or line number].”
- DO: The promise returned by the request at line 31 will resolve with a response body containing the JSON we need to parse and possibly flatten.
- DON’T: That method call will give us the data we need to check out.
Maybe it’s just me, but I find it painful to watch someone use only arrow keys to move a cursor or use slow mouse movements to scroll to the top or bottom of a file. Although, I admit that I could be a tad unfair in the typing department (I rock triple-digit WPM so …booya).
Can you intuit that these slides are about promise-land of virtual filesystems inspired by #FunctionalProgramming ? pic.twitter.com/AGiupUies9
— Jeff Lee (@RebootJeff) May 23, 2015On May 21st, I traveled to Boulder for LambdaConf 2015, a functional programming (FP) conference. Overall, it wasn’t as beginner-friendly as I had hoped, but it gave me plenty of food for thought as I explore FP. Today, I’m going to summarize some key points and takeaways from the talks that really stuck with me. I didn’t understand everything I heard, but still learned a thing or two …I think.
Apparently, the Ouroboros (serpent eating its own tail) in this talk represents all programmers (and perhaps even all computer users) who are eating their own tails by accepting the current model for filesystems (files, folders, directories, etc). Phillips suggests that he has the cure (the ipecac).
What if computers used virtual filesystems? Imagine if filesystems were more like databases, and retrieving files would be like using expressions that define queries and which files to retrieve. You would not need to rely on knowing filepaths and file names. You wouldn’t end up with multiple copies of the same files/folders in various directories. You would rely on useful metadata to get your latest photos. You could even ask for “all the photos with person X” (via facial recognition).
Spiewak claims that FP gurus suck at articulating to non-FP programmers about why FP rocks. According to him, FP’s strengths boil down to reasonability, testability, and concurrency.
As a beginner in the world of FP, I partially agree. For me, it’s easy to grasp why FP rocks in theory, but sometimes it’s hard to understand in practice because it can be so difficult to start writing FP code.
Instead of going on about abstract algebra, Spiewak says FP evangelists should emphasize reasonability, testability, and concurrency. For intro classes, FP teachers should focus less on manipulating data and more on how to do data-centric programming instead of behavior-centric programming.
FP emphasizes data over behavior, and it’s easier to reason about data than behavior (especially if the behavior can be different due to side-effects, implicit inputs, etc –in other words, impurity makes it difficult to reason about behavior).
Side-effects leads to difficult testability leads to devs hating testing leads to devs writing fewer/poorer tests leads to lower software quality. This plagues the software industry.
Using FP algebra leads to simpler logic and better testability. By writing a “real” interpreter that performs side-effects and a “fake” interpreter that inspects, testing becomes easy. Free monads enable this pattern. Free monads make it easy to write these 2 “interpreters”.
flatMap
or for-
comprehensions ~ monadszip
~ applicativesNote: In case it isn’t obvious already, I had trouble comprehending this part of the Spiewak’s talk. My understanding is that the purity of FP lends itself to easily distributing computation of expressions and composing the results.
Imperative programming requires you to maintain state in your head. At the very least, you have to remember values stored in all sorts of variables, maybe different state for each iteration of a loop, etc. With imperative programming, your brain uses a lot of energy on maintaining state (and types in an untyped language) when it should be focused on just solving the problem. This is really annoying if you love the expressions from physics/math where you simply derive solutions to problems.
Math has referential transparency (algebra is just lots of substitution), which is straightforward. FP brings referential transparency (and therefore, more algrebraic concepts) into programming.
Or: Thoughts on teaching Haskell (and just “teaching” in general).
Allen is a professional Haskeller, but he also does a lot of teaching. He spent a lot of time introducing co-workers to the language, and he eventually created a free guide on Haskell. It was great to hear his perspective on education in the realm of coding.
Boom: http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
Functional programming used to be considered rather academic and unpractical, but nowadays, there are a lot of languages and corresponding communities that make FP friendlier and useful. Consequently, there are plenty of people using FP for “real” software.
Judging from the conference, Scala, Clojure, and Haskell are the most popular functional programming languages. Haskell seems to have the fewest programmers, but the most momentum/interest. Not only is Haskell favored by the purists, but its static type system is lauded as being the near-panacea that programmers don’t realize they need until they learn it.
However, I saw enough Clojure code to walk away impressed by it. It seems far less intimidating than Haskell, but perhaps that’s largely due to my background in JavaScript (JS and Clojure are both dynamically typed). The funny thing is that there seemed to be a theme where Clojure developers end up finding enlightenment in Haskell thanks to its strict ways. Perhaps learning Clojure is the perfect stepping stone for learning Haskell? If you’re intrigued, check out:
In my first article on Communication For Engineers, I ranted about my disappointment surrounding engineering and communication skills. I ended that blog post with a list of communication-related topics that I promised to write about. Instead of addressing any of those topics (sorry!), this post will talk about how software engineers can improve their communication while coding collaboratively or while solving coding challenges for a job interview.
Warning: JavaScript is my specialty, so some of the advice below is JS-centric, and all code examples are written in JS.
Notice that these steps don’t magically provide a complete guide to actually solving problems. For example, they don’t tell you which data structures to use. Instead, these steps show you how to communicate better as you solve a challenge. They help you talk with your interviewer or colleague about the problem space, your initial impressions, your ability to break down the problem into sub-problems, and your quality assurance process.
Admittedly, this step could be optional. Drawing is best for folks who work well with visuals. But even if you’re not an artist, you should still consider drawing a diagram or picture of the problem because visuals tend to be effective tools for communicating complex subjects and situations. For example, data structures are usually easier to talk about after you draw them out.
Furthermore, you might reveal certain questions through the act of drawing. At the very least, drawing stuff out can help an interviewer follow you. Going back to the data structures example: imagine you’re supposed to work with a binary tree. It’s easier to talk about it if you draw a tree and point to nodes rather than just saying, “First we will process the root node, then we will go to the left child and do blah blah blah. At that point, depending on the value, we might go down to the child’s child or we might…”
By the way, you don’t have to stick to drawing pictures. This step could be about writing down example data, example inputs, example outputs, example use cases; and then mapping them together by drawing arrows, circles, etc. Examples are great for communication, and they are also good for problem-solving in general. Try to think of examples that are really simple (to get a basic grasp of the problem), examples that are more realistic, and examples that are crazy (to reveal edge cases and potential validation concerns).
Do not follow any of your assumptions without asking a question first. It’s tempting to hear a challenge or puzzle and immediately get into solving it. But there are real-world concerns for real-world problems, and you should demonstrate your familiarity with such issues.
Also, you can save time by asking clarifying questions during an interview because interview challenges tend to be contrived. Do you have to account for crazy input values? Does the output need to be formatted in a certain way? If the puzzle involves numbers, do you have to account for negative values, decimals, etc? Are you expected to do input validation, error handling, or memory optimization?
At this point, you might have a solution in mind and you’re eager to get coding. Or you might just have a partial solution. Either way, take a moment to give a quick overview of the purpose of the code you’re about to write. Also, give a sense of what algorithms or concepts will be implemented as part of your approach to the problem at hand.
For example, “This looks like a problem we can solve with a recursive solution that traverses all nodes of the dataset.” In this example, “recursion” is the concept and traversal is the purpose.
When it comes time to actually write out some code (or pseudocode), write out as much as possible at a high-level before going into the low-level details. For example, if your solution requires looping over objects received from an AJAX request in order to parse some data, don’t dive into that AJAX request. That’s a low-level detail. Start from the high-level approach of “fetching data” and then immediately move to the next high-level step of “parsing data”. With this strategy, you cover the whole breadth of the solution before diving into any detail of the solution.
In other words, write modular code by using a breadth-first mindset. Everyone knows it’s a good idea to write several small functions rather than one giant function, so apply that approach to your communication too. When you explain how a computer works, you start the explanation at a high level (e.g., “hard drives store data, CPUs crunch data, …”) rather than starting at a low level (e.g., “the flow of electrons is controlled by gates known as transistors”).
In the example above, you should write code one “phase” at a time. Starting with psuedocode is optional, but it might be a good idea to at least verbalize it if you don’t plan on writing it. Then write the code in a declarative style as seen in “Phase 1”. Lastly, flesh out the functionality of your solution by writing the code that actually makes things work.
By the way, I’ve never actually used the Twitter API, so the example code might not follow best practices or might not take into account how it actually behaves. For instance, maybe the API accepts a parameter to do the date filtering for you.
Once you’ve reached the point where the code seems to solve the challenge at hand, it’s time to refactor. If you’re writing under pressure in an interview situation, it’s likely that you haven’t written the cleanest code. If you’re writing without any pressure, it’s still good to refactor your first draft into a more readable/maintainable variant. Here’s a list of tips for deciding what to refactor:
map
, filter
, reduce
, etc where possible.all
, spread
, etc where possible.Admittedly, this Step 5 isn’t as directly related to communication as other steps. It’s mostly focused on improving your code. However, there is still a communiation-related opportunity here. As you are refactoring, verbalize your intentions. Discuss what you want to improve before you improve it. Explain the rationale behind the improvements. Mentions the pros and cons of your code without the improvements and with the improvements (i.e., before vs after).
At this point, your code should be presentable. By following the previous steps, your audience should already have a solid, high-level understanding of your code. So now it’s time to give a detailed walkthrough.
Explain any nuances, use precise terminology, and expound on any interesting control flow or references (e.g., closures in JavaScript). You can also mention any implications regarding speed, memory, I/O, security, etc. But overall, your goal is to describe your code in detail.
You might actually want to perform this step before step 6, but it depends on how you roll. After you’ve gotten to the point where you have a solution that seems to be good, take a minute to describe how you’d make sure it’s robust. When you normally write code on your own, you of course test it out by running it with various inputs or circumstances. Describe them; verbalize them.
For example, if you’re writing a function with some parameters, you’ll probably run the function with a bunch of different arguments with different values and maybe different datatypes.
I came up with these 7 steps based on…
When I teach JavaScript workshops, I usually have teaching assistants who can help students complete classwork exercises. The TAs mostly focus on helping beginners debug their code rather than just giving solutions and walking through them.
Here’s the advice that I give TAs:
Remember that you should avoid giving away direct solutions. When students ask for your help, they will often not know exactly what puzzles them. They will often just ask, “Can you help me?” rather than asking something more precise such as, “Why doesn’t this function return the value I expect?”
Your role is to understand the particular problem that the student is facing. Try to find out what precise questions should be asked and relay them to the student. This might require vocalizing your step-by-step thought process for solving the problem, and finding the first step that confuses the student.
When debugging, try to debug the student’s code one step at a time. Explain those steps so the student can learn how to debug (e.g., where to put console.log
s, which variables need to be checked, etc).
Never give the hungry student a cooked fish. Teach the student how to use a fishing pole, a gutting knife, a cooking fire, and Chrome DevTools.
Do everything you can to show a student how to get the solution. Showing a student the actual solution is the last resort. At that point, you should not only show the student the solution, but walk through it and ask the student questions to test their understanding. Oftentimes, asking a student “do you understand?” is not effective. You will get nods thanks to a superficial level of a understanding. That understanding must be tested by asking the student to walk through the code verbally, asking the student values of specific variables, and so on.
]]>A few months ago, the JavaScript community had a rather negative reaction to an announcement about Angular v2.0. Quick aside: my boss lost faith in Google and jumped on the ReactJS bandwagon. On a recent episode of the Adventures in Angular podcast, the Angular core dev team tried to clear the air regarding the general approach for Angular 2.0 and the differences between Angular 1.3 and 2.0. The podcast is surprisingly well-done. There are 9 people included (1 of them is THE John Papa; 4 of them are Angular team members) and yet they never accidentally interrupt one another or talk over one another.
I’ve listed some interesting bits I gleaned:
$scope
is disappearing because they realized “controller as” syntax is best, so they want to revamp that system completely to avoid common $scope
confusion.controllerAs
instead of $scope
).I know I sound like I’m defending the Angular team. To a certain extent, that’s true (I need to try some React.js one day to hopefully reduce my bias for Angular), but it really comes down to:
Angular 1.4 is coming in Spring 2015.
News of 1.4 landed after the podcast aired. It will bring the new router I mentioned earlier, a “first class” I18N system, slick-looking documentation (using Angular-Material), and other goodies –including some breaking changes. :D
]]>Last update on Nov 30, 2014 to add a great link to the “Compilations” section.
These three moments have had my brain wondering about how to point coding newbies in the right direction. After some Googling and recalling my own past, I’ve gathered some links that will hopefully help beginners and maybe even intermediate folks. However, I should warn you that I haven’t tried out all the various services for myself.
This Imgur post lists 6 sites that provide tutorials for getting started in coding. I’ve personally used Code School and Codecademy. They’re great, but after awhile, you’ll want to explore other options. They are not sufficient by themselves.
These sites gather tutorials and various resources into one place. Most of these also give some guidance or roadmap to help beginners prioritize what to learn:
If you’re specifically trying to learn the quirks of JavaScript, then classes like the one I teach are perfect for you. If you’re not near San Francisco, you can try online classes taught by the one who helped me become a teacher (@BiancaGando).
But these aren’t free. Ya know what is free? This great gathering of words describing vital JS concepts: 16 JavaScript Concepts JavaScript Professionals Must Know Well
San Francisco is my neck of the woods. If you’re lucky enough to be around here, then you should take advantage of the stellar community. There are lots of free meetups/events that can help you learn. If you’re not in the area, check Meetup.com for groups that provide similar events.
If you’re female, you might want to search for organizations that provide free support for women. Some examples:
Back in the day, I used a free, online curriculum created by Railsbridge to learn some web dev skills.
A Hack Reactor alum recently launched a free service called Hackvard. It helps people quickly find nearby programmers who want to meet up. After a few weeks (or days?), it was renamed to Codaround. One of the co-founders contacted me and mentioned that Codaround might be changed to focus on helping match mentors/teachers with students/beginners. I don’t know any details, but it’s worth keeping an eye on this.
Want to play while you program? Here are some sites that turn learning to code into a game:
Let me know in the comments (or via Twitter) if you know of any other solid resources that help people learn JavaScript and other programming skills.
]]>Last Thursday, I published a blog post in which I summarized the main attack techniques (XSS, CSRF, and MITM) used by baddies to screw with the web. That post also covered two header-based solutions available to help you defend your site: CSP and HSTS. To supplement all that info, I am providing a bunch of articles, references, videos, and tools to help you learn more and take advantage of CSP and HSTS.
Cross-browser support for CSP is pretty good. The latest versions of IE require the CSP header to use a special prefix (much like vendor prefixes for certain CSS features). Older crap like IE9 and below have no CSP support.
Sadly, CSP reduces Angular’s performance because the framework does some optimizations that run afowl of CSP. I imagine that the performance loss shouldn’t be a problem unless you have a ton of Angular expressions on the page at once (e.g., you use ng-repeat
to generate hundreds of expressions).
Despite these concerns, CSP is highly recommended by the AngularJS FAQ page. For more info on how to use CSP with AngularJS, check out the docs for the ngCSP directive.
Most browsers get a passing grade when it comes to HSTS support –except for…
Internet Explorer doesn’t support HSTS—which means that there’s basically no such thing as a secure website in IE
Note: The video above provides outdated browser support info. Updated info can be found here: CanIUse.com.
Do you use Node.js? Does your Node.js app use Express? Want some middleware to help secure that app? Perhaps you should consider using Lusca, a free module created by Paypal to quickly add and configure various security features such as CSP and HSTS. I haven’t personally tried it yet, but I plan to do so soon. Their README file makes Lusca look very easy for devs to use.
You can pick and choose which security features you want to enable. For example, if you’re already using JSON Web Tokens, then you may not want to use Lusca’s CSRF method while you take advantage of Lusca’s legacy browser XSS protection.
By the way, don’t get confused: Paypal uses their own open-source, Express-based framework called KrakenJS, but Lusca works with Kraken apps and Express apps.
You can check out the slides here: click here if you dare. You can watch the lectures here:
But if you don’t feel like sitting through 2.5 hours of lecture, allow me to summarize the best parts:
I won’t go into detail about any particular topic. This blog post will simply get you started in understanding fundamental web security. I suggest you use Google to research more about hacks/attacks or wait for me to post another blog post that provides a collection of links to sweet videos, references, and articles that I found particularly helpful for learning more about all these topics.
How are websites and web apps compromised? Why are sites often “hacked”? There are three main types of attacks that you should worry about: XSS, CSRF, and MITM.
When a punk manages to get your code to run their JavaScript, that’s XSS. A simple example is when an unprotected website just accepts text from the user and adds it to the site’s HTML code. If that text is actually JS, then the site ends up sending the browser user-generated code. Damn.
XSS is one of the most common problems plaguing web security today. This is pretty depressing because there are plenty of frameworks and libraries that help fight XSS, but so many site operators just don’t use them and some fools even try to write their own anti-XSS code.
Let’s say a user logs into your website or web app. They are now authenticated, right? Well it depends. It could be that the user’s browser is authenticated. An attacker could take advantage of this authentication and get the user’s browser to submit an HTTP request crafted with nefarious intentions. The request will be accepted because the browser has the right authentication cookie data, for example.
How is the evil HTTP request initiated? It could be through XSS, it could be through convincing a victim to visit a malicious site that sends HTTP requests, etc. Most examples mention authenticated cookies being used by attackers.
There’s a reason why public internet is unsafe. When you’re on a shared network, other users on the same network can try to intercept your data. Not only can man-in-the-middle attacks read your data, they can also send you bad data/code. Some attackers merely intercept web pages you’re accessing, add more advertisements, and feed you the web page with extra ads. Other attackers might intercept your attempt to visit http://www.facebook.com, give you a fake Facebook login page, and convince you to submit your login info to them.
Obviously, protecting a network by requiring a password to connect can help. However, if you’re using public WiFi in a coffee shop where the password is given to anybody who asks for it, then you’re in trouble again. As I shall mention, HTTPS is crucial for fighting MITM pain.
It’s great if you’re aware of threats. Now it’s time to learn the basics on how to combat the threats. At the meetup, the Google peeps focused on three types of solutions: frameworks/libraries, CSP, and HTTPS with HSTS. I will also mention a couple other technologies (BONUS) for your consideration.
One of the Google experts emphasized that XSS is a much bigger problem than it should be because there are so many frameworks and libraries that help fight XSS. He said that no one should be writing their own anti-XSS libraries. Instead, use one of the many open-source solutions. Also, it’s quite possible that you’re already using a framework that has anti-XSS features that just need to be activated or configured.
For example, in some templating libraries, a simple syntax change will enable anti-XSS escaping features. Other templating libraries automatically escape contents by default. Some frameworks like AngularJS do “round-trip escaping on all strings for you” to protect your app from XSS and other injection attacks.
A server can instruct a browser to use a whitelist to decide which resources should be loaded and which should be blocked. This is done when a server adds a CSP to a response header.
For example, a CSP whitelist can tell a browser to trust script files from the server and Google CDNs, images from the server and Amazon CDNs, CSS files from the server, and web fonts from Google. Everything else will be blocked. In-line JavaScript will be blocked, in-line styles will be blocked, images hosted by 3rd parties will be blocked, Flash will be blocked, iframes will be blocked, etc.
Your CSP can be configured based on various types of resources. Check this CSP Cheatsheet for the list of options. I recommend that you investigate server-side libraries, frameworks, or middleware that can help you implement CSP. When writing your CSP, you can try starting with the most restrictive whitelist and then see what needs to be unblocked.
You can also set up a reporting system to find out what your CSP has managed to block (thereby identifying failed attacks).
A Googler suggested using the CSP reporting feature without an enforced whitelist to help you examine what browsers are actually digesting when they visit your site or app. For example, you could set up a CSP that has a whitelist and just asks browsers to report non-whitelisted sources without actually blocking them. This gives you the ability to tweak your whitelist based on production usage without changing production usage. After you’re done tweaking, change the CSP to force browsers to report and block uninvited resources and content.
To protect data transfers from MITM attacks, many sites connect to visitors via HTTPS. HTTPS connections not only protect typical payloads like JSON, but also static files and cookies that would otherwise be vulnerable to CSRF attacks. The hard part about using HTTPS is making sure no part of the site ever falls back to unencrypted HTTP.
For example, let’s say you’re browsing a site that provides free icons and graphics. Are all files served over HTTPS? HTML, CSS, and JavaScript files are no-brainers. What about images? Yeah that’s pretty standard too. But what about when you get an icon pack? You click a download link, and the browser starts downloading a zip file. Is that using the HTTPS protocol? It’s easy to make mistakes.
Furthermore, what if a user visits the site using HTTP first? It’s pretty common for people to type “somewebsite.com” in the URL bar and the browser will turn that into “http://somewebsite.com”. After they visit that URL, the site can redirect the visitor to “https://somewebsite.com”. But sadly, that initial connection via http wasn’t secure. It’s susceptible to a MITM attack.
With HTTP Strict Transport Security, the browser can automatically turn “somewebsite.com” into “https://somewebsite.com”. HSTS works by setting a header that tells the browser to enforce HTTPS for requests sent to the domain (“somewebsite.com”) for the next X number of seconds. Yes, you can set X to be a very large number such that HSTS is enforcing HTTPS for the next year, if you want to be cool like that.
This blog post was getting pretty lengthy, so I decided to split it into two parts. In a follow-up blog post, I will provide a list of references, tutorials, and videos to help you research more about CSP, HSTS, and some complementary tools/libraries.
]]>How do I know that software engineers aren’t expected to have stellar communication abilities? While I don’t have hard data, I have met, worked with, or listened to a lot of engineers who have sub-par comm skills. And no one makes a big fuss of it, which makes me think no one has high standards for the skills I’m talking about.
On top of that, job interviews target coding skills, web tech trivia, and algorithms with minimal examination of proficiency in structuring arguments, explaining complex concepts, and intelligent discussion. There’s a pretty great article by the CTO of npm that drills into this topic.
Maybe it’s all rooted by the tendency for engineering schools to suck at emphasizing communication in their curricula. My time in college certainly didn’t include any lessons on effective speaking. You often hear schools talk about the importance of group projects and working together, but they never explain what good teamwork looks like, what common pitfalls plague discussions/meeting, etc. Instead, they focus on teaching the hard sciences and math. Then class after class of students walk away with little or no appreciation for the subtleties and subjective nuances of conveying ideas to one another.
I find it so funny that programmers laugh at all these subjective fields of endeavor when that is what they do.
The ability to “work well with others” is often mentioned as a requirement in job descriptions for programming positions, but how many interviewers and interviewees really know wtf that means? Does it mean employees are expected to avoid conflict like their lives depend on it? Is it benchmarked by low quantum of drama? Should it be deeply linked to “likeability”?
No. It’s about empathy, open-mindedness with regards to homo sapiens, and communication skills (among other things).
My point is that it’s time to stop letting engineers off the hook for lacking skills in listening, speaking, presenting, asking, writing, and critiquing. I’m no master in these subjects. My own skills are far from honed, but you don’t need to be a master to have some ideas on how to improve. Also, it can be fun to explore communication issues just like how it can be fun to solve mysteries in web app development. Besides, as engineers, we pride ourselves in being good at what we do, so shouldn’t we put some effort into gaining communication skills that make us even better at what we do?
If you’re pondering my motivation for making such a big deal out of all this, then let me just say that impatience is a potent impetus. I started analyzing communication when I started noticing miscommunication and the toll it took on my patience. I’m not just talking about miscommunication during meetings at work. I’m also referring to poor presentations at meetups, chatting at networking events, conversing during job interviews, writing open-source documentation, writing test descriptions, etc.
When I don’t understand someone, I tend to wonder, “Wtf is this person even saying?” Then that little voice in my head chimes in, “Don’t be so harsh, Jeff. Maybe you’re just too dumb to understand.” After that, another inner commentator adds, “Fellas. Shut up. Let’s use our detail-oriented brain to brainstorm reasons why communication has fallen apart here.”
We engineers are problem-solvers, right? Well here’s a problem: miscommunication. So let’s solve it. What’s the first step for solving stuff? Comprehend the problem space. Break it down. Then divide and conquer.
We’ve confirmed miscommunication. Now what are the root causes? There are too many possibilities to cover now, but here are a few:
If X, then Y.
Et cetera. One at a time. We can get through this together! Let’s hold hands! –or not. Because even the nicest people fail to wash their hands frequently enough to earn hand-holding privileges. Don’t let your guard down.
The next blog post in my Communication for Engineers series will focus on tips for presenting a tech talk. I’m oddly excited about it. I haven’t done any big tech talks, but I’ve attended plenty. There are some easy ways they could be better. There are common issues that are easy to solve. That said, I’m also working on a blog post covering web security fundamentals. In due time, I will write tips for:
If I’m not burnt out from writing about communication skills, I will also blog about:
This blog post is going to focus on a gotcha that rears its ugly head when you have a fixed nav bar. Nowadays, it’s pretty common to see fixed nav bars. Let’s use Twitter as an example. Twitter doesn’t use Angular, so you wouldn’t want to test their site using Protractor, but what I’m about to talk about can also be applied to WebDriver (which can be used for non-AngularJS sites).
Here’s the problem: what if we want Protractor to click on the avatar under the fixed nav bar as seen in the screenshot above? Obviously, a human user would intuitively scroll to find an element before clicking on it. However, Protractor’s perspective is different.
When you use .click()
, you might expect Protractor (or WebDriver, which serves as the underlying engine for Protractor) will try to scroll the web page until the target element is displayed before clicking. However, Protractor will only scroll until the target element is in the browser viewport.
Now imagine your test suite includes several tests (ooh la la!). In test #1, the actions of the test cause Protractor to scroll to the bottom of the page. In test #2, the test tries to perform the actions of Example A. Therefore, during test #2, Protractor tries to scroll back up the page until the target avatar is in the viewport, but this just brings the avatar directly under the fixed nav bar.
Then Protractor attempts a click by finding the center of the target. So even if a tiny portion of the avatar’s butt is displayed just below the bottom of the fixed nav bar, it won’t be clicked. Instead, Protractor will throw an error saying that the target could not be clicked. The error will also mention that the nav bar would receive the click event.
There are two main solutions to consider:
The first solution might not be a great idea because it’s a major alteration for the sake of testing. What if the fixed position of the nav bar causes other issues that your tests will reveal? I believe you want E2E tests to interact with a product that is very close to the product users will interact with. Changing the nav bar’s position just for testing goes against this philosophy. The main exception to this rule is animation: I believe it’s ok to disable animations for E2E testing just because it can take up a lot of time, slowing down your test/build process. Also, animations can just be very cumbersome for automated E2E systems like Protractor to deal with.
The solution I use for dealing with fixed nav bars is to define and use a helper function that invokes element.scrollIntoView(false)
. This method is a native DOM element method that you can read about on MDN. You can’t simply invoke it on a Protractor ElementFinder object. You can’t call elemFinder.scrollIntoView()
the same way you call elemFinder.click()
.
Also, you may have noticed that false
is passed into scrollIntoView
. This tells the browser to scroll as far as it can in an attempt to align the bottom of the target element with the bottom of the scroll area. In other words, this solution only solves issues with fixed nav bars at the top of the viewport. Using element.scrollIntoView(false)
will fail if your web app uses a fixed nav bar at the bottom of the viewport.
There are 3 syntax options above because I just wanted to present a few different coding styles. As you can probably tell, browser.executeScript()
accepts a couple of parameters. The first one is the script, the second one is the script’s parameter. The script can either be a function (technically speaking, it’s a function reference) or a string representation of the script’s body. Syntax Option #3 was inspired by a Stack Overflow answer for a very similar situation (it was for WebDriver, but it was easy to translate to Protractor).
You may have noticed that the solution in Example B mentions promises, but the code in Example C does not use them. My understanding is that it’s not crucial to use every single promise that Protractor and WebDriverJS provide. For example, even though the .click()
method returns a promise, you don’t see devs writing Protractor tests with exampleButton.click().then(function() { ... });
all the time.
So why did I mention promises in Example B? Just to reinforce the fact that browser.executeScript()
will return a promise. By storing the result in a variable called “promise”, it tells other devs what to expect. That said, I admit it may not be terribly valuable. Let me know your opinion on this or any other part of the solution presented here.
In my previous post, I described my experience using LinkedIn, Whitetruffle, Hired, and Dice. This time around, I’m going to cover a crop of sites that I used less extensively. Although they didn’t yield fruitful leads, they’re still pretty interesting to me, and with job searching, you can’t not explore more than a few avenues.
The Readyforce website has undergone a big redesign since my job searching days. I was originally drawn to the site by its large selection of companies listing their open positions. However, the site is clearly marketed towards college grads, and the creators want job seekers to “connect” with employers through their own social(?) network.
When I visited the site a few days ago, it looked quite different. While it does look cooler nowadays, it also feels buggier. On top of that, there doesn’t seem to be a clear way to apply for jobs. Maybe I just don’t understand their model, or more likely: maybe I have to register an account first.
I love what The Muse is doing. Muse peeps travel to employers’ offices to take professional photos and record video interviews with current employees to highlight the benefits of working for the employers. It’s great to see photos of cool offices, and although the videos have mediocre audio/visual quality, they still provide some decent insight. The end result is that The Muse feels like a portal for quick tours of hiring companies. I felt like I was getting a fun, behind-the-scenes look at a bunch of tech jobs rather than just browsing endless, cookie-cutter job descriptions like you do with most other job sites.
During my first few visits to their site, I was so enamored with The Muse that I signed up for their email newsletter. That’s right, I actually wanted their spam. Sadly, their emails are pretty lame. Each message uses a click-bait subject line like “This Genius Formula Can Tell You Your Dream Job”. Opening one of these emails just reveals a giant button to take you to their blog where the short articles don’t live up to the hype of their titles/headlines. By the way, the “genius formula” is gifts + passions + values = your calling
. Genius.
You can find a lot of job postings on The Sourcery. The companies that use The Sourcery for recruiting will often post on other job sites, but there will be a note at the bottom of the job description that mentions the requirement to apply via The Sourcery. After filling out a job application on The Sourcery, one of their recruiters will let you know whether or not your candidacy will be pursued.
For me, the problems come from the recruiters. They noticed I was a Hack Reactor grad, and they immediately labeled me as just another coding bootcamp grad –in a bad way. Although they were friendly, the recruiters implied that all coding bootcamp grads are the same, that they’re all “great” junior-level coders, and that they all can’t handle more than the average entry-level job. What’s really weird is that I would get emails from some recruiters telling me that my job application was rejected due to a lack of work experience, but then other Sourcery recruiters would contact me and tell me that they want to interview me for the exact same job. Maybe the recruiters reach out to rejected applicants if the pool of applicants is running low for a particular job.
Obviously, The Sourcery is not the only company that treats bootcamp grads as low-level programmers. This is why Hack Reactor doesn’t want you to talk about them during interviews. It’s also why Hack Reactor avoids calling itself a bootcamp. I’m getting off-topic, but the gist is: the bootcamp market is getting bigger, and the quality is very inconsistent. Consequently, the mediocre bootcamps are hurting the reputation for all bootcamps. The Sourcery’s expectations for bootcamp grads have already been adjusted downwards.
In my last couple of weeks at Hack Reactor, I was instructed to make sure I had 3 online profiles ready to show off: LinkedIn, GitHub, and AngelList. The nice thing about AngelList is that you’re more likely to get in contact with an in-house recruiter. You don’t have to go through 3rd party recruiters. The bad thing about AngelList is that you might not get in contact with any one. When I say it’s “hit-or-miss”, what I mean is that I know some colleagues who were contacted via AngelList by several companies, and I know other colleagues who were getting zero interest. There was no apparent reason for the two distinct outcomes.
I was only contacted by a few companies via AngelList, and I wasn’t too interested in them. There are plenty of startups on the site, and if you’re hoping to join a tiny company, you should at least try to use AngelList.In my experience, although some companies reached out to me, none of the contacts yielded real conversations about interviewing. Also, there are a ton of companies that don’t distinguish themselves (i.e., there are a ton of startups in the advertising industry –and their profiles look too similar).
Many moons ago, a ridiculous fellow Hack Reactor grad pointed out that Venture Capital websites tend to have giant lists of job openings for their respective startups. I eventually validated his insight for myself by checking out job lists maintained by:
You can find a huge number of jobs. It definitely helps keep your hopes up, knowing that if you fail a job interview, there are so many other jobs to go for. But the caveat to remember is that these job postings are just like any other: it’s hard to get noticed when applying for a job without a referral/connection. For smaller companies, you have a much better chance, but overall, you will have to apply to a lot of jobs just to hear back from a couple employers. Like with all job openings, I recommend putting in some extra effort by checking LinkedIn (or maybe other social networks like Twitter?) to see if you can contact the employer’s engineers, hiring managers, and/or in-house recruiters.
I’m exicted to start a new series of blog posts covering various tips, tricks, hacks, best practices, puzzles, challenges, questions, and mysteries (both solves and unsolved) that I’ve encountered at work. This “Learned On The Job” series will be arriving shortly!
That said, I haven’t finished writing about what I learned from the job search process. More job hunt-related content is still to come (including “WTF moments” :D), but I want to mix things up a bit too. After all, talking about software engineering is more fun than talking about searching for software engineering jobs, right?
]]>Back in December of 2013, I graduated from Hack Reactor. After graduating, I started casually looking for a job, but due to the winter holidays, I didn’t start searching in earnest until early-to-mid January. In hindsight, perhaps I should’ve spent less time searching by myself and more time using Hack Reactor’s network/connections. That said, Hack Reactor encourages grads to look for jobs using all sorts of resources, and I benefited from other forms of job search support from the HackR staff.
This blog post covers a bunch of online resources I tried out myself. I ultimately found my current job through a recruiter, but that doesn’t mean that job sites felt useless to me. Therefore, I’m happy to share some opinions and experiences with you. Maybe you’ll have better results. At the very least, job sites showed me just how many awesome jobs are available, which kept my spirits up during my battles with job interview stress.
It feels a bit hollow. Much like with online dating, everyone makes a profile. Companies look at job seekers’ profiles, and job seekers like you can look at companies’ profiles. There are Like buttons to express interest. Mutual interest leads to a match. A match leads to an email notification. An email notification is supposed to lead to a conversation or some sort of initial phase of job candidacy…right?
You are also given notifications when an employer says they like your profile. The site will nag you to respond to the employer. However, in my experience, employers didn’t respond after I indicated mutual interest. Boooo! This made me wonder if employers just click the Like button on every profile (i.e., spamming) in hopes of stirring up job seeker interest.
Hired is quite an ambitious setup. Job seekers must pass a few coding challenges to enter their pool of candidates, but when I joined, the site hadn’t yet implemented the challenges, so I was able to join after my profile was approved. Hired must have convinced employers that their candidates are top notch because employers were “bidding” salaries between $105,000 and $130,000 on me.
However, the auction format is quite misleading because it implies that you must accept the highest bid. It also implies that employers must hire you and offer you whatever they bid. This is not the case. There are no strict obligations. You must still pass whatever interview process employers have. Employers can still ultimately reject you. Employers can offer you whatever salary they want to offer you if you pass their interviews. In other words, Hired simply uses an auction format as a gimmick to get people excited to participate. It’s a trick, but I’m not even mad.
Why not? Because the pool of employers on Hired is pretty darn good. I got serious interest from 5+ companies. I got multiple on-site interviews. I got two offers. Plus, if you get a job, Hired will give you a $2,000 bonus. Awesome, right?
Now it’s not all rosy. Some companies that were interested in me seemed really boring. The companies that gave me offers both offered me salaries below their respective bids. In the end, I didn’t accept any job offers because I didn’t think I was going to fit well within the companies or something irked me about the company. I should also note that Hired “provides” you with an “advocate” –in less disguised terms, Hired assigns a recruiter to you. The recruiter will call you pretty often to help plan interviews and to eventually nudge you into accepting an offer. If this sounds potentially annoying to you, don’t fret because I’ve dealt with many recruiters, and my Hired recruiter was definitely one of the nicer ones (my only beef is that the recruiter would sometimes call me in the morning when I was sleeping in late).
Caveat: some of my friends used Hired, and they didn’t have a great experience. For me, the only real bummer was when Hired stopped including me in auctions. I think I may have disappointed my “advocate” by not accepting job offers, and I may have reacted poorly to the recruiter’s nudging because at the time, I thought it was a bit too much. Little did I know that he was far less pushy than most recruiters.
Dice is an ugly site that is incredibly helpful in a painful way. First, I created a résumé specifically for Dice. What does this mean? Dice is for when you WANT spam from recruiters. Dice is for when you want to turbocharge your job search. Dice is for when you’re finally ready to destroy your fear of sharks, so you jump in a shark tank with craploads of bleeding tuna attached to your wetsuit. Do you get the picture, or must I throw more ridiculous warnings at your eyes? You must be mentally prepared to be inundated with contact from recruiters. They can sometimes be…unpleasant.
The onslaught of recruiter spam arrives from Dice because your profile is public. Your profile is rather pointless except for the résumé part of the profile. This means that your résumé has to be public, so it’s a good idea to upload a variant that excludes your contact info. Recruiters will check out your résumé and contact you via Dice messaging (which gets sent to your email). You then respond to recruiters, and work with them to get interviews and get hired. It’s a very clunky process. I could rant for several more paragraphs on the downsides of working with recruiters. However, it can be worth it. I’m very happy at my current job, which I earned through a recruiter.
I didn’t get a ton of recruiters reaching out to me via LinkedIn. It can’t compete with Dice in that department, but at least with LinkedIn, you get contacted by in-house recruiters, not just 3rd party recruiters.
That said, after I got a job, I updated my LinkedIn profile to show my new gainful employment. Consequently, I’ve been contacted by recruiters at least a few times a week even though I’m not actively trying to get a job. In other words, the recruiter “spam” really only pours in if you’re currently employed (or experienced).
Not to give false hope, but you may want to consider paying for a LinkedIn pro account. This lets you send a few messages to people you’re not connected with. I used this feature to contact executives and engineers at a few companies I was interested in. A couple of folks at one company actually replied to my messages, in which, I sincerely gushed about the company (and bragged about my 1337ness of course).
I consider my LinkedIn profile to be a way for me to show off a bit of my personal style. Some people try to be edgy or unique by formatting their résumés in a different way, but I’ve heard that’s actually a bad idea. Not to mention, a lot of people just don’t come up with good designs. Some do, but plenty don’t. Besides, résumés need to be easily skimmed by human eyes and easily scanned by software. After I got hired, I switched from being a job seeker to being an interviewer within my first week at the company. I saw over 10 resumes and sadly, the bland-looking ones were generally easier to skim. The uniquely formatted ones showed good intentions, but poor execution. You should think twice before you use bombastic fonts and lighter colors.
Oh! Back to my original point: I use my LinkedIn profile to demonstrate a bit of my personality through writing style –not through formatting (although I do add bullet points because their text organization powers are un-friggin’-paralleled). In fact, for pretty much any job site that required me to create a profile, I put in quite a bit of effort to write something actually interesting. It can be difficult to flex creative muscles for such tasks, but I believe it’s worth it to prevent your profile from being read with the same dry tone as every other candidates’ boring dossier. If you have 5+ years of perfectly relevant skills, then you can probably write a profile devoid of personality/creativity, and you’ll still stand out as a stellar candidate. Hooray for when that day arrives.
Check back (somewhat) soon for more opinions and anecdotes on software developer job search sites. In part 2 of this Dev Job Searching Tools Roundup, I will ramble about Readyforce, The Muse, The Sourcery, AngelList, VC job listings, and more.
In future blog posts, I will cover other software engineering job hunting topics. I’m particularly excited to discuss my impressions from the other side of interview process. Also on my to-blog list: inheritance in JavaScript and lots of AngularJS best practices / app architecture patterns.
]]>Author of Cracking the Coding Interview, @gayle , talking to @hackreactor pic.twitter.com/aVbcohgqSG
— Jeff Lee (@RebootJeff) January 16, 2014In a previous post, I mentioned that attended a talk given by Gayle Laakmann McDowell when she visited Hack Reactor. She’s the author of the famous Cracking the Coding Interview, which is a book that helps developers perform better when interviewed for a new job. Her text mostly focuses on algorithm challenges, but there’s also a lot of content that has more to do with coaching up interview candidates.
I really liked McDowell’s presentation at Hack Reactor. There were plenty of intriguing anecdotes, and of course, there was plenty of good advice. Plus, she included a lot of insight into the hiring process. Many of her stories and comments provided the Hack Reactor community with a “behind the scenes” sort of perspective.
Keep in mind that she worked for companies like Apple, Microsoft, and Google, so her advice comes from the perspective of giant companies. I doubt her tips apply equally to smaller employers. For example, McDowell heavily emphasized the importance to study certain algorithms (e.g., various sorting and searching algos) and data structures (e.g., trees, hashes, etc). In my experience mostly interviewing with smaller companies (fewer than 500 employees; as few as 5 employees), studying textbook algorithms and data structures wouldn’t have helped me as much as studying more web-specific skills.
That said, I still want to share some of the more interesting takeaways from McDowell’s talk.
When I was at Google, I referred a number of candidates, and ran a little (informal) experiment. How well could people judge their performance?
After each candidate completed their interview, I’d ask them how they did. Then, I’d look up their actual performance. And guess what? There was no correlation. None. Zip. Zero. Zilch.
<div>
elements, and they both have margin: 10px;
, then how much space is between them? You’d expect there to be 20px of space between them, but instead, there is only 10px thanks to margin collapsing.TODO
comments in your code for important-but-tangential stuff like input validationI use Sublime Text 2 as my text editor for coding. I don’t use a fancy IDE like WebStorm, but I do plan on trying out WebStorm more at work. Actually, I should probably upgrade to ST3, but for now, I’m happy with ST2.
However, ST2’s light weight comes at a cost: you probably need to configure some stuff before you’re really ready to roll. Here’s what I do when I first install ST2 on a machine.
First, I change the keyboard shortcuts for cycling through open tabs. The default behavior is based on your usage history (most recently viewed tabs), but I prefer just cycling from left to right. There’s actually another key binding that can cycle tabs from left to right, but I prefer using Ctrl+Tab
.Therefore, I edited my key bindings like so…
Next up, I make sure my whitespace is configured to my liking. I think most coders who lift hefty amounts of JavaScript go with indentation 2 spaces at a time, so that’s what I do. I prefer it because it takes up less space than a typical 4-space tab, which is critical when viewing code in split-screen mode. I also like having the option to manually change indentation with spaces if necessary for alignment purposes. Mixing spaces and tabs gets messy.
I also configure Sublime Text to automatically add a new line at the end of every file whenever I save. It won’t add a new line if one already exists at EOF. I personally never suffer from lack of new line at EOF, but some UNIX tools won’t work without them, and I know lots of hardcore coders out there like using such tools. I don’t want to screw them over. With that said, allow me to present my ST2 settings…
I use the Nexus theme, which you can find here: https://github.com/EleazarCrusader/nexus-theme. The readme file explains a bunch of different installation options, but I recommend installing via Package Manager. The readme also tells you how to activate the theme after installation.
Sublime Text doesn’t come with many bells and whistles. Instead you add them as packages. First, you must install the package manager by following these instructions. After that, get ready to discover a giant pool of all the bells and whistles you could possibly want. If you need to adjust the settings for any of these packages, you can usually find good documentation from the readme files of their respective GitHub repos.
After you install Package Manager, you can access it by hitting Ctrl+Shift+P
(or perhaps Cmd+Shift+P
for Macs?) and then typing “package control” into the search box. The typeahead will reveal your various options, but you mostly be using “Package Control: Install Package”. There will be some load time necessary to provide you a list of available packages, but after it’s done, you can search for packages by name. Installation will similarly require some load time. Check the bottom-left of the ST2 window to see relevant status messages.
Here are the packages I installed:
Prettify your code by aligning multiple lines of variable definitions and hash objects. For example…
This may look stupid to you, but I don’t use it all the time. The main place I like to use it is with multiple var example = require('npm package name here');
statements at the top of a JS file. By the way, I had to edit the package settings to get alignment for object literals. I added the ":"
seen below…
Add indicators in your gutter so then you can see which lines of code have been changed since the last git commit. See the left edge of this screenshot:
I prefer live linting over build-time linting. SublimeLinter supports a ton of languages, and I have it set to simply bring up an indicator in the gutter and some underscores to point to any issues it finds. It’s not too obtrusive.
Extraneous whitespace is bad. Trailing whitespace is worse. I use this package to highlight any trailing whitespace in bright pink. I bet I could set my linter to do this, but oh well.
Who doesn’t love Markdown? It makes GitHub README files and wiki pages look great. It makes dev blogs look great. It makes writing dev-related text easy. Sometimes, I write rough drafts of blog posts within Google Docs or Dillinger, which is a sweet online Markdown editor. In the end, I always complete my blog posts by writing Markdown within Sublime Text.
I recently found a sweet ST package to help edit Markdown files: MarkdownEditing. It completely transforms the look and syntax highlighting of your Markdown. Sadly, I use CodeRay for codeblocks rather than standard Markdown markup. So MarkdownEditing can’t beautify my codeblocks within Sublime Text, but inline code snippets like this one
are highlighted in a very helpful way. You can see all the ways that the package alters your Markdown here. Keep in mind that there are a couple other themes available specifically for MarkdownEditing. I use the dark theme of course.
You might also find it handy to install packages for specific languages. For example, I dabble with CSS pre-processors and templating languages. I’m currently checking out LESS for CSS and Jade for HTML, so I’ve installed syntax highlighters for them. The package names are simply “LESS” and “Jade”.
]]>The events discussed in this blog post occurred in December 2013 and January 2014 because a blogging hiatus caused a bit of a delay. Plus, I’ve just been lazy with blogging recently.
My “final” two weeks at Hack Reactor weren’t really final. As explained in a Quora post of mine, I continued going to Hack Reactor for additional lectures and learning exercises AFTER graduation.
Weeks 11 and 12 were all about preparing for job hunting and prepping for hiring day by practicing presentations. These are definitely the least intense weeks of the program. Some students were motivated enough to start new projects. Some students (like me) spent some time to refactor code from our Hack Reactor projects from weeks 6-10. Throughout the final two weeks, we received a wide variety of lectures on how to find a job, on how to approach whiteboarding, and on a few different tech topics too. Most of these lectures were only an hour, and many of them didn’t have tightly associated classwork (which is unlike the first half of the program).
One thing I found odd was the emphasis that staff put on downplaying Hack Reactor when job hunting. I’m not the only one to feel funny about it. The reason is that you don’t want employers to frame their perspective of you within the confines of “recent student.” I can understand that, but I didn’t bother editing my blog to avoid “exposing” myself as a recent graduate of a training program.
Unfortunately, the final stages of the Hack Reactor curriculum ran into issues. Fortunately, Hack Reactor managed to pull together the resources to compensate. I explain later in this blog post.
One of my favorite guest speakers during my time at Hack Reactor was Pamela Fox. Pamela already gave a talk at Hack Reactor, but it was a more technical talk about Backbone. This time around, she gave a talk about the culture of professional software engineering. It was a great presentation that discussed what commonalities and differences you can expect to see when comparing engineering teams. A lot of what she said ended up influencing the questions I ask employers when searching for a job.
For the first time in Hack Reactor history, a consultant was brought in specifically to give a 2-day workshop on job search prep. The consultant, David Daniels, did all the usual stuff like resume review (which would make him the 5th person to review our resumes during the job search prep portion of Hack Reactor), but he also conducted exercises on networking and personality testing. Plus, he gave a lecture about what companies like Microsoft look at when evaluating candidates.
“Tell me about yourself” is such a common opener for job interviews (especially in the phone screen stages), but it’s funny how hard it can be to come up with a coherent answer without any practice. Therefore, David had us all practice giving quick, autobiographical pitches that would not ony sound concise (no rambling!), but also provide all the relevant info that recruiters want to hear (what you’ve been working on, what specific skills you have, what you look for in a new job, etc).
Students were also instructed to practice giving “pitches” on why they want to work for company XYZ in response to the frequently asked question of “Why do you want to work here?” Admittedly, this is something I did not give much attention to after graduation, and I regret that. It’s definitely important to practice answering that question for all the different companies you apply to.
The other major activity conducted by David was post-survey analysis. What survey? The Strengths Finder survey. It’s a personality test that focuses on your “strengths” in a way that is supposed to help you inspect your personality in a way that is relevant to professional/work life.
Here are my top 5 (paraphrased) strengths according to the test:
My results put me in the “typical” engineer group. Together, with the fellow students with similar strengths, we built a Google Spreadsheet to further analyze our results and find out who was most similar to whom. Damn. We nerdy.
I’m not a fan of personality tests. Any one who has taken an intro psych class knows that personality tests are often flawed by the wording of the questions, the limited options provided by multiple-choice formats, etc. On top of that, I don’t like the effect that personality tests have. There’s a lot of confirmation bias. Test takers tend to allow the results to define them as a self-fulfilling prophecy. When people learn of other people’s test results, they might end up pigeonholing each other. “Oh that test said you have a tendency to over-analyze situations? I should call you out on it whenever you offer criticism.” (Ok that last hypothetical example is a bit melodramatic, but it’s the type of crap that starts happening on conscious and subconscious levels)
Perhaps what I despise most is that personality tests can solidify self-perceptions and stifle personal change as a result. I believe people can change. They change all the time. This is not optimism. I believe people change for the better and the worse all the time. My point is that some fools take personality tests and believe the results always involve immutable properties. Such belief is more ridiculous than using programming jargon to discuss psychology concepts ;)
There was booze, dancing, food, funny photos, and good times :D
The day after graduation (which was in late December), my cohort returned for a follow-up. The follow-up included asking us not to reveal too many of Hack Reactor’s trade secrets, asking us for feedback about the course, and some extra heartfelt moments.
Then we parted ways. Some flew back home, never to return. Most of us went home for the winter holidays and returned in January for post-graduation job search help. This included mock interviews conducted by Hack Reactor staff (more specifically, Cameron Boehmer, an awesomely nice guy who created Squirt.io). It also included practicing whiteboarding with peers, lots of mentoring, and a few additional lectures about stuff like user authentication and SEO.
The author of the mucho famous book, Cracking the Coding Interview, gave a talk at Hack Reactor in January. She gave a ton of great advice. I will regurgitate much of it in a future blog post. For now, I just want to share the most interesting tidbit.
Gayle mentioned that you will suck at surmising your own interview success. Apparently, surveys have been conducted, and they reveal zero correlation between how well a candidate thinks they did versus how the candidate’s interviewer thinks they did. You may think you aced an interview, but you actually said something that’s a deal-breaker. Or you may think you bombed, but you actually did better than all the other candidates.
Unique to my cohort, hiring day was hosted at Hack Reactor after graduation. We presented group projects in front of an audience of 15 or so companies. We then went into a mini-interview marathon akin to speed dating. Each Hack Reactor student got a chance to speak with about 7 or 8 companies based on preferences submitted to Hack Reactor staff beforehand. After the crazy “speed dating”, there was an open networking session (basically a happy hour). There was a lot of stress leading up to this day, but ya know what? It really wasn’t that bad.
I would say about 1/3 or 1/2 of my peers who participated actually got hired by the companies that showed up. For me, hiring day was just the beginning of a nearly-3-month-long search.
I should (re-)mention that about a third of my cohort didn’t actually participate in hiring day because they weren’t interested in starting a new job soon or they had joined Hack Reactor’s Hacker-in-Residence program.
As you can imagine, I have a lot to talk about with regards to job searching. I’m excited to blog in detail about the ups and downs of the search. To cut to the chase, let me mention that I am fully employed. I’m a professional software engineer working on a web app that uses full-stack JavaScript. I don’t mean to brag (much), but the gig is pretty friggin’ sweet. Hack Reactor was a success!
I learned so much about job hunting. I will go into details in a future blog post, but for now, I will outline some of what I picked up when searching for a job:
Yesterday, I went to my cohort’s “3-month” reunion hosted by Hack Reactor. It’s actually been closer to 5 months since graduation, but whatever. At the reuinion, the founders of Hack Reactor did a Q&A panel where they provided career advice and asked us how things were going at our new jobs. After the panel, we were told that Hack Reactor HQ is expanding. It’s already expanded once since my cohort ended by using a second floor of the building. That expansion increased the size of Hack Reactor cohorts. More staff have been hired too.
A third floor will be opening in June. It will mostly be used as offices for the newly augmented staff, but it will also have a new lounge area for alumni to use! Niiice. Wheels have been set in motion to organize alumni events and general activity. For example, there are plans to use the alumni network as an avenue for project collaboration (e.g., Feel like starting a random side project? Get ideas and possibly form a team with alumni).
]]>