<![CDATA[RSS Feed: https://ericrallen.dev/]]>https://ericrallen.devGatsbyJSMon, 14 Aug 2023 19:46:24 GMT<![CDATA[Advent of Rust: Part II]]>https://ericrallen.dev/blog/advent-of-rust-2022-pt-iihttps://ericrallen.dev/blog/advent-of-rust-2022-pt-iiWed, 07 Dec 2022 23:31:14 GMT<p><strong>Last Updated</strong>: 2022-12-08</p> <p>In Part 2 of my <a href="https://ericrallen.dev/blog/advent-of-rust-2022/">Advent of Rust series</a> we'll explore the puzzles 6 through 10 of <a href="https://adventofcode.com/2022">2022's Advent of Code challenge</a>.</p> <p><strong>GitHub Repository</strong>: <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/days/day_six.rs">https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/days/day_six.rs</a></p> <p><a id="table-of-contents"></a></p> <h2>Table of Contents</h2> <ul> <li><a href="#challenges">Challenges</a></li> <li><a href="#getting-started">Getting Started</a></li> <li><a href="#wrapping-up">Wrapping Up</a></li> </ul> <p><a id="challenges"></a></p> <h3>Challenges</h3> <ul> <li><a href="#day-six">Day Six</a></li> </ul> <p><strong>Note</strong>: Each challenge has a <strong>Real Talk</strong> section where I share some <strong>Takeaways</strong> about what I learned during that challenge and how it contributed to my overall goal of learning Rust, various <strong>Notes</strong> I wrote down while going through the challenge, all of the <strong>Searches</strong> I made while working through the challenge, and what my key <strong>Next Steps</strong> were so you can see how I broke down trying to learn these concepts by doing.</p> <p><a id="getting-started"></a></p> <h2>Getting Started</h2> <p>After successfully solving days 1 through 5, I'm feeling okay about basic syntax and concepts, though I'm still trying to fully grok ownership and lifetimes, and want to address one thing things that was just weird before I started solving puzzles:</p> <ul> <li>I <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/main.rs#L65-L74">implemented</a> a <code class="language-text">test</code> <a href="https://doc.rust-lang.org/cargo/reference/features.html">feature</a> instead of relying on <code class="language-text">cargo</code>s built-in test runner</li> </ul> <p>I'll go back and convert the previous solutions to use the built-in testing functionality at some point, but my goal is to use it for every solution going forward. It helped that <a href="#day-six">Day 6</a> was the first to introduce multiple example inputs, which didn't fit into the pattern I was using previously.</p> <p><a id="conclusions"></a></p> <h2>Conclusions</h2> <p>Below are some conclusions I've come to during this stage of my journey (along with the date that I came to that conclusion just in case my thoughts change over time).</p> <ul> <li><strong>2022-12-07</strong>: Rust is still pretty neat. I might actually like it.</li> </ul> <p><a id="day-six"></a></p> <h2>Day Six</h2> <p><a href="https://adventofcode.com/2022/day/6">Day Six</a> is a deceptively easy challenge where we need to identify a sequence of unique characters in a longer string.</p> <p>Like some more complex puzzles might do later on, we are given several examples with their solutions, so the first thing we should do is create a <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/days/day_six.rs#L69-L106">test for each input</a> and then we can be reasonably sure we've got things right when all of our tests pass.</p> <h3>Real Talk</h3> <p>We're given several examples inputs:</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">mjqjpqmgbljsphdztnvjfqwrcgsmlb bvwbjplbgvbhsrlpgdmjqwftvncz nppdvjthqldpwncqszvftbrmjlhg nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw</code></pre></div> <p>And asked to find the index of the last character in a sequence of 4 unique characters.</p> <p>Breaking this one down into some logical steps:</p> <ol> <li>Check to see if the first 4 characters are unique</li> <li>Iterate through each character after the first one and see if it plus the next 3 characters are unique</li> </ol> <p>Part Two introduces another Advent of Code trope: Adjusting the count of items you need to consider from your input. In this case we're going to start looking for a sequence with 14 unique characters instead of only 4.</p> <p><strong>Note</strong>: Another, potentially better approach might maintain a single stack of <code class="language-text">N</code> characters and just keep removing the first character and appending the next character in the larger sequence.</p> <h4>My Solution</h4> <p>The first thing we'll need is a way to check if a given set of characters is unique. Rust's <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup"><code class="language-text">.dedup()</code></a> method removes consecutive duplicate items in a <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html">Vector</a>, so we can <a href="https://doc.rust-lang.org/core/iter/trait.Iterator.html#method.collect"><code class="language-text">.collect()</code></a> our string's characters into a Vector and then <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort"><code class="language-text">.sort()</code></a> and <code class="language-text">.dedup()</code> them.</p> <div class="gatsby-highlight" data-language="rust"><pre class="language-rust"><code class="language-rust"><span class="token keyword">fn</span> <span class="token function-definition function">check_for_unique_sequence</span><span class="token punctuation">(</span>sequence<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">str</span><span class="token punctuation">,</span> size<span class="token punctuation">:</span> <span class="token keyword">usize</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">bool</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> <span class="token keyword">mut</span> sequence_array<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token operator">&lt;</span><span class="token keyword">char</span><span class="token operator">></span> <span class="token operator">=</span> sequence<span class="token punctuation">.</span><span class="token function">chars</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// `.dedup()` only removes consecutive duplicates</span> <span class="token comment">// so it needs a sorted Vector for our use case</span> sequence_array<span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> sequence_array<span class="token punctuation">.</span><span class="token function">dedup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> sequence_array<span class="token punctuation">.</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> size <span class="token punctuation">}</span></code></pre></div> <p><strong>Note</strong>: It probably would have been more efficient to just compare the size of the deduplicated sequence to the size of the original sequence instead of passing the size in, too.</p> <p>This utility method is technically extraneous, but it made the code feel a bit cleaner without the <a href="">Range</a> (<code class="language-text">start..end</code>) needing to include the math for calculating the correct indices. It also gave me a chance to play around with returning and working more with <a href="https://doc.rust-lang.org/std/option/enum.Option.html"><code class="language-text">Option</code> types</a>.</p> <div class="gatsby-highlight" data-language="rust"><pre class="language-rust"><code class="language-rust"><span class="token keyword">fn</span> <span class="token function-definition function">get_sequence</span><span class="token punctuation">(</span>stream<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token class-name">String</span><span class="token punctuation">,</span> start<span class="token punctuation">:</span> <span class="token keyword">usize</span><span class="token punctuation">,</span> end<span class="token punctuation">:</span> <span class="token keyword">usize</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Option</span><span class="token operator">&lt;</span><span class="token operator">&amp;</span><span class="token keyword">str</span><span class="token operator">></span> <span class="token punctuation">{</span> <span class="token comment">// this could have just been a regular `.get()` call in the code below</span> <span class="token comment">// but having the index math in the Range was hard to read</span> stream<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>start<span class="token punctuation">..</span>end<span class="token punctuation">)</span> <span class="token punctuation">}</span></code></pre></div> <p>Finally, we need to actually check our string for a unique sequence of some defined length.</p> <p><strong>Note</strong>: Initially the length was hardcoded to a specific <a href="https://doc.rust-lang.org/std/keyword.const.html">constant</a>, but it was easy to just make the length a function argument and pass in the relevant constant for each part of the puzzle.</p> <div class="gatsby-highlight" data-language="rust"><pre class="language-rust"><code class="language-rust"><span class="token keyword">fn</span> <span class="token function-definition function">find_end_of_sequence</span><span class="token punctuation">(</span>stream<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token class-name">String</span><span class="token punctuation">,</span> length<span class="token punctuation">:</span> <span class="token keyword">usize</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">usize</span> <span class="token punctuation">{</span> <span class="token comment">// check the first N characters before we start iterating</span> <span class="token keyword">let</span> first_sequence <span class="token operator">=</span> <span class="token function">get_sequence</span><span class="token punctuation">(</span>stream<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> length<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token function">check_for_unique_sequence</span><span class="token punctuation">(</span>first_sequence<span class="token punctuation">,</span> length<span class="token punctuation">)</span> <span class="token punctuation">{</span> length <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// we'll update this once we find the right ending index</span> <span class="token comment">// TODO: find a pattern that can make this `panic!()` if we</span> <span class="token comment">// never find a unique sequence</span> <span class="token keyword">let</span> <span class="token keyword">mut</span> sequence_end_index<span class="token punctuation">:</span> <span class="token keyword">usize</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>index<span class="token punctuation">,</span> _<span class="token punctuation">)</span> <span class="token keyword">in</span> stream<span class="token punctuation">.</span><span class="token function">chars</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">enumerate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// skip first character since we already checked the first sequence</span> <span class="token keyword">if</span> index <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">{</span> <span class="token comment">// get the next sequence to check</span> <span class="token keyword">let</span> test_sequence <span class="token operator">=</span> <span class="token function">get_sequence</span><span class="token punctuation">(</span>stream<span class="token punctuation">,</span> index<span class="token punctuation">,</span> index <span class="token operator">+</span> length<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token function">check_for_unique_sequence</span><span class="token punctuation">(</span>test_sequence<span class="token punctuation">,</span> length<span class="token punctuation">)</span> <span class="token punctuation">{</span> sequence_end_index <span class="token operator">=</span> index <span class="token operator">+</span> length<span class="token punctuation">;</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> sequence_end_index <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>Now all we have to do is call <code class="language-text">find_end_of_sequence()</code> with our input string and the desired length of the unique sequence.</p> <p><a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/days/day_six.rs">View on GitHub</a></p> <h5>Testing</h5> <p>Adding unit tests to the solution was really easy, although I'm still not sure if I put them in the right place. I think I'm a fan of the simplicity of Rust's built-in testing.</p> <div class="gatsby-highlight" data-language="rust"><pre class="language-rust"><code class="language-rust"><span class="token attribute attr-name">#[cfg(test)]</span> <span class="token keyword">mod</span> <span class="token module-declaration namespace">test</span> <span class="token punctuation">{</span> <span class="token keyword">use</span> <span class="token keyword">crate</span><span class="token punctuation">::</span><span class="token punctuation">{</span>read_input<span class="token punctuation">,</span> read_solution<span class="token punctuation">,</span> days<span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token attribute attr-name">#[test]</span> <span class="token keyword">fn</span> <span class="token function-definition function">day_six_part_one</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// I put the first example for day 6 part 1 into a file</span> <span class="token comment">// like I have used for testing the previous puzzles</span> <span class="token keyword">let</span> input <span class="token operator">=</span> <span class="token function">read_input</span><span class="token punctuation">(</span><span class="token string">"6"</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token function">read_solution</span><span class="token punctuation">(</span><span class="token string">"6"</span><span class="token punctuation">,</span> <span class="token string">"1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token namespace">days<span class="token punctuation">::</span>day_six<span class="token punctuation">::</span></span><span class="token function">part_one</span><span class="token punctuation">(</span>input<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> output<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token attribute attr-name">#[test]</span> <span class="token keyword">fn</span> <span class="token function-definition function">day_six_part_one_extra</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// the other examples inputs and solutions</span> <span class="token keyword">let</span> inputs <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token string">"bvwbjplbgvbhsrlpgdmjqwftvncz"</span><span class="token punctuation">,</span> <span class="token string">"nppdvjthqldpwncqszvftbrmjlhg"</span><span class="token punctuation">,</span> <span class="token string">"nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"</span><span class="token punctuation">,</span> <span class="token string">"zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">let</span> outputs <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"5"</span><span class="token punctuation">,</span> <span class="token string">"6"</span><span class="token punctuation">,</span> <span class="token string">"10"</span><span class="token punctuation">,</span> <span class="token string">"11"</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>index<span class="token punctuation">,</span> input<span class="token punctuation">)</span> <span class="token keyword">in</span> inputs<span class="token punctuation">.</span><span class="token function">iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">enumerate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token namespace">days<span class="token punctuation">::</span>day_six<span class="token punctuation">::</span></span><span class="token function">part_one</span><span class="token punctuation">(</span>input<span class="token punctuation">.</span><span class="token function">to_string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> outputs<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token attribute attr-name">#[test]</span> <span class="token keyword">fn</span> <span class="token function-definition function">day_six_part_two</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> inputs <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token string">"mjqjpqmgbljsphdztnvjfqwrcgsmlb"</span><span class="token punctuation">,</span> <span class="token string">"bvwbjplbgvbhsrlpgdmjqwftvncz"</span><span class="token punctuation">,</span> <span class="token string">"nppdvjthqldpwncqszvftbrmjlhg"</span><span class="token punctuation">,</span> <span class="token string">"nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"</span><span class="token punctuation">,</span> <span class="token string">"zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">let</span> outputs <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"19"</span><span class="token punctuation">,</span> <span class="token string">"23"</span><span class="token punctuation">,</span> <span class="token string">"23"</span><span class="token punctuation">,</span> <span class="token string">"29"</span><span class="token punctuation">,</span> <span class="token string">"26"</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>index<span class="token punctuation">,</span> input<span class="token punctuation">)</span> <span class="token keyword">in</span> inputs<span class="token punctuation">.</span><span class="token function">iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">enumerate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token namespace">days<span class="token punctuation">::</span>day_six<span class="token punctuation">::</span></span><span class="token function">part_two</span><span class="token punctuation">(</span>input<span class="token punctuation">.</span><span class="token function">to_string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> outputs<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <h4>Takeaways</h4> <p>This is the fist challenge where I really felt like I understood what I was doing and wrote code that I didn't feel bad about. It was really helpful to have another slightly easier puzzle as a way to try putting together everything I've learned about the language so far.</p> <p>I'm also glad I took the time to abstract some of it so that I could easily reuse everything in Part Two by just adding a second parameter that would accept the desired length of the sequence we wanted to check.</p> <h4>Notes</h4> <blockquote> <p>I bet Day 7 is going to be much harder</p> </blockquote> <h4>Searches</h4> <p>Here are the actual search strings I used, taken directly from my browser's history.</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">rust testing best practices rust break out of for loop</code></pre></div> <p><a id="day-six-next-steps"></a></p> <h4>Next Steps</h4> <ul> <li>Should eventually figure out if having the tests live inside of the <code class="language-text">.rs</code> file that they are testing is the best approach or if there is a better spot for them</li> <li>Update previous day's solutions to use unit tests instead of <code class="language-text">test</code> feature</li> </ul> <p><a href="#challenges">Back to List of Challenges</a></p> <p><a id="wrapping-up"></a></p> <h2>Wrapping Up</h2> <p><em>Coming Soon.</em></p><![CDATA[Advent of Rust: Part I]]>https://ericrallen.dev/blog/advent-of-rust-2022-pt-ihttps://ericrallen.dev/blog/advent-of-rust-2022-pt-iWed, 07 Dec 2022 23:17:04 GMT<p><strong>Last Updated</strong>: 2022-12-07</p> <p>In Part 1 of my <a href="https://ericrallen.dev/blog/advent-of-rust-2022/">Advent of Rust series</a> we'll explore the first 5 puzzles for <a href="https://adventofcode.com/2022">2022's Advent of Code challenge</a>.</p> <p><a id="table-of-contents"></a></p> <h2>Table of Contents</h2> <ul> <li><a href="#challenges">Challenges</a></li> <li><a href="#getting-started">Getting Started</a></li> <li><a href="#wrapping-up">Wrapping Up</a></li> </ul> <p><a id="challenges"></a></p> <h3>Challenges</h3> <ul> <li><a href="#day-one">Day One</a></li> <li><a href="#day-two">Day Two</a></li> <li><a href="#day-three">Day Three</a></li> <li><a href="#day-four">Day Four</a></li> <li><a href="#day-five">Day Five</a></li> </ul> <p><strong>Note</strong>: Each challenge has a <strong>Real Talk</strong> section where I share some <strong>Takeaways</strong> about what I learned during that challenge and how it contributed to my overall goal of learning Rust, various <strong>Notes</strong> I wrote down while going through the challenge, all of the <strong>Searches</strong> I made while working through the challenge, and what my key <strong>Next Steps</strong> were so you can see how I broke down trying to learn these concepts by doing.</p> <p><a id="getting-started"></a></p> <h2>Getting Started</h2> <p>Anyone who has dealt with Python, Node, or Ruby versions knows that you probably shouldn't just install whatever language you wnat to work with without first researching the ecosystem and figuring out how people really manage versions, packages, etc. You <em>can</em> just install the default toolchain and go for it, but you'll eventually regret it.</p> <p>As I was searching for the right <a href="https://users.rust-lang.org/t/best-way-to-install-rust-on-os-x-rustup-or-brew/6362">package to install from Homebrew for this</a>, I learned the first thing that I <strong>love</strong> about Rust.</p> <p>Rust's default, recommended installation method, <code class="language-text">rustup</code> <a href="https://rust-lang.github.io/rustup/concepts/index.html">handles this for you</a> so that you don't need to figure out whether you should be using <code class="language-text">nvm</code> or <code class="language-text">volta</code> or <code class="language-text">pyenv</code> or <code class="language-text">poetry</code>.</p> <p>This instantly made the languages I have been using for years feel very outdated.</p> <p><a id="conclusions"></a></p> <h2>Conclusions</h2> <p>Below are some conclusions I've come to during this stage of my journey (along with the date that I came to that conclusion just in case my thoughts change over time).</p> <ul> <li><strong>2022-12-02</strong>: Rust is pretty neat. I might actually like it.</li> <li><strong>2022-12-04</strong>: Fighting to get the right types (like <code class="language-text">&amp;str</code>, <code class="language-text">String</code>, <code class="language-text">char</code>, <code class="language-text">&amp;&amp;str</code>, etc.) more than I am actually programming. Hoping this is just like the initial hurdles I encountered switching from JavaScript to TypeScript.</li> <li><strong>2022-12-05</strong>: Like any language, it seems like it is not hard to write mediocre, naive implementations in Rust.</li> <li><strong>2022-12-06</strong>: Feeling a bit more comfortable.</li> <li><strong>2022-12-07</strong>: What a roller coaster of emotion.</li> </ul> <p><a id="day-one"></a></p> <h2>Day One</h2> <p>Now that we've got rust up and running, it's time to see what <a href="https://twitter.com/ericwastl">@ericwastl</a> has in store for us with Advent of Code this year.</p> <p>Luckily <a href="https://adventofcode.com/2022/day/1">Day One</a> eases us into things with iterating through some collections of numbers and adding them together.</p> <p>As is <a href="https://github.com/ericrallen/advent-of-code/blob/main/2018/utils/solution.class.js">tradition</a>, I first needed to <a href="https://github.com/ericrallen/advent-of-code/tree/main/2022">over-engineer</a> a way to test the example inputs against the example solutions and run code for the various parts of each day.</p> <blockquote> <p>Before we can solve Advent of Code, we must <a href="https://www.phy.cam.ac.uk/blog/how-make-apple-pie-scratch#:~:text=In%20the%201980s%20blockbuster%20science,must%20first%20invent%20the%20universe&#x27;.">first invent</a> an <a href="https://github.com/Bogdanp/awesome-advent-of-code#project-templates">Advent of Code helper</a>.</p> </blockquote> <p><strong>Note</strong>: I first actually needed to figure out how to get the <a href="https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer"><code class="language-text">rust-analyzer</code> VSCode Extension</a> to cooperate with the subdirectory I used for my crate.</p> <p><strong>Another Note</strong>: I'll also probably streamline the input gathering at some point so that my inputs are pulled down from the Advent of Code site automatically and cached, but we need to <a href="https://idioms.thefreedictionary.com/walk+before+you+run">walk before we can run</a> and we're taking baby steps here.</p> <h3>Real Talk</h3> <p>We're given an example input:</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">1000 2000 3000 4000 5000 6000 7000 8000 9000 10000</code></pre></div> <p>And told that each collection of numbers represents some collection and we want to sum those collections and find the biggest one.</p> <p>Breaking this problem down into logical steps (assuming we've already solved the problem of getting the input into our program):</p> <ol> <li>split the input on double line breaks to get each collection</li> <li> <p>iterate through the collections</p> <ol> <li>split them on line breaks to get each value</li> </ol> </li> <li> <p>iterate through the values</p> <ol> <li>parse them as numbers</li> <li>add them together</li> <li>return the sum</li> </ol> </li> <li>find the maximum value among the totals for each collection</li> </ol> <p>Part Two sees us taking the same logic, but sorting the collection and adding the top 3 totals together.</p> <h4>Takeaways</h4> <p>What's great about a simple challenge like this one for learning a new language is that it lets you play around with concepts that you are likely already familiar with and just sort of familiarize yourself with the syntax and how you execute programs in this new language.</p> <p>Things <a href="https://github.com/ericrallen/advent-of-code/commit/859cd5ed6114adfcd958c6db6980aaae8e224116">may not have been perfect</a>, but this felt like a very successful start with the language.</p> <h4>Notes</h4> <blockquote> <p>Rust is harder than I thought</p> </blockquote> <blockquote> <p>I guess I do need to read about this whole borrowed vs. owned thing</p> </blockquote> <blockquote> <p>Woah, this IDE integration with the <code class="language-text">rust-analyzer</code> is amazing</p> </blockquote> <blockquote> <p>I'm so glad I fell in love with TypeScript before I tried to pick up Rust</p> </blockquote> <blockquote> <p>Why can't I join these numbers into a string? I guess I'll just dump the whole array.</p> </blockquote> <blockquote> <p>I need to read the instructions more carefully.</p> </blockquote> <h4>Searches</h4> <p>Here are the actual search strings I used, taken directly from my browser's history.</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">rust read file input rust concatenate strings with variables rust analyzer failed to discover workspace rust import from another file rust string vs &amp;string rust match bindings cannot shadow statics rust default value for argument rust split string rust sum of array rust number types rust apply function to each item in vector rust sort array cannot return value referencing temporary value rust sort descending</code></pre></div> <p>You can pretty much reconstruct how I arrived at <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/days/day_one.rs">my solution for Day One</a> by following that trail of search strings.</p> <p><a id="day-one-next-steps"></a></p> <h4>Next Steps</h4> <p>I still had lots of things to figure out, like:</p> <ol> <li>How to implement verbose debugging messages without needing to manually flip a Boolean in the code</li> <li>How to pass named parameters to the executable</li> <li>How to actually test the output of the executable against the example solution when providing the example input</li> </ol> <p><a href="#challenges">Back to List of Challenges</a></p> <p><a id="day-two"></a></p> <h2>Day Two</h2> <p><a href="https://adventofcode.com/2022/day/2">Day Two</a> has us tackling a Rock, Paper, Scissors game with some complex scoring rules.</p> <p>Before I dug into the problem, I really wanted to tackle those <a href="#day-one-next-steps">Next Steps</a> from <a href="#day-one">Day One</a>.</p> <p>This is when I learned about the second thing I <strong>love</strong> about Rust: <a href="https://doc.rust-lang.org/cargo/reference/features.html">Features</a>.</p> <p>Having a built-in way to specify features for your program and a built-in way to have your code <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/main.rs#L11-L21">behave differently</a> depending on <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/main.rs#L30-L34">the state of those features</a> is awesome.</p> <p>There are certainly ways to achieve this in every language, but this might be the simplest and easiest to implement that I've encountered.</p> <h3>Real Talk</h3> <p>Once again, we're given an example input:</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">A Y B X C Z</code></pre></div> <p>And told that each line represents a round of Rock, Paper, Scissors and that we need to model the outcomes and provide the relevant total score based on the game's outcome and our chosen weapon.</p> <p>Breaking this problem down into logical steps:</p> <ol> <li> <p>iterate through each line</p> <ol> <li>get the other player's choice (first column)</li> <li>get our choice (second column) and its associated point value</li> <li>execute the game's rules to decide who won</li> <li>get the value of the round for us (based on win, loss, or draw)</li> <li>add the value of the outcome and the value of our choice</li> <li>return that sum</li> </ol> </li> <li>add up all the individual round sums to get our final score</li> </ol> <p>Day 2's puzzle is the first to introduce the Advent of Code trope of Part Two changing how you interpret the input, and asks us to figure out what choice we should make in each round to achieve a desired outcome and then provide the final total score based on those choices.</p> <p>It requires us to change things a little bit, but most of the logic is still there.</p> <h4>Takeaways</h4> <p>This one was also great to start groking the ins and outs of Rust because it takes a <a href="https://en.wikipedia.org/wiki/Rock_paper_scissors">game</a> we're likely already familiar with, adjusts it minimally, and makes us think about how to model those rules programmatically.</p> <p>There are many approaches to the problem that give us a chance to explore <a href="https://en.wikipedia.org/wiki/Control_flow">control flow</a> and <a href="https://woz-u.com/blog/how-to-get-programming-logic/">logic</a> in our chosen language while maybe also exploring some of its more complex <a href="https://www.geeksforgeeks.org/data-structures/">data structures</a></p> <h4>Notes</h4> <blockquote> <p>Rock, paper, scissors is actually a little harder than I thought; the point system here makes it a little more complicated, too</p> </blockquote> <blockquote> <p>I know there has to be a better way than <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/days/day_two.rs#L20-L50">all these ifs</a>, but I guess I'll learn that later</p> </blockquote> <blockquote> <p>I still have no idea when I'm supposed to use <code class="language-text">&amp;</code> and when I'm not; I'm really glad this IDE integration exists</p> </blockquote> <h4>Searches</h4> <p>Here are the actual search strings I used, taken directly from my browser's history.</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">rust println! in debug only rust debug! rust how to get feature rust trim string rust enum rust get value from enum rust import macro from another file rust match multiple statements rust remove empty elements from vector</code></pre></div> <h4>Next Steps</h4> <ol> <li>Okay, it's time to actually dig into this borrowed vs owned thing</li> <li>I need to take some time to learn about the differences with <code class="language-text">struct</code>s and <code class="language-text">enum</code>s</li> <li>Am I overusing <code class="language-text">.collect()</code> and <code class="language-text">.iter()</code>? Do I need them as often as I have been using them? When should I chain methods and when should I not?</li> </ol> <p><a href="#challenges">Back to List of Challenges</a></p> <p><a id="day-three"></a></p> <h2>Day Three</h2> <p><a href="https://adventofcode.com/2022/day/3">Day Three</a> has us comparing parts of a string and looking for duplicates.</p> <p>This time I decided to try to make myself to explore the available functions in my IDE's Intellisense suggestions before searching for a solution to something. I think it worked out okay, and as a result you'll see that there are a lot less search strings focused on a specific task - and a lot more focused on a specifc error message I received while working in this way.</p> <h3>Real Talk</h3> <p>Example Input:</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">vJrwpWtwJgWrhcsFMMfFFhFp jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL PmmdzqPrVvPwwTWBwg wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn ttgJtRGJQctTZtZT CrZsJsPPZsGzwwsLwLmpwMDw</code></pre></div> <p>We're supposed to split these strings in half and find the character that appears in both halves, then convert that character to a numerical value and add them all together.</p> <h4>Takeaways</h4> <p>This one sort of reinforces what we've already started learning and gives us a chance to explore those concepts a little further.</p> <p>So far, using Advent of Code to learn a new programming language seems like a good idea, but I worry when the difficulty really increases it will result in a wall of frustration.</p> <h4>Notes</h4> <blockquote> <p>Okay, we're doing another reduce/sum of an Array; hopefully I get the hang of the language before we get into more complex structures</p> </blockquote> <blockquote> <p>That <a href="https://youtu.be/TJTDTyNdJdY">Rust Demystified</a> video sort of actually helped me understand the <code class="language-text">&amp;</code> and I kind of get some of the lifecycle stuff now, too - I definitely need to watch it a couple more times over the rest of the month to come back and pick up more</p> </blockquote> <blockquote> <p>I cannot figure out why it seems so hard to map through stuff in Rust; I must be doing something really wrong or doing things in a way that isn't idiomatic</p> </blockquote> <h4>Searches</h4> <p>You may notice that many of the search strings are mostly error messages that are getting a little more complex - not sure what the takeaway from that is just yet.</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">a value of type `&amp;str` cannot be built from an iterator over elements of type `&amp;str` consider introducing a named lifetime parameter: `&lt;&#39;a&gt;`, `&#39;a `, `&#39;a `, `&#39;a `, `&#39;a ` this function&#39;s return type contains a borrowed value, but the signature does not say which one of `pockets`&#39;s 3 lifetimes it is borrowed from a value of type `Vec&lt;&amp;str&gt;` cannot be built from an iterator over elements of type `Vec&lt;&amp;str&gt;` the trait `FromIterator&lt;T&gt;` is implemented for `Vec&lt;T&gt;` rust vector remove duplicates rust usize to i32 rust expected slice `[&amp;str]` found tuple `(_, _, _)` refutable pattern in function argument cannot return value referencing local variable</code></pre></div> <h4>Next Steps</h4> <ol> <li>Figure out if Vectors are even the right approach for this kind of thing; I think I'm doing it wrong</li> <li>Revisit the ownership thing again - it still hasn't sunk in yet</li> <li>Look into lifetimes more, I sort of understand why I needed to add a named lifetime (like <code class="language-text">&lt;&#39;a&gt;</code>) but it's still kind of unclear, too</li> </ol> <p><a href="#challenges">Back to List of Challenges</a></p> <p><a id="day-four"></a></p> <h2>Day Four</h2> <p><a href="https://adventofcode.com/2022/day/4">Day Four</a> has us converting some strings into number ranges and seeing if they overlap completely.</p> <p>I started off the day by trying to clean up <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/main.rs">my very naive approach</a> to the <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/days/day_one.rs#L41-L46">two parts of a puzzle per day</a> pattern and think about <a href="https://github.com/ericrallen/advent-of-code/blob/main/2022/advent/src/lib.rs#L26-L63">a more Object-oriented approach to setting up each day's solution</a>, but ended up deciding I didn't quite grok enough of the language's idioms yet and decided to keep pushing forward with the current status quo for now.</p> <p>I also wanted to switch from the <code class="language-text">cargo run --features test</code> approach that I took and use the built-in <a href="https://doc.rust-lang.org/book/ch11-01-writing-tests.html"><code class="language-text">#[cfg(test)]</code></a> functionality so that I can just run <code class="language-text">cargo test</code>, but will tackle that another day.</p> <h3>Real Talk</h3> <p>Example Input:</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">2-4,6-8 2-3,4-5 5-7,7-9 2-8,3-7 6-6,4-6 2-6,4-8</code></pre></div> <p>Once again we're doing a lot of splitting of strings here. We could probably do something with a Regular Expression if we wanted to, but I'm not ready to dig into if/how RegEx is handled in Rust just yet, so we'll probably naively:</p> <ol> <li>Split on <code class="language-text">&quot;\n&quot;</code></li> <li>Split on <code class="language-text">&quot;,&quot;</code></li> <li>Split on <code class="language-text">&quot;-&quot;</code></li> <li>Create a range for each number sequence</li> <li>Check both ranges to see if either fully contains the other</li> </ol> <p>The second part introduces another common Advent of Code puzzle trope: Switching between a complete and partial match. So we just need to flip our <code class="language-text">.all()</code> to a <code class="language-text">.any()</code> and we're good to go.</p> <h4>Takeaways</h4> <p>The first part of this one gave me a chance to try to apply what I have learned so far and the second part gave me an opportunity to refactor and make my code more reusable, but I was lazy and just duplicated it instead of trying to follow the Don't Repeat Yourself (<a href="https://www.digitalocean.com/community/tutorials/what-is-dry-development">DRY</a>) principle and clean things up.</p> <h4>Notes</h4> <blockquote> <p>I was able to do this all without too much trouble, but the code is definitely not what I would like it to be.</p> </blockquote> <blockquote> <p>I actually felt like I kind of knew what I was doing this time. That might be some progress.</p> </blockquote> <h4>Searches</h4> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">rust struct // still haven&#39;t mentally accepted this one, I guess rust default function argument value rust check if two vectors contain same elements rust create array from range</code></pre></div> <h4>Next Steps</h4> <ol> <li>Should really be using <code class="language-text">cargo test</code> instead of the <code class="language-text">cargo run --features test</code> approach</li> <li>Would love to use more of the language's features (<code class="language-text">struct</code>s, <code class="language-text">enum</code>s, <code class="language-text">trait</code>s, etc.)</li> <li>Need to learn more about handling <code class="language-text">Option&lt;T&gt;</code> types and best practices for when and how to <code class="language-text">unwrap()</code> them idiomatically</li> </ol> <p><a href="#challenges">Back to List of Challenges</a></p> <p><a id="day-five"></a></p> <h2>Day Five</h2> <p>Well, that escalated quickly. <a href="https://adventofcode.com/2022/day/5">Day Five</a> introduces another Advent of Code trope: data visualization.</p> <p>I started off thinking about making one of those fancy data viz solutions you see on the <a href="https://www.reddit.com/r/adventofcode/">subreddit</a>, but decided that I should probably just catch up to the current day first instead.</p> <h3>Real Talk</h3> <p>Example Input:</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text"> [D] [N] [C] [Z] [M] [P] 1 2 3 move 1 from 2 to 1 move 3 from 1 to 3 move 2 from 2 to 1 move 1 from 1 to 2</code></pre></div> <p>This one is a bit more challenging because we have to parse the input in multiple different ways. We need to understand the total number of stacks we are dealing with and which item is in which stack while also parsing the instructions for moving items from one stack to another.</p> <p>Breaking this down we're going to want to:</p> <ol> <li>Split on <code class="language-text">&quot;\n\n&quot;</code> to separate the stack visualization from the instructions</li> <li>Pop the stack numbers from the stack visualization so we know how many stacks we need to keep track of</li> <li>Parse the crates in each stack</li> <li>Parse each instruction and manipulate our stacks</li> </ol> <p><strong>Note</strong>: One thing I've learned over the years with Advent of Code is that you can simplify and reduce your chance of bugs by just inserting an empty item as the first element in your Arrays when you are dealing with things indexed at <code class="language-text">1</code> like these stacks of crates. Rather than having to constantly convert indices, you can just go with what's written and then filter out the empty item at the end if necessary.</p> <p>And part two has us pulling multiple containers off the stack instead of doing them one by one, which is similar to the Advent of Code trope from <a href="#day-four">Day Four</a>, except this one has to do with moving from processing a stack as individual items to processing it as groups of items. Luckily most of the logic is still the same.</p> <h4>Takeaways</h4> <p>The most challenging part of this one was actually parsing the initial stack state correctly. It also introduced another Advent of Code trope: the reduced example case doesn't have edge cases that your real input might have (like multiple empty spots in a row so it isn't quite as easy to make sure you put the right crate on top of the right stack).</p> <h4>Notes</h4> <blockquote> <p>This one ramped up the complexity a good bit; there usually seems to be a bit of a hockey stick in terms of the difficulty scaling - and that's often reflected in the decreasing number of stars awarded.</p> </blockquote> <blockquote> <p>Let myself get too behind by overthinking and messing this one up at first</p> </blockquote> <h4>Searches</h4> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">// I ended up not using this one rust update output in console // stuff I actually used rust regular expressions rust for in get index rust iterate n times rust remove first item from array rust can&#39;t compare `&amp;str` with `str` rust borrowed value does not live long enough rust compar char to str</code></pre></div> <h4>Next Steps</h4> <ol> <li>Should <strong>really</strong> switch to using <code class="language-text">cargo test</code> instead of the <code class="language-text">cargo run --features test</code> approach I ended up with</li> <li>Get better at making reusable functions for this stuff (I've been avoiding it due to some lifetime and ownership issues) so that these kind of day two slight tweaks can just be a new function or parameter to an existing function instead of repeating so much code</li> </ol> <p><a href="#challenges">Back to List of Challenges</a></p> <p><a id="wrapping-up"></a></p> <h2>Wrapping Up</h2> <p>Five days down; twenty to go.</p> <p>I feel like I've already learned a lot and am starting to feel more comfortable and less frustrated with the language, but I know there's a long way to go before I'll be writing idiomatic Rust, much less efficient Rust.</p> <p>I've always tried to follow the <a href="https://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast">"Make it work. Make it Right. Make it Fast."</a> philosophy, and feel like I'm definitely still in the <code class="language-text">Make it work.</code> phase and probably won't make it to the <code class="language-text">Make it fast.</code> phase during this exercise, but that's okay.</p><![CDATA[Advent of Rust]]>https://ericrallen.dev/blog/advent-of-rust-2022https://ericrallen.dev/blog/advent-of-rust-2022Fri, 02 Dec 2022 20:26:39 GMT<p><strong>Last Updated</strong>: 2022-12-07</p> <p><a href="https://www.rust-lang.org/">Rust</a> always <a href="https://stackoverflow.blog/2020/01/20/what-is-rust-and-why-is-it-so-popular/">sounded</a> <a href="https://blog.logrocket.com/why-is-rust-popular/">pretty</a> <a href="https://www.sheshbabu.com/posts/rust-wasm-yew-single-page-application/">cool</a>, but then I always heard you had to read this book to actually learn it.</p> <p>I like reading, but I don't learn that way. I'm an <a href="https://www.niu.edu/citl/resources/guides/instructional-guide/experiential-learning.shtml#:~:text=%E2%80%9CExperiential%20%5Blearning%5D%20is%20a,Association%20for%20Experiential%20Education%2C%20para">experiential learner</a> and I really like to just get hands on with something when I'm first trying to understand it.</p> <p>So, I decided to just dive in and tackle <a href="https://adventofcode.com/2022">2022's Advent of Code</a> using Rust.</p> <p>After I grasp the basics of something and I can decide if I'm interested in pursuing it further, I circle back to research and reading to get a better understanding.</p> <p>This series of posts will document my trials, tribulations, successes, failures, and <a href="https://en.wikipedia.org/wiki/Eureka_(word)#Archimedes">"Eureka!" moments</a> in hopes that you may gain some insight into this journey if you decide to follow a similar path.</p> <p>The goal here is to stay in the <a href="https://www.simplypsychology.org/Zone-of-Proximal-Development.html">Zone of Proximal Development</a> long enough to grok the language well enough to start digging into slightly more advanced topics and <a href="https://hamre-erik.medium.com/desirable-difficulty-why-you-should-make-learning-more-difficult-on-purpose-c65223046d6b">reinforce all of the learning</a> with spaced repetition (daily coding challenges) and increasing complexity.</p> <p><strong>Disclaimer</strong>: There is a chance that I will not make it to Day 25 Part 2 - I have never completed a full Advent of Code calendar in the past.</p> <p><a id="table-of-contents"></a></p> <h2>Table of Contents</h2> <p>Due to the ongoing nature of this post's updates, here are some quick links to relevant top-level sections in case you want to skip straight to a specific day.</p> <p><a id="sections"></a></p> <h3>In This Post</h3> <ul> <li><a href="#series">Series</a></li> <li><a href="#getting-started">Getting Started</a></li> <li><a href="#resources">Resources</a></li> <li><a href="#conclusion">Conclusion</a></li> </ul> <p><a id="Posts"></a></p> <h4>Series</h4> <p>This post serves as a hub with links to the rest of the posts in the series, some general information about the journey, my first impressions with Rust, and links to some resources I've found super helpful as a wannabe <a href="https://www.rustaceans.org/">rustacean</a>.</p> <p><strong>Posts</strong>:</p> <ul> <li><a href="https://ericrallen.dev/blog/advent-of-rust-2022-pt-i">Part I: Days 1-5</a></li> <li><a href="https://ericrallen.dev/blog/advent-of-rust-2022-pt-ii">Part II: Days 6-10</a></li> <li>Part III: Days 11-15: <em>Coming Soon.</em></li> <li>Part IV: Days 16-20: <em>Coming Soon.</em></li> <li>Part V: Days 21-25: <em>Coming Soon.</em></li> </ul> <p><a id="background"></a></p> <h2>Background</h2> <p>For some context about me to help you understand how I'm approaching this and if this approach might work for you, too:</p> <ul> <li>I'm a developer (currently working as a Developer Advocate) with just over a decade of professional experience and I've been programming as a hobby for a little over 20 years.</li> <li>In the past I've played around with all sorts of languages (<em>roughly in order: HTML, CSS, Visual Basic, Java, ActionScript, PHP, Ruby, Objective-C, Swift, JavaScript, Bash, TypeScript, Solidity, and Python</em>), but my primary focus has been JavaScript/Typescript.</li> <li>I've liked a few things about a lot of languages, but haven't found one that resonates with me like TypeScript has.</li> <li>I don't remember much about most of the languages I've explored in the past because I always ended up returning to something more comfortable. </li> </ul> <p>Much like suddenly <a href="https://www.daskeyboard.com/blog/qwerty-vs-dvorak-vs-colemak-keyboard-layouts/">switching from QWERTY to Colemark</a> or <a href="https://betterprogramming.pub/should-you-learn-vim-as-a-developer-in-2020-75fde02c5443">VS Code to Vim</a>, I've rarely felt that the investment in learning an entirely new language, toolchain, and ecosystem is worth the time and effort.</p> <p>So, why am I interested in learning Rust then? It seems to be the next thing for Web Assembly and has an interesting programming model that I think will really challenge my understanding of programming and programming ability.</p> <p>So, why should you care? You probably shouldn't, but if you're interested in how to use coding challenges as a springboard for learning, getting some insight into how an experienced developer tackles learning a new language, or just want to see that a senior developer also searches for a lot of the same things that a junior developer does then you might find this post interesting.</p> <p><a id="github-repository"></a></p> <h2>GitHub Repository</h2> <p><a href="https://www.olivercoding.com/2021-05-29-learning-in-open/">Learning in the open</a> only counts if you actually share it, right?</p> <p><strong>Repo</strong>: <a href="https://github.com/ericrallen/advent-of-code/tree/main/2022">https://github.com/ericrallen/advent-of-code/tree/main/2022</a></p> <p><a id="getting-started"></a></p> <h2>Getting Started</h2> <p>Anyone who has dealt with Python, Node, or Ruby versions knows that you probably shouldn't just install whatever language you wnat to work with without first researching the ecosystem and figuring out how people really manage versions, packages, etc. You <em>can</em> just install the default toolchain and go for it, but you'll eventually regret it.</p> <p>As I was searching for the right <a href="https://users.rust-lang.org/t/best-way-to-install-rust-on-os-x-rustup-or-brew/6362">package to install from Homebrew for this</a>, I learned the first thing that I <strong>love</strong> about Rust.</p> <p>Rust's default, recommended installation method, <code class="language-text">rustup</code> <a href="https://rust-lang.github.io/rustup/concepts/index.html">handles this for you</a> so that you don't need to figure out whether you should be using <code class="language-text">nvm</code> or <code class="language-text">volta</code> or <code class="language-text">pyenv</code> or <code class="language-text">poetry</code>.</p> <p>This instantly made the languages I have been using for years feel very outdated.</p> <p><a id="resources"></a></p> <h2>Resources</h2> <p>Here are some resources that I've found particularly enlightening throughout this journey (in roughly the order that I found them in):</p> <h3>Documentation</h3> <ul> <li><a href="https://rust-lang-nursery.github.io/rust-cookbook/intro.html">Rust Cookbook</a>: <em>there are a lot of helpful examples in here</em></li> </ul> <h3>Blog Posts</h3> <ul> <li><a href="https://blog.logrocket.com/how-to-organize-your-rust-tests/">How to Organize Your Rust Tests</a>: <em>LogRocket always kills it with the content</em></li> </ul> <h3>Videos</h3> <ul> <li><a href="https://youtu.be/br3GIIQeefY">Rust for the Impatient</a></li> <li><a href="https://youtu.be/5C_HPTJg5ek">Rust in 100 Seconds</a></li> <li><a href="https://youtu.be/oY0XwMOSzq4">Rust is Boring</a></li> <li><a href="https://youtu.be/TJTDTyNdJdY">Rust Demystified</a>: <em>this one is amazing</em></li> </ul> <p><a id="conclusions"></a></p> <h2>Conclusions</h2> <p>Below are some conclusions I've come to during this journey (along with the date that I came to that conclusion just in case my thoughts change over time).</p> <ul> <li><strong>2022-12-02</strong>: Rust is pretty neat. I might actually like it.</li> <li><strong>2022-12-04</strong>: Fighting to get the right types (like <code class="language-text">&amp;str</code>, <code class="language-text">String</code>, <code class="language-text">char</code>, <code class="language-text">&amp;&amp;str</code>, etc.) more than I am actually programming. Hoping this is just like the initial hurdles I encountered switching from JavaScript to TypeScript.</li> <li><strong>2022-12-05</strong>: Like any language, it seems like it is not hard to write mediocre, naive implementations in Rust.</li> <li><strong>2022-12-06</strong>: Feeling a bit more comfortable. Adding in the overhead of keeping track of all the searches, righting down notes, and cirlcing back to the blog has definitely made this more of an undertaking than I thought it would be.</li> <li><strong>2022-12-07</strong>: What a roller coaster of emotion after messing up Day 5 and having to step back and come back to it later and then flying through Day 6. Rust is still pretty neat. I definitely might actually like it.</li> </ul><![CDATA[How I Interview Developers]]>https://ericrallen.dev/blog/how-i-interview-developers/https://ericrallen.dev/blog/how-i-interview-developers/Sat, 29 Jan 2022 21:15:07 GMT<p>I'd like to talk about interviewing.</p> <p>I know what you're thinking:</p> <blockquote> <p>Another blog post about hiring developers? Don't we have enough of those already?</p> </blockquote> <p>We probably do, but I've spent a lot of time on both sides of the interview table lately and I get asked about interviewing often enough that I thought I should try to consolidate some of my thoughts and share them here.</p> <p><strong>Disclaimer</strong>: This post only reflects my personal approach to interviewing and does not necessarily reflect the thoughts of any past, present, or future employers.</p> <h2>Why Might You Consider Listening to Me?</h2> <p>If you don't know me (thanks for reading this, internet stranger!), you're probably also wondering why I think I'm qualified to talk about this subject. </p> <p><strong>Note</strong>: If you don't care about any of that and just want to see what questions I ask, you can skip to <a href="#my-interview-questions">My Interview Questions</a>.</p> <p>I have interviewed well over a thousand developers for front end and full stack positions in my last few roles - one role in particular involved over 500 interviews over the course of a year for positions across various front end teams and physical locations - 60 of those were in a single week during a "hiring blitz."</p> <p>As much time as I've spent interviewing candidates, I've spent even more time reading about interviews; talking about interviews with other developers, recruiters, managers (pretty much anyone who will talk with me about them); and refining my approach. Several of my employers have also had extensive interview training related to <a href="https://www.indeed.com/career-advice/interviewing/how-to-prepare-for-a-behavioral-interview">behavioral interviewing</a> and <a href="https://www.linkedin.com/pulse/mega-blog-mini-guide-inclusive-recruitment-dana-kohava-segal/">inclusive interviewing</a>, though I am by no means an expert in either.</p> <p>At this point in my career, I feel confident saying that I am a good interviewer. Candidates seem to have a good experience - so much so that I've even received thank you messages from candidates that we didn't end up hiring.</p> <p>Here's an actual message I received from a candidate we did not hire after an interview in 2018:</p> <blockquote> <p>Hey! Thanks for the swell interview experience the other day! :)</p> </blockquote> <p>I share all of this with you not to inflate my own ego, but to hopefully establish some credibility with you and show you that I've been putting in the work when it comes to interviews.</p> <p>If you still aren't sure about me, that's cool - I get it. I have provided some links to great posts from lots of other people you might want to listen to instead in <a href="#further-reading">Further Reading</a>.</p> <p><strong>Disclaimer</strong>: I do have to confess that I wasn't always a good interviewer. In fact, I started out as a pretty bad one who fumbled through dozens of interviews before starting to understand there was a problem and wanting to fix it. If you're one of those unlucky candidates I interviewed early on, I'm sorry - hit me up if you ever want help preparing for another interview, a resume review, or just to tell me how bad I was at it. If I have interviewed you recently and you want to refute my assertions that I'm a good interviewer, feel encouraged to reach out - I genuinely want to hear from you.</p> <h2>The Interview</h2> <p>I prefer to schedule one hour if the candidate has that much time free, but this same interview can be performed in 45ish minutes with some practice on knowing how long you can let a candidate take to answer and how long you can take to respond to questions, but you may have to cut out a few things.</p> <p>This can also be condensed to 30ish minutes once you've got a really good feel for the timing of everything, but it leaves significantly less time for conversation and for the interviewee to ask questions, and ultimately provides a less optimal experience for everyone involved. Shorter interview windows generally leave the candidate with less time to ask their own questions. I always prefer to schedule a longer interview and end early if we're both out of questions than to schedule a short one and end with either of us having unanswered questions.</p> <p>While this isn't necessarily always the order or the exact wording of the questions I ask, what I'm outlining below is pretty close to the interview experience that every developer <em>should</em> have with me.</p> <p>Some roles or candidates involve digging into other topics a little more deeply or a candidate's answer may provide an interesting segue to learn more about them or may answer another question I was going to ask, etc. This means things change in small ways here and there, but the goal is to give everyone a similar experience that helps enable them to feel comfortable and present the best version of themselves. Interviews are already stressful situations (even for experienced interviewees) so there's no need to push anyone towards a panic attack.</p> <p><strong>Aside</strong>: I did actually have a candidate start to have a mild panic attack once - it was during that "hiring blitz" I mentioned earlier. It all turned out okay, but it really solidified for me just how stressful these things can be.</p> <p>While you can't always avoid it, I try not to take too many notes during the discussion. Just some high-level bits and then I flesh them out after. You really want to engage with the candidate as another human being and that requires listening and actively participating in the conversation. If something feels really important and you want to make sure you capture it, ask the candidate if they are okay pausing for a few seconds so you can write it down correctly and then get back to the conversation.</p> <h2>My Interview Questions</h2> <p><a id="my-interview-questions"></a></p> <p>I break a basic interview into roughly 6 parts:</p> <ol> <li> <p><strong>Introduction</strong> (<em>1-2 minutes</em>): set expectations</p> <ul> <li>Make sure it's still a good time and the candidate is free for the scheduled duration. You should also find out if they have a hard stop at the end and let them know if you do - sometimes interview discussions go out of the original timebox and that's okay if it's a good conversation and interviewer and interviewee are equally engaged.</li> <li>Basic introduction: just your name, role, and how long you've been with the company; anything more is wasting time - the candidate can ask if they are curious.</li> <li>This will be a conversational interview; questions, follow-up questions, and back and forth discussion are all encouraged - due to time constraints, we may need to move on from a topic, but we can circle back or follow up in email.</li> <li>There are no right or wrong answers.</li> <li>There will be time for their questions near the halfway point and again at the end.</li> <li>Don't hesitate to ask for clarification or more explanation.</li> <li><strong>Protip</strong>: Let them know upfront if you might have to mute a bunch because your dog somehow knows when you're interviewing and sometimes decides to be as annoying as possible during interviews</li> </ul> </li> <li> <p><strong>Interviewer Questions Round 1</strong> (<em>15-30 minutes</em>): This section has some easy getting started questions and then some specific behavioral interview questions.</p> <ol> <li> <p>Tell me briefly about a project you've been working on in the last 6-12 months. What tech stack have you been using?</p> <ul> <li>There's no need to get into everything a candidate has done throughout their career - you've seen their resume and/or LinkedIn, right? - just get into what they've been doing lately as that's generally the most relevant.</li> <li><strong>Protip</strong>: You may need to stop the candidate if they go too long on this one; about 5 minutes should be the upper bound, but 2-3 minutes is ideal.</li> </ul> </li> <li> <p>What kind of role are you looking for? Are there any other experiences you'd like to highlight that you think would make you successful in that role?</p> <ul> <li>This gives them a chance to describe what they are looking to do in their next role and also gives you a deeper dive into any other experience they have that might be relevant.</li> </ul> </li> <li> <p>What technologies are you looking to work with? Are there any you would specifically like to avoid working?</p> <ul> <li>Avoiding some tech is totally okay. Sometimes a specific language, framework, etc. just isn't our thing. I avoid Java and Ember because I just don't really like or fully grok them.</li> </ul> </li> <li> <p>Tell me about a project where you feel like you really succeeded. What about your contribution to that project made it so successful?</p> <ul> <li>Let them tell you about that time they totally crushed it. This is a chance to ask more questions and dig deeper into what they did, how they did it, and what they feel they are bringing to the table.</li> </ul> </li> <li> <p>Tell me about a project where you feel like you failed. What happened? What, if anything, would you do differently now?</p> <ul> <li>Everyone has struggled on a project at some point. It's okay to fail as long as you learn something from it. (Ask me how I know you always need to back up the production database.) This is a chance for the candidate to be a little vulnerable, show how they take (or shift) responsibility, and how they've learned from past mistakes.</li> <li>Some people won't feel comfortable talking about failure, so if someone gives you a non-commital answer you may need to probe deeper for an actual real-world example. Be sure to let them know that failure is a thing that happens to all of us and they don't have to incriminate themselves for taking down <code class="language-text">us-east-1</code>, but we want to hear about a situation where they learned from a mistake.</li> </ul> </li> <li> <p>Tell me about a conflict you had with a coworker, stakeholder, customer, etc. What happened? How did you resolve it? In hindsight, would you approach it differently?</p> <ul> <li>How do they approach conflicts? What do they do when they can't come to an agreement? No one wants conflict at work, but there are lots of times that we might disagree about how to approach solving some problem, how some business request degrades user experience, or how some user request is not possible given our current resources.</li> <li><strong>Protip</strong>: This could be a good time to reflect on how your current team approaches conflict and maybe briefly discuss it with the candidate in relation to their answer.</li> </ul> </li> </ol> </li> <li> <p><strong>Candidate Questions Round 1</strong> (<em>5-10 minutes</em>): This is a good time to shift gears and let the candidate ask some questions - remember this is as much a chance for them to interview the company as it is for the company to interview them.</p> <ul> <li>Engage as openly and honestly with the candidate as you can. Try not to ramble and to answer questions concisely. After you've done a lot of interviews, you'll start to refine the answers to certain questions and find that you've got certain responses ready.</li> <li><strong>Protip</strong>: To avoid rambling, sometimes I start a stopwatch and glance at it every so often while answering a question so I know how long I've been talking. Remember, this is the candidate's time to learn about the company, and the longer you spend answering one question the less time they have to ask other questions.</li> </ul> </li> <li> <p><strong>Interviewer Questions Round 2</strong> (<em>10-15 minutes</em>): This section gets into some more technical interview questions and also allows you a chance to dig deeper into any follow-up questions you want to ask based on anything that's been talked about so far.</p> <ol> <li> <p>Tell me about an interesting or particularly challenging problem you solved in the last 3-6 months. What made this problem interesting? How did you approach solving it?</p> <ul> <li>This gives the candidate another chance to show off their skillset and talk about it passionately. You can probe deeper into any specifics around this and just sort of talk about it with them a bit.</li> </ul> </li> <li> <p>Tell me about a tradeoff you had to make in the last 6-12 months. What were the options? How did you choose between them?</p> <ul> <li>A lot of what we do involves managing tradeoffs: performance vs readability, faster delivery vs future maintainability, abstraction vs repetition, etc. This is a chance to dig into how the candidate thinks about these things and how they navigate the often nebulous waters around this kind of decision-making.</li> </ul> </li> <li> <p><strong>Follow-Up Questions</strong>: if you have anything you want to expand on based on your conversation with the candidate so far, this is the time for that. Want to hear more about how they used AWS for a project? Did they mention navigating a rewrite at a large company and you want to hear more about the planning and execution? Dig in a little.</p> </li> <li> <p><strong>For Senior-ish Roles</strong>: Pretend that I'm a junior developer without much context and explain <code class="language-text">[insert topic here]</code> to me.</p> <ul> <li> <p>Some Example Topics (pick something relevant to the candidate's actual day-to-day work and previous experience, and, it should go without saying, but make sure you are comfortable with the topic):</p> <ul> <li><a href="https://launchdarkly.com/blog/what-are-feature-flags/">Feature Flags</a></li> <li><a href="https://www.redhat.com/en/topics/devops/what-is-blue-green-deployment">Blue/Green Deployments</a></li> <li><a href="https://www.optimizely.com/optimization-glossary/abn-testing/">A/B/N Testing</a></li> <li><a href="https://css-tricks.com/specifics-on-css-specificity/">CSS Specificity</a></li> <li><a href="https://developer.mozilla.org/en-US/docs/Glossary/Scope">Scope in JavaScript</a></li> <li><a href="https://www.freecodecamp.org/news/the-model-view-controller-pattern-mvc-architecture-and-frameworks-explained/">Model-View-Controller (MVC)</a>, <a href="https://www.raywenderlich.com/34-design-patterns-by-tutorials-mvvm">Model-View-ViewModel (MVVM)</a>, or some other pattern relevant to their past work or your codebase</li> <li><a href="https://en.wikipedia.org/wiki/Functional_programming">Functional Programming</a>, <a href="https://en.wikipedia.org/wiki/Object-oriented_programming">Object-Oriented Programming</a>, or any other programming paradigm that might be relevant to their past work or your codebase</li> <li><a href="https://www.atlassian.com/continuous-delivery/principles/continuous-integration-vs-delivery-vs-deployment">Continuous Integration / Continuous Deployment (CI/CD)</a></li> <li><a href="https://www.splunk.com/en_us/data-insider/what-are-serverless-functions.html">Serverless Functions</a> (<a href="https://docs.aws.amazon.com/lambda/latest/dg/welcome.html">AWS Lambda</a>, <a href="https://docs.microsoft.com/en-us/azure/azure-functions/">Azure Functions</a>, <a href="https://cloud.google.com/functions/docs">Google Cloud Functions</a>, etc.)</li> <li><a href="https://www.cloudflare.com/learning/cdn/what-is-caching/">Caching</a></li> <li><a href="https://www.docker.com/resources/what-container">Containers</a></li> </ul> </li> </ul> </li> <li> <p><strong>For Junior-ish Roles</strong>: What language, library, framework, etc. are you looking forward to learning and working with in the near future? What tech is exciting to you right now?</p> </li> </ol> </li> <li> <p><strong>Candidate Questions Round 2</strong> (<em>remaining time minus 30 seconds to a minute</em>)</p> </li> <li> <p><strong>Wrap Up</strong> (<em>30 seconds-1 minute</em>)</p> <ol> <li>Inform the candidate of the process from here and about how long they should expect to wait before hearing back. I also always let them know that if there is a bottleneck in the process, it is almost certainly my fault and not the fault of our internal recruiters.</li> <li>Let them know that they can email you (or their recruiting contact) if they think of any more questions.</li> <li>Thank them for their time.</li> <li><strong>Protip</strong>: Take a few minutes after the interview to compile your initial thoughts and shoot them over to your recruiting partner. If you need to think on it a little more, save that email as a Draft and set a reminder for a couple of hours - hiring is crazy right now, if you wait too long, you could easily lose that candidate.</li> </ol> </li> </ol> <h2>Why This Approach</h2> <p>There are several benefits to this approach:</p> <ul> <li><strong>Human-Centered</strong>: It treats candidates as humans, and as equal participants in a conversation.</li> <li><strong>Hard to Game</strong>: There isn't really any coaching that can prepare someone for this interview. I've worked with a lot of recruiters and consulting firms over the years and sharing knowledge about interview questions always comes up when you're the interviewee. With these questions, you could do something like publish them on the Internet for everyone to see, and it would have no effect on the efficacy of the interview.</li> <li><strong>Enjoyable</strong>: I might be personally biased on this one, but as the interviewer, I enjoy this kind of conversation a lot more than pop quiz style interviews I've been asked to conduct in the past. As I mentioned already, candidates seem to enjoy this interview process, too.</li> </ul> <p>There are some possible drawbacks, too:</p> <ul> <li><strong>Time-Consuming</strong>: If you are in a high-throughput recruiting situation (at one point I was reviewing 30-40 resumes a day for dozens of open positions), you won't have the time to engage with each person at this level and might need to introduce something that creates a quicker filter before this kind of interview. You might also want to work on improving the quality of your filter at the application stage, resume review stage, and any initial recruiter call that might happen after a resume has been reviewed.</li> <li><strong>Not Directly Technical</strong>: You only learn as much about a candidate's technical ability as you are comfortable digging into during the discussion. Some people will maintain that you need to put a candidate through some kind of whiteboard question where they are put on the spot to write code in a context that is entirely unlike their normal work, and they <em>could</em> be right.</li> </ul> <h2>Further Reading</h2> <p><a id="further-reading"></a></p> <p>Here are some articles about interviewing that I've found insightful and some that have challenged my beliefs about interviewing, too.</p> <ul> <li><a href="https://qz.com/258066/this-is-why-you-dont-hire-good-developers/">This is why you never end up hiring good developers</a></li> <li><a href="https://www.joelonsoftware.com/2006/10/25/the-guerrilla-guide-to-interviewing-version-30/">The Guerrilla Guide to Interviewing</a></li> <li><a href="https://fossbytes.com/tech-job-interview-assess-performance-anxiety-instead-of-coding-skills-report/">Tech Job Interviews Assess Performance Anxiety Instead Of Coding Skills</a></li> <li><a href="https://www.jarednelsen.dev/posts/The-horrifically-dystopian-world-of-software-engineering-interviews">The Horrifically Dystopian World of Software Engineering Interviews</a></li> <li><a href="https://sockpuppet.org/blog/2015/03/06/the-hiring-post/">The Hiring Post</a></li> <li><a href="https://hiringsuccess.com/human-centered-design-is-the-key-to-better-hiring/">Human-centered design is the key to better hiring</a></li> <li><a href="https://fulcrum.lever.co/a-better-way-to-interview-software-engineers-fa9b5d2b5316">A better way to interview software engineers</a></li> <li><a href="https://leaddev.com/hiring-onboarding-retention/fixing-neutral-hiring-policies-stop-excluding-best-candidates">Fixing ‘neutral’ hiring policies to stop excluding the best candidates</a></li> <li><a href="https://thenewstack.io/how-to-make-tech-interviews-suck-less/">How to Make Tech Interviews Suck Less</a></li> <li><a href="https://www.freecodecamp.org/news/why-is-hiring-broken-it-starts-at-the-whiteboard-34b088e5a5db/">Why is hiring broken? It starts at the whiteboard.</a></li> <li><a href="https://www.hrdive.com/news/is-culture-fit-code-for-bias-recruiters-must-be-wary-experts-say/507272/">Is 'culture fit' code for bias? Recruiters must be wary, experts say</a></li> <li><a href="https://karat.com/blog/post/inclusive-hiring-best-practices-for-software-engineering-leaders/">Inclusive hiring: 5 best practices for software engineering leaders</a></li> <li><a href="https://par.nsf.gov/servlets/purl/10139106">Hiring is Broken: What Do Developers Say About Technical Interviews?</a></li> <li><a href="https://glenmccallum.com/2019/05/14/senior-developers-rejected-jobs/">Senior Developers are Getting Rejected for Jobs</a></li> <li><a href="https://blog.plan99.net/in-defence-of-the-technical-interview-966f54a58927">In defense of the technical interview</a></li> <li><a href="https://www.techrepublic.com/article/coding-interviews-are-terrible-can-we-make-them-better/">Coding interviews suck. Can we make them better?</a></li> <li><a href="https://medium.com/@Johnmont_67962/rethinking-how-we-interview-in-microsofts-developer-division-8f404cfd075a">Rethinking how we interview in Microsoft’s Developer Division</a></li> </ul><![CDATA[Introducing @RSS bot]]>https://ericrallen.dev/introducing-rss-bothttps://ericrallen.dev/introducing-rss-botSat, 25 May 2019 12:50:06 GMT<p>We have a lot of developers working in different places at different times at <a href="https://skookum.com/">Skookum</a>. People are sharing interesting, useful, and/or important articles at various times throughout the day. Unfortunately a lot of that content is missed by the majority of developers.</p> <p>Enter <a href="https://www.rssbot.app/">@RSS bot</a>, a Slack bot that will generate an RSS feed of links shared in channels it is invited into.</p> <p>Every time a user shares a link in a channel it is listening to @RSS bot will ask that user if they would like to add the link to the channel's RSS feed, so users have control over what appears in their RSS feed.</p> <p>Are you tired of missing links shared in your Slack channels?</p> <p><a href="https://www.rssbot.app/">Get @RSS bot today</a>!</p><![CDATA[Senior Developers]]>https://ericrallen.dev/blog/senior-developershttps://ericrallen.dev/blog/senior-developersSun, 03 Mar 2019 14:19:16 GMT<p>While I don't care about title inflation or title absurdity, I do care about what the people doling out and receiving some of these titles assume that they mean.</p> <p>One title modifier, in particular, Senior, is important to me, not because I have it, but because without people who embody its <em>Core Principle</em> I wouldn't be where I am today.</p> <p>I wouldn't be able to help others get here if that principle hadn't been instilled in me.</p> <h2>Meaningless Titles</h2> <p>In an industry where two people can do the same job, but one is an Engineer while the other is a Ninja, I think it's safe to say that our titles are meaningless.</p> <p>Which is good. You could spend your whole career chasing ever-loftier titles. That way lies madness. Unfortunately, a lot of companies either use title changes in lieu of pay raises, or tie pay to titles in a way that requires doling out new ones or adding modifies (How many of you are a [Title] II or a [Title] III?) to them every 12-18 months.</p> <p>When I worked for Bank of America, my title was so long that they stripped almost all of the vowels from it and it also featured a hyphen (-) and a semicolon (;). Add to that the fact that basically every full-time employee who writes code is a "Vice President" and you end up with a silly VP title that means absolutely nothing and is impossible to explain to anyone.</p> <p>I don't have any solution for this insanity in our industry, and it's not really important to me that we change it, but I wanted to make sure that we covered how meaningless we've made all of our titles before I explain why Senior is actually important and why the meaninglessness we've created could lead to an industry-wide problem.</p> <p>It's also worth mentioning that the Engineer title is ridiculous given the generally ephemeral and fragile nature of what we build and the lack of any oversight or credentialing body, but that's a topic for a different rant.</p> <h2>The Senior Core Principle</h2> <p>A Senior Developer (or Engineer, Ninja, Rockstar, etc.) is not just someone who has more experience or one who is the lead on a team or a project.</p> <p>The Senior title comes with a vitally important responsibility: <strong>to make those around you better Developers</strong>.</p> <p>That responsibility is the <em>Core Principle</em> of the Senior and it is one that should span our entire industry. It is rarely listed in job descriptions, but it should be.</p> <p>What we see an alarming amount of today is Developers being put into Senior positions as the next logical step in their career progression or as some reward for sticking around. While this won't have a huge immediate impact, it will radiate through the following generations of developers and amplify the effect over time.</p> <p>When a Senior who embodies the <em>Core Principle</em> teaches the next generation of Senior developers, they go on to embody that principle and instill it in the following generation, too. Life is good.</p> <p>When a Senior who only has the title doesn't instill that principle in the next generation - or, even worse, instills the idea that Seniors are arrogant and unhelpful - then that idea trickles down and more arrogant, unhelpful Senior Developers will be created. Here there be dragons.</p> <p>If that eventually becomes the norm, how much more toxic would Developer culture become? How hard would it be for someone to transition into the field? How hard would it be for Junior developers to grow into Senior developers?</p> <p>If you're a Senior right now: <strong>What are you doing to make those around you better Developers?</strong></p> <h2>My Senior Philosophy</h2> <p>My approach to embodying this <em>Core Principle</em> involves several things, but the primary directive is trying to make time for other Developers to ask questions, talk through solutions, vent about clients, ask for code reviews, and ask about career advice.</p> <p>I always caveat that my code reviews and my advice may not always be the best solution, but they are what I would do and then provide the reasoning behind that decision. I've found that it helps people learn when you show your work, and it also invites the other Developer to question your thought process and provide their own insights on things you might be overlooking.</p> <p>In the service of making myself and other Developers better at what we do, I organized a few initiatives during my time at <a href="http://skookum.com/">Skookum</a> and continue to do similar things at every other place I work.</p> <ul> <li><strong>Monthly Coding Challenges</strong>: Every month we will tackle a new coding challenge and help keep each other motivated in a dedicated <code class="language-text">#coding-challenges</code> channel in Slack. Each challenge is different and allows a wide range of Developers to hone their skills.</li> <li><strong>Monthly Developer Presentations</strong>: Every month we will invite one of our developers to present a Web-related topic to the rest of the Development Team. Hopefully, this helps Developers iron out presentations for Meetups and conferences while also giving the rest of us some new perspectives.</li> <li><strong>Bi-Weekly Video Series</strong>: Every 2 weeks we watch a Web-related video and discuss it as a group. This was previously an initiative, but the developer who started it left the company, so a colleague and I resurrected it. This gives us a chance to experience conference talks we would otherwise miss out on and also facilitates conversation between Developers at all levels.</li> </ul>