<?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[Stories by Gonzalo on Medium]]></title>
        <description><![CDATA[Stories by Gonzalo on Medium]]></description>
        <link>https://medium.com/@gonchub?source=rss-e6c79a0d1847------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*JgfKEinB21XiPU1ysBo2Qw@2x.jpeg</url>
            <title>Stories by Gonzalo on Medium</title>
            <link>https://medium.com/@gonchub?source=rss-e6c79a0d1847------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 30 May 2026 05:39:17 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@gonchub/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Paying technical debt in the front-end]]></title>
            <link>https://medium.com/miro-engineering/paying-technical-debt-in-the-front-end-8666ef0c32d1?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/8666ef0c32d1</guid>
            <category><![CDATA[collaboration]]></category>
            <category><![CDATA[teamwork]]></category>
            <category><![CDATA[frontend]]></category>
            <category><![CDATA[technical-debt]]></category>
            <category><![CDATA[software]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Thu, 16 Sep 2021 08:30:14 GMT</pubDate>
            <atom:updated>2021-09-16T08:30:14.168Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*ohRWI4bA_LpzcOt6" /><figcaption><a href="https://unsplash.com/photos/Olki5QpHxts">https://unsplash.com/photos/Olki5QpHxts</a></figcaption></figure><p>We all love to hate technical debt. It’s one of the main reasons projects don’t reach their milestones on time. Tasks take longer than expected, and what should be a simple change ends up being a huge endeavor that nobody can predict, nor estimate. What can we do when technical debt bogs us down, sprint after sprint? <strong>Pay the debt.</strong></p><p>As with finance, the bigger your debt, the longer it takes to pay it back. At some point in the past, building technical debt allowed the company to move forward faster: move fast now, implement technical improvements later. It’s only after some time that this debt starts to collect interest in the form of delayed tasks. We need to take action and <strong>come up with a plan</strong>.</p><p>In our case, we had a huge debt to pay in terms of the front-end libraries we used. A year and a half ago, most of the code you stumbled upon in Miro’s front-end client was written in an outdated version of Angular. Although React was on our guild’s roadmap for new features, there were still big chunks of Angular floating around in the codebase.</p><p>Fortunately, our client was already modular, with the application being split into 3 distinct parts: the board, the dashboard, and the settings. It was natural for us to <strong>divide and conquer</strong>, tackling each of these concerns one at a time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d-9wjMNcMD4y3korH5yQig.png" /><figcaption>Security settings for a company</figcaption></figure><p>I’ll focus on the settings part of the migration from Angular to React.</p><p>If you have never used Miro before, or if you’ve never been an admin, this is how our top-level company settings look like. Navigation is on the left, and the main content is displayed on the right, along with some extra navigation controls such as profile and going back to the dashboard. The pages on the left can include tabs and other navigation levels to provide admins with a set of controls to change settings, and to manage their users.</p><p>Our teams were growing fast, and that meant 2 things for us:</p><ul><li>We could leverage the power of <strong>collaboration</strong> and move faster in this migration. The more, the merrier.</li><li>Different teams also have their own objectives, so we couldn’t stop all development and just migrate. This meant that some functionality would evolve while migrating; this increased complexity.</li></ul><p>Fortunately, all the teams wanted to move away from the legacy version of Angular, and although we were not fully dedicated to this project, we had the buy-in to improve things as a whole front-end stream.</p><p>We started our journey by analyzing the current status of the codebase, visualizing and color-coding the different technologies that were being used to build the whole solution.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xdMAsyCSuEdI8_Jq48xV1g.png" /><figcaption>The partial status of the migration is shown using Miro. Pink means Angular code, Black means React code.</figcaption></figure><p>This very simple representation of our codebase allowed us to further split the problem into smaller chunks that we could tackle in sprints: <strong>divide and conquer.</strong></p><p>As a side note, we love to use Miro to build Miro. We created a huge board just for this migration, which also contained presentations to show progress to stakeholders, and to recruit others to join our quest during front-end guild meetings.</p><h3>Enter the migration</h3><p>Our team was only a few months old when we started this migration; the codebase had been there for years before us. Nobody in our team had a complete understanding of how the small moving parts made up the whole solution. But who doesn’t love layered cakes?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*gD05IqV_ll7_jo5j" /><figcaption><a href="https://unsplash.com/photos/PPfAUR-jAis">https://unsplash.com/photos/PPfAUR-jAis</a></figcaption></figure><p>Layered architectures have been around for a long time. It’s a simple, yet powerful way to separate concerns. In general, you see this approach involving the front-end, the back-end, the database, and all the other parts you need to build a product. We wanted to use the same approach, but zooming in for the front-end only. This allowed us to split our big problem even further!</p><p>The 3 main layers in the front-end were:</p><ul><li>State management layer: it used a legacy library that we were also planning to deprecate. We decided to not touch it at this point, and to abstract the implementation details as much as possible from our codebase, making it <strong>easy to change</strong> in the future.</li><li>Business logic layer: making HTTP calls to our server and implementing business rules. A mix of fat Angular components and some JavaScript services and functions. These components also implemented responsibilities from the next layer.</li><li>Presentation layer: rendering our UI. Multiple Angular components built this layer. Many of them were reused in other parts of the application, outside the scope of our settings module.</li></ul><h4>The bottom layer</h4><p>To maximize our impact during the migration, we opted for a bottom-up approach. We wanted to start from the visual layer, extracting some of our reusable components into the work-in-progress design system that we were also building. We were also shaping design system contracts, and starting discussions on how to interact with them. Our migration helped other teams with their migrations: <strong>teamwork is key</strong> in big migrations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/794/1*pwtQ_5-9wqtMIp8zXcZi1g.png" /><figcaption>Partial extension of the middle layer to add consistency to the bottom layer.</figcaption></figure><p>During this part, we had to extract some pieces of logic that weren’t entirely presentational upwards in the chain of responsibility, sometimes extending our already fat Angular components to do some extra heavy lifting. This was temporary, as the business layer was next on our list.</p><h4>The middle layer</h4><p>The business layer was one of the trickiest to migrate, mainly because many of us were still learning some domain rules and objects that were at play in these fat Angular components. We already had a working product, so we did not want to break it during our migration. It would have been amazing if we’d had 100% complete documentation on how our components were supposed to work, but asking for that is science fiction. To solve this, <strong>teamwork</strong> played a key part again: we knew who to ask questions to, and we were not shy to do so. We were all in this together, and we wanted to complete the puzzle.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T0Sg7kQaZSqOMu3AbnKv9Q.png" /><figcaption>Using custom hooks to encapsulate form logic.</figcaption></figure><p>Since we were migrating from Angular to React, we made heavy use of custom hooks, built-in hooks, and context to split the existing fat components into slimmer ones, with fewer responsibilities. We composed and reused small components as much as possible, and we completely abstracted state management from these components. We wanted to have a single connection between our state management layer and the tree of components we were building. Our abstractions aimed toward this goal, which would make <strong>change easier</strong> in the upcoming migration.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Rroptt8RWDyempsj02Kq9A.png" /><figcaption>Separating a feature into layers, using Miro.</figcaption></figure><h4>The top layer</h4><p>Although changing the state management layer wasn’t in our scope, we knew that the next migration would involve replacing it as a whole. Working through Layer 1 and Layer 2 gave us enough knowledge about how the system worked; this was key in understanding what steps we needed to take for the migration, and how to <strong>minimize its risks</strong>.</p><h4>The quality assurance</h4><p>At each phase of the migration, we had a working product; we had a working product even before starting migrating. We didn’t want to introduce regressions as we migrated; <strong>quality is of paramount importance</strong>. Unfortunately, most Angular components lacked unit tests. Writing unit tests for each component we rewrote made us confident that we could ship regularly.</p><p>It’s extremely important to write unit tests as you go. There are so many components, and telling yourself you’ll write them all after completing the migration is wishful thinking. Writing tests is key to understanding what role your components play in the whole solution; this helps improve your component APIs, and also test against regressions you might introduce (we’re not perfect, bugs do happen).</p><p>We also did a lot of manual testing to increase the existing coverage of our end-to-end tests.</p><h3><strong>Finishing your quest</strong></h3><p>Starting a big migration is a huge step forward toward improving your day-to-day operations and developer experience. Finishing it is crucial. Nobody likes technical migrations that last forever. We’re software engineers <strong>delivering product increments</strong> — this is our key metric.</p><p>We stated a clear scope to finish the migration. Our scope was the settings module. As it can take a lot of time, showing progress and intermediate milestones to stakeholders and other front-end engineers helped us reach the finish line. We ran presentations at guild meetings to share progress and learnings, and to inspire other engineers to join our crusade against this huge technical debt. We organized our migration into a big epic in JIRA, and allowed others to join us whenever they had free time in their sprint. By harnessing <strong>collaboration</strong> <strong>and</strong> <strong>parallelization</strong> of tasks, you get to finish earlier, and knowledge spreads organically across the collaborators.</p><h4>What did we unblock?</h4><p>Since the beginning, our goal was to unblock future initiatives. We just could not make them happen in time without paying some of our technical debt.</p><p>After finishing the first iteration of the React migration, we unlocked progress in these areas:</p><ul><li>Accessibility features: with Angular out of the way, we were now ready to start implementing them.</li><li>State management migration to Redux: all the knowledge we gained, as well as abstracting details away from components, meant we were ready for the next step.</li><li>Speed of development: better developer experience and unit tests sped up the development of <strong>all features</strong>.</li><li>Taking care of our codebase: as we’re not dealing with “legacy code” anymore, there are more initiatives to improve our codebase, little by little.</li><li>Faster onboarding of new engineers: nobody wants to deal with an unsupported version of a front-end library.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fR9A-mWpiZ6IcLUEGed-2A.png" /><figcaption>Using Miro to build Miro, harnessing sync &amp; async collaboration 😍</figcaption></figure><h3>Join our team!</h3><p>Would you like to be an Engineer at Miro? Check out opportunities to join the <a href="https://miro.com/careers/">Engineering team</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8666ef0c32d1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/miro-engineering/paying-technical-debt-in-the-front-end-8666ef0c32d1">Paying technical debt in the front-end</a> was originally published in <a href="https://medium.com/miro-engineering">Miro Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Working with priorities that change]]></title>
            <link>https://medium.com/@gonchub/working-with-priorities-that-change-bce2b798cd04?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/bce2b798cd04</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[scrum]]></category>
            <category><![CDATA[project-management]]></category>
            <category><![CDATA[agile]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Fri, 10 Sep 2021 12:37:10 GMT</pubDate>
            <atom:updated>2021-09-10T12:37:10.558Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1mMGkOOCjna6GXlTsDuUPw.jpeg" /></figure><p>One thing you learn from working at a <strong>B2C</strong> company is the following: the priorities of your team will change for the company to maximize value to the customer, which in turn maximizes value for the company 💰.</p><p>We, software engineers, are not hired to sit down and produce lines of code (at least I hope) that get sent into an s3 bucket. We are hired to build a product that will be consumed ✨.</p><p>The product we end up building gets affected by several factors. Some of these factors are not controlled by the team, but may still end up affecting the team’s roadmap. A couple of examples are:</p><ul><li>🤑 Strategic partnerships</li><li>👩‍⚖️ Legal deadlines</li><li>📣 Customer feedback</li><li>📈 Funnel optimizations</li><li>📉 Cost optimizations</li><li>🎛 Integration with other flows/teams</li></ul><p>To be completely fair, at any point in time a company might value one of these things over the others depending on the context. This will, in turn, alter the team backlog and priorities 🎯.</p><h3>Don’t panic 🥵</h3><p>Changes in priorities are a normal thing that can happen in any company, and that’s ok. <strong>Constantly </strong>changing directions and priorities is something to be avoided. If you are constantly changing what’s important, the team will start losing trust in your definition of important or high priority.</p><h3>Some suggestions from a fellow engineer 👨‍💻</h3><h4>Don’t create abstractions, go declarative 🖼</h4><p>If priorities and projects are changing very quickly, it starts getting hard to build good data structures and abstractions that fit the model. What covers “all scenarios” today might not be the same tomorrow.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f234d33ae18ecf7401141b5ce924dcb1/href">https://medium.com/media/f234d33ae18ecf7401141b5ce924dcb1/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/066eabd51e5e11ac031d8c25a3011b31/href">https://medium.com/media/066eabd51e5e11ac031d8c25a3011b31/href</a></iframe><p>If I had to choose between these two implementations, in an environment where product specs are not stable, I would go with Option 1. It is more verbose, it <strong>duplicates code</strong>, it takes up more space, but I don’t need to maintain a method that should cover “all possible payment methods” (the ones that we have, and the ones we will have). If a spec arrives saying that we should track differently with PayPal than with credit card, the change is trivial.</p><p>Cheng Lou gave a great talk about the cost of abstraction at <a href="https://www.youtube.com/watch?v=mVVNJKv9esE&amp;t=1s">react-Europe 2016</a>.</p><h4>Invest in refactoring what’s stable 🐴</h4><p>If we take the approach mentioned in the previous point with everything, soon we will have a very “duplicated” codebase. A changing environment doesn’t impact all parts of the codebase equally.</p><p>What we thought a while ago was a “workaround” might very well be our new “way of doing things”. When this happens, it is worth considering doing a refactor and removing some of the duplications and inconsistencies.</p><h4>Feature flag your development 🚩</h4><p>Feature flags allow teams to modify the behavior of their products without changing the code. This means that by just changing configuration (the values of the feature flags/feature toggles) our code behaves differently.</p><p>This is useful mainly for two things:</p><ol><li>It allows you to mitigate the risk of your new features getting released. If the new features can just be turned off, the risk is decreased at the time of release. This also allows you to release before a product launch (you can release 1 week before the launch and just turn it on when the time is right).</li><li>It allows you to merge incompatible code into your master branch. For example, things could break when migrating from v1 to v2 of your API endpoints. If your changes would just replace v1 calls with v2, a full revert/rollback would be needed if anything goes wrong at the time of release. With a feature flag, your code works with both v1 and v2.</li></ol><p>As a downside, working in this way might have a considerable learning curve for the team.</p><h4>Focus in stabilizing and automating your workflow 🤖</h4><p>If your product definitions are changing, you can still focus on everything else. Are you happy with your tests? Are you wasting time doing manual tasks? Is your release pipeline stable?</p><p>Invest the time that will enable the team to be faster and more productive in times where product definitions are not great.</p><h4>Don’t rush features, have a clear plan 🏃‍♀️</h4><p>Rushing will only make matters worse.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bce2b798cd04" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Hiring a team or hiring resources?]]></title>
            <link>https://medium.com/@gonchub/hiring-a-team-or-hiring-resources-1b019f50f384?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/1b019f50f384</guid>
            <category><![CDATA[management]]></category>
            <category><![CDATA[talent]]></category>
            <category><![CDATA[hiring]]></category>
            <category><![CDATA[growth]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Mon, 06 Jan 2020 11:14:35 GMT</pubDate>
            <atom:updated>2020-01-06T13:56:20.183Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HGs9pgk9gyzkrDM6wd9h5w.jpeg" /><figcaption><a href="https://unsplash.com/photos/2xaF4TbjXT0">Black chair lot</a> in Gothenburg, Sweden</figcaption></figure><h3>Different ways of growing teams</h3><p>Different companies have different growth needs, and they undergo their growth at different times and paces. Within companies that grow their development workforce, you can find companies that are <strong>almost always</strong> looking to hire people, at a stable pace, because their business and business prospects are also growing linearly. On the other side, you have companies that are about to take on a big challenge (in terms of the organization’s history) and need to <strong>grow fast</strong> to avoid missing the current business opportunities.</p><p>My last 4 jobs have been in companies that need to <strong>grow fast</strong> (some faster than other ones), and I’ve mainly experienced two different ways this growth usually takes place:</p><ul><li><strong>Burst</strong>: understand how much more capacity (in terms of talent or manpower) you need and hire it as fast as you can get a hold of the talent. You will feel the output difference very early, as you get all your capacity “working” straight away. The biggest challenge lies in making sure more output is actually contributing to the original company goal, or if so many people were hired that some are pulling in a direction that does not contribute to the overarching goal. Another thing to take into account is whether your HR solution is able to onboard talent in big batches and follow up properly.</li><li><strong>Controlled</strong>: instead of hiring all at once, do it iteratively. Build individual teams “one by one” (or a rate that allows you to pivot and learn from your own process). This approach is less risky. It allows you to learn about your own process and is less tricky for new-joiners, but the growth is slower and the output difference takes more time to become a reality.</li></ul><p>When deciding how to grow, remember the following:</p><blockquote>“Adding manpower to a late software project makes it later.”<br><em>Fred Brooks in his 1975 book</em> The Mythical Man-Month</blockquote><h3>What makes up a team?</h3><p>A group of people assigned to work together is not a <em>team</em>. In order to build teams that produce greater results than the sum of the individual team member’s contribution, one must look at the <strong>soft side</strong> of software engineering.</p><p>In his book <em>Peopleware: Productive Projects and Team</em>s from 1987, Tom DeMarco and Timothy Lister introduce the concept of <em>jell</em> to define a particular phenomenon:</p><blockquote>“Once a team begins to jell, the probability of success goes up dramatically. The team can become almost unstoppable, a juggernaut for success. Managing these juggernaut teams is a real pleasure. You spend most of your time just getting obstacles out of their way, clearing the path so that bystanders don’t get trampled underfoot. […] They don’t need to be managed in the traditional sense, and they certainly don’t need to be motivated. They’ve got momentum.”</blockquote><p>When we understand that teams are made up of people that will work together (hopefully) for a very long time, the personality and ways of working of individuals play a big part in the team’s success. Even in the same organization, two teams can be very different and have different expectations for a new team member.</p><p>If you have 2 teams that need a front end engineer it is worth doing a debrief focusing on soft compatibilities and personalities, and not just team priorities in terms of business deadlines. The roadmap and future challenges a team will have can also be key differentials in retaining and motivating new joiners.</p><p>Thinking about your growth in terms of capacity requirements (man-hours, number of projects) instead of team requirements (teams that can solve problems within a domain), might lead you to a bunch of very good talent that doesn’t know how to work properly together. It might also lead you to the best possible talent that also works well together, but it is a gamble.</p><h3>The role of the Engineering Manager</h3><p>What is expected and what success looks like for an engineering manager (EM) changes widely from one company to the next one. The level of importance each company gives for business or completion objectives varies, and it should. What usually remains constant is the importance of the EM to hire new talent, retain existing talent, and helping team members in their career path.</p><p>Different stages of a company may require the role of the EM to have a bit less or a bit more of software involvement. In very mature and usually big companies, it is not very common to see EMs coding or discussing implementation details. Their day to day work revolves around identifying and resolving team blockers. In smaller startups, EMs are expected to help more with development tasks. At the end of the day, developers will do the heavy lifting in terms of work, so company objectives cannot be the responsibility of a single person (there are different ways to align goals, like <a href="https://rework.withgoogle.com/guides/set-goals-with-okrs/steps/introduction/">OKRs</a>). A manager can have different incentives to do so, but help from the development team is inevitable.</p><p>In terms of the number of direct reports, magic numbers are usually not very accurate. Some say a manager cannot have more than 7 direct reports, some say 10, some say more is possible. Being a role that requires so much soft skill, the number of people a manager can “take care of” depends greatly on the specific people he is managing and his own skillset in the current context. One thing is clear, <strong>at least for me</strong>: there is no way that a single person can be responsible for the growth and development of 20 people while still doing the rest of his job.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1b019f50f384" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A story on React, refactors and reuse]]></title>
            <link>https://medium.com/@gonchub/a-story-on-react-refactors-and-reuse-e86766358a93?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/e86766358a93</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[front-end-development]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Fri, 21 Jun 2019 08:52:24 GMT</pubDate>
            <atom:updated>2019-06-21T08:52:24.447Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LJjAhsvRPUZnznVMAcxh5Q.jpeg" /><figcaption>A React developer looking for “the best way” to do forms in a universe of alternatives and flavors. (I did not steal this image alt joke from a <a href="https://medium.com/u/db72389e89d8">Kent C. Dodds</a> article at all 😜)</figcaption></figure><p>I want to build a React sign in form. I’m a very experienced developer, so I know stuff like SOLID and DRY and I know performance is important in React, I don’t want my app to re-render every time, I’m better than that.</p><h4>What are we building?</h4><p>2 text inputs: one for email, one for password. A form wrapping both inputs. Some labels. When I submit the form, I want to alert the email and password values.</p><p><strong><em>Note to reader: I hacked all of these components in a couple of minutes. I could have committed React perjury. Viewer discretion is advised</em></strong></p><h3>Coding time</h3><p>I will start with CRA, because it is quite straightforward.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9ba1235ea3190d81e88f8add3f6dcab9/href">https://medium.com/media/9ba1235ea3190d81e88f8add3f6dcab9/href</a></iframe><p>I need two inputs and a submit button inside a form, and I need to be able to handle changes on these inputs, so I can update my local state. I can’t use hooks, because we don’t have the latest version of React at work.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/92b841e3fb1900b41d336c9d0c01360f/href">https://medium.com/media/92b841e3fb1900b41d336c9d0c01360f/href</a></iframe><p>Inputs seem to be very similar, so I can rewrite them to reuse a bit of code. I don’t want to repeat myself, I know what DRY means. I will create a TextInput component that receives a property name via props to render the appropriate components. Something like:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4becba37a7b066dc0c06a8aed31c2fad/href">https://medium.com/media/4becba37a7b066dc0c06a8aed31c2fad/href</a></iframe><p>Also, every time I change one of the inputs, the whole form will re-render. I know PureComponent checks the property values and will save me any additional re-renders. I know there’s something called React.memo, but IDK if that is something about hooks. I can’t use hooks in my project yet, so let’s trust in PureComponent:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/25b0a090a0117403ce6d6a4bcf178d76/href">https://medium.com/media/25b0a090a0117403ce6d6a4bcf178d76/href</a></iframe><p>I want my form component to still be able to submit the form with the relevant information. But information now also lives inside my TextInput component (because it has internal state to handle onChange). How can I reach that? I heard context is good for shared state, and there’s even official docs on how to update parent state from your nested components! That’s what I need! <a href="https://reactjs.org/docs/context.html#updating-context-from-a-nested-component">https://reactjs.org/docs/context.html#updating-context-from-a-nested-component</a></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0eabe645eb1ec39f3c23227d50d675ec/href">https://medium.com/media/0eabe645eb1ec39f3c23227d50d675ec/href</a></iframe><h3>Bye 👋</h3><p>These 2 solutions generate the same output, at least as far as “what I wanted to build”. If we want, we can get really smart, reuse and come up with abstractions that work right now. Should we?</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e86766358a93" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jest: Our journey into performant unit tests]]></title>
            <link>https://medium.com/dazn-tech/jest-our-journey-into-performant-unit-tests-a6efcb4bd9b?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/a6efcb4bd9b</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[jest]]></category>
            <category><![CDATA[unit-testing]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[performance]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Mon, 15 Apr 2019 08:11:00 GMT</pubDate>
            <atom:updated>2019-04-15T08:11:00.908Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E5YisxNx6MevEfrgsRzT-Q.jpeg" /><figcaption>Source: @bradbadmore <a href="https://unsplash.com/photos/YO-zXii_vlo">https://unsplash.com/photos/YO-zXii_vlo</a></figcaption></figure><h3>Introduction</h3><p>We recently migrated all of our unit tests from <a href="https://github.com/avajs/ava">AVA</a> to <a href="https://github.com/facebook/jest">Jest</a>. Our tests are <strong>11 (eleven) times faster</strong> now that we are done. We learned a lot during the process, and there are some things we would have done differently.</p><p>Do you feel your unit tests could be more performant? Do you feel your unit tests are not really testing <strong>units</strong>? Are you just curious about how we did it? Then you are in the right place.</p><h3>Start with why</h3><p>First of all, we had accumulated quite some technical debt in our tests. <strong><em>This is 100% on us</em></strong>, and we are not going to blame AVA or praise Jest for solving it. There were several AVA features we were not leveraging correctly, several tests were over-bloated, inconsistent implementations of same testing helpers, etc. This had a huge impact on the performance of our tests. A fresh look was something we were longing for.</p><p>We wanted to start doing mutation testing. Stryker has better support for Jest (<a href="https://github.com/stryker-mutator/stryker/blob/master/packages/jest-runner/README.md">jest-runner</a>) than AVA (<a href="https://github.com/stryker-mutator/stryker/issues/243">there are still ways to do it</a>) out of the box. In a nutshell:</p><blockquote>Bugs, or <em>mutants</em>, are automatically inserted into your production code. Your tests are ran for each mutant. If your tests <em>fail</em> then the mutant is <em>killed</em>. If your tests passed, the mutant <em>survived</em>. The higher the percentage of mutants killed, the more <em>effective</em> your tests are.</blockquote><p>Last but not least, we felt there were better tools than the ones we were using, and the Jest ecosystem is growing a lot.</p><h3>(Unit testing)</h3><p>I want to do a small stop here to introduce a few concepts, and to understand what we mean with unit testing. If we look it up in Wikipedia, we will find this particular bit:</p><blockquote>Ideally, each test case is independent from the others. Substitutes such as method stubs, mock objects, fakes, and test harnesses can be used to assist testing a module in isolation. Unit tests are typically written and run by software developers to ensure that code meets its design and behaves as intended.</blockquote><p>We want our tests to be independent. In order to do that we are going to follow <strong>3 basic principles:</strong></p><ol><li><strong>Mock all the things</strong>: if there is a dependency, mock it. Always favor isolation.</li><li><strong>Write once, configure many</strong>: if you create a mock of a module inside a test, make it configurable and move it to a shared place (more on this later).</li><li><strong>Understand your mock API</strong>: there are different actions that can be performed on mocks (<a href="https://jestjs.io/docs/en/mock-function-api.html#mockfnmockclear">see how Jest defines</a> mockClear , mockReset and mockRestore). There are also different ways of writing and generating mocks (see <a href="https://jestjs.io/docs/en/manual-mocks">manual mocks</a>).</li></ol><p><strong>Understand how the library you are using works. What is happening when you mock? This might seem trivial, but it is not.</strong></p><h3>The how — process and tools 🔧</h3><h4>Big bang ☄️</h4><p>We took a controversial, yet key, decision at the beginning of the migration: “<em>we are going to merge this in one go”</em>. Full big bang. No pull requests getting merged gradually into master.</p><p>You might think we are crazy. All that risk into a massive PR? What if it fails Who will code review it? We were confident enough to know that we would be in a better place after the migration, and we wanted to finish as fast as possible.</p><p>There is one clear benefit after making this decision: you don’t have 2 systems doing the same thing, at the same time. How do you calculate coverage with 2 test runs? We did not want to find out.</p><p>The main issue we found with this approach was conflict resolution, as we were modifying EVERY test file. Git conflicts were guaranteed, but we trusted our git skills.</p><h4>Conventions 🛑</h4><ul><li><strong>No mocks are automatically reset/restored</strong>: if you are faking behavior, be explicit about it when you set it up and tear it down. We clear our mocks after every run.<br><em>This reduced the “magic” factor when running tests for us.</em></li><li><strong>No external test helpers</strong>: avoid creating test abstractions that are needed just for tests. If we are repeating something a lot, let’s take a closer look, but don’t rush the test/helpers/**/*.js.<br><em>This made our tests very declarative, we don’t need to check another file to see what a test does.</em></li><li><strong>No console output</strong>: you should not output to the console during tests. Make sure you are not outputting prop-type warnings or something similar. These are hard to remove when you have more than one test running in parallel.<br><em>This allowed us to spot such warnings and fix them. Also, less noise.</em></li></ul><h3>The what — show me some code plz ⌨️</h3><p>You’ve made it this far without a single line of code. Let’s change that.</p><p>There are three major types of files throughout our codebase.</p><ol><li>Javascript functions or modules: normal javascript functions/classes/services, whatever you write in plain JS.</li><li>React components: the stuff you use to implement the <a href="https://github.com/mdn/sprints/issues/967">MDN header</a> 😬.</li><li><a href="https://github.com/mobxjs/mobx-state-tree">MST</a> stores: for state management, flow control, etc.</li></ol><blockquote><strong>Tip</strong>: Are you using redux? Interested in what MST is? Check out <a href="https://codeburst.io/the-curious-case-of-mobx-state-tree-7b4e22d461f">The Curious Case of Mobx State Tree</a></blockquote><p>Take a look at how we ended up testing each of these types by following what we explained before.</p><h4>Javascript functions or modules λ</h4><p>Not much to be added here. As long as you correctly mock your dependencies and follow our/your conventions, you should be good to go. Never used test.each before? <a href="https://jestjs.io/docs/en/api#testeachtable-name-fn-timeout">Take a look</a></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/82a8390576f7ecbb8679d27536fa67a3/href">https://medium.com/media/82a8390576f7ecbb8679d27536fa67a3/href</a></iframe><p>In this example, we are not stubbing the return value of getString. That is because we don’t really care about the actual value of a string. We just need them to be the same (by spec). getString works and its behavior is asserted in another <strong>unit </strong>test.</p><h4>React components ⚛️</h4><p>Our tests for React components are pretty similar across the board. We have very little business or any other logic in components itself, so they are easy to test and are only concerned about rendering &amp; calling back. We use <a href="https://github.com/airbnb/enzyme">Enzyme</a> to test their output. We don’t mount our components because, as we are unit testing, we don’t want to render the full tree (as of Enzyme v3, shallow rendering calls componentDidMount lifecycle hook, so we can still cover that).</p><p>Let’s take the following example of a Page component. It wraps the given body of the page (in the form of children) between a header and some footer links. We also expose TEST_IDS constants to be used in unit and other types of tests.</p><p>In many of our component tests you will find a getWrapper function, which provides a way to get the component that is currently being tested with some default props and the ability to override them. When you need a certain prop value for your test, you pass it along. When you don’t need anything in particular, just get something to work with (<em>write once, configure many</em>).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/86e0400b5fa9be85d162318b7d2f9c14/href">https://medium.com/media/86e0400b5fa9be85d162318b7d2f9c14/href</a></iframe><p>There are several ways of achieving similar coverage. Some people prefer to import specific components they want to assert are rendered. We find it enough to snapshot test these situations.</p><p>In order to simulate click, change or other events, we use Enzyme’s <a href="https://airbnb.io/enzyme/docs/api/ShallowWrapper/simulate.html">simulate API</a> a lot.</p><blockquote><strong>Tip</strong>: Using React, Enzyme &amp; Jest? Consider using <a href="https://github.com/FormidableLabs/enzyme-matchers/blob/master/packages/jest-enzyme/README.md#assertions">enzyme-matchers</a>, which allow you to write more expressive assertions.</blockquote><h4>MST Stores 🥤</h4><p>This was the most important part of the migration for us. Our MST stores hold all of the business logic and control every React component (directly or indirectly) being rendered. We needed to do this one right.</p><p>All of our stores are created in the following way:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f309b6629107583d0b144da44fa4350d/href">https://medium.com/media/f309b6629107583d0b144da44fa4350d/href</a></iframe><p><strong>Key difference in these tests:</strong> when we test MST stores, there isn’t a direct import to the file being tested. Weird, right?</p><p>We do this because we want to share our mocks throughout our tests. We don’t want to know how to create and configure our dependencies. I don’t know how to stub every method of my dependencies that might get called. So we always import a file from a mocks folder, but the exported default is not a mock…</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c59f0183c7ad714f410cb9bb37b8ab2e/href">https://medium.com/media/c59f0183c7ad714f410cb9bb37b8ab2e/href</a></iframe><p>This is the file that we will be testing. It is importing the implementation of the UserStore but we don’t import it from the test. The store is then created with its environment as Jest mocks. We also export a way to create a store with a given initial state (<em>write once, configure many</em>).</p><p>Apart from the configuration of the store itself, we also create a barebones manual mock for each of our <em>stores-with-mocked-dependencies</em> (the API is also modeled as an MST store). We just export the mocked API our tests will need to override behavior for:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e1f5ba197844a23ca5f888fa3eaeacce/href">https://medium.com/media/e1f5ba197844a23ca5f888fa3eaeacce/href</a></iframe><p>One could say this file structure is the only “helper” (or indirection) one needs to understand. Once you grasp this, you can test your stores like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9ff050e51615ddba2a31dd933ea944ec/href">https://medium.com/media/9ff050e51615ddba2a31dd933ea944ec/href</a></iframe><p>And there we go. api is already mocked and our store holds the correct reference. Same goes with errorStore , so we can just stub behavior and check that the code does what we need. These mocks are cleared after every test.</p><p>The test is expressive enough to understand what is going on. This makes it easier to find culprits for failing tests 🎉.</p><h3>Outcome</h3><h4>In numbers 💯</h4><ul><li>5 people from 2 teams were involved</li><li>Just <strong>1 sprint​</strong> 🏅</li><li>1 pull request</li><li>157 test suites​</li><li>958 tests​</li><li>22k lines rewritten​</li><li>More than <strong>11 times faster</strong>: 340s to 30s​</li><li>Line coverage 93.76%​</li></ul><p>As you can see it was a tremendous effort that involved a LOT of team collaboration and knowledge sharing.</p><h4>In words ✍️</h4><ul><li>Feeling of ownership: we now feel way more confident with our codebase. We have a very good feeling of ownership of our own code. We understand it, we have a plan for it.</li><li>Team bonding: this migration involved a lot of people. Although 5 people were the core collaborators for the migration, multiple people were onboarded during the process, because they wanted to help out. What did that do to the team? We bonded a lot during those 2 weeks, and we shared a lot thanks to the collaboration.</li><li>Thanks to Jest’s ecosystem and built-in features, we got rid of dependencies like sinon, timeout-promisify, enzyme-json, nyc and some others. We believe in using the right tool for the right job, don’t take us wrong. In this case, these dependencies were there to “make things work”. We did not take the time needed to understand them properly, which ended up in working around them rather than leveraging them.</li></ul><h4>Technical improvements 👩‍💻</h4><p>Some of the improvements we are now benefitting from came strictly because of the fact that we were rewriting our whole suite. We could take a fresh look into our WHOLE test codebase and change what we did not like.</p><p>A couple of things we fixed along the process that made a difference:</p><ul><li>Timezone agnostic: before this, our test script looked something like this &quot;test&quot;: &quot;TZ=UTC ava --config file.whatever”. We hated that TZ=UTC. We are doing very little with dates and times, so this was the first to go. See <a href="https://github.com/date-fns/date-fns/issues/571#issuecomment-470859100">date-fns/issues/571</a> for more.</li><li>No downloading: remember how I previously said we don’t care about the actual values of strings? Well, we used to have that by downloading the latest version of strings before every run… Yeah, we know.</li><li><strong>Speed: +10x 🏎💨</strong></li></ul><h3>Time to say bye</h3><p>But first, let me share some 🔑 learnings with you.</p><h4>What would we do differently? 🤷‍♂️</h4><p>Our biggest struggle was towards the end of the migration, and we could have mitigated by doing the following:</p><ul><li>Earlier feedback on coverage: we did not check for coverage for individual files we were migrating or testing. We should have had this check before every commit or similar.</li><li>Migrate by type of file (services, components &amp; stores): each of us grabbed a particular folder or feature to migrate at a time. This was very easy to coordinate, but delayed the acquired knowledge until the very end. Why? Because we did not finish testing one type of file and learning how to do it best before starting to test another type. Also, some problems about particular approaches arose by the end of the migration (more on the next section).</li></ul><h4>Things to look out for and how we solved them 🐛</h4><ul><li>Memory leak: this was a pretty tough one. The last MST store test that we migrated was taking around 20 seconds to finish, and sometimes node aborted the run after running out of memory. The workaround for us was to use manual mocks instead of generating an automatic one based on the exported store instance. <strong><em>If you are using MST, be careful with this</em></strong>. We isolated the issue as best as we could in <a href="https://github.com/facebook/jest/issues/8112">jest/issues/8112</a>.</li><li>Order of imports: if you go back at the way we mock stores in order to test them, you will notice there are several jest.mock(&#39;...&#39;) calls in different imported files. The order of the imports affected which was the store that was holding the mock references. Our advice is to check how jest.mock works to understand this.</li><li>window.location, Date &amp; friends: these are always tricky. Different projects handle these differently as mocks. See how we ended up configuring Jest ourselves <a href="https://gist.github.com/GonchuB/2c55f374488dcb94d456d50f67ef4452">here</a>.</li><li>Async error handling: if you have async tests that have a try/catch block where you are asserting some error handling, make sure you call <a href="https://jestjs.io/docs/en/expect#expecthasassertions">expect.hasAssertions()</a>. Else, the test will pass even though you don’t run the expectations in your catch block.</li></ul><h4>Last piece of advice to other teams 🚀</h4><ul><li>Don’t be scared of big tasks, sometimes 1 sprint is all it takes.</li><li>Trust in strong collaboration.</li><li>Don’t be tempted to fix bugs within the migration: it will just be another merge pain, and you want that fix in “master”.</li><li>Merge your “master” often. Several small conflicts are better than a huge one.</li><li>Share tips of how you are solving something constantly: communication is key. Share tips. Validate your understanding of how something works. Leave comments in the PR. Always.</li><li>Try to rethink your tests, codemods won’t save you: at least we did not find a “silver bullet” that migrated our tests AVA -&gt; Jest by running a script.</li><li>This is the time to try stuff that might give you big returns: do you have an idea that might improve your testing experience? Timebox it to a couple of hours. Try it out. Maybe you find a golden nugget 🏆.</li><li>Have a clear timeline to deliver, prevent scope creep as much as possible: timebox your migration. Define what you expect to deliver by the end.</li><li>Have fun testing! I hope you learn as much as we did.</li></ul><p>👋</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a6efcb4bd9b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/dazn-tech/jest-our-journey-into-performant-unit-tests-a6efcb4bd9b">Jest: Our journey into performant unit tests</a> was originally published in <a href="https://medium.com/dazn-tech">DAZN Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How public writing helps me become a better professional]]></title>
            <link>https://medium.com/@gonchub/how-public-writing-helps-me-become-a-better-professional-485da5d654cf?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/485da5d654cf</guid>
            <category><![CDATA[writing]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[communication]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Thu, 03 Jan 2019 09:37:59 GMT</pubDate>
            <atom:updated>2019-01-03T09:37:59.607Z</atom:updated>
            <content:encoded><![CDATA[<p>And why you should try it out, too.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YX8Aar-_MJAzdrpfgZFlIg.jpeg" /><figcaption>The image is not related, but it looked good ¯\_(ツ)_/¯</figcaption></figure><p>Writing is a journey, with the end result being what you actually write. What you learn along the way and the skills you develop while doing it are yours to keep.</p><p>As with anything else in life, your writing is influenced by the things you’ve done, read and experienced before.</p><h3>Me</h3><p>Writing helped me improve 5 traits that allow me to be better at my job (and continue to improve).</p><h4>Empathy</h4><p>You are writing for others. You could read it yourself, but if you are publishing it, you are not the main audience. You are considering them every time you write something weird way and try to rephrase. Every time you think a paragraph is too long. Every time you think you went into too much detail. Every time you want to be funny. Every time you try to be dramatic.</p><p>If team members cannot empathize, are they really a team?</p><h4>Communication</h4><p>Well of course, at the end of the day you are trying to articulate a point, tell a story or whatever is you are writing about. But this is a particular form of communication.</p><p>It is an offline conversation. The recipient cannot interrupt. Questions in your writing are rhetorical in the sense that they can’t be addresses until afterward. Your reader can jump right into the comments before finishing or wait, you have no control over it.</p><p>This is not a form of communication you might be used to, but it happens in the workplace a lot. Emails, code reviews, RFCs, you name it.</p><p>With practice, you will be able to articulate your thoughts better at work, and that is great.</p><h4>The thing you are writing about</h4><p>You don’t have to be an expert to write about something, but I can guarantee that you will learn more about what you are writing after doing so. In order to explain something in writing, you have to process it properly first. That processing usually ends up in a better understanding or even some further research into the topic.</p><p>In a way, when we are writing these articles we are exposing ourselves. We are saying “this is what I think about X” or “this is how Y works” or “this is what I learned doing Z”. I don’t know about you, but when I expose myself that way, I like to be confident about the things I write about. I don’t want the first comment to be “you got this wrong”. That is one of my motivators for quality, you can pick a healthier one :)</p><h4>Design</h4><p>The platforms we have at our disposal nowadays are endless. Whether you have your own customized blog, medium blog or blogger, you are designing each and every article you write. You are trying to make it attractive. You want people to actually land in your article and read it. Design helps with that.</p><p>Do your research when picking a blogging/writing platform. Know how you would like it to look. Understand how much you can customize your space.</p><h4>Confidence</h4><p>I’ve touched this earlier, but you need to believe in yourself before publishing something. You are saying “this is what I think and here is a link to it”. Trust yourself. Maybe your article is not featured on the main page, but we are not here for the fame and fortune (at least not me). We are here to learn something. We are here to become better at what we do. We are here because our opinion matters, even if we are wrong.</p><h3>Take the leap</h3><p>Pick a subject. Any subject you think you are good at. Anything, no matter how small or simple. Now write something about it and don’t feel bad after it. Ask for feedback if you are unsafe. Hit that publish button.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=485da5d654cf" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Instagram’s app redesign (now reverted) made total sense]]></title>
            <link>https://uxdesign.cc/why-instagrams-app-redesign-now-reverted-made-total-sense-b6e8ded2707c?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/b6e8ded2707c</guid>
            <category><![CDATA[product-design]]></category>
            <category><![CDATA[usability]]></category>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[instagram]]></category>
            <category><![CDATA[ux]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Thu, 27 Dec 2018 18:11:00 GMT</pubDate>
            <atom:updated>2018-12-29T23:33:17.113Z</atom:updated>
            <content:encoded><![CDATA[<p>I don’t work at Instagram. These are just my opinions as a user (I don’t even have the update yet, just basing this on some twitter videos).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Yd5IzwZtq4kv_ryByu2EAQ.jpeg" /></figure><p>Some of you might already got the update, but basically Instagram is changing the way you consume content in their mobile apps (at least), ditching the classic timeline into a more gallery-like format.</p><p>These are some of the reasons I believe this to be a step in the right direction.</p><h4>Right/Left navigation is here already</h4><p>We are already used to this. This is just “surprising” right now because we were use to a classic timeline like Twitter, Facebook, LinkedIn, and even Instagram until some days ago.</p><p>But, in fact, sideways temporal navigation has been here for some time. Instagram stories work that way. You want to see the next person’s story? Swipe right. Want to go back? Swipe left.</p><p>In other services it is not quite the same, but still temporal navigation is sideways. If you wan’t to advance some seconds in a YouTube video? Double tap right edge of your phone.</p><p>As users, we will eventually get used to considering left/right as “time traveling”.</p><h4>No taps to see content</h4><p>Want to see the comments of a photo? Swipe down a bit. Want to go back to the picture? Swipe up.</p><p>Navigating to specific “pages” in a mobile app feels less continuous than having the whole content displayed and just “discovering” the unseen parts with scrolling.</p><h4>Easier to determine engagement</h4><p>This might no impact users directly but I’m positive that it will affect future product decisions, therefore impacting users directly. Currently, it is a bit hard to determine which post you are actually engaging with and how long with the vertical-scroll timeline.</p><p>After you’ve gone past a post, you might take a peek on the suggested comments but part of the next post is being showed already (maybe even more than half of it). Which post are you currently engaging with? How can a computer tell what are you looking at if both things are in the screen? The new type of navigation removes that problem completely. If you are engaging with a post, it is very easy to determine which one and for how long, as it is the only thing in your screen.</p><p>This data is relevant to companies like Instagram. This data makes your timeline better (some people disagree). This data fuels AB tests.</p><h4>Preventing dead ends</h4><p>Ever got shared a particular post by a friend? Once you click that link you are viewing that post and that post only. If you want to continue using Instagram you need to go back to your timeline, or go to someplace else.</p><p>With this new type of navigation there are no dead ends. If you get a post shared to you, just swipe right and you can see what other content Instagram puts there for you (this might not be true right now, as I said I don’t have the update, but it sure opens the door for it).</p><p>Every post is a timeline view. People spend time in the timeline view. Good for business 💸.</p><h3>Redesign reverted</h3><p>It seems that Instagram rolled back the changes and blamed it on a bug (even before I could publish this post). I still think it would have been a step in the right direction.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2F50d69a%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2Fux&amp;image=https%3A%2F%2Fucarecdn.com%2F6e8986c7-e64a-4116-9afb-fd71a476f0a9%2F&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/a19f46680bac3cbdc42953c920d0c104/href">https://medium.com/media/a19f46680bac3cbdc42953c920d0c104/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b6e8ded2707c" width="1" height="1" alt=""><hr><p><a href="https://uxdesign.cc/why-instagrams-app-redesign-now-reverted-made-total-sense-b6e8ded2707c">Why Instagram’s app redesign (now reverted) made total sense</a> was originally published in <a href="https://uxdesign.cc">UX Collective</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Something to thunk about…]]></title>
            <link>https://medium.com/@gonchub/something-to-thunk-about-d563660e43b2?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/d563660e43b2</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[redux]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Tue, 27 Nov 2018 13:28:34 GMT</pubDate>
            <atom:updated>2018-11-27T13:47:25.514Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yd5l65dZ19QuUCR6MSLyFQ.jpeg" /><figcaption>Spaces or tabs? Thunks or Sagas? JS or TS?</figcaption></figure><p>For the last couple of months, I’ve been involved in some discussions trying to find the “best way to write components while using redux-thunk”. Some points have been made both for and against the library and around the overall use of getState.</p><p>In this particular post I am not going to expose my personal opinion, but rather show the different flavours I’ve ran into. If you are currently using some other approach, please reach out! I would love to understand the motivations behind it, and the pitfalls or benefits of such approach.</p><p>If you are interested in some further reading(about thunks, sagas, etc), I strongly recommend <a href="https://blog.isquaredsoftware.com/2017/01/idiomatic-redux-thoughts-on-thunks-sagas-abstraction-and-reusability/">https://blog.isquaredsoftware.com/2017/01/idiomatic-redux-thoughts-on-thunks-sagas-abstraction-and-reusability/</a></p><h4>Preconditions</h4><p>Let’s start with some existing code and constraints. Let’s image we already have a way of showing an auth (login / register) modal. We already have an action that only makes sense if a user is logged in (for example, “Edit this page”). We have a couple of selectors to fetch some data from our redux store.</p><p>Now we want to create a button component that, when clicked, shows the auth modal if the user is not logged in or performs the action if the user is logged in (previously, that button was hidden when the user was logged out).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bf5db6ad9727b9c5d39e724acb6f1d85/href">https://medium.com/media/bf5db6ad9727b9c5d39e724acb6f1d85/href</a></iframe><h4>The thunk + getState approach</h4><p>The first approach to solve this problem uses a new thunk and fetches parameters for the action directly from state, using the getState function.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/748763230b89018df9b3a5fcc0ea44cb/href">https://medium.com/media/748763230b89018df9b3a5fcc0ea44cb/href</a></iframe><h4>The container approach</h4><p>This approach defines all the functionality in the container component, making use of react-redux connect ‘s three parameters.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e564a46736875b1775345c58602c971e/href">https://medium.com/media/e564a46736875b1775345c58602c971e/href</a></iframe><h4>The “pass only arguments along” approach</h4><p>In this next approach, we have a new thunk which receives the parameters and just invokes either one action creator or the other one.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c1d9729d37e76b9fb230473d17393cdc/href">https://medium.com/media/c1d9729d37e76b9fb230473d17393cdc/href</a></iframe><h4>The “pass everything along” approach</h4><p>This approach just passes everything from the container to the presentational component. The presentational component then defines a new function that decides what to do.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/56b5cba944c0545f97e56279ed489739/href">https://medium.com/media/56b5cba944c0545f97e56279ed489739/href</a></iframe><h3>Conclusion</h3><p>I don’t think there is one. It is mostly about flavours. Some of these approaches scale better in some scenarios, some scale worse in some other scenarios. Or maybe there is a “best” approach. Who knows?</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d563660e43b2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reimplementing React hooks]]></title>
            <link>https://medium.com/@gonchub/reimplementing-react-hooks-9032a6909538?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/9032a6909538</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[hooks]]></category>
            <category><![CDATA[facebook]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Mon, 05 Nov 2018 11:26:03 GMT</pubDate>
            <atom:updated>2018-11-05T12:15:54.881Z</atom:updated>
            <content:encoded><![CDATA[<p>This weekend I came around a very interesting <a href="https://www.youtube.com/watch?v=9TBCmCN82w0">talk</a> by <a href="https://medium.com/@maxgallo">Max Gallo</a> where he shows two pieces of code: one using Mobx and the other one using RxJS. During the talk, he comments out the specific imports from the libraries and implements its own version that matches the API and works.</p><p>This really inspired me to do something similar with the fresh new React hooks. I decided I could write one function with this shiny new additions and then implement myself.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_1zLVs6boFR-kjeEk9OlbA.jpeg" /><figcaption>Build</figcaption></figure><p>I’m quite happy with the result but I would encourage NO ONE to use this implementation. I am really happy because, by coding it, I started to realize the importance of what is going on with hooks and why they are revolutionary in their own way. Also, once you do something like this, you start to understand some rules like “don’t make conditional useHook calls”.</p><p>In order to spend less than a couple of hours playing with it, I decided to implement just the useState hook instead of something more generic (or more tied to React like useEffect and it’s relationship with component lifecycle). On a side note, React’s useState implementation uses useReducer internally, and mine does not.</p><p>So here is the code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4d3e316b1440151555045a236abd1162/href">https://medium.com/media/4d3e316b1440151555045a236abd1162/href</a></iframe><p>The code is divided into three main parts. The first part is the implementation of useState , which I will dive a bit more in a bit. The second part defines two “components” (functions which in the case just return an api). I’m saying they are components because this is not hooked into React, so I’m just returning an api object. In a real React application, that object would not exist, and the functions would be called when clicking an element or something. The third consists of invoking these functions and playing with asynchronous calls.</p><p>The useState implementation is pretty straightforward. Basically, I keep the previous call of useState from a particular component and, from there, I can define the particular behavior of the returned value and setValue . The values are just stored in a simple array per component, and the amount of useState calls per component are stored per component, too. I have a little helper renderFn which just resets some values (that could be handled by the rendering library itself, but this example is a dummy).</p><p>Functions (or “components”) just use the hook twice, to console.log the current state and to modify the songs later on.</p><p>The third part is just setting some timeouts after which songs get set, in order to see how the solution works not only in synchronous situations (after each setSong the functions get called again and the console.log calls are triggered.</p><p>Hope you like the approach and hope it eventually inspires some of you to do something similar.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9032a6909538" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Investing in your team: communal growth]]></title>
            <link>https://medium.com/@gonchub/investing-in-your-team-communal-growth-885e8e07e1de?source=rss-e6c79a0d1847------2</link>
            <guid isPermaLink="false">https://medium.com/p/885e8e07e1de</guid>
            <category><![CDATA[team]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[growth]]></category>
            <category><![CDATA[teamwork]]></category>
            <category><![CDATA[investing]]></category>
            <dc:creator><![CDATA[Gonzalo]]></dc:creator>
            <pubDate>Thu, 25 Oct 2018 14:51:27 GMT</pubDate>
            <atom:updated>2018-10-25T14:51:27.525Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*44WpsmyBxNa2Xkm82SMt9g.jpeg" /></figure><p>A single point of failure (SPOF) is a part of a system that, if it fails, will stop the entire system from working. SPOFs are undesirable in any system with a goal of high availability or reliability, be it a business practice, software application, or other industrial systems.</p><p>This is the definition of a Single Point of Failure from Wikipedia. This concept is widely used in software engineering when thinking about non-functional requirements (or everything that is not about the features itself, but about performance, reliability, etc). Not so often do we think in terms of people and talent.</p><h3>That ONE person</h3><p>Can you think of one colleague of yours that your team can’t live without? What would happen if that person decided to leave? I am not going to elaborate on how or why is a good idea to retain talent and to decrease employee attrition. To prevent this single point of failure to appear, you need to foster an environment of growth that allows knowledge to be spread across your organization (or at least within a team).</p><h3>How do I make this happen?</h3><p>There are several ways to make knowledge accessible to everyone. I will enumerate a couple, but you can sure get more creative:</p><h4>Prevent the same person from always solving the same type of issue</h4><p>If the same person develops the feature and fixes its bugs, then that one person is more likely to retain a lot of the knowledge. Instead, try rotating who picks up what tasks. Specialization is good in terms of performance, but it is better to allow your team’s knowledge to grow as a whole.</p><h4>Organize workshops or talks</h4><p>Encourage people to give short talks about a particular subject they have been working on. They don’t need to be experts on the subject. Trying to explain how something works is a great way of knowing more about that subject. You need to encourage 2 things here. First of all, people should want to give such talks and, second of all, these talks should have attendees. Understand what would motivate your team to attend these types of talks or workshops.</p><h4>Make mentorship part of your career ladder</h4><p>As people gain more experience they start to make an impact on a broader scale. More senior team members should be encouraged to mentor other less senior team members. Mentoring is no easy feat, not everyone likes/wants to do it, but it is a key factor in autonomous team growth.</p><h3>What do these 3 ideas have in common?</h3><p>Resources. At least these 3 need more resources in one way or another. In rotating who grabs what tasks, you will experience a temporary decrease in team performance. As knowledge spreads, this decrease would be eliminated, but you still have to invest in it. To make workshops happen, people need to prepare them, so you invest time in the preparation and in the actual event (N team members * x hours of the talk/workshop). Mentoring also takes time, and it takes time and effort to make people GOOD mentors.</p><h3>Investment</h3><p>This is an investment you are making in your team. In most cases, this investment will be in the form of time. Growing and scaling takes time but is necessary. Trust and empower your team members and your investment will pay off.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=885e8e07e1de" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>