<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Code Red - Medium]]></title>
        <description><![CDATA[The Redfin Engineering Blog - Medium]]></description>
        <link>https://medium.com/code-red?source=rss----1f8b86d56cad---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Code Red - Medium</title>
            <link>https://medium.com/code-red?source=rss----1f8b86d56cad---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 10:43:43 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/code-red" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[3 Lessons to Succeed as a New Software Engineer]]></title>
            <link>https://medium.com/code-red/3-lessons-to-succeed-as-a-new-software-engineer-6ccd7947a35a?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/6ccd7947a35a</guid>
            <category><![CDATA[software-engineer]]></category>
            <category><![CDATA[lessons]]></category>
            <category><![CDATA[new-grad]]></category>
            <category><![CDATA[reflections]]></category>
            <category><![CDATA[engineering]]></category>
            <dc:creator><![CDATA[Nathan Yang]]></dc:creator>
            <pubDate>Thu, 09 Sep 2021 00:41:57 GMT</pubDate>
            <atom:updated>2022-10-09T17:08:21.692Z</atom:updated>
            <content:encoded><![CDATA[<p>Even though I still feel like one sometimes, I’m no longer considered a new grad. As of the writing of this, it’s been two years since I <a href="https://nathan-yang.medium.com/5-reasons-why-i-loved-ucla-de9d0704126e">graduated from UCLA</a> and joined Redfin as a software engineer.</p><p>A lot has happened in that time: getting my first promotion, switching teams, winning a hackathon, and shipping a lot of great software. I’ve also been fortunate enough to have grown so much in an incredibly open and supportive environment at Redfin. Here are the biggest lessons I’ve learned so far, along with some advice for those early in their careers.</p><h3>🧠 Prioritize for impact, not perfection.</h3><p>Going into Redfin, I was very much in the student mentality where everything had to be done to perfection. As a student, the goal was to get A’s, but I quickly had to readjust my mindset since that’s not how things work in industry. There are often way more ideas than there are engineers to implement them so work should be prioritized and done based on potential impact.</p><p>This dilemma can manifest in several ways. One situation could be building a product with only a few features that solve an important problem rather than building all the features that were thought of. Another could be fixing a few bugs that account for the majority of a team’s errors rather than fixing the highest number of bugs possible. There’s always the opportunity to iterate and tackle the other work in the future.</p><p>There’s a principle called the 80/20 rule, also known as the <a href="https://en.wikipedia.org/wiki/Pareto_principle">Pareto Principle</a>, that was shared with me that’s especially relevant here. Essentially, the principle states that we should aim to deliver 80% of the value with 20% of the effort/time. This has helped me gauge priorities and reason what we should and shouldn’t work on.</p><p>Similarly for personal growth, prioritizing what you do so you’re making the highest impact on your areas of growth can help you meet your goals and get you to the next step in your career faster, whether that’s getting a promotion or that dream job. The next time you work on something, I challenge you to question whether it’s the most important thing you could be doing right now and whether you can re-prioritize your work to make the highest impact possible.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BxicUZhqtwEjo5EnDRd5Zw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VVu0FEM0ou8hV-Siu3hA0A.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9wXu5-fO4lYvnW2N0aGovQ.jpeg" /><figcaption>Snapshots from Redferno, our annual company-wide conference.</figcaption></figure><h3><strong>🙋 Don’t be afraid to ask questions, ever.</strong></h3><p>Don’t be afraid to ask questions, especially a lot of them. In school, students often work on assignments alone. But in industry, you’re on a team where teammates want to share their knowledge and help you succeed. It’s a collective effort to move the team, organization, and company forward. Your success is the team’s success, which is ultimately the company’s success.</p><p>For those early in their careers, this lesson is especially important. It’s okay and expected to not know everything. This is a great time to build up technical skills, learn about your interests and passions, and grow as an individual. Setting yourself up for success now will pay dividends years into the future.</p><p>My biggest regret from a past internship was not asking the company’s then-VP of Product for a 1:1 coffee chat, regardless of whether he would have accepted it. Back then, I was lucky enough to sit next to the company’s leadership team so I frequently saw VPs and C-level executives out and about. I actually ran into this person a handful of times in the hallway and politely smiled, but was always deathly afraid to start a conversation. Looking back, I would have loved to speak with him about his journey from being a designer to a product leader. This individual is <a href="https://www.instagram.com/mosseri/">Adam Mosseri</a>, who is now the Head of Instagram. Because of this experience, I’ve made it a personal goal of mine to ask people that I want to get to know better and learn from at Redfin for 1:1s and it’s led to some great conversations and friendships! (I’m looking at you, <a href="https://www.linkedin.com/in/hanzhu1/">Han Zhu</a> and <a href="https://www.linkedin.com/in/schiebel/">Austin Schiebel</a>!)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xbM_rTXKzvK5lc4kZQ8s_A.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JtR0z3yrmkCgr_zKgo1svQ.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Lo3vpeG27KzCl8BJ1vsKRQ.jpeg" /><figcaption>Left: the view from Redfin’s SF office. Middle: team birthday lunch! Right: a cake from a product launch celebration.</figcaption></figure><h3><strong>🖖 Embrace uncertainty.</strong></h3><p>In school, I was very used to everything being very defined for me. For some of my projects, professors would share software requirement documents (aka tech specs) that were up to <a href="https://github.com/thenathanyang/UCLA/blob/master/CS32/Projects/Project3/spec.pdf">50 pages long</a> describing every little detail that needed to be implemented. In industry, however, we don’t have that luxury.</p><p>The job of a software engineer includes doing technical investigations, gathering requirements, and writing tech specs. That also means frequently working with new and unfamiliar technologies and areas of the codebase. Simply put, dealing with uncertainty can be daunting. But fear not! Uncertainty is a great opportunity to try and learn new technologies and approaches.</p><p>Throughout college, I would avoid certain work because I wasn’t familiar with it. For example, as part of a group project in my full-stack web development class, I only worked on the Node.js backend while my friend worked on the Angular frontend. At the time, I only had backend experience and found writing frontend code daunting. I just didn’t think frontend development was for me, but I was so wrong.</p><p>At Redfin, I finally embraced the fact that I needed to learn how to write frontend code, specifically in React. After getting past the initial learning curve, I was pleasantly surprised by how much I actually enjoyed it! There was one particularly memorable moment when my teammates and I were looking at a screenshot and couldn’t tell whether it was a screenshot of the actual feature I implemented or the design in Figma.</p><p>Since then, I’ve had the opportunity to work with other interesting technologies such as GraphQL, Apache Kafka, Apache Samza, and Netflix Conductor!</p><p>Uncertainty isn’t a bad thing and can actually lead to a lot of opportunities. Being uncomfortable means you’re growing so embrace it!</p><p>Even though I’ve learned a lot during my two years with Redfin, I still have so much more to learn. I’ve only scratched the surface of what it means to be in industry. And even though I still feel like a new grad sometimes, I believe that just means that I’m still pushing myself to be uncomfortable and grow. Equipped with the lessons I’ve learned so far, I’m excited for what the future holds! 🚀</p><h3>Acknowledgements</h3><p>Everyone I’ve worked with at Redfin has contributed to my growth in some way and I’m thankful for that. However, there are a few individuals who have been incredibly impactful in my journey that I’d like to shout out. Big thanks to <a href="https://www.linkedin.com/in/donle/">Don Le</a>, <a href="https://www.linkedin.com/in/jiaqi-wang-sea/">Jiaqi Wang</a>, <a href="https://www.linkedin.com/in/eleanornesbit/">Eleanor Nesbit</a>, <a href="https://www.linkedin.com/in/tian-luo-7242323/">Tian Luo</a>, and <a href="https://www.linkedin.com/in/danehrman/">Dan Ehrman</a> for setting me up for success while I explored my career interests and eventually made the transition to product management.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ccd7947a35a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/3-lessons-to-succeed-as-a-new-software-engineer-6ccd7947a35a">3 Lessons to Succeed as a New Software Engineer</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PostgreSQL EXPLAIN Explained]]></title>
            <link>https://medium.com/code-red/postgresql-explain-explained-4a2d5c5e0ac5?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/4a2d5c5e0ac5</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[database]]></category>
            <dc:creator><![CDATA[Richa Sehgal]]></dc:creator>
            <pubDate>Mon, 28 Jun 2021 18:06:47 GMT</pubDate>
            <atom:updated>2021-06-28T22:22:31.705Z</atom:updated>
            <content:encoded><![CDATA[<h4>So, you want to make your queries fast?</h4><p>When a SQL statement is sent to a PostgreSQL server for execution, Postgres will decipher various parts of the query and define an execution plan in an attempt to retrieve and manipulate that data in the most effective way possible The great news is that you can view these plans to gain insight into how your queries are interpreted, and tune them to make your queries faster than ever!</p><p>Before diving into the query plans, it will be helpful to know your tables: the number of rows stored in the table (that Postgres might have to loop through), the columns which have indexes (so an index scan can be performed as opposed to sequential scan) and the typical way of querying the data.</p><h3>Examining <a href="https://www.postgresql.org/docs/9.1/sql-explain.html">Postgres EXPLAIN</a>, the Holy Grail of Query Optimization</h3><pre>EXPLAIN [ANALYZE] statement</pre><p>This command displays the execution plan that the PostgreSQL planner generates for the supplied statement. The execution plan shows how the table(s) referenced by the statement will be scanned — by plain sequential scan, index scan, etc. — and if multiple tables are referenced, what join algorithms will be used to bring together the required rows from each input table, plus any auxiliary steps needed, such as sort nodes or aggregate-function calculation nodes.</p><p>If you run EXPLAIN with ANALYZE option, the statement is not only planned but also executed. The total elapsed time expended within each plan node (in milliseconds) and total number of rows the query actually returned are added to the display. This is useful for seeing whether the planner’s estimates are close to reality.</p><h3>Let’s walk through a real example</h3><p>Let’s walk through a simple query involving three tables: <em>listings</em>, <em>search_keys</em>, and <em>markets</em>. The listings table is used to store data relevant to a listing, the search_keys table contains all the data needed for home search based on various filters, and the markets table stores information about a real estate market. The goal of the query is to find all rows in the <em>search_keys</em> table within a range of listing ids, which are also present in the <em>listings</em> table for a given <em>market</em> where country_code is null or US.</p><pre>EXPLAIN ANALYZE</pre><pre>SELECT</pre><pre>*</pre><pre>From</pre><pre>search_keys this_</pre><pre>LEFT OUTER JOIN listings listing1_ on this_.listing_id = listing1_.listing_id</pre><pre>LEFT OUTER JOIN markets market4_ on this_.primary_market_id = market4_.market_id</pre><pre>WHERE</pre><pre>listing1_.listing_id between 113115554 and 113125553</pre><pre>AND (listing1_.country_code is null or listing1_.country_code=&#39;US&#39;)</pre><p>The generated query plan looks like:</p><pre>QUERY PLAN</pre><pre>--------------------------------------</pre><pre>Hash Left Join  (cost=7.92..6981.79 rows=12762 width=8369) (actual time=2.375..473.754 rows=30 loops=1)</pre><pre>Hash Cond: (this_.primary_market_id = market4_.market_id)</pre><pre>-&gt;  Nested Loop  (cost=0.99..6829.09 rows=12762 width=1253) (actual time=1.880..473.134 rows=30 loops=1)</pre><pre>-&gt;  Index Scan using listings_pkey on listings listing1_  (cost=0.57..1196.67 rows=9273 width=827) (actual time=0.685..452.927 rows=9896 loops=1)</pre><pre>Index Cond: ((listing_id &gt;= &#39;113115554&#39;::bigint) AND (listing_id &lt;= &#39;113125553&#39;::bigint))</pre><pre>Filter: ((country_code IS NULL) OR (country_code = &#39;US&#39;::text))</pre><pre>Rows Removed by Filter: 104</pre><pre>-&gt;  Index Scan using search_keys_listing on search_keys this_  (cost=0.43..0.60 rows=1 width=426) (actual time=0.002..0.002 rows=0 loops=9896)</pre><pre>Index Cond: (listing_id = listing1_.listing_id)</pre><pre>-&gt;  Hash  (cost=5.89..5.89 rows=83 width=7116) (actual time=0.456..0.456 rows=83 loops=1)</pre><pre>Buckets: 1024  Batches: 1  Memory Usage: 271kB</pre><pre>-&gt;  Index Scan using markets_pkey on markets market4_  (cost=0.14..5.89 rows=83 width=7116) (actual time=0.003..0.176 rows=83 loops=1)</pre><pre>Execution time: 474.093 ms</pre><pre>(13 rows)</pre><p>The structure of the query is</p><pre>Hash Join</pre><pre>--&gt; Nested Loop Join</pre><pre>    --&gt; Index Scan on listings</pre><pre>    --&gt; Index Scan on search_keys</pre><pre>--&gt; Hash</pre><pre>    --&gt; Index Scan on markets</pre><p>The query involves three tables and the final result is built by a tree of join steps, each with two inputs. A nested loop join is performed on <em>listings</em> and <em>search_keys</em> table, the result of which is joined with the <em>markets</em> table using Hash join strategy. You can also view the query plan using <a href="https://tatiyants.com/pev/#/plans/new">Postgres Explain Visualizer (pev)</a> (shown below) or <a href="https://explain.depesz.com/">PostgreSQL’s explain analyze made readable</a> which makes the plan easier to grok.</p><p>The visualizer needs the plan in JSON format, so you will have to run EXPLAIN with FORMAT JSON option.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jcnkzGwoGNrALBPDs2w4yA.png" /></figure><p>Let’s dig deeper into each of these steps.</p><h3>Nested Loop Join</h3><p>The simplest of all join strategies, a nested loop join works by fetching the result from the left relation (<em>listings</em>), and for each row of the result, iterating over the right relation (<em>search_keys</em>) to find matching rows. Let’s look deeper at each row of nested loop join:</p><pre>Nested Loop (cost=0.99..6829.09 rows=12762 width=1253) (actual time=1.880..473.134 rows=30 loops=1)</pre><p>This node represents the action taken (“Nested loop”). The numbers that are quoted in the cost estimate (cost=0.99..6829.09 rows=12762 width=1253) are (left to right):</p><ul><li>Estimated start-up cost. This is the time (ms) at which this node can begin working.</li><li>Estimated total cost. This is stated on the assumption that the plan node is run to completion, i.e., all available rows are retrieved. In practice a node’s parent node might stop short of reading all available rows (see the LIMIT example below).</li><li>Estimated number of rows output by this plan node.</li><li>Estimated average width of rows output by this plan node (in bytes).</li></ul><p>Since we ran EXPLAIN with the ANALYZE option, the query was actually executed and timing information was captured with (actual time=1.880..473.134 rows=30 loops=1) in the plan node. The numbers depict the actual start up time (1.880 ms) when the node began execution, the total time taken for node to execute (473.134 ms), the number of rows returned by the node (30) and the number of times nested loop was executed 1 time (loops value).</p><p>In the case when a node is executed more than once, the actual time is an average of each iteration and we would multiply the value by the number of loops to get total time.</p><p>Next, let’s look at the sub actions for Nested Loop node.</p><pre>Index Scan using listings_pkey on listings listing1_ (cost=0.57..1196.67 rows=9273 width=827) (actual time=0.685..452.927 rows=9896 loops=1)</pre><pre>Index Cond: ((listing_id &gt;= ‘113115554’::bigint) AND (listing_id &lt;= &#39;113125553&#39;::bigint))</pre><pre>Filter: ((country_code IS NULL) OR (country_code = &#39;US&#39;::text))</pre><pre>Rows Removed by Filter: 104</pre><p>Postgres performs an index scan on the listings relation using listings_pkey as its scan key to fetch listing_id(s) that match the index condition. The index condition corresponds to the SQL where listing1_.listing_id between 113115554 and 113125553. The Filter condition shows the number of rows removed by filter condition (listing1_.country_code is null or listing1_.country_code=&#39;US&#39;)</p><p>Next, for each listing_id returned by the above step, postgres performs an index scan on search_keys to find matching rows.</p><pre>Index Scan using search_keys_listing on search_keys this_ (cost=0.43..0.60 rows=1 width=426) (actual time=0.002..0.002 rows=0 loops=9896)</pre><pre>Index Cond: (listing_id = listing1_.listing_id)</pre><p>The loops value reports the total number of executions of the node. The actual time and rows values shown are averages per loop execution. This is done to make the numbers comparable with the way that the cost estimates are shown. To get the total time and rows, the actual time and rows value need to be multiplied by loops values. However since postgres rounds up these averages, the actual row values are shown as zero.</p><p>The result of the nested loop action is joined with the markets table using hash join strategy.</p><h3>Hash Join</h3><p>This join strategy involves scanning the right relation first and loading it into a hash table, using its join attributes as hash keys. Next the left relation is scanned and the appropriate values of every row found are used as hash keys to locate the matching rows in the hash table.</p><pre>Hash Left Join (cost=7.92..6981.79 rows=12762 width=8369) (actual time=2.375..473.754 rows=30 loops=1)</pre><pre>Hash Cond: (this_.primary_market_id = market4_.market_id)</pre><p>The above node represents the estimated and actual cost of hash join of the result of nested loop join and markets.</p><p>Let’s look into the node which loads the <em>markets</em> relation to a hash table using <em>market_id</em> as its hash key.</p><pre>Hash (cost=5.89..5.89 rows=83 width=7116) (actual time=0.456..0.456 rows=83 loops=1)</pre><pre>Buckets: 1024 Batches: 1 Memory Usage: 271kB</pre><pre>-&gt; Index Scan using markets_pkey on markets market4_ (cost=0.14..5.89 rows=83 width=7116) (actual time=0.003..0.176 rows=83 loops=1)</pre><p>The Hash node includes information about the number of hash buckets and batches, as well as peak memory usage along with estimated and actual costs of building up the hash table.</p><p>After the hash table is built, the result of the nested loop join is scanned and using the primary_market_id as the hash key the hash table is probed to find all matching rows. (Hash Condition in hash join node).</p><h3>Can we optimize the query?</h3><p>In the query plan, the majority of the time (452.93 ms out of total 474.09 ms) is spent in the index scan of listings table to find the range between 113115554 and 113125553 which returns <strong>9896</strong> rows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/819/1*ZNLdQWpTV9eaLmOA9LLkUg.png" /></figure><p>The corresponding query plan row is:</p><pre>Index Scan using listings_pkey on listings listing1_ (cost=0.57..1196.67 rows=9273 width=827) (actual time=0.685..452.927 rows=9896 loops=1)</pre><p>You will notice that the final result of the nested loop join between listings and search_keys table returns only 30 rows out of <strong>9896</strong> rows matched from the listings table. Looking closely, the listings and search_keys tables are joined on the listing table’s id, which has a far higher number of matching rows for the range of listing ids than what is needed.</p><p>Let’s modify the query’s WHERE clause to select listing ids in desired range from <em>search_keys</em> table instead of <em>listings</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-N-8UkygbbasqmPxa4LHag.png" /></figure><p>The execution plan for above query is:</p><pre>QUERY PLAN</pre><pre>-----------------------------------</pre><pre>Hash Left Join  (cost=7.92..303.55 rows=303 width=8369) (actual time=1.138..12.669 rows=30 loops=1)</pre><pre>Hash Cond: (this_.primary_market_id = market4_.market_id)</pre><pre>-&gt;  Nested Loop Left Join  (cost=0.99..293.17 rows=303 width=1253) (actual time=0.501..11.987 rows=30 loops=1)</pre><pre>Filter: ((listing1_.country_code IS NULL) OR (listing1_.country_code = &#39;US&#39;::text))</pre><pre>Rows Removed by Filter: 7</pre><pre>-&gt;  Index Scan using search_keys_listing on search_keys this_  (cost=0.43..38.76 rows=319 width=426) (actual time=0.050..5.378 rows=37 loops=1)</pre><pre>Index Cond: ((listing_id &gt;= &#39;113115554&#39;::bigint) AND (listing_id &lt;= &#39;113125553&#39;::bigint))</pre><pre>-&gt;  Index Scan using listing_id_available_photos on listings listing1_  (cost=0.57..0.79 rows=1 width=827) (actual time=0.175..0.175 rows=1 loops=37)</pre><pre>Index Cond: (this_.listing_id = listing_id)</pre><pre>-&gt;  Hash  (cost=5.89..5.89 rows=83 width=7116) (actual time=0.586..0.586 rows=83 loops=1)</pre><pre>Buckets: 1024  Batches: 1  Memory Usage: 271kB</pre><pre>-&gt;  Index Scan using markets_pkey on markets market4_  (cost=0.14..5.89 rows=83 width=7116) (actual time=0.004..0.263 rows=83 loops=1)</pre><pre>Execution time: 13.070 ms</pre><pre>(13 rows)</pre><p>The optimized query takes 13 ms compared to 474 ms earlier. The key difference here is:</p><pre>Index Scan using search_keys_listing on search_keys this_ (cost=0.43..38.76 rows=319 width=426) (actual time=0.050..5.378 rows=37 loops=1)</pre><pre>Index Cond: ((listing_id &gt;= &#39;113115554&#39;::bigint) AND (listing_id &lt;= &#39;113125553&#39;::bigint))</pre><p>An Index Scan on <em>search_keys</em> table is performed to find <em>listings</em> with ids in range (&#39;113115554&#39; and &#39;113125553&#39;) which takes 5.378 ms and returns <strong>37</strong> rows in contrast to <strong>9896</strong> rows in 452.927 ms returned by the previous execution plan that scanned listings table for the same.</p><h3>More Resources</h3><p><a href="https://www.postgresql.org/docs/9.6/using-explain.html">https://www.postgresql.org/docs/9.6/using-explain.html</a></p><p><a href="https://pganalyze.com/docs/explain">https://pganalyze.com/docs/explain</a></p><p><a href="https://tatiyants.com/pev/#/plans/new">https://tatiyants.com/pev/#/plans/new</a></p><p><strong>PS</strong> — The query used an example here was optimized by <a href="https://medium.com/u/ad7de2f3dea1">Ken Brush</a> and <a href="https://medium.com/u/54e4c938cd33">Robert Gay</a> during a site outage event in Feb, 2020. Thanks Ken and Robert!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4a2d5c5e0ac5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/postgresql-explain-explained-4a2d5c5e0ac5">PostgreSQL EXPLAIN Explained</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Micro-Frontends Are Remote UI Components]]></title>
            <link>https://medium.com/code-red/micro-frontends-are-remote-ui-components-7354e5751863?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/7354e5751863</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Dan Fabulich]]></dc:creator>
            <pubDate>Tue, 19 Jan 2021 19:08:48 GMT</pubDate>
            <atom:updated>2021-01-19T19:08:48.248Z</atom:updated>
            <content:encoded><![CDATA[<h4>Also: Seven reasons why you might not want/need remote UI rendering</h4><p><em>Dan Fabulich is a Principal Engineer at Redfin. (</em><a href="https://www.redfin.com/about/jobs?utm_source=engblog"><em>We’re hiring</em></a><em>!)</em></p><p>When I first read the definition of micro-frontends, I didn’t “get it.” Specifically, when I read <a href="https://martinfowler.com/articles/micro-frontends.html">Cam Jackson’s article on martinfowler.com</a> and <a href="https://micro-frontends.org/">Michael Geers’ mini-site micro-frontends.org</a>, I was still asking myself questions like:</p><ul><li>Are we already doing micro-frontends? We’ve been using UI component frameworks for years. Are micro-frontends just UI components?</li><li>If not, how would our code be different if we <em>were</em> using micro-frontends?</li><li>But, seriously, what <em>are</em> micro-frontends?!</li></ul><p>After more thinking and research, I’ve now figured out why I was struggling: both articles go to some lengths to avoid giving “micro-frontends” a clear definition, instead preferring to define the term using code examples and analogies. I think I’ve figured out a simple definition that makes more sense to me; I hope it makes more sense to you.</p><p><strong>Micro-frontends are <em>remote UI components</em></strong>, where subcomponent renderer code runs in a separate process from the “composer” code that composes subcomponents.</p><p>As a result of running subcomponents in separate processes:</p><ul><li>You can redeploy/restart a “micro-frontend” subcomponent process without redeploying/restarting other subcomponents, or the composer process. If a subcomponent process crashes, it doesn’t take down the other processes.</li><li>The subcomponent processes don’t have to share any code with the composer. Taken to an extreme, each subcomponent can use its own UI component framework. (We probably want to avoid this, but if we want to switch frameworks, it’s nice to have this tool in our toolbox.)</li><li>The composer can be very lightweight, since it doesn’t have to include subcomponent code. This is especially useful when the composer has to run on the client side, where downloading more code means launching more slowly.</li><li>Subcomponents can render in parallel. (You don’t have to run subcomponents in separate processes to render them in parallel, but running them in separate processes does ensure that subcomponents <em>can</em> be run in parallel.)</li><li>As in any distributed system, sometimes the composer may be unable to access its subcomponents. Ideally, the composer can fail gracefully, rendering at least some parts of the UI that are available. (But, on the other hand, we might want a particular component to fail completely if certain critical subcomponents aren’t available.)</li></ul><h3>There are many kinds of remote UI components (many kinds of micro-frontends)</h3><p>UI components come in many shapes and sizes; each UI framework offers a different approach to composing UI out of reusable pieces. Similarly, there’s a wide variety of UI frameworks that support remote UI rendering.</p><ul><li>Server-side frameworks can have remote subcomponents. For example, you can have a no-JS server-side composer that requests pre-rendered HTML fragments from other backend services and assembles them into an HTML document. (This composer can be as simple as a web proxy, e.g. <a href="https://en.wikipedia.org/wiki/Edge_Side_Includes">edge-side includes</a>.)</li><li>Some client-side frameworks, like Turbo (aka Turbolinks), support fetching different parts of the UI with parallel requests and composing them on the client side.</li><li>Or you can go old-school and build a page out of &lt;iframe&gt;s! (But iframes mess with the browser’s back button—they’re like a miniature tab in the middle of your webpage—so you might prefer to use a lightweight mini-framework, making little gadgets that look like iframes but don’t mess with the back button.)</li><li>New in 2021, React has <a href="https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html">Server Components</a> whose code runs only on the server side; React can fetch the HTML for these components and embed them into the page without requiring the client to download client-side code to render/rerender the components.</li></ul><p><strong>This is the reason why why it’s so hard to wrap your head around micro-frontends.</strong> There are so many different kinds of micro-frontends, at least as many as there are UI frameworks. It’s notoriously difficult to do an apples-to-apples comparison of UI frameworks, and micro-frontend frameworks are no exception.</p><h3>Seven reasons why you might not want/need remote UI rendering</h3><p>Micro-frontends are the right choice for organizations that can afford the overhead in order to scale up. But you might not be able to afford the overhead, and you might not need those benefits in order to scale.</p><ul><li>All of the popular introductions to micro-frontends talk about how micro-frontends “allow” you to have multiple full-stack teams of developers, each team owning their own frontend and backend code. But you don’t have to use <em>remote UI components</em> to have multiple full-stack teams. You can have a monolithic UI runtime, where each team owns UI components that run together in the same process. (This is how most native apps have worked, since forever.) But beware, any one component in a monolithic UI process can take the whole app down with it.</li><li>If subcomponents need to communicate with each other, it may be faster/easier to run them in the same process.</li><li>If each subcomponent process is running duplicated framework code, it may save server resources (memory/CPU/money) to combine them into a single process. In addition, each process has to be monitored separately, which adds to the overhead of a distributed system.</li><li>If you don’t need to redeploy subcomponents separately, you might not need remote UI components. (For example, if all subcomponents share the same UI framework, and you redeploy all subcomponents whenever you upgrade the framework, it might be better to just run them all in a single process and redeploy them all whenever any subcomponent changes.)</li><li>You might want to run all of your code in a single process on the client for performance reasons. First-load performance is typically faster when you render on the server, running as little code as possible on the client, but once the client has all of the code, second-load performance can be faster when you render on the client, making as few network requests as possible. It’s a tradeoff!</li><li>Sometimes we don’t want/need graceful degradation, when we want the whole UI to show an error if any component isn’t available.</li><li>It’s possible to allow UI teams to deploy on different schedules while running code in a monolithic UI runtime by having the composer download renderer code, rather than requesting rendered UI from separate services. On the client side, this is the difference between rendering remote HTML in an &lt;iframe&gt; vs. downloading remote &lt;script&gt; and running it in the current page. (This is a typical pattern for “Login with Google/Facebook/Apple” buttons.) When you download renderer code at runtime, you get the advantages of decoupled deploys and easy communication between components, but you also take on the risk of one component crashing the entire UI.</li></ul><p><em>P.S. </em><a href="https://www.redfin.com/about/jobs?utm_source=engblog"><em>Redfin is hiring</em></a><em>.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5FwQq7Otr60kxj6gU0cUvA.jpeg" /><figcaption>A puzzle piece built out of smaller puzzle pieces. It’s like life.</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7354e5751863" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/micro-frontends-are-remote-ui-components-7354e5751863">Micro-Frontends Are Remote UI Components</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Node Modules at War: Why CommonJS and ES Modules Can’t Get Along]]></title>
            <link>https://medium.com/code-red/node-modules-at-war-why-commonjs-and-es-modules-cant-get-along-9617135eeca1?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/9617135eeca1</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[webpack]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Dan Fabulich]]></dc:creator>
            <pubDate>Wed, 05 Aug 2020 18:28:35 GMT</pubDate>
            <atom:updated>2023-04-21T16:55:34.475Z</atom:updated>
            <content:encoded><![CDATA[<h4>Interop between them is possible, but it’s a hassle</h4><p><em>Dan Fabulich is a Principal Engineer at Redfin. (</em><a href="https://www.redfin.com/about/jobs?utm_source=engblog"><em>We’re hiring</em></a><em>!)</em></p><p>In Node 14, there are now two kinds of scripts: there are old-style CommonJS (CJS) scripts and new-style ESM scripts (aka MJS). CJS scripts use require() and module.exports; ESM scripts use import and export.</p><p><strong>ESM and CJS are completely different animals.</strong> Superficially, ESM looks very similar to CJS, but their implementations couldn’t be more different. One of them is a honey bee, and the other is a murder hornet.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ljab8kLJtGC-o36VQ7vBZg.jpeg" /><figcaption>A hornet and a honey bee. One of these is like ESM and the other is like CJS, but I can never remember which one is which. Credit: <a href="https://en.wikipedia.org/wiki/File:Hornet-vespa.jpg">wikimedia</a>, <a href="https://commons.wikimedia.org/wiki/File:Honey_bee_(Apis_mellifera).jpg">wikimedia</a></figcaption></figure><p><strong>Calling CJS from ESM and vice versa is possible, but it’s a hassle.</strong></p><p>Here are the rules, which I’ll explain in more detail below:</p><ol><li>You can’t require() ESM scripts; you can only import ESM scripts, like this: import {foo} from &#39;foo&#39;</li><li>CJS scripts can’t use static import statements like the one above.</li><li>CJS scripts <em>can</em> use asynchronous dynamic import() to use ESM, but that&#39;s a hassle, compared to synchronous require.</li><li>ESM scripts <em>can</em> import CJS scripts, but only by using the “default import” syntax import _ from &#39;lodash&#39;, not the “named import” syntax import {shuffle} from &#39;lodash&#39;, which is a hassle if the CJS script uses named exports. (Except, sometimes, unpredictibly, Node can figure out what you meant!)</li><li>ESM scripts <em>can</em> require() CJS scripts, even with named exports, but it’s typically not worth the trouble, because it requires even more boilerplate, and, worst of all, bundlers like Webpack and Rollup don’t/won’t know how to work with ESM scripts that use require().</li><li>CJS is the default; you have to opt-in to ESM mode. You can opt-in to ESM mode by renaming your script from .js to .mjs. Alternately, you can set &quot;type&quot;: &quot;module&quot; in package.json, and then you can opt-out of ESM by renaming scripts from .js to .cjs. (You can even tweak just an individual subdirectory by putting a one-line {&quot;type&quot;: &quot;module&quot;} package.json file in there.)</li></ol><p>These rules are <em>painful</em>. Worse, for many users, especially newbies to Node, these rules are <em>incomprehensible</em>. (Fear not, I’ll explain them all here in this article.)</p><p>Many observers of the Node ecosystem have speculated that these rules are due to a failure of leadership, or even hostility toward ESM. But, as we’ll see, all of these rules are here for a good reason, which will make it very difficult to break these rules in the future.</p><p>I’ll conclude with four guidelines for library authors to follow:</p><ul><li>Consider shipping only ESM</li><li>If you’re not shipping only ESM, ship CJS only</li><li>Test that your CJS works in ESM</li><li>If needed, add a thin ESM wrapper for your CJS named exports</li><li>Add an exports map to your package.json</li></ul><p><strong>It’s all gonna be OK.</strong></p><p><a href="https://www.reddit.com/r/node/comments/i4jwb7/node_modules_at_war_why_commonjs_and_es_modules/">Discuss on Reddit</a><br><a href="https://news.ycombinator.com/item?id=24067748">Discuss on Hacker News</a></p><h3>Background: What’s CJS? What’s ESM?</h3><p>Since the dawn of Node, Node modules were written as CommonJS modules. We use require() to import them. When implementing a module for other people to use, we can define exports, either “named exports” by setting module.exports.foo = &#39;bar&#39; or a “default export” by setting module.exports = &#39;baz&#39;.</p><p>Here’s a CJS example using <strong>named exports</strong>, where util.cjs has an export named sum.</p><pre>// @filename: util.cjs<br>module.exports.sum = (x, y) =&gt; x + y;</pre><pre>// @filename: main.cjs<br>const {sum} = require(&#39;./util.cjs&#39;);<br>console.log(sum(2, 4));</pre><p>Here’s a CJS example where util.cjs sets a <strong>default export</strong>. The default export has no name; modules using require() define their own name.</p><pre>// @filename: util.cjs<br>module.exports = (x, y) =&gt; x + y;</pre><pre>// @filename: main.cjs<br>const whateverWeWant = require(&#39;./util.cjs&#39;);<br>console.log(whateverWeWant(2, 4));</pre><p>In ESM scripts, import and export are part of the language; like CJS, they have two different syntaxes for named exports and the default export.</p><p>Here’s an ESM example with <strong>named exports</strong>, where util.mjs has an export named sum.</p><pre>// @filename: util.mjs<br>export const sum = (x, y) =&gt; x + y;</pre><pre>// @filename: main.mjs<br>import {sum} from &#39;./util.mjs&#39;<br>console.log(sum(2, 4));</pre><p>Here’s an ESM example where util.mjs sets a <strong>default export</strong>. Just like in CJS, the default export has no name, but the module using import defines its own name.</p><pre>// @filename: util.mjs<br>export default (x, y) =&gt; x + y;</pre><pre>// @filename: main.mjs<br>import whateverWeWant from &#39;./util.mjs&#39;<br>console.log(whateverWeWant(2, 4));</pre><h3>ESM and CJS are completely different animals</h3><p><strong>In CommonJS, </strong><strong>require() is synchronous</strong>; it doesn&#39;t return a promise or call a callback. require() reads from the disk (or perhaps even from the network), and then immediately runs the script, which may itself do I/O or other side effects, and then returns whatever values were set on module.exports.</p><p><strong>In ESM, the module loader runs in asynchronous phases.</strong> In the first phase, it parses the script to detect calls to import and export without running the imported script. In the parsing phase, the ESM loader can immediately detect a typo in named imports and throw an exception without ever actually running the dependency code.</p><p>The ESM module loader then asynchronously downloads and parses any scripts that you imported, and then scripts that your scripts imported, building out a “module graph” of dependencies, until eventually it finds a script that doesn’t import anything. Finally, that script is allowed to execute, and then scripts that depend on that are allowed to run, and so on.</p><p>All of the “sibling” scripts in the ES module graph download in parallel, but they execute in order, guaranteed by the loader specification.</p><h3>CJS is the default because ESM changes a lot of stuff</h3><p>ESM changes a bunch of stuff in JavaScript. ESM scripts use Strict Mode by default (use strict), their this doesn&#39;t refer to the global object, scoping works differently, etc.</p><p>This is why, even in browsers, &lt;script&gt; tags are non-ESM by default; you have to add a type=&quot;module&quot; attribute to opt into ESM mode.</p><p>Switching the default from CJS to ESM would be a big break in backwards compatibility. (<a href="https://deno.land/">Deno</a>, the hot new alternative to Node, makes ESM the default, but as a result, its ecosystem is starting from scratch.)</p><h3>CJS can’t require() ESM because of top-level await</h3><p>The simplest reason that CJS can’t require() ESM is that ESM can do top-level await, but CJS scripts can&#39;t.</p><p><a href="https://v8.dev/features/top-level-await">Top-level </a><a href="https://v8.dev/features/top-level-await">await</a> lets us use the await keyword outside of an <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">async function</a>, at the “top level.”</p><p>ESM’s multi-phase loader makes it possible for ESM to implement top-level await without making it a “footgun.” Quoting from the <a href="https://v8.dev/features/top-level-await">V8 team’s blog post</a>:</p><blockquote>Perhaps you have seen the <a href="https://gist.github.com/Rich-Harris/0b6f317657f5167663b493c722647221">infamous gist</a> by <a href="https://twitter.com/Rich_Harris">Rich Harris</a> which initially outlined a number of concerns about top-level await and urged the JavaScript language not to implement the feature. Some specific concerns were:</blockquote><blockquote>• Top-level await could block execution.<br>• Top-level await could block fetching resources.<br>• There would be no clear interop story for CommonJS modules.</blockquote><blockquote>The stage 3 version of the proposal directly addresses these issues:</blockquote><blockquote>• As siblings are able to execute, there is no definitive blocking.<br>• Top-level await occurs during the execution phase of the module graph. At this point all resources have already been fetched and linked. There is no risk of blocking fetching resources.<br>• Top-level await is limited to [ESM] modules. There is explicitly no support for scripts or for CommonJS modules.</blockquote><p>(Rich now approves of the current top-level await implementation.)</p><p>Since CJS doesn’t support top-level await, it’s not even possible to <em>transpile</em> ESM top-level await into CJS. How would you rewrite this code in CJS?</p><pre>export const foo = await fetch(&#39;./data.json&#39;);</pre><p><a href="https://github.com/nodejs/modules/issues/454">There’s an active debate on how to </a><a href="https://github.com/nodejs/modules/issues/454">require() ESM in this thread.</a> (Please read the whole thread and the linked discussions before commenting. If you dive in, you’ll find that top-level await isn’t even the only problematic case… what do you think happens if you synchronously require ESM which can asynchronously import some CJS which can synchronously require some ESM? What you get is a sync/async zebra stripe of <em>death</em>, that’s what! Top-level await is just the last nail in the coffin, and the easiest to explain.)</p><p>It’s frustrating, because the vast majority of ESM scripts don’t use top-level await, but, as one commenter wrote in that thread, “I don’t think designing a system with the blanket assumption that some feature just won’t get used is a viable path.”</p><p>Reviewing that conversation, it doesn’t look like we’re going to be able to require() ESM any time soon!</p><h4>CJS Can import() ESM, but It’s Not Great</h4><p>For now, if you’re writing CJS and you want to import an ESM script, you’ll have to use asynchronous dynamic import().</p><pre>(async () =&gt; {<br>    const {foo} = await import(&#39;./foo.mjs&#39;);<br>})();</pre><p>It’s… fine, I guess, as long as you don’t have any exports. If you do need to do some exports, you’ll have to export a Promise instead, which may be <a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/">a huge inconvenience to your users</a>:</p><pre>module.exports.foo = (async () =&gt; {<br>    const {foo} = await import(&#39;./foo.mjs&#39;);<br>    return foo;<br>})();</pre><h3>ESM can’t import named CJS exports unless CJS scripts execute out of order</h3><p>You can do this:</p><pre>import _ from &#39;./lodash.cjs&#39;</pre><p>But you can’t do this:</p><pre>import {shuffle} from &#39;./lodash.cjs&#39;</pre><p>That’s because CJS scripts compute their named exports as they <em>execute</em>, whereas ESM’s named exports must be computed during the <em>parsing</em> phase.</p><p>Fortunately for us, there’s a workaround! The workaround is annoying, but totally doable. We just have to import CJS scripts like this:</p><pre>import _ from &#39;./lodash.cjs&#39;;<br>const {shuffle} = _;</pre><p>There are no real downsides to this, and ESM-aware CJS libraries can even provide their own ESM wrappers that encapsulate this boilerplate for us.</p><p>This is totally fine! But don’t you just… wish it were better?</p><h4>Out-of-order execution would work, but it might be even worse</h4><p>A number of people have proposed executing CJS imports before ESM imports, out of order. That way, the CJS named exports could be computed at the same time as ESM named exports.</p><p>But that would <a href="https://github.com/nodejs/modules/issues/81#issuecomment-391348241">create a new problem</a>.</p><pre>import {liquor} from &#39;liquor&#39;;<br>import {beer} from &#39;beer&#39;;</pre><p>If liquor and beer are both initially CJS, changing liquor from CJS to ESM would change the ordering from liquor, beer to beer, liquor , which would be nauseatingly problematic if beer relied on something from liquor being executed first.</p><p><a href="https://github.com/nodejs/modules/issues/509">Out-of-order execution is still under debate</a>, though the conversation seems to have mostly fizzled out a few weeks ago.</p><h4>Dynamic Modules could save us, but their star is poisoned</h4><p>There’s an alternative proposal that doesn’t require out-of-order execution or wrapper scripts, called <a href="https://github.com/nodejs/dynamic-modules">Dynamic Modules</a>.</p><p>In the ESM specification, the exporter statically defines all named exports. Under dynamic modules, the importer would define the export names in the import. The ESM loader would initially just trust that dynamic modules (CJS scripts) would provide all required named exports, and then throw an exception later if they didn’t satisfy the contract.</p><p>Unfortunately, dynamic modules would require some JavaScript language changes to be approved by the TC39 language committee, and they <a href="https://github.com/tc39/ecma262/pull/1306#issuecomment-467761625">do not approve</a>.</p><p>Specifically, ESM scripts can export * from &#39;./foo.cjs&#39;, which means to re-export all of the names that foo exports. (This is called a “<strong>star export</strong>.” 🤩)</p><p>Unfortunately, there’s no way for the loader to know what’s being exported when we star export from a dynamic module.</p><p>Dynamic-module star exports also create issues for spec compliance. For example, export * from &#39;omg&#39;; export * from &#39;bbq&#39;; is supposed to throw when both omg and bbq export the same named export wtf. Allowing the names to be user/consumer-defined means this validation phase needs to be post-handled / ignored somehow.</p><p>Proponents of dynamic modules proposed banning star exports from dynamic modules, but <a href="https://github.com/tc39/ecma262/pull/1306#issuecomment-467761625">TC39 rejected that proposal</a>. One TC39 member referred to this proposal as “syntax poisoning,” as star exports would be “poisoned” by dynamic modules.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/461/1*YFBh0ZgMSA9Qzx1mBqlfgA.png" /><figcaption>This poison star is very angry with you. Credit: <a href="https://www.seekpng.com/ipng/u2q8e6r5o0e6t4y3_mk3ds-poison-star-illustration/">seekpng</a></figcaption></figure><p>(In my opinion, we’re already living in a world of syntax poison. In Node 14, named imports are poisoned, and under dynamic modules, star exports would be poisoned. Since named imports are extremely common and star exports are relatively rare, dynamic modules would reduce syntax poison in the ecosystem.)</p><p>This may not be the end of the road for dynamic modules. One proposal on the table is for <em>all</em> Node modules to become dynamic modules, even pure ESM modules, abandoning the ESM multi-phase loader in Node. Surprisingly, this would have no user-visible effect, except perhaps slightly worse startup performance; the ESM multi-phase loader was designed for loading scripts over a slow network.</p><p>But I don’t feel lucky. The Github issue for dynamic modules was recently closed, because <a href="https://github.com/nodejs/modules/issues/252">there has been no discussion of dynamic modules in the last year</a>.</p><h4>Sometimes Node can synthesize named exports from CJS (but it’s unpredictable</h4><p>The Node team, noticing how painful this is, put in a heroic effort to try to automatically parse CJS files to autodetect possible named exports! 😮</p><p>Node’s <a href="https://github.com/nodejs/cjs-module-lexer">cjs-module-lexer</a> attempts to automagically detect patterns like these:</p><pre>exports.a = &#39;a&#39;;<br>exports[&#39;b&#39;] = &#39;b&#39;;<br>if (false)<br>  exports.c = &#39;c&#39;;<br><br>Object.defineProperty(exports, &#39;d&#39;, { value: &#39;d&#39; });<br>module.exports = {e: &#39;e&#39;}</pre><p>The problem is, it’s imperfect. It doesn’t work if the CJS uses patterns like these:</p><pre>Object.defineProperty(exports, &#39;a&#39;, {<br>  get () {<br>    return &#39;nope&#39;;<br>  }<br>});<br><br>Object.defineProperties(...)<br><br>module.exports = {<br>  a,<br>  ...d, // ignored<br>  b: require(&#39;c&#39;),<br>  c: &quot;not detected since require(&#39;c&#39;) above bails the object detection&quot;<br>}</pre><p>The good news is, it was specifically designed to target the transpiled outputs of TypeScript, Babel, and Rollup. If you write your code in a TypeScript .cts file, Node will definitely detect all of your named exports!</p><h3>ESM can require(), but it’s probably not worth it</h3><p>require() is not in scope by default in ESM scripts, but <a href="https://nodejs.org/api/modules.html#modules_module_createrequire_filename">you can get it back very easily</a>.</p><pre>import { createRequire } from &#39;module&#39;;<br>const require = createRequire(import.meta.url);<br><br>const {foo} = require(&#39;./foo.cjs&#39;); </pre><p>The problem with this approach is that it doesn’t really help; it’s actually more lines of code than just doing a default import and destructuring.</p><pre>import cjsModule from &#39;./foo.cjs&#39;;<br>const {foo} = cjsModule;</pre><p>Plus, bundlers like Webpack and Rollup have no idea what to do with this createRequire pattern. So what’s the point?</p><h3>What should you publish?</h3><h4>1. Consider shipping only ESM</h4><p>ESM is the future, and there’s a solid movement of folks trying to put this whole fiasco behind us, and have everyone writing only ESM code.</p><p>The problem with shipping only ESM is that it’s a big inconvenience to CJS users. Your CJS users will have to await import your code instead of being able to synchronously require it.</p><p>If you already ship a library with CJS, shipping ESM-only is a backwards-incompatible breaking change. (Note that it’s easy to write an ESM wrapper for CJS libraries, but it’s not possible to write a CJS wrapper for ESM libraries.)</p><h4>2. If you must publish CJS, publish only CJS</h4><p>If you’re transpiling from TypeScript, you <em>could</em> transpile to both CJS and ESM, but this introduces a hazard that users may accidentally both import your ESM scripts and require() your CJS separately. (For example, suppose one library omg.mjs depends on index.mjs, while another library bbq.cjs depends on index.cjs, and then you depend on both omg.mjs and bbq.cjs.)</p><p>Node normally dedupes modules, but Node doesn’t know that your CJS and your ESM are the “same” files, so your code will run twice, keeping two copies of your library’s state. That can cause all kinds of weird bugs.</p><p>So, if you’re publishing CJS at all, and you’re writing in TypeScript or another language that transpiles to JS, transpile only to CJS.</p><h4>3. Test that your CJS library works in ESM</h4><p>Write a little test in a .mjs file, in ESM JS (without transpiling) and make sure you can import your CJS in the way you expect.</p><p>If you expect your ESM users to use a default import, like import mylibrary from &#39;mylibrary&#39;, make sure that works. If you export your ESM users to use named imports, like import {foo} from &#39;mylibrary&#39;, make sure <em>that</em> works.</p><p>If it doesn’t, you might need to provide a thin ESM wrapper for your CJS.</p><h4><strong>4. If necessary, provide a thin ESM wrapper for your CJS</strong></h4><p>(Again, note that it’s easy to write an ESM wrapper for CJS libraries, but it’s not possible to write a CJS wrapper for ESM libraries.)</p><pre>import cjsModule from &#39;./index.cjs&#39;;</pre><pre>export const foo = cjsModule.foo; </pre><p>Put your ESM wrapper in a file using the .mjs extension.</p><h4><strong>5. Add an </strong><strong>exports map to your </strong><strong>package.json</strong></h4><p>Like this:</p><pre>&quot;exports&quot;: {<br>    &quot;require&quot;: &quot;./index.cjs&quot;,<br>    &quot;import&quot;: &quot;./index.mjs&quot;<br>}</pre><p><strong>Beware: adding an </strong><strong>exports map is always a “</strong><a href="https://semver.org/"><strong>semver major</strong></a><strong>” breaking change. </strong>By default, your users can reach into your package and require() any script they want, even files that you intended to be internal. The exports map ensures that users can only require/import the entry points that you deliberately expose.</p><p>That’s almost certainly a good thing! <a href="https://medium.com/javascript-in-plain-english/is-promise-post-mortem-cab807f18dcc">But it is a breaking change.</a></p><p>(If you allow your users to import or require() other files in your module, you can set up separate entry points for those, as well. <a href="https://nodejs.org/api/esm.html">See the Node documentation on ESM for details.</a>)</p><p><em>Always include file extensions in export map targets. </em>Refer to &quot;index.cjs&quot; not just &quot;index&quot; or a directory like &quot;./build&quot;.</p><p><strong>If you follow these guidelines, your users will be OK. Everything’s going to be all right.</strong></p><p><em>P.S. </em><a href="https://www.redfin.com/about/jobs?utm_source=engblog"><em>Redfin is hiring</em></a><em>.</em></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FOD3F7J2PeYU%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DOD3F7J2PeYU&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FOD3F7J2PeYU%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/ac671d57c97d45099cc37a5d99efe280/href">https://medium.com/media/ac671d57c97d45099cc37a5d99efe280/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9617135eeca1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/node-modules-at-war-why-commonjs-and-es-modules-cant-get-along-9617135eeca1">Node Modules at War: Why CommonJS and ES Modules Can’t Get Along</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Boost PostgreSQL Cache Performance]]></title>
            <link>https://medium.com/code-red/how-to-boost-postgresql-cache-performance-8db383dc2d8f?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/8db383dc2d8f</guid>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[cache]]></category>
            <category><![CDATA[database]]></category>
            <dc:creator><![CDATA[Calvin Li]]></dc:creator>
            <pubDate>Mon, 06 Jan 2020 23:10:15 GMT</pubDate>
            <atom:updated>2020-01-06T23:10:15.678Z</atom:updated>
            <content:encoded><![CDATA[<h4>In times like these, cache is king for databases</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JHGJ98mdQ9d18XUWuMNMqw.jpeg" /></figure><p>When thinking about caching data for incredibly fast retrieval, technologies like Redis and Memcached often come to a developer’s mind. I, however, want to discuss a less commonly acknowledged cache that also helps with improving data retrieval time: a cache within a database.</p><p>The ability to fetch data quickly is crucial for any high throughput application and service. For the Notifications team at Redfin (the team I work on), it ensures that we can capture the updates in the US and Canadian real estate markets and inform our users within minutes of them occurring. A difference of several tens of milliseconds in process time per update event is enough to disrupt our pipelines and prevent us from delivering updates to our users in a timely manner.</p><p>In fact, that was exactly what happened to our email and push sending pipelines earlier last year. They couldn’t process the events quickly enough during times of peak traffic, so notifications were delayed to our customers. After some investigation, we discovered that the main bottleneck was the performance of retrieving data from our PostgreSQL database replica.</p><p>Although introducing external caching stores like Redis or Memcached to our applications would have been beneficial, we wanted to make sure that we were properly utilizing our database. In particular, we discovered in our investigation that our configurations for our database could have been modified for improved performance. Let’s walk through some of the techniques we did to discover and fix this.</p><h4>Investigating bottlenecks in the query performance</h4><p>Before looking for a solution, it is important to first understand why the queries are slow. There can be an assortment of reasons why, and some of them may not be related to the database. To narrow down the possibilities, you should look into the general health of the machines your applications are running on and the performance of all the various queries being made.</p><p>For instance, any CPU or network bottlenecks on the machine your application is running on can negatively impact its ability to quickly fetch data from the database. Other possibilities are that the queries are poorly written or that the tables don’t have certain indices that can help speed up those queries. If only one or a few queries are slow, that’s indicative that improving those queries will resolve the problem. If all of the queries are slow, even primary key lookups, then that’s a strong signal that the problem is unrelated to the query.</p><p>In the case that all queries are slow, you should examine the health of the machine that the database runs on. Bottlenecks in the machine’s computational power or I/O means that you will need to scale up your database. Good ways to examine this is to look at the CPU utilization of the machine, disk I/O, and network I/O.</p><p>One way to determine whether or not your database is maxing out on its processing ability is to take samples of the number of active queries running. To sample the number of active queries running on our PostgreSQL database, we can query the pg_stat_activity table:</p><pre>select count(*) from pg_stat_activity where state=&#39;active&#39;</pre><p>If that number consistently exceeds the number of CPU cores of the machine, then that’s a good sign that your database is under-resourced.</p><h4>Investigating the database’s internal cache performance</h4><p>If your investigation leads you to believe that there are database performance issues, then you should consider analyzing the cache performance of your database. PostgreSQL databases use both an internal cache and the machine’s page cache for storing commonly requested data. That way, instead of pulling the data from disk, which can take milliseconds, the database replica can fetch the data in-memory in sub-millisecond times.</p><p><a href="https://www.postgresql.org/docs/10/monitoring-stats.html">Postgres provides cache hit rate statistics</a> for all tables in the database in the pg_statio_user_tables table. The two useful columns in that table are the heap_blks_read, defined as the “number of disk blocks read from this table” and the heap_blks_hit, defined as the “number of buffer hits in this table”. If we run the following query,</p><pre>select heap_blks_read, heap_blks_hit from pg_statio_user_tables where relname=&#39;&lt;table_name&gt;&#39;;</pre><p>we get the number of disk block reads and buffer hits for that given table since the creation of the table. If we store those values and run the above query again after some period of time, we can calculate the cache hit rate for that time period. To simplify doing the math every time, you can run the below query:</p><pre>select<br> heap_blks_read — &lt;result from prev heap_blks_read&gt; as misses,<br> heap_blks_hit — &lt;result from prev heap_blks_hit&gt; as hit,<br> (heap_blks_hit — &lt;result from prev heap_blks_hit&gt;)::float/(heap_blks_read — &lt;result from prev heap_blks_read&gt; + heap_blks_hit — &lt;result from prev heap_blks_hit&gt;) as hit_ratio<br>from pg_statio_user_tables<br>where relname=&#39;&lt;table_name&gt;&#39;;</pre><p>Ideally, you will want the hit_ratio to be greater than 90%. Otherwise, you may need to tune your database configurations to improve the cache hit rate.</p><h4>Improving Postgres internal cache performance</h4><p>One of the main reasons why the cache hit rate for a table is low is that the database doesn’t have enough space allocated in its internal cache buffer. This internal cache buffer is used for loading the table rows from disk to memory, and if there isn’t enough space allocated, then the database server will constantly have to fetch the data from disk.</p><p>For PostgreSQL databases, the cache buffer size is configured with the <a href="https://www.postgresql.org/docs/current/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-MEMORY">shared_buffer</a> configuration. It tells the database how much of the machine’s memory it can allocate for storing data in memory. The default is incredibly low (128 MB) because some kernels do not support more without changing the kernel settings. The optimal value ultimately depends on the data access patterns for a given database, but PostgreSQL recommends that you should initially configure it to 25% of the machine’s total memory if you are using a dedicated database server. More memory can be beneficial for larger databases, but there’s a limit to the optimization since PostgreSQL databases also use the system’s cache. The more memory you allocate to the shared_buffer, the less memory will be available for the machine’s cache.</p><h4>Final Thoughts</h4><p>There are also many other database configurations, such as the <a href="https://www.postgresql.org/docs/9.5/runtime-config-query.html">effective_cache_size</a>, that are worth looking into and tuning if you still are seeing database performance issues. The optimal values for those configurations will depend on the data access patterns of the database, so having a good understanding of what tables are commonly queried and rows commonly fetched can help with guiding the decisions for those configurations. Ultimately, knowing how to tune them or whether they will have a significant impact is hard to say, so it’s always good to test some changes out and see their effects.</p><p>As mentioned earlier, a possible alternative would be to place an external cache (e.g. Redis, Memcached) in front of the database. It may come with the additional cost of maintaining the cache operationally or concerns with fetching data. However, for services and applications that share commonly fetched data, it can be a quick and cheap way of reducing data fetching latency.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8db383dc2d8f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/how-to-boost-postgresql-cache-performance-8db383dc2d8f">How to Boost PostgreSQL Cache Performance</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Coding with Tomorrow’s STEM Leaders in San Francisco]]></title>
            <link>https://medium.com/code-red/coding-with-tomorrows-stem-leaders-in-san-francisco-79a3d2040331?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/79a3d2040331</guid>
            <category><![CDATA[education]]></category>
            <dc:creator><![CDATA[Laurel Korwin]]></dc:creator>
            <pubDate>Mon, 23 Dec 2019 17:29:39 GMT</pubDate>
            <atom:updated>2019-12-23T17:29:39.025Z</atom:updated>
            <content:encoded><![CDATA[<h3>Redfin Hosted a Field Trip with Two Dozen Middle School Students, and So Should You</h3><p>Redfin’s San Francisco office was thrilled to welcome 23 students from Everett Middle School for a visit earlier this month. The students were on a field trip with <a href="http://www.igniteworldwide.org/">IGNITE Worldwide</a>, a nonprofit that seeks to inspire young girls and non-binary students to pursue careers in STEM.</p><p>The day began with a tour of Redfin’s office, including a visit to our snack cabinets for some “brain food” for the morning ahead. Next, the students divided into smaller groups led by Redfin engineers for workshops that illustrated a day-in-the-life of various technical roles at Redfin.</p><p>Our employees worked with the students to experiment with redesigning Redfin’s mobile homepage, code styling changes to Redfin’s website in Chrome DevTools, and pick out differences in an image diff to demonstrate testing a hypothetical feature.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*uVISGa8orJOtL_NW" /></figure><p>After the workshops, we had a panel discussion with six women in technical roles at Redfin who shared the stories of their journeys to careers in tech and answered the students’ questions about college and STEM careers. One of our favorites — especially given the generational gap — was when one of the students asked when we each got our first computers. A kid after our own hearts!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Uw6gqR1-Pb-Em174" /></figure><p>We ended our time together with lunch, where we discussed our favorite apps and what it means to be a successful woman, and a final trip to the snack cabinets before sending the students on their way. We were happy to hear that after the visit, 92% of the students were more interested in STEM, and eight more would like to investigate taking a STEM course. We had a wonderful time and hope they continue to explore the world of STEM!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-R2QZFMPmm_SwVQk" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=79a3d2040331" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/coding-with-tomorrows-stem-leaders-in-san-francisco-79a3d2040331">Coding with Tomorrow’s STEM Leaders in San Francisco</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Redfin Is Opening a Dallas Engineering Office]]></title>
            <link>https://medium.com/code-red/why-redfin-is-opening-a-dallas-engineering-office-f10978218249?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/f10978218249</guid>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[hiring]]></category>
            <dc:creator><![CDATA[Ben “Ditto” Lasley]]></dc:creator>
            <pubDate>Wed, 13 Feb 2019 22:08:22 GMT</pubDate>
            <atom:updated>2019-02-13T22:08:21.920Z</atom:updated>
            <content:encoded><![CDATA[<h4>Third Engineering location to open in May 2019</h4><p>Since 2006, Redfin has had engineering offices in two locations: Seattle and San Francisco. Having multiple locations with different composition of teams and roles allows Redfin to attract a wider range of talent. Now, in 2019, it’s time to add another engineering location to our portfolio and to welcome talented engineers to Redfin in a new place. That new place is Dallas.</p><p>While we’re planning to hire new engineers in Dallas this year, we also have a few Redfinnians making the move from our existing offices, including myself! After nearly seven years in San Francisco, I’m excited to meet new people, get to know a new area, and establish the next chapter of Redfin Engineering in Texas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4MMJCLDvwal2VN6Wp3-ebg.png" /><figcaption><em>The author’s wife (also a Redfinnian) and son, experimenting with a cowboy hat</em></figcaption></figure><p>Dallas is a booming area, with a lot of engineering talent. At the same time, it’s much more affordable than San Francisco or Seattle. We set out to find a growing metro with great talent and a different feel from our West Coast offices, and Dallas promises to be an excellent new home.</p><h3>Redfin already has key businesses in Dallas</h3><p>As a real estate brokerage, Redfin employs people across the country (and in <a href="https://www.redfin.ca/">Canada</a>!), not just in Seattle and San Francisco. Seattle is where the company was founded, and hosts our bustling headquarters with people in every department. San Francisco has been focused on technology from the beginning, with a smaller, more intimate atmosphere. In Dallas, we’ll have something in between: we already have a diverse array of roles and businesses operating in the Dallas area, including our core brokerage, Redfin Mortgage, support operations, and most recently, <a href="http://press.redfin.com/phoenix.zhtml?c=252734&amp;p=irol-newsArticle&amp;ID=2386896">RedfinNow</a>. Our local engineers will join these groups in a brand new office in Frisco, TX, working closely alongside these teams to build even better products for our customers.</p><h3>Dallas presents new opportunities</h3><p>The first engineers we hire to the new Dallas office have the unique opportunity to shape our engineering culture. While joining a company with nearly 200 engineers, they’ll also be setting the tone for the new Redfin Dallas identity and how we work with our existing offices in Seattle and San Francisco. We’re looking for people who are eager to build a new team atmosphere from the ground up, who can communicate with clarity and empathy both in person and virtually, and who love to roll up their sleeves and get things done.</p><p>The first full-stack engineering positions for our new office have been posted to our careers site. We’re starting with just a few positions on our Tours team (my team!), and we expect to open a few more roles later this year. We hope our new location will offer current Redfin engineers a new option for where to live, and bring new talent and perspectives from the Dallas area to Redfin as a whole.</p><p>You can always find our currently available engineering positions <a href="https://www.redfin.com/careers/departments/engineering">here</a>. We’re hiring in all three engineering locations!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f10978218249" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/why-redfin-is-opening-a-dallas-engineering-office-f10978218249">Why Redfin Is Opening a Dallas Engineering Office</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[You Can Cheat When Fixing HTML Accessibility in Legacy Code]]></title>
            <link>https://medium.com/code-red/you-can-cheat-when-fixing-html-accessibility-in-legacy-code-ee41ac2d0df0?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/ee41ac2d0df0</guid>
            <category><![CDATA[html]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[accessibility]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Dan Fabulich]]></dc:creator>
            <pubDate>Thu, 10 Jan 2019 19:02:46 GMT</pubDate>
            <atom:updated>2019-01-10T19:02:46.588Z</atom:updated>
            <content:encoded><![CDATA[<h4>How and when to cheat on semantic HTML accessibility guidelines</h4><p><em>Dan Fabulich is a Principal Engineer at Redfin. (</em><a href="https://www.redfin.com/about/jobs?utm_source=engblog"><em>We’re hiring</em></a><em>!)</em></p><p>I’ve been spending the last month or so updating some legacy HTML to support <a href="https://webaim.org/techniques/screenreader/">screen readers</a>. Screen-reader software can read a web page aloud, allowing visually impaired users to understand and interact with the page.</p><p>The problem is, sometimes the developers used &lt;span&gt; or &lt;div&gt; elements where they could have used &lt;button&gt; elements. Keyboard users can focus &lt;button&gt; elements with the Tab key, and click on them with the Enter key or Space bar; screen readers use the same rules.</p><p>By default, none of those keyboard shortcuts work for &lt;span&gt; or &lt;div&gt; elements. (In some cases, developers used &lt;a&gt; elements without an href attribute, which, as we’ll see, is no better than a &lt;span&gt; for accessibility.)</p><p>The “right thing” is to convert these elements into proper &lt;button&gt; elements, and, if needed, update the corresponding CSS rules to match the &lt;button&gt; instead of the old &lt;span&gt;/&lt;div&gt; element.</p><p>But the right thing turns out to be harder than you might think. Below are a few situations where the “right thing” can run into trouble; where possible, I’ve provided ways to cheat.</p><blockquote><em>It’s like the right thing, but … different.</em></blockquote><h3>Buttons Can’t Display Inline</h3><p>Check out <a href="https://codepen.io/dfabulich/pen/gZdrMB">this sample</a>. It includes a simple &lt;button&gt; with all: unset anddisplay: inline.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodepen.io%2Fdfabulich%2Fembed%2Fpreview%2FgZdrMB%3Fheight%3D600%26slug-hash%3DgZdrMB%26default-tabs%3Dhtml%2Cresult%26host%3Dhttps%3A%2F%2Fcodepen.io&amp;url=https%3A%2F%2Fcodepen.io%2Fdfabulich%2Fpen%2FgZdrMB&amp;image=https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fm.cdpn.io%2Fscreenshot-coming-soon-small.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codepen" width="800" height="600" frameborder="0" scrolling="no"><a href="https://medium.com/media/49b1d1c9f18f7ee9bfa461cd271414c8/href">https://medium.com/media/49b1d1c9f18f7ee9bfa461cd271414c8/href</a></iframe><p>Even though we forced the button to display: inline, you&#39;ll find that it&#39;s using display: inline-block, ignoring the style we set. That&#39;s why the “bar” button wraps to the second line, rather than appearing on the same line as “foo.”</p><p>This is the specified behavior in the <a href="https://www.w3.org/TR/html53/rendering.html#the-button-element-rendering">HTML Rendering specification</a>.</p><blockquote><strong><em>10.5.2. The button element</em></strong></blockquote><blockquote><em>The </em><em>&lt;button&gt; element is expected to render as an &#39;inline-block&#39; box rendered as a button whose contents are the contents of the element.</em></blockquote><p>This language is a bit cryptic, but what it means is that &lt;button&gt; elements will refuse to display: inline, even if you use !important.</p><h4>Use the Dark Side: Make a Fake Accessible Button</h4><p>The only way to cook up a button with display: inline is to do the “wrong” thing, using a non-button &lt;span&gt; element with an onclick handler.</p><p>To make those spans behave like buttons in a screen reader, you can add the <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role">role=&quot;button&quot;</a> attribute and the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex">tabindex=&quot;0&quot;</a> attribute. You&#39;ll also want to add a keydown handler to handle the Enter and Space keys, like this:</p><pre>span.addEventListener(&#39;keydown&#39;, function(e) {<br>  if (e.keyCode === 32 /*Space*/ || e.keyCode === 13 /*Enter*/) {<br>    e.target.click();<br>  }<br>});</pre><p>In my case, this is very close to what was already there in the legacy code, so adding the roleand tabindex attributes plus a keydown handler is sometimes quicker and easier than doing the “right thing.”</p><p>By using the tag name that was already in the code, I didn’t need to modify any CSS to fix selectors that were expecting a &lt;span&gt;.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/620/0*e_GB0MopfdAzwP4t.jpg" /><figcaption>Emperor Palpatine would be proud</figcaption></figure><h3>Buttons Will Submit Forms by Default</h3><p>If the &lt;div&gt; that we&#39;re converting to a &lt;button&gt; happens to appear in a &lt;form&gt;, you&#39;ll find that the &lt;button&gt; becomes a submit button for the form.</p><p>That’s probably not what you intended!</p><p>&lt;button&gt; is implicitly &lt;button type=&quot;submit&quot;&gt; by default. To prevent this, you can use &lt;button type=&quot;button&quot;&gt; instead.</p><p>type=&quot;button&quot; is clearly defined in the <a href="https://www.w3.org/TR/html53/sec-forms.html#element-statedef-button-type-button">HTML spec</a>:</p><blockquote><em>Do nothing.</em></blockquote><p>That’s my kind of button! <em>Some</em> people say that nothing is impossible, but type=&quot;button&quot;proves them all wrong.</p><p>(Or you can use a fake button, as above.)</p><h3>Links Without Href Aren’t Accessible</h3><p>Occasionally, UI designers call for buttons that have link-like styling. In the legacy code I’m working on, I see a lot of &lt;a&gt; elements with no href and an onclick handler; these are effectively buttons that look like links.</p><p>But code like this is secretly busted:</p><pre>&lt;a onclick=&quot;alert(&#39;hi&#39;)&quot;&gt;hi&lt;/a&gt; </pre><p>In Chrome, that HTML won’t even appear as a link; it won’t have the default underline styling, and it won’t have a cursor pointer when you hover over it. Developers sometimes work around that by adding styling:</p><pre>a {<br>  text-decoration: underline;<br>  cursor: pointer;<br>} </pre><p>… but that doesn’t fix the accessibility issues with these broken &lt;a&gt; elements. You can&#39;t use the Tab key to select these broken links, and you can&#39;t use the Enter key to use them.</p><p>&lt;a&gt; without href is no better than a &lt;span&gt;.</p><p>So, what can we do?</p><ol><li>Add a fake href to the link, e.g. href=&quot;javascript:void(0)&quot;</li><li>Convert the &lt;a&gt; into a &lt;button&gt;, but beware the issues raised above.</li><li>Convert the &lt;a&gt; into a fake button, as above. They&#39;ll need tabindex=&quot;0&quot; and a keydown handler. While you&#39;re at it, you might as well add role=&quot;button&quot;.</li></ol><h3>Keyboard Accessibility Requires a Visible Focus State</h3><p>The default focus outline for links and buttons doesn’t always look great. Some developers “fix” this by removing the outline entirely, with outline: none styling on all buttons and links.</p><p>But when you’re tabbing around the screen, the focus outline is the only way to know which element is selected. Thus, outline: none breaks keyboard navigation, even if all of the elements are technically keyboard navigable.</p><p>(This is an example where we need to think about multiple forms of accessibility. Blind users may not benefit from visible focus states if their screen reader provides auditory cues to indicate which element is selected, but other users who require a keyboard will benefit.)</p><p>In my case, the original designers didn’t like the default focus outline, but they were careful about adding a nice hover state for all elements, using the :hover pseudo-selector. By adding the :focus pseudo-selector to those same rules, I could use our lovely hover state as the focus state.</p><p><strong>That’s all for now! Now get out there and do your best.</strong></p><p><em>P.S. </em><a href="https://www.redfin.com/about/jobs?utm_source=engblog"><em>Redfin is hiring</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ee41ac2d0df0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/you-can-cheat-when-fixing-html-accessibility-in-legacy-code-ee41ac2d0df0">You Can Cheat When Fixing HTML Accessibility in Legacy Code</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Redfin Engineering’s Hour of Code Event at Local Schools]]></title>
            <link>https://medium.com/code-red/redfin-engineering-hour-of-code-event-at-local-schools-709d465594c1?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/709d465594c1</guid>
            <category><![CDATA[hour-of-code]]></category>
            <category><![CDATA[community]]></category>
            <category><![CDATA[volunteering]]></category>
            <category><![CDATA[giving-back]]></category>
            <category><![CDATA[education]]></category>
            <dc:creator><![CDATA[Tim Duffey]]></dc:creator>
            <pubDate>Fri, 04 Jan 2019 21:23:37 GMT</pubDate>
            <atom:updated>2019-01-08T19:00:28.392Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*01JhUsCoolw66X2bvdA_6A.jpeg" /><figcaption>Redfin engineers posing in front of the signs of the Seattle area middle schools they visited for the Hour of Code event.</figcaption></figure><h3>Redfin engineers attended Seattle area middle schools to lead an Hour of Code event.</h3><p>Redfin recently led an event to give back to the community and provide our engineers an opportunity for team building. During a single day of the 2018 <a href="https://csedweek.org/about">Computer Science Education Week</a>, groups of Redfin engineers traveled to seventeen Seattle middle school STEM classes to run an <a href="https://hourofcode.com/us">Hour of Code</a> with over 400 students. The goal: to inspire students to explore technology. The hope: to have students get excited about a technology career they would like to explore. Maybe, some would even become a Redfin engineer! Redfin provided each of the nine participating teachers with a choice of three hands-on, “unplugged” activities. Alvin Tran, one of our engineers, said about the event, “I really liked the feeling of having inspired some children in getting more interested in Computer Science. It also gave me a good chance to meet with members of teams other than my own, and to converse with them more.”</p><p>In order to ready our engineers for the event, we held three orientation sessions, one for each activity. At these sessions, the large group of engineers watched a small group of their peers demonstrate the activity. Through this strategy, all the engineers rose to the occasion. Early in December, each group of engineers hopped in a rideshare and headed out from Redfin headquarters to their assigned school. Although not every engineer felt totally confident about facing a class of middle schoolers, each engineer who responded to the post-event survey said he or she would do this type of event again. “It felt good that Redfin was giving back to the community,” said Shri Repp another of our engineers. “Was great to do something to help a younger generation get involved in tech.”</p><p>As for the teachers, all who responded to the survey also said they would like to participate again. “[I liked] how interactive the engineers were with the students. I think it helped them see the engineers as people like them which helps with role modeling,” said Dianna King, a teacher at Whitman Middle School. According to the teachers surveyed, the activities also went over well with the students. “Several students in [my] coding [class] understood the internet better after the lesson,” said Beverly Ferguson, a teacher at Hazel Wolf STEM K-8 School.</p><p>At the end of each class, a Q&amp;A session gave students the opportunity to ask our engineers how they got into technology and what it’s like working in the technology industry. Annie Jarnagan, a teacher at Asa Mercer International Middle School, exclaimed, “This was by far the students’ favorite part!”</p><p>One of the highlights and heartwarming moments for our engineers, was a drawing created by one of the students at Catharine Blaine K-8 School. During class, the student hand drew a picture of what she thought Redfin is. She then handed it to one of our engineers at the end of class.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_KWjoJlN2geT1bgtIJfFXA.jpeg" /><figcaption>A drawing of Redfin by one of the students at Catharine Blaine K-8 School in Seattle given as a gift to one of the Redfin engineers helping to lead her class for the Hour of Code event.</figcaption></figure><p>If you or your organization would like to lead a similar event at your local area schools, feel free to comment on this blog article and let us know. We would be happy to provide tips and lessons learned to get your event off the ground running.</p><p>Also, if you’re considering a career change or are looking for work, Redfin is hiring! Check out the <a href="https://www.redfin.com/careers">Redfin careers page</a> to learn more and apply.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=709d465594c1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/redfin-engineering-hour-of-code-event-at-local-schools-709d465594c1">Redfin Engineering’s Hour of Code Event at Local Schools</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[My Redfin Internship]]></title>
            <link>https://medium.com/code-red/my-redfin-internship-68d6de9e00dd?source=rss----1f8b86d56cad---4</link>
            <guid isPermaLink="false">https://medium.com/p/68d6de9e00dd</guid>
            <category><![CDATA[redfin]]></category>
            <category><![CDATA[software-developer]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[redfintern]]></category>
            <category><![CDATA[internships]]></category>
            <dc:creator><![CDATA[Redfin Engineering]]></dc:creator>
            <pubDate>Fri, 07 Dec 2018 15:01:01 GMT</pubDate>
            <atom:updated>2018-12-10T18:22:12.939Z</atom:updated>
            <content:encoded><![CDATA[<p>Seattle or San Francisco? Why not both?</p><blockquote>By Kyle Wong</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/947/1*x7ETgTL70meMQ2ORgtHXoA.png" /></figure><p>As someone who was born and raised in California, avocados are staple food. On my first day of internship, after meeting all the interns, my amazing team (<strong>Agent Efficiency #AE</strong>), and a few other Redfin employees, I had some free time to explore the office. Out of curiosity, I checked out the kitchen, only to realize that there are so many avocados, even more than my previous internship in Downtown LA! This inspired my daily routine during work. When I arrive at the office around 8 AM, I make avocado toasts with different variations: with whole wheat bread or everything bagel, and any combination of the following: lemon, egg, sunflower seeds, pumpkin seeds, olive oil, salt, and black pepper. Now, I can still be a Californian in the beautiful city of Seattle.</p><p>Besides the daily routine, I had a very worthwhile internship. Based on what I hear from friends in some companies, I enjoyed the fact that Redfin gives a lot of important responsibility to interns, treating them as full-time employees. For instance, my team encouraged me to take on the tech debt representative role during the Seattle Redfin Summer 2018 Hackathon, which was initially daunting since I only had knowledge in a small subset of the team’s codebase.</p><blockquote>Regardless, no matter which Redfin office I was at, Redfin consistently has an amazing company culture.</blockquote><p>Also, Redfin interns (aka Redfinterns) get the chance to work on something challenging. For me, I had minimal experience working in the backend, which gives my team more reason to give me a project that has a heavy backend component. While I struggled a lot, asked many questions, and getting roasted on code reviews, I ended my internship learning so much and became a better software engineer. I also ended up producing a working feature in the agent tools: New Mutual Notifications on the Deal Queue. This project provides notifications to transaction coordinators on what deals reached the mutual acceptance stage recently, so the transaction coordinators can quickly work on those deals. According to my mentor and manager, this project is impactful as it meets the quarterly goal of making the deal queue more efficient by reducing response time of new mutual deals by 10% and providing ways to improve the customer experience of buying houses at Redfin. I am grateful I got to make a real impact to the company during the short period of time that is 12 weeks.</p><p>I also enjoyed the work-life balance Redfin strongly encourages. While working, there are Slack channels that are meant to be entertaining such as the #donuts channel, where you get “donuted” if you forget to lock your laptop when you leave the room; in other words, you have to bring donuts if someone posts “I bring donut” from your unlocked laptop in the #donuts channel :woot:! In the office, there is a wonderful game room with a ping pong table, video games, and a huge selection of board games. There are also fun outdoor intern events such as white water rafting at the Sauk River and hiking with Glenn the CEO at Poo Poo Point. In addition, we also got to participate in the general company events such as the summer hackathon, “social hours,” and picnic.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/930/0*84Fr98ZnPKmzCPm8" /></figure><p>Personally, outside of work, I visited many places in Seattle, from the typical Space Needle and Chihuly Garden and Glass to hidden gems such as Chophouse Row and sunset at the Volunteer Park “donut” (It’s actually called the “Black Sun”). To satisfy my wanderlust, my manager even allowed me to work at the San Francisco office for a week (they have fewer avocados, ironically), so I got to experience the best of both worlds! Regardless, no matter which Redfin office I was at, Redfin consistently has an amazing company culture. I met amazing and brilliant people at both places; without all the people I met at Redfin, I honestly would not have learned as much and would not have gotten a lot out of this internship.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*uBAc2GDt8v4BnR9kNBsl-Q.png" /><figcaption>Kyle Wong, Software Developer — Agent Efficiency Team</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=68d6de9e00dd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/code-red/my-redfin-internship-68d6de9e00dd">My Redfin Internship</a> was originally published in <a href="https://medium.com/code-red">Code Red</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>