<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kenneth Skovhus</title>
    <description>The latest articles on DEV Community by Kenneth Skovhus (@kenneth_skovhus).</description>
    <link>https://dev.to/kenneth_skovhus</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F320106%2Ff403b3f3-bf62-49b3-a5d1-e43b972d9bd0.png</url>
      <title>DEV Community: Kenneth Skovhus</title>
      <link>https://dev.to/kenneth_skovhus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kenneth_skovhus"/>
    <language>en</language>
    <item>
      <title>Addressing Client/Server Compatibility in tRPC</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Tue, 11 Jul 2023 22:00:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/addressing-clientserver-compatibility-in-trpc-9le</link>
      <guid>https://dev.to/kenneth_skovhus/addressing-clientserver-compatibility-in-trpc-9le</guid>
      <description>&lt;p&gt;I'm a huge fan of removing the boundary between the frontend and backend environment, as seen in libraries like &lt;a href="https://trpc.io/"&gt;tRPC&lt;/a&gt; and web application frameworks like &lt;a href="https://remix.run/"&gt;Remix&lt;/a&gt; and &lt;a href="https://vercel.com/solutions/nextjs"&gt;Next.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M2eCMfU0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bt9tpwm9xe0wtbi5ht5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M2eCMfU0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bt9tpwm9xe0wtbi5ht5v.png" alt="tRPC removing the boundaries between the frontend and backend environment." width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the main selling points of tRPC is "End-to-end typesafe APIs made easy", but this doesn't hold if you are not mindful about keeping your client/server versions in sync. Stale web or mobile applications will eventually make calls to a newer version of the server, leading to potential compatibility issues. This is also known as &lt;a href="https://www.industrialempathy.com/posts/version-skew/"&gt;version skew&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The magnitude of the issue can vary from detectable API failures to subtle UI problems or even data inconsistencies.&lt;/p&gt;

&lt;p&gt;In this blog post, I'll share the solution we came up with when addressing this issue for the tRPC-powered Backend-For-Frontend setup at &lt;a href="https://www.pleo.io/"&gt;Pleo.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Library Guidelines &amp;amp; Best Practices
&lt;/h2&gt;

&lt;p&gt;Frameworks and tools tackle the compatibility challenge differently. For example, GraphQL recommends &lt;a href="https://graphql.org/learn/best-practices/#versioning"&gt;making all changes backward compatible&lt;/a&gt;. Next.js only recently introduced a beta of a new &lt;a href="https://vercel.com/blog/version-skew-protection"&gt;skew protection feature&lt;/a&gt;, but also &lt;a href="https://nextjs.org/docs/deployment#automatic-updates"&gt;automatically update to the latest version&lt;/a&gt; in the background when routing, but API routes (used for actions/forms) are not automatically versioned. Remix does not handle automatic upgrades – any action on the page will break if the client is outdated and the loader is incompatible. For tRPC, it is suggested by the community to keep the client and server in sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  General Strategies
&lt;/h2&gt;

&lt;p&gt;There are several general strategies to resolve the client/server version compatibility issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enforce clients to be in sync&lt;/strong&gt; with the latest server. We cannot guarantee this, but we can nudge the user to reload their browser, update when the user navigates, and add a reload call to action in case of API failures for forms/actions in the application. For mobile applications using React Native we can use &lt;a href="https://github.com/microsoft/react-native-code-push"&gt;CodePush&lt;/a&gt;, although it does introduce some lag and doesn't ensure all clients to upgrade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintain backward compatibility for a grace period&lt;/strong&gt; until we expect the clients to be updated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manually or automatically version&lt;/strong&gt; the API endpoints and gracefully keep old versions around until clients have migrated to the new endpoints. Manual versioning is standard practice but isn't suitable for tRPC, Next.js, or Remix, where the actual endpoints are abstracted away.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each strategy has tradeoffs regarding infrastructure complexity, ease of rollback, and friction for developers and end-users.&lt;/p&gt;

&lt;p&gt;Let us explore two of the most promising strategies in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution: Backward Compatibility
&lt;/h2&gt;

&lt;p&gt;Maintaining backward compatibility is a fairly standard solution and doesn't require any special infrastructure setup (i.e. multiple server versions).&lt;/p&gt;

&lt;p&gt;However, without any custom build time tooling it introduces some friction for the developer that needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;maintain backward compatibility&lt;/li&gt;
&lt;li&gt;clean up old procedures or fields in input/output DTOs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can be mitigated by building a custom validation script that would compare the latest server code with an older version (e.g. from a week ago depending on the grace period). The script would ensure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the latest server code compatible with the older version (e.g. input and output DTOs are a superset of previous versions, and existing procedures are not removed)&lt;/li&gt;
&lt;li&gt;inform the developer if some deprecated code should be removed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even though this approach is viable, it introduces some friction for the developer and requires custom tooling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution: Auto-Versioning
&lt;/h2&gt;

&lt;p&gt;To avoid any friction for the developer, we opted for making our tRPC server code immutable and auto-versioned. It requires some custom infrastructure setup, but it allows for a great developer experience and a seamless end-user experience – especially for web applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cnlAxzhY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eymiu6vcfiaigh7f6wcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cnlAxzhY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eymiu6vcfiaigh7f6wcn.png" alt="Traffic pattern of an auto-versioned immutable tRPC service. The coloring shows new deployments slowly taking over traffic. Notice the long tail caused by stale web clients." width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This can be implemented using serverless services like Cloudflare Workers or AWS Lambda. The solution shares similarities with Next.js' &lt;a href="https://vercel.com/blog/version-skew-protection"&gt;new skew protection feature&lt;/a&gt;, but we recommend keeping the version active for longer than 24 hours to ensure compatibility with running applications.&lt;/p&gt;

&lt;p&gt;For every deployment we:&lt;br&gt;
1) Calculate a stable hash (e.g. version) of the server source code, configuration, deploy script, and relevant environment variables&lt;br&gt;
2) Verify if any deployed function matches the hash (if so, then skip to step 4)&lt;br&gt;
3) Create a new function with a unique URL&lt;br&gt;
4) Bake the function's URL into your web or mobile application&lt;/p&gt;

&lt;p&gt;That's all. 🥂&lt;/p&gt;

&lt;p&gt;Want to see some code? &lt;a href="https://github.com/skovhus/auto-versioned-trpc-aws-lambda"&gt;Here is an early prototype&lt;/a&gt; using the node.js AWS SDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Word of Caution for Mobile Applications
&lt;/h2&gt;

&lt;p&gt;The design choice of making the server code immutable and auto-versioned has some tradeoffs. What if server business logic needs to be updated? What if the database schema or the underlying API services changes? The turnaround time for these changes depends on the time it takes for clients to upgrade. For web applications, it's usually a matter of days, but for mobile applications, it can be months or worse (even when using CodePush).&lt;/p&gt;

&lt;p&gt;I would still recommend using auto-versioned servers for tRPC-enabled mobile applications, but I suggest relaxing the immutability requirement by making it easy to update the server code of existing server versions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Beyond Bug-Squashing: Start Improving Your System</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Fri, 30 Apr 2021 10:00:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/my-mental-model-for-fixing-software-bugs-367p</link>
      <guid>https://dev.to/kenneth_skovhus/my-mental-model-for-fixing-software-bugs-367p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;If debugging is the process of removing software bugs, then programming must be the process of putting them in.&lt;/p&gt;

&lt;p&gt;– Edsger Dijkstra&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I really enjoy fixing software bugs! The detective work, building up a hypothesis about the underlying root cause, digging through paper trails and turning stones to find the culprit. But what I enjoy the most is the &lt;strong&gt;opportunity to improve the system&lt;/strong&gt;. Unfortunately, developers sometimes skip this last step by quickly squashing a bug and then carrying on with other activities.&lt;/p&gt;

&lt;p&gt;While a quick fix seems efficient you miss important learnings and a perfect opportunity to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clean up technical debt and making your system easier to maintain&lt;/li&gt;
&lt;li&gt;helping co-workers and future you to not commit the same mistake again&lt;/li&gt;
&lt;li&gt;understand the quality of your system’s safety nets&lt;/li&gt;
&lt;li&gt;lay the groundwork for spending less time fire fighting and more time developing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tried to generalize my mental model for fixing bugs. It boils down to a 4 step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;determine the severity: do we need to do anything about the issue right now?&lt;/li&gt;
&lt;li&gt;improve safety nets: how can we catch the bug now and avoid similar bugs in the future?&lt;/li&gt;
&lt;li&gt;the actual fix&lt;/li&gt;
&lt;li&gt;post-mortem analysis (if applicable)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 1: Determine the severity 🐛
&lt;/h3&gt;

&lt;p&gt;When you discover a bug (or incident), the first step is to determine the severity. If you are working on fixing an issue that is already triaged or prioritized, you can skip this step and go straight to step 2.&lt;/p&gt;

&lt;p&gt;Some questions to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if the issue revealed itself after a release, should we just roll back or revert?&lt;/li&gt;
&lt;li&gt;is there anything else we can do right now to restore the service(s)?&lt;/li&gt;
&lt;li&gt;do we need to inform anyone about the issue (e.g. product owner, customers or your co-workers)?&lt;/li&gt;
&lt;li&gt;when should the issue be fixed? We should always be mindful to avoid &lt;a href="https://blog.doist.com/context-switching/" rel="noopener noreferrer"&gt;context switching&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Improve safety nets 🚨
&lt;/h3&gt;

&lt;p&gt;How can we enable our system to catch or highlight the issue – now &lt;em&gt;and&lt;/em&gt; in the future?&lt;/p&gt;

&lt;p&gt;You might answer this question by adding one or more of the following safety nets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;improve the linting setup&lt;/li&gt;
&lt;li&gt;introduce or refine a static type&lt;/li&gt;
&lt;li&gt;automated tests (unit, integration, end-to-end)&lt;/li&gt;
&lt;li&gt;add support for feature flags for faster rollbacks&lt;/li&gt;
&lt;li&gt;improve monitoring, alerting or observability&lt;/li&gt;
&lt;li&gt;manual test protocol (should be a last resort).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Word of caution:&lt;/strong&gt; establish these safety nets by working &lt;em&gt;within the system&lt;/em&gt; and avoid extensive refactoring that might introduce new regressions.&lt;/p&gt;

&lt;p&gt;At the end of this step, you should have a red lamp.&lt;/p&gt;

&lt;p&gt;If you feel you don't have time to improve your safety nets before fixing the issue then take a step back. How can you get more time to fix this properly? If the production system is in a really bad state, can you revert to a previous version? Could you disable the broken feature by flipping a feature flag? Buy yourself some time to improve the system (hopefully it will pay off).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: The fix ✅
&lt;/h3&gt;

&lt;p&gt;Now is the time to fix the code, infrastructure configuration, or what caused the bug or regression. Turning the lamp green is often the easy part.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Debrief
&lt;/h3&gt;

&lt;p&gt;You should consider if the severity of the bug merits an incident debrief (traditionally called post-mortem).&lt;/p&gt;

&lt;p&gt;A debrief is a blame-free analysis and discussion soon after an incident or event has taken place to learn from the experience. It ensures that an incident is documented, that all contributing root cause(s) are well understood, and, especially, that we learn from the incident and that preventive actions are put in place to reduce the likelihood and/or impact of recurrence.&lt;/p&gt;

&lt;p&gt;I recommend that you trigger a debrief in case of data loss of any kind, user-visible downtime or degradation, manual developer intervention (e.g. release rollback) or when we lost a substantial amount of time firefighting.&lt;/p&gt;

&lt;p&gt;This &lt;a href="https://www.atlassian.com/incident-management/postmortem" rel="noopener noreferrer"&gt;guide by Atlassian&lt;/a&gt; or &lt;a href="https://incident.io/guide/learn-and-improve/post-mortems-and-debriefs/" rel="noopener noreferrer"&gt;this one by incident.io&lt;/a&gt; seems like a great resources if you want to learn more about incident management and debriefs.&lt;/p&gt;

&lt;p&gt;Happy debugging!&lt;/p&gt;

&lt;p&gt;&lt;a href="/static/93d75744a55f1e21c758caa060772e7c/e5166/bug.jpg"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fskovhus.github.io%2Fstatic%2F93d75744a55f1e21c758caa060772e7c%2F1c72d%2Fbug.jpg" title="On September 9, 1947, the world's first computer bug was recorded by Grace Hopper. It was a real-life moth that was causing issues with the computer’s hardware.&amp;lt;br&amp;gt;
" alt="On September 9, 1947, the world's first computer bug was recorded by Grace Hopper. It was a real-life moth that was causing issues with the computer’s hardware.&amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;On September 9, 1947, the world's first computer bug was recorded by Grace Hopper. It was a real-life moth that was causing issues with the computer’s hardware.&lt;br&gt;
&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Guidelines for Better Pull Requests</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Wed, 12 Aug 2020 10:00:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/guidelines-for-better-pull-requests-3bho</link>
      <guid>https://dev.to/kenneth_skovhus/guidelines-for-better-pull-requests-3bho</guid>
      <description>&lt;p&gt;Pull requests play a crucial role in ensuring quality code and efficient collaboration within software development teams. In this blog post, we'll explore 7 guidelines to help you create better pull requests that will enhance your workflow, streamline feedback, and elevate the quality of your projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;During my work to align our development efforts at &lt;a href="https://leoinnovationlab.com/"&gt;Leo Innovation Lab&lt;/a&gt; I stumbled upon &lt;a href="http://blog.ploeh.dk/2015/01/15/10-tips-for-better-pull-requests/"&gt;10 tips for better Pull Requests by Mark Seemann (2015)&lt;/a&gt;. The blog post aligned well with our perception of a good pull request (PR) and was a great starting point for discussions.&lt;/p&gt;

&lt;p&gt;Below is my iteration of the original post. This is a condensed version with a focus on automation, tooling, context, and my personal learnings.&lt;/p&gt;

&lt;p&gt;The goal of these guidelines is to make the pull request review process easier and will likely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;improve the feedback you get on your work&lt;/li&gt;
&lt;li&gt;reduce the risk that your pull request will be rejected or become stale&lt;/li&gt;
&lt;li&gt;elevate overall the quality of the code and product.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Guidelines
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. A single concern per pull request
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;The more concerns you address in a single Pull Request, the bigger the risk that at least one of them will block acceptance of your contribution. Do only one thing per Pull Request. It also helps you make each Pull Request smaller.&lt;/p&gt;

&lt;p&gt;– Mark Seemann&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you often clutter PRs with multiple concerns then ask yourself why. Maybe your CI setup is slow? Maybe merging is cumbersome? In any case, start by fixing the underlying problems to enable you to &lt;strong&gt;do only one thing and make your PRs small&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What is a small PR? A good rule of thumb is to limit the scope of your PR to a maximum of a few days of work, preferably less. For instance, if you're fixing a bug, make sure the PR only addresses that specific issue, rather than including unrelated improvements or refactoring. This also gives a great sense of progress. And usually you can break work up into smaller daily deliverables.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Short-lived feature branches
&lt;/h3&gt;

&lt;p&gt;Avoid any long-lived feature branches. Getting your changes into the main branch as quickly as possible is often the most productive. It might require that you invest in setting up a system for supporting &lt;a href="https://martinfowler.com/articles/feature-toggles.html"&gt;feature toggles&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Utilize proper tooling
&lt;/h3&gt;

&lt;p&gt;A reviewer should not spend any time nitpicking over style, ensuring that tests pass or figuring out if the code coverage dropped. Instead you should &lt;strong&gt;invest in tooling and automate any verification steps&lt;/strong&gt;. Block any merging until your CI server is happy and let your reviewers focus on more interesting topics than nitpicking over line width or spinning up the project on their local machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Add appropriate context
&lt;/h3&gt;

&lt;p&gt;Adding context for the suggested change is important for the review process. This also serves for future reference when someone is trying to understand why a change was made.&lt;/p&gt;

&lt;p&gt;Include the following in your PR description:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;link to bug ticket or issue (if a link is missing this is usually an indicator that the work is not planned)&lt;/li&gt;
&lt;li&gt;a description of the suggested change&lt;/li&gt;
&lt;li&gt;relevant design considerations and alternative solutions considered&lt;/li&gt;
&lt;li&gt;checklist with TODOs if the pull request is a draft&lt;/li&gt;
&lt;li&gt;if the change can be represented visually, then add a screenshots/gif/video showing how the state before and after the change. Note that this also applies for a backend change (e.g. diff the GraphQL endpoint, show a database optimization using &lt;code&gt;EXPLAIN&lt;/code&gt; or similar)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I recommend using a &lt;strong&gt;pull request template&lt;/strong&gt; to guide and ensuring that the relevant fields are filled out.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Document your code
&lt;/h3&gt;

&lt;p&gt;Strive for self-documenting code (e.g. using clear and consistent naming, types and function signatures). But if you need to explain the code logic in the PR description, then it probably calls for better code comments.&lt;/p&gt;

&lt;p&gt;Code comments should document the why, not the how. Commit messages is also a great place for additional context.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Write well
&lt;/h3&gt;

&lt;p&gt;Use correct spelling, grammar, and punctuation in code, code comments, &lt;a href="https://chris.beams.io/posts/git-commit/"&gt;commit messages&lt;/a&gt;, and pull requests. If you don’t, your prose (and code) is harder to understand for the reviewers and future maintainers. Note that most code editors can be configured to help you with these concerns.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Avoid commit thrashing
&lt;/h3&gt;

&lt;p&gt;When a PR is in review, please avoid rewriting the history on the branch (e.g. amending, squashing, or rebasing in general) and address any review comments in new commits.&lt;/p&gt;

&lt;p&gt;If you need to update the branch then avoid trashing the commit history with &lt;code&gt;Merge branch 'master' into MY-BRANCH&lt;/code&gt; commits. This can be done by using &lt;strong&gt;rebase instead of merging&lt;/strong&gt; (e.g. &lt;code&gt;git pull --rebase origin master&lt;/code&gt; if you are using git).&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In summary, creating better pull requests involves focusing on a single concern, keeping feature branches short-lived, utilizing proper tooling, providing context in your PR, and documenting your code effectively. By following these guidelines, you'll improve your collaboration with your team and elevate the overall quality of your projects.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Migrating from Flow to TypeScript using flow-to-ts</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Mon, 10 Feb 2020 12:00:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/migrating-from-flow-to-typescript-using-flow-to-ts-532p</link>
      <guid>https://dev.to/kenneth_skovhus/migrating-from-flow-to-typescript-using-flow-to-ts-532p</guid>
      <description>&lt;p&gt;Over the last couple of years, I have been migrating several codebases from &lt;a href="https://flow.org/en/"&gt;Flow&lt;/a&gt; to &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; with minimal effort. In this post, I will describe my motivation and the approach I would recommend.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TL;DR I recommend migrating using the &lt;a href="https://github.com/Khan/flow-to-ts"&gt;flow-to-ts&lt;/a&gt; codemod by Khan Academy.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;I started using Flow shortly after it was open sourced by Facebook in &lt;a href="https://engineering.fb.com/web/flow-a-new-static-type-checker-for-javascript/"&gt;2014&lt;/a&gt;. It supports many of the same features as TypeScript (open sourced by Microsoft 2012) but focuses on being a static type checker where TypeScript is also a compiler. I originally picked it over TypeScript due to the momentum in the React community and the easy gradual migration path for existing code.&lt;/p&gt;

&lt;p&gt;But as the TypeScript community and tooling have been rapidly improving, I decided to abandon the Flow ship. This also seems to be a trend in the open source community (example: &lt;a href="https://github.com/facebook/jest/issues/7807"&gt;Jest&lt;/a&gt;, &lt;a href="https://dev.to/arcanis/introducing-yarn-2-4eh1"&gt;Yarn&lt;/a&gt;, and &lt;a href="https://github.com/expo/expo/issues/2164"&gt;Expo&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;My primary motivation for moving to TypeScript:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript seems more &lt;strong&gt;well-maintained&lt;/strong&gt; and more people working on it: In January 2020 TypeScript had 29 contributors, Flow had 14 contributors, and there were 156 pull requests merged compared to no Flow pull requests merged&lt;/li&gt;
&lt;li&gt;in my experience, it is easier to onboard new people to a TypeScript codebase as it is &lt;strong&gt;more widely used and the online material is vast&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;in most &lt;strong&gt;editors&lt;/strong&gt; (notably Microsoft' Visual Studio Code) TypeScript shines: auto import, refactoring, quick error reporting out of the box&lt;/li&gt;
&lt;li&gt;more &lt;strong&gt;third-party types&lt;/strong&gt; are available (estimated to roughly 8X)&lt;/li&gt;
&lt;li&gt;more &lt;strong&gt;libraries are written in TypeScript&lt;/strong&gt; (naturally improving the quality of the interface types compared to reverse engineering the types)&lt;/li&gt;
&lt;li&gt;too often I've discovered &lt;strong&gt;Flow silently bailing&lt;/strong&gt; out type checking, I have not experienced this with TypeScript&lt;/li&gt;
&lt;li&gt;although Flow should be more &lt;a href="https://github.com/facebook/flow/issues/7365#issuecomment-454956694"&gt;&lt;em&gt;sound&lt;/em&gt; by design&lt;/a&gt;, I uncovered &lt;strong&gt;type-related bugs&lt;/strong&gt; after migrating a codebase from Flow (maybe related to Flow silently bailing out type checking)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;installing types using npm&lt;/strong&gt; / &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped"&gt;DefinitelyTyped&lt;/a&gt; makes a lot of sense compared to &lt;a href="https://github.com/flow-typed/flow-typed"&gt;flow-typed&lt;/a&gt; where type definitions are checked into your repository (and you forget to update them)&lt;/li&gt;
&lt;li&gt;the feature sets and syntax are very comparable, so &lt;strong&gt;migration is easy&lt;/strong&gt; (see this great &lt;a href="https://github.com/niieani/typescript-vs-flowtype"&gt;comparison&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;I have experienced &lt;strong&gt;Flow running out of memory&lt;/strong&gt; when type checking a React Native projects. It was a real defeat that I needed to disable type-checking on CI as we ran out of memory. 🤦🏼‍♂️&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Approach
&lt;/h2&gt;

&lt;p&gt;I tried out a bunch of different tools (codemods), that automates the refactoring from Flow to TypeScript. If the concept of automated refactoring with codemods is new to you, you might find &lt;a href="https://www.youtube.com/watch?v=eMI0UBav8Q4"&gt;a talk I gave on the topic&lt;/a&gt; interesting.&lt;/p&gt;

&lt;p&gt;The best migration tool I have found is Khan Academy's &lt;a href="https://github.com/Khan/flow-to-ts"&gt;flow-to-ts&lt;/a&gt;. From their README:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The goal of this project is to provide a tool that can translate 95% of Flow to TypeScript while maintaining a high percentage of the existing type information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;⚠️ A word on code reviews&lt;/strong&gt;: You will end up changing most files in your project, so it will be difficult to review. To make this process as easy as possible, I recommend that you make a separate commit for each of the following steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Prepare your codebase
&lt;/h3&gt;

&lt;p&gt;Before running flow-to-ts I recommend preparing your codebase for type-checking using  TypeScript.&lt;/p&gt;

&lt;p&gt;1) Remove any checked-in types (typically in a flow-typed folder) and config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; flow-typed .flowconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Install the TypeScript package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; typescript
&lt;span class="c"&gt;# or&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Remove the Flow package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn remove flow-bin
&lt;span class="c"&gt;# or&lt;/span&gt;
npm remove flow-bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) Setup a tsconfig.json file for configuring TypeScript. There are many ways to do this, but running &lt;code&gt;npx tsc --init&lt;/code&gt; is a good start. &lt;a href="https://www.typescriptlang.org/docs/handbook/tsconfig-json.html"&gt;Read more&lt;/a&gt; about the configuration file.&lt;/p&gt;

&lt;p&gt;5) Update your linter to support TypeScript. I would recommend using &lt;a href="https://github.com/typescript-eslint/typescript-eslint"&gt;TypeScript ESlint&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6) Update your build setup to support TypeScript. Here are a few pointers for some popular setups:&lt;br&gt;
    - &lt;a href="https://create-react-app.dev/docs/adding-typescript/"&gt;Create React App&lt;/a&gt;&lt;br&gt;
    - &lt;a href="https://devblogs.microsoft.com/typescript/typescript-and-babel-7/"&gt;Babel setup&lt;/a&gt;&lt;br&gt;
    - &lt;a href="https://webpack.js.org/guides/typescript/"&gt;Webpack&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Migrate all the things!
&lt;/h3&gt;

&lt;p&gt;1) Run the flow-to-ts code transformation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Replace src with your source folder or a glob&lt;/span&gt;
npx @khanacademy/flow-to-ts &lt;span class="nt"&gt;--write&lt;/span&gt; &lt;span class="nt"&gt;--delete-source&lt;/span&gt; src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) [Optional] If you use a code formatter (like &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt;) then format your new codebase&lt;/p&gt;

&lt;p&gt;3) Commit the changes (e.g. "Migrate to TypeScript using flow-to-ts codemod")&lt;/p&gt;

&lt;p&gt;4) This is the most &lt;strong&gt;time-consuming&lt;/strong&gt; part: try compiling the project with TypeScript and fix each problem you encounter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tsc &lt;span class="nt"&gt;--noEmit&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start from the top and move your way through... It will take some time. You probably need to install a bunch of types for your libraries (e.g. &lt;code&gt;@types/react&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If you find yourself doing a lot of repetitive fixes, please share these in an issue over at the &lt;a href="https://github.com/Khan/flow-to-ts"&gt;flow-to-ts repository&lt;/a&gt; and help improve the codemod.&lt;/p&gt;

&lt;p&gt;5) Finally, when everything compiles again, check that you can lint and build your project&lt;/p&gt;

&lt;p&gt;6) 🥂&lt;/p&gt;

&lt;p&gt;7) [Optional] You can now remove any &lt;a href="https://flow.org/en/docs/config/options/#toc-suppress-comment-regex"&gt;Flow suppression comments&lt;/a&gt; (e.g. &lt;code&gt;$FlowFixMe&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;8) [Optional] Some Flow utility types are replaced by the &lt;a href="https://github.com/piotrwitek/utility-types"&gt;utility-types&lt;/a&gt; package. You can get rid of some of them if you like (e.g. &lt;code&gt;$Keys&amp;lt;T&amp;gt;&lt;/code&gt; can be replaced by &lt;code&gt;keyof T&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  How much effort does it take?
&lt;/h2&gt;

&lt;p&gt;It all depends on the quality of your Flow types, the libraries you use, and the size of your codebase.&lt;/p&gt;

&lt;p&gt;With the flow-to-ts codemod, you can quickly try out TypeScript on an existing codebase and assess how much work the manual part of the migration would take.&lt;/p&gt;

&lt;p&gt;I converted a 30K lines React Native app in a few days. While doing this, I also spend time fixing a few potential bugs that TypeScript uncovered. 🎁&lt;/p&gt;

&lt;p&gt;So long Flow! 👋 And thanks for all the checking + healthy competition in the static type space.&lt;/p&gt;

</description>
      <category>flow</category>
      <category>typescript</category>
      <category>codemod</category>
      <category>migration</category>
    </item>
    <item>
      <title>Software Engineering Principles</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Mon, 13 Jan 2020 20:00:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/software-engineering-principles-7da</link>
      <guid>https://dev.to/kenneth_skovhus/software-engineering-principles-7da</guid>
      <description>&lt;p&gt;After reading the &lt;a href="https://react.christmas/2019/24"&gt;principles of the React team&lt;/a&gt; I got inspired to write this post on the &lt;em&gt;high-level technical principles and beliefs that I operate by&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;These 8 principles, gathered over 20 years, are not exhaustive and may change as I (&lt;em&gt;hopefully&lt;/em&gt;) gain new perspectives and wisdom. I have added a bunch of links and recommendations, that I hope you find inspiring. ☕️&lt;/p&gt;

&lt;h2&gt;
  
  
  People first, technology second
&lt;/h2&gt;

&lt;p&gt;Technology’s ultimate purpose is to advance humanity. If we do not put the human first in everything we do, then what is the point?&lt;/p&gt;

&lt;p&gt;Before I studied computer science, I worked as a technical illustrator and later as a freelance web designer. I was always fascinated by human-computer interaction. Reading &lt;em&gt;Designing Web Usability&lt;/em&gt; (1999) by Jakob Nielsen was a real eye-opener. Later in life, working together with really skilled UX designers and product owners changed how I approach problems.&lt;/p&gt;

&lt;p&gt;We can easily forget about users while getting carried away solving problems. I believe all technologists will benefit from understanding user-centered and human-centered design.&lt;/p&gt;

&lt;p&gt;Recommended material:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.offscreenmag.com/"&gt;Offscreen&lt;/a&gt; is my favorite print magazine on how we shape technology and how technology shapes us&lt;/li&gt;
&lt;li&gt;Donald Norman’s classic best-selling book &lt;em&gt;The Design of Everyday Things&lt;/em&gt; studies fundamental principles of great and meaningful design.&lt;/li&gt;
&lt;li&gt;Steve Jobs, just returned to Apple in 1997, as a &lt;a href="https://www.youtube.com/watch?v=dI93BvrBxQ0"&gt;response&lt;/a&gt; to a tech-focused insult: &lt;em&gt;“You’ve got to start with the customer experience and work backward to the technology. You can’t start with the technology and try to figure out where you’re going to sell it.”&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The only constant is change
&lt;/h2&gt;

&lt;p&gt;The greek philosopher Heraclitus knew it 2500 years ago: &lt;em&gt;“Everything changes and nothing stands still”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Software differs greatly from construction engineering or architecture, despite the common metaphor. Code is organic, it evolves, and needs constant maintenance. I love the &lt;a href="https://www.artima.com/intv/garden.html"&gt;analogy&lt;/a&gt; that software development resembles gardening. We are gardeners constantly dealing with things changing. And most changes do not turn out the way you expected.&lt;/p&gt;

&lt;p&gt;To optimize a codebase for change:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep things simple&lt;/li&gt;
&lt;li&gt;Prefer boring, explicit code&lt;/li&gt;
&lt;li&gt;Invest in documentation, automation, and tests&lt;/li&gt;
&lt;li&gt;Encapsulate code that is likely to change (e.g. vendor-dependent modules, business rules, and implementation details)&lt;/li&gt;
&lt;li&gt;Make ownership clear, and consider &lt;a href="https://martinfowler.com/articles/products-over-projects.html"&gt;product-mode over projects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Write code that is easy to delete, not easy to extend &lt;a href="https://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to"&gt;(recommended reading)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Start with why before jumping into solution mode
&lt;/h2&gt;

&lt;p&gt;I find it so rewarding to solve the right problem in a lean and simple way, and to avoid wasting time on the wrong path.&lt;/p&gt;

&lt;p&gt;Solving problems is fun—usually more fun than planning. But you might find yourself jumping into solution-mode before understanding the problem. This can also happen when leadership above you commands you or your team to do a certain task without a clear why. Instead, incorporate asking questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What problem are we trying to solve?&lt;/li&gt;
&lt;li&gt;What ideas do we have to solve it?&lt;/li&gt;
&lt;li&gt;What are the positive and negative implications?&lt;/li&gt;
&lt;li&gt;Are there simpler solutions to the problem?&lt;/li&gt;
&lt;li&gt;What are our core assumptions?&lt;/li&gt;
&lt;li&gt;What are the technical details of the technologies used?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Be curious and come up with more open questions!&lt;/p&gt;

&lt;h2&gt;
  
  
  Build-Measure-Learn
&lt;/h2&gt;

&lt;p&gt;Requirements and your perspective will change as soon as you ship your solution (or simply show it to users). So avoid gold-plating your design or code, and get your solution in front of real users as fast as possible. It's better to fail fast than to waste time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In most projects, the first system built is barely usable… Hence plan to throw one away; you will, anyhow.&lt;/p&gt;

&lt;p&gt;– Fred Brooks, The Mythical Man-Month (1975)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Build quick prototypes, cut down on scope, and plan to throw code and designs away. Shorten the build-measure-learn cycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prefer duplication over the wrong abstraction
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;“Don’t Repeat Yourself” (DRY)&lt;/em&gt; is often misunderstood. Although programming is often about being lazy and avoiding repetition, prematurely sharing code can be really expensive. Even if the code and functionality look the same at the time, the requirements or direction might differ down the line.&lt;/p&gt;

&lt;p&gt;Recommended material:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sandi Metz &lt;a href="https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction"&gt;&lt;em&gt;The Wrong Abstraction&lt;/em&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Joe Spolsky &lt;a href="https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/"&gt;&lt;em&gt;The Law of Leaky Abstractions&lt;/em&gt;&lt;/a&gt;. “All non-trivial abstractions, to some degree, are leaky”&lt;/li&gt;
&lt;li&gt;Dan Abramov &lt;a href="https://overreacted.io/goodbye-clean-code/"&gt;&lt;em&gt;Goodbye Clean Code&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Invest in safety nets
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;“We don’t have time to write tests”&lt;/em&gt; means you spend too much time bug fixing because you don’t have the necessary safety nets. Have enough safety nets to not be afraid to deploy to production when merging your main branch. In case you end up breaking production, make sure to identify root causes, learn from your mistakes, and figure out new safety nets to implement.&lt;/p&gt;

&lt;p&gt;Safety nets checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bunch of automated unit and integration tests&lt;/li&gt;
&lt;li&gt;A few automated end-to-end system tests&lt;/li&gt;
&lt;li&gt;Documented manual procedures and test protocols (if needed)&lt;/li&gt;
&lt;li&gt;Infrastructure as code&lt;/li&gt;
&lt;li&gt;Ensure proper monitoring and alarms&lt;/li&gt;
&lt;li&gt;Process for incident &lt;a href="https://landing.google.com/sre/sre-book/chapters/postmortem-culture/"&gt;postmortems&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cross-functional teams
&lt;/h2&gt;

&lt;p&gt;Splitting teams based on competence, or where in the stack their code runs, is easy, but often counter-productive. It introduces an overhead in terms of communication and requirements specifications. The most effective teams I have worked in, where all diverse and cross-functional (design, UX, frontend, backend, product, domain experts).&lt;/p&gt;

&lt;h2&gt;
  
  
  Give back to the OSS community
&lt;/h2&gt;

&lt;p&gt;Most software companies rely heavily on Open Source Software (OSS). Just enumerate all the different projects you depend on!&lt;/p&gt;

&lt;p&gt;In 2017 my &lt;a href="https://speakerdeck.com/skovhus/making-open-source-my-new-years-resolution"&gt;new year’s resolution&lt;/a&gt; was to give back to the OSS community. It has been a great ride so far. Heck, one might say that this blog post is a continuation of that.&lt;/p&gt;

&lt;p&gt;I do not expect anyone to spend their weekends and late evenings on open source. But why not convince your employer to contribute? Get time reserved for reporting bugs, triaging issues, doing pull requests, sharing knowledge in blog posts and talks, open-sourcing some useful homegrown system, or simply sponsor projects you depend upon.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are your engineering principles?
&lt;/h3&gt;

&lt;p&gt;These are some of the high-level engineering principles I operate by when building software – I hope you found them useful.&lt;/p&gt;

&lt;p&gt;Do you, or your team have a set of principles? I would love to hear about them.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This blog post was cross-posted from &lt;a href="https://skovhus.github.io/software-engineering-principles/"&gt;https://skovhus.github.io/software-engineering-principles/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://twitter.com/penzington"&gt;Maciek Pekala&lt;/a&gt; for reviewing this post.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>development</category>
      <category>principles</category>
      <category>inspiration</category>
      <category>career</category>
    </item>
    <item>
      <title>Converting an app to React Native — How to get started</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Fri, 13 Apr 2018 15:05:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/converting-an-app-to-react-native-how-to-get-started-g0f</link>
      <guid>https://dev.to/kenneth_skovhus/converting-an-app-to-react-native-how-to-get-started-g0f</guid>
      <description>&lt;p&gt;This is the second part of a series on migrating existing native apps to React Native. Check out &lt;a href="https://medium.com/leoilab/converting-an-app-to-react-native-why-and-how-b56c02c07b96" rel="noopener noreferrer"&gt;the first blog post&lt;/a&gt; if you want to know why we went for React Native and how we approached it.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Native under the hood, a crash course
&lt;/h2&gt;

&lt;p&gt;To understand how React Native works on mobile, you first need to look at the virtual DOM (Document Object Model) that is used in both React and React Native. If you’ve ever done web development, you know how the DOM works in the browser. If not, you might be interested in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction" rel="noopener noreferrer"&gt;reading up on it&lt;/a&gt;. In short: The DOM represents a page as nodes and objects. In plain React, &lt;a href="https://reactjs.org/docs/faq-internals.html" rel="noopener noreferrer"&gt;the virtual DOM&lt;/a&gt; is an in-memory representation of the UI on top of the actual DOM. When a node or object changes, React will diff the virtual DOM and the actual DOM, and only update those nodes or objects that have changed. In React Native, there is no browser DOM. Instead, the virtual DOM is rendered into native iOS or Android views.&lt;/p&gt;

&lt;p&gt;&lt;a href="/static/e964a98fe5f036fb3805b0a58b517587/bcbcb/react-native-vdom.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fskovhus.github.io%2Fstatic%2Fe964a98fe5f036fb3805b0a58b517587%2F799d3%2Freact-native-vdom.png" title="Virtual DOM in React and React Native" alt="Virtual DOM in React and React Native"&gt;&lt;/a&gt;Virtual DOM in React and React Native&lt;/p&gt;

&lt;p&gt;While you write plain JavaScript and JSX (tag syntax that is an extension to JavaScript) to define how your React Native app should look and behave, the UI is still rendered natively. Whenever there is a change in one of the nodes or objects, React Native will update the relevant parts of the UI automatically.&lt;/p&gt;

&lt;p&gt;This is what sets React Native apart from other cross-platform solutions. Rendering native components significantly speeds up interaction with the app, and while this also introduces some complexities (sometimes you will need to create a custom UI component), for us, it was definitely a good trade-off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigation is hard
&lt;/h2&gt;

&lt;p&gt;Navigation has always been a bit of a problem on React Native, but the vast amount of packages that are available show that this area is under development. Ideally, Facebook would create or, at least, recommend one solution. But for now, that’s not the case, and we all have to choose a third party library and stick with it. For us, the main contenders were &lt;a href="https://github.com/react-navigation/react-navigation" rel="noopener noreferrer"&gt;react-navigation&lt;/a&gt; and &lt;a href="https://github.com/wix/react-native-navigation" rel="noopener noreferrer"&gt;wix/react-native-navigation&lt;/a&gt;. The first is very flexible and runs everything purely in JavaScript, while the second one is based on native navigation on both platforms. We decided to go with react-native-navigation because we felt like native components would make the app feel more familiar to our users.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EDIT FROM JANUARY 2019: the native feel of react-native-navigation didn’t make up for the amount of Android bugs, tight coupling with screen components, and non-declarative API. We &lt;a href="https://twitter.com/kenneth_skovhus/status/1076186546322243584" rel="noopener noreferrer"&gt;migrated to react-navigation&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting used to JavaScript
&lt;/h2&gt;

&lt;h4&gt;
  
  
  JavaScript? No, thanks
&lt;/h4&gt;

&lt;p&gt;In mobile development circles, most people cringe at the thought of writing an entire app in JavaScript. Why would you even do such a thing? JavaScript has a lousy reputation, and rightfully so. If you worked with JavaScript a decade ago, you likely had a horrible experience. Suitable for small scripts on websites, but not ideal for developing an application of any significant size.&lt;/p&gt;

&lt;p&gt;However, things have changed, and over the last ten years there have been significant development efforts in tooling, frameworks, and engines. We saw the creation of &lt;a href="https://jquery.com/" rel="noopener noreferrer"&gt;jQuery&lt;/a&gt;, &lt;a href="https://developers.google.com/v8/" rel="noopener noreferrer"&gt;V8&lt;/a&gt;, &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;Node&lt;/a&gt;, &lt;a href="http://backbonejs.org/" rel="noopener noreferrer"&gt;Backbone&lt;/a&gt;, … All of these efforts propelled JavaScript into one of the most used languages in the world. Today, Google’s &lt;a href="https://angularjs.org/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt; and Facebook’s &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; are the two most popular JavaScript frameworks. They are used by Google and Facebook themselves and provide a solid foundation for app development.&lt;/p&gt;

&lt;h4&gt;
  
  
  Modern JavaScript
&lt;/h4&gt;

&lt;p&gt;JavaScript itself also saw significant advances in the last few years. When &lt;a href="http://www.ecma-international.org/ecma-262/6.0/" rel="noopener noreferrer"&gt;EcmaScript 6&lt;/a&gt; came out, developers finally had access to features that were already common in most modern programming languages, such as classes, arrow functions (aka lambdas), string interpolation, &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt;, and &lt;a href="https://github.com/lukehoban/es6features" rel="noopener noreferrer"&gt;many more&lt;/a&gt;. Meanwhile, &lt;a href="http://coffeescript.org/" rel="noopener noreferrer"&gt;CoffeeScript&lt;/a&gt; and &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; pioneered &lt;a href="https://scotch.io/tutorials/javascript-transpilers-what-they-are-why-we-need-them" rel="noopener noreferrer"&gt;transpilation&lt;/a&gt; so everyone could start using new language features that were not yet implemented by all browsers or engines. ES 7 and 8 kept on advancing the language significantly, and by now we can say that JavaScript can be a very nice language to work with.&lt;/p&gt;

&lt;p&gt;Of course, it’s not all sunshine and rainbows. While the language itself is getting better, it is still difficult to set up a good development environment. Because of the dynamic nature of the language, doing something as simple as renaming a variable can still be a challenge. Coming from Android, you might find JetBrains’ &lt;a href="https://www.jetbrains.com/idea/" rel="noopener noreferrer"&gt;IntelliJ&lt;/a&gt; useful, because of its familiarity. Web developers tend to stick with editors like &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VSCode&lt;/a&gt; or &lt;a href="https://atom.io/" rel="noopener noreferrer"&gt;Atom&lt;/a&gt; when they go to React Native. As long as the plugins are there to support what you need, you can use any editor you want.&lt;/p&gt;

&lt;p&gt;We found that a lot of JavaScript’s shortcomings can be countered with internal coding conventions and a good tooling setup to enforce them. Once you get into the habit of writing good, idiomatic JavaScript in a proper architecture, it becomes quite nice, even when you come from Swift or Kotlin in native land.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;After we understood how React Native works and decided to make peace with JavaScript, we wanted to make sure we had the right tooling set up to enforce best practices, and that the native developers on our team are made aware when they write non-idiomatic JavaScript. The setup, with a variety of tools from the JavaScript and React ecosystem, also helps us write more maintainable code that is easier to read.&lt;/p&gt;

&lt;h4&gt;
  
  
  Static analysis and code consistency
&lt;/h4&gt;

&lt;p&gt;The dynamic and loosely-typed nature of JavaScript makes it especially prone to runtime errors. To help us find these errors before running the app, we use &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESlint&lt;/a&gt;. ESlint also helps us see dead code and detect problematic patterns that sneak into the codebase. Our configuration is based on the widely used &lt;a href="https://www.npmjs.com/package/eslint-config-airbnb" rel="noopener noreferrer"&gt;eslint-config-airbnb&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Although ESlint can also check that a codebase adheres to a specific style guideline, we strongly believe that a code style should be enforced by a tool. Instead of debating over coding style, we use &lt;a href="https://prettier.io/docs/en/why-prettier.html" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; to format our code. It &lt;a href="https://github.com/prettier/eslint-plugin-prettier" rel="noopener noreferrer"&gt;integrates&lt;/a&gt; with ESlint, so when hitting save in our editor the code is formatted and statically analyzed.&lt;/p&gt;

&lt;h4&gt;
  
  
  State management
&lt;/h4&gt;

&lt;p&gt;For state management, we enjoy the simplicity and testability of &lt;a href="https://redux.js.org/" rel="noopener noreferrer"&gt;Redux&lt;/a&gt;. We use the &lt;a href="https://github.com/rt2zz/redux-persist" rel="noopener noreferrer"&gt;redux-persist&lt;/a&gt; middleware to read and write parts of our Redux store to disk.&lt;/p&gt;

&lt;h4&gt;
  
  
  Static type checking
&lt;/h4&gt;

&lt;p&gt;We started rebuilding the application in React Native without types. But as the application grew, it became clear that a static type checking tool like Flow or TypeScript would help us refactor and discover bugs. The more of the codebase we covered with types, the more bugs we uncovered.&lt;/p&gt;

&lt;p&gt;TypeScript by Microsoft and Flow by Facebook are similar tools, providing gradual static typing capabilities, a similar syntax, and widespread usage.&lt;/p&gt;

&lt;p&gt;For React Native, Flow was a natural choice. It integrates nicely with the build tool, and most third-party libraries already provide Flow types.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EDIT FROM JANUARY 2019: After TypeScript gained more momentum, we decided to give TypeScript another change. We migrated most of our projects to TypeScript and didn’t look back. The editor support and the library support is 👌&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A type checker is not a silver bullet, though. The learning curve is steep, and you find yourself fighting the type system. But we are happy that a lot of development is happening in this area. One of the most promising options for the future is &lt;a href="https://reasonml.github.io/" rel="noopener noreferrer"&gt;Reason&lt;/a&gt; (also by Facebook), a type-safe language build on top of OCaml which compiles to very readable JavaScript.&lt;/p&gt;

&lt;h4&gt;
  
  
  Storybook as a productivity booster
&lt;/h4&gt;

&lt;p&gt;Storybook is a UI development environment for your UI components. With it, you can visualize different states of your UI components and develop them interactively.&lt;/p&gt;

&lt;p&gt;If we were to dream up a productive setup for developing UI components and screens, it would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work on components and screens in isolation without starting the entire application&lt;/li&gt;
&lt;li&gt;Be able to describe and quickly switch between components and screens in different states&lt;/li&gt;
&lt;li&gt;Support hot reloading when styles and markup changes&lt;/li&gt;
&lt;li&gt;Have multiple simulators and cross-platform devices connected and see them all update when updating the code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are happy to see that &lt;a href="https://storybook.js.org" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; delivers all of these. It is a major productivity booster when developing UIs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Automated testing
&lt;/h4&gt;

&lt;p&gt;For unit and integration testing, we are using &lt;a href="https://facebook.github.io/jest/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;—another great open source tool by Facebook. It provides a testing framework with excellent watch mode, coverage support, fairly simple mocking and swift feedback when writing tests. As it runs in Node, you mock out all native components (though it requires some &lt;a href="https://github.com/facebook/react-native/blob/1490ab12ef156bf3201882eeabfcac18a1210352/jest/setup.js" rel="noopener noreferrer"&gt;setup&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;We have experimented with Appium and Amazon Device Farm for cross-platform UI automation tests. But currently, we’re focusing on a solid and fast unit testing setup that helps us catch bugs and documents the expected behavior of our code.&lt;/p&gt;

&lt;h4&gt;
  
  
  Editor support
&lt;/h4&gt;

&lt;p&gt;Everyone on the team uses their preferred editor, whether it be Visual Studio Code, Atom, or IntelliJ IDEA. To have a good and consistent development experience we ensure that all of our editors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show ESlint errors&lt;/li&gt;
&lt;li&gt;Call eslint  -- fix on file save (we never do manual formatting, we have Prettier for that)&lt;/li&gt;
&lt;li&gt;Understand Flow declarations, so we get autocompletion and type errors in the editor&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;While we are quite happy with the current setup, there is room still for improvement. One thing we want to do is to have a big set of UI tests. We’re not entirely sure yet what the best option for that would be. But in general, we now have a solid foundation on which we can build more features, and we have great checks in place that make sure our code adheres to best practices and our internal style. The development cycle is also a lot faster because of the unit tests and Storybook.&lt;/p&gt;

&lt;p&gt;There is one more thing we feel is important when converting to React Native, and that is native modules and UI components. We will cover that in our next blog post.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Co-authored by &lt;a href="http://www.kevinpelgrims.com/" rel="noopener noreferrer"&gt;Kevin Pelgrims&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This blog post was cross-posted from &lt;a href="https://skovhus.github.io/converting-an-app-to-react-native/" rel="noopener noreferrer"&gt;https://skovhus.github.io/converting-an-app-to-react-native/&lt;/a&gt; and originally posted on &lt;a href="https://medium.com/leoilab/converting-an-app-to-react-native-how-to-get-started-924548ff6c62" rel="noopener noreferrer"&gt;Leo Innovation Labs’ medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Type safe CSS Modules with Flow</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Wed, 21 Jun 2017 15:00:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/type-safe-css-modules-with-flow-3ojp</link>
      <guid>https://dev.to/kenneth_skovhus/type-safe-css-modules-with-flow-3ojp</guid>
      <description>&lt;p&gt;&lt;a href="///static/82781fd79c387e48bc41c57f9f86025a/75d76/css-modules-flow.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yLGCXBNu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://skovhus.github.io/static/82781fd79c387e48bc41c57f9f86025a/799d3/css-modules-flow.png" alt="CSS Modules + Flow = type safety and editor autocompletion" title="CSS Modules + Flow = type safety and editor autocompletion"&gt;&lt;/a&gt;CSS Modules + Flow = type safety and editor autocompletion&lt;/p&gt;

&lt;p&gt;I’ve been dreaming about type safety and editor autocompletion when using &lt;a href="https://github.com/css-modules/css-modules"&gt;CSS Modules&lt;/a&gt;. There are a few TypeScript tools for this (see &lt;a href="https://medium.com/@sapegin/css-modules-with-typescript-and-webpack-6b221ebe5f10"&gt;this&lt;/a&gt; and &lt;a href="https://github.com/Quramy/typed-css-modules"&gt;this&lt;/a&gt;), but I didn’t find any solid tools for &lt;a href="https://flow.org/"&gt;Flow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TL;DR I’ve made some &lt;a href="https://github.com/skovhus/css-modules-flow-types"&gt;new tools&lt;/a&gt;, and when trying them on a codebase I’m working on, Flow found &lt;strong&gt;a lot of dead code (and potential bugs)&lt;/strong&gt;&lt;/em&gt; 😬&lt;/p&gt;

&lt;h2&gt;
  
  
  The problems
&lt;/h2&gt;

&lt;p&gt;It is quite easy to misspell a class name or forget to update consumers after removing a class in a .css file. As an example, the class &lt;code&gt;foo&lt;/code&gt; might not be defined in &lt;code&gt;Button.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* @flow */
import styles from './Button.css';
const Button = () =&amp;gt; &amp;lt;button className={styles.foo} /&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;p&gt;To teach Flow about CSS Modules file, we can create a definition file &lt;code&gt;Button.css.flow&lt;/code&gt; containing the class names exposed by &lt;code&gt;Button.css&lt;/code&gt;. By doing so we can get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;static type checks showing usage of non-existing classes&lt;/li&gt;
&lt;li&gt;editor autocompletion of CSS classes (for editors supporting Flow)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To generate these .flow files I was thinking of two use cases. One using a simple CLI and another using webpack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution: CLI
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/css-modules-flow-types-cli"&gt;css-modules-flow-types-cli&lt;/a&gt; is a CLI that quickly generate .flow files.&lt;/p&gt;

&lt;p&gt;Let us install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev css-modules-flow-types-cli

# or

yarn install -D css-modules-flow-types-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then just run the CLI on your source directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;css-modules-flow-types src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I recommend using the CLI on your CI system (like Travis or Circle) to ensure that all .flow files are up-to-date before running Flow. This will catch potential styling errors before deploying.&lt;/p&gt;

&lt;p&gt;Another use case is quick feedback loop when developing and changing CSS Modules files. The CLI includes a watch mode for this, but I myself would like to avoid having yet another tool that needs to be running while developing. As a lot of people already have webpack running, I did a small loader consuming the tokens from style-loader.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution: webpack loader
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/css-modules-flow-types-loader"&gt;css-modules-flow-types-loader&lt;/a&gt; is a webpack loader keeping .flow files updated by consuming the tokens from &lt;code&gt;style-loader&lt;/code&gt;. I recommend using this when developing as part of a webpack-dev-server setup. It will give a small slowdown, as the loader potentially needs write a lot of files.&lt;/p&gt;

&lt;p&gt;To get started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev css-modules-flow-types-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update your webpack config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  test: /\.css$/, // or the file format you are using
  use: [
    'style-loader',
    'css-modules-flow-types-loader', // right after style-loader
    // Other loaders like css-loader after this:
    ...
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then sit back and enjoy CSS Modules being type checked by Flow. 🍺&lt;/p&gt;

&lt;p&gt;Please let me know what you think… And give a little ⭐️ over at &lt;a href="https://github.com/skovhus/css-modules-flow-types"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This blog post was cross-posted from &lt;a href="https://skovhus.github.io/type-safe-css-modules-with-flow/"&gt;https://skovhus.github.io/type-safe-css-modules-with-flow/&lt;/a&gt; and originally posted on &lt;a href="https://hackernoon.com/type-safe-css-modules-with-flow-dd95e761bbe5"&gt;hackernoon&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>flow</category>
      <category>cssmodules</category>
      <category>typesafety</category>
      <category>types</category>
    </item>
    <item>
      <title>React PropTypes to Flow codemod</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Tue, 11 Apr 2017 15:00:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/react-proptypes-to-flow-codemod-4gh8</link>
      <guid>https://dev.to/kenneth_skovhus/react-proptypes-to-flow-codemod-4gh8</guid>
      <description>&lt;p&gt;&lt;em&gt;I’m presenting how to automatically convert your existing codebase using React PropTypes to use more powerful Flow annotations. If you already seen why this is valuable, you can skip down to the next section.&lt;/em&gt; 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="/static/4822d2d94a48a54d885e84246876a4ac/6e525/flow-unsplash.jpg"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fskovhus.github.io%2Fstatic%2F4822d2d94a48a54d885e84246876a4ac%2F88218%2Fflow-unsplash.jpg" title="Eye candy, because you deserve it (unsplash.com/@thekorus)" alt="Eye candy, because you deserve it (unsplash.com/@thekorus)"&gt;&lt;/a&gt;Eye candy, because you deserve it (unsplash.com/@thekorus)&lt;/p&gt;

&lt;p&gt;If React were Facebook’s gateway drug to declarative and composable UI, React PropTypes introduced a lot of people to type checking.&lt;/p&gt;

&lt;p&gt;PropTypes documents a given component’s props and gives runtime validation of props during development. I find them really helpful, but they also have &lt;a href="http://technologyadvice.github.io/eradicate-runtime-errors-in-react-with-flow/" rel="noopener noreferrer"&gt;several shortcomings&lt;/a&gt;. Most notably we should aim to catch errors before opening our browser. Say hello to static type checking.&lt;/p&gt;

&lt;p&gt;To statically type-check an application, you can use JavaScript extensions like &lt;a href="https://flow.org/" rel="noopener noreferrer"&gt;Flow&lt;/a&gt; or &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;. In this blog post I’m focusing on Flow, but the same approach can be applied to TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  No doubt (to me): Static type checking (using Flow or TypeScript) at build time is vastly superior to runtime validation.
&lt;/h2&gt;

&lt;p&gt;If you are new to Flow, the &lt;a href="https://flow.org/" rel="noopener noreferrer"&gt;new documentation is really good&lt;/a&gt;. After setting up Flow you can now start type annotating your components state and props. For a simple component it might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* 1) Using good old PropTypes */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;
&lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;oneOfType&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nx"&gt;isRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/* 2) Using Flow annotations */&lt;/span&gt;
&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far so good. But transitioning an existing codebase to use Flow annotations instead of PropTypes can be tedious… However this is a perfect task for a codemod!&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to mod the code
&lt;/h2&gt;

&lt;p&gt;To automate the conversion of React PropTypes to Flow annotations, we are using another tool popularized by Facebook: &lt;a href="https://github.com/facebook/jscodeshift" rel="noopener noreferrer"&gt;jscodeshift&lt;/a&gt; (JavaScript codemod toolkit).&lt;/p&gt;

&lt;p&gt;If the concept of automated refactoring with codemods is new to you, I’ll promote a meetup talk I did: &lt;a href="https://www.youtube.com/watch?v=eMI0UBav8Q4" rel="noopener noreferrer"&gt;“Introduction to automated refactoring with JS codemods (Copenhagen.js Meetup, December 2016)”&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=eMI0UBav8Q4" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.youtube.com%2Fvi%2FeMI0UBav8Q4%2F0.jpg" alt="Introduction to automated refactoring with JS codemods (Copenhagen.js Meetup, December 2016)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enough talk. Time to get rid of the PropTypes! Turns out &lt;a href="https://github.com/billyvg" rel="noopener noreferrer"&gt;Billy Vong&lt;/a&gt; already did a lot of the hard work for us with &lt;a href="https://github.com/billyvg/codemod-proptypes-to-flow" rel="noopener noreferrer"&gt;codemod-proptypes-to-flow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So to automatically convert all components in a folder my-components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git clone https://github.com/billyvg/codemod-proptypes-to-flow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;jscodeshift -t codemod-proptypes-to-flow/src/index.js my-components&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Look no PropTypes! (Although &lt;code&gt;createClass&lt;/code&gt;, imported and custom PropTypes validators are not supported — yet!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve successfully used this codemod for multiple projects, and it eased the transition remarkably. Now Flow starts finding errors while you write code instead of when the code is executed! 🍷 🙌🏻&lt;/p&gt;




&lt;p&gt;Notice that there are cases where you want to keep your PropTypes (possible alongside Flow annotations):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PropTypes in library code can help consumers and document an interface&lt;/li&gt;
&lt;li&gt;If you have no automated tests validating your flow definitions of any external resources (like an API), PropTypes can be really helpful. For this I would recommend using &lt;a href="https://github.com/brigand/babel-plugin-flow-react-proptypes" rel="noopener noreferrer"&gt;babel-plugin-flow-react-proptypes&lt;/a&gt; to add PropTypes at build time&lt;/li&gt;
&lt;li&gt;PropTypes are still great for learning material on React (no need to burden new people with Flow/TypeScript)&lt;/li&gt;
&lt;li&gt;PropTypes can be more flexible than what the Flow type-checker currently supports (e.g. &lt;a href="https://twitter.com/Daniel15/status/851232924225556480" rel="noopener noreferrer"&gt;validating a number is in a particular range&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This blog post was cross-posted from &lt;a href="https://skovhus.github.io/react-prop-types-to-flow-codemod/" rel="noopener noreferrer"&gt;https://skovhus.github.io/react-prop-types-to-flow-codemod/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://twitter.com/penzington" rel="noopener noreferrer"&gt;Maciek Pekala&lt;/a&gt; and &lt;a href="https://twitter.com/Mads_Hartmann" rel="noopener noreferrer"&gt;Mads Hartmann&lt;/a&gt; for reviewing this post.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>proptypes</category>
      <category>react</category>
      <category>flow</category>
      <category>codemod</category>
    </item>
    <item>
      <title>Abandoning the mothership</title>
      <dc:creator>Kenneth Skovhus</dc:creator>
      <pubDate>Wed, 16 Dec 2015 12:00:00 +0000</pubDate>
      <link>https://dev.to/kenneth_skovhus/abandoning-the-mothership-4g35</link>
      <guid>https://dev.to/kenneth_skovhus/abandoning-the-mothership-4g35</guid>
      <description>&lt;p&gt;The time had come to pour into our front-end code the same poison we had given our back-end systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="/static/39811723aaa825729504ddb878b338eb/e735c/deathstar.jpg"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fskovhus.github.io%2Fstatic%2F39811723aaa825729504ddb878b338eb%2F88218%2Fdeathstar.jpg" title="Abandoning the mothership" alt="Abandoning the mothership"&gt;&lt;/a&gt;Abandoning the mothership&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;COMMENT FROM DECEMBER 2019: This blog post was released when Star Wars: Episode VII – The Force Awakens came out… 🎬😄&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For many years, issuu’s engineering group was organized around component teams. Our late great Team Monster handled the front-end code and the rest of the teams provided APIs and back-end infrastructure.&lt;/p&gt;

&lt;p&gt;As we scaled the engineering organization, this classical split became counterproductive. A lot of cross team coordination was required for releases. Business logic and remappings were spread across multiple layers of the application. Dependencies and ownership of features were unclear. Finally, the Monsters had way too much on their plate!&lt;/p&gt;

&lt;p&gt;So in 2013, several of our teams transitioned from component teams to customer-centric, cross-component feature teams. One focused on the end-to-end reading experience, another team handled all publisher-related features and so on. Next was taking ownership of the entire code stack, from database to front end. Our back-end system quickly transitioned into smaller microservices written in technologies the team deemed best (OCaml, Erlang, Python, node.js, MySQL, Postgres, Redis, AMQP).&lt;/p&gt;

&lt;p&gt;Until recently, though, the front-end code running issuu.com was still one big, monolithic codebase. It had turned into such an unmanageable beast that we were all fighting with each other to get features out to users. We identified several blockers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With one big pile of code, team ownership and dependencies were unclear;&lt;/li&gt;
&lt;li&gt;we stepped on other people’s toes all the time;&lt;/li&gt;
&lt;li&gt;and as a result the rate of feature deployment decreased. (Oh yes, big-bang releases!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Besides, we had a major technology lockdown due to a very customized build system. This alone was around 3.000 lines of code, including a home-built Browserify and a lot of magical grunt tasks. As nobody dared to touch that part of the system, we were locked to our own require system, ES5 and Ruby SASS. Also the size of the codebase made builds painfully slow.&lt;/p&gt;

&lt;p&gt;It was time to pour into our front-end code the same poison we gave our back-end systems, splitting it all apart into maintainable chunks. Our vision was to make each feature team own, build and deploy its front-end code autonomously – and to make things that ought to be trivial actually trivial!&lt;/p&gt;

&lt;h2&gt;
  
  
  To the lifeboats!
&lt;/h2&gt;

&lt;p&gt;We started by dividing the front-end codebase into four chunks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;shared serving infrastructure;&lt;/li&gt;
&lt;li&gt;pages;&lt;/li&gt;
&lt;li&gt;widgets;&lt;/li&gt;
&lt;li&gt;and UI components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="/static/94804a1eeb24eeb80466e8118e2d738a/d9e23/infrastructure.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fskovhus.github.io%2Fstatic%2F94804a1eeb24eeb80466e8118e2d738a%2F799d3%2Finfrastructure.png" title="Partitioning our frontend-end code base" alt="Partitioning our frontend-end code base"&gt;&lt;/a&gt;Partitioning our frontend-end code base&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;shared serving infrastructure&lt;/strong&gt; is a thin horizontal node.js application responsible for routing and serving &lt;strong&gt;pages&lt;/strong&gt;. It holds the configuration for which version of a page to be served.&lt;/p&gt;

&lt;p&gt;A feature team delivers products consisting of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;pages&lt;/strong&gt; (node.js handlers, templates and assets like compiled JavaScript/CSS);&lt;/li&gt;
&lt;li&gt;and some &lt;strong&gt;widgets&lt;/strong&gt; (shared functionality used on multiple pages, like a message hub, streams or drag-and-drop functionality to initiate a publication upload).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our &lt;strong&gt;UI component&lt;/strong&gt; package provides high-level building blocks and styling for the site. It is our shared horizontal toolkit for keeping a consistent look and not reinventing buttons, form elements, modals and colors for each page and widget.&lt;/p&gt;

&lt;p&gt;To handle internal code dependencies, we decided to use the same tool we use for all other dependencies in JavaScript: &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;. So we set up a &lt;strong&gt;private npm repository&lt;/strong&gt; using the open-source &lt;a href="https://github.com/rlidwka/sinopia" rel="noopener noreferrer"&gt;Sinopia tool&lt;/a&gt;. When pushing code on master for one of our front-end repositories, our CI server will test and publish a new version of the package to Sinopia.&lt;/p&gt;

&lt;p&gt;To release a change to a page, you simply bump the product version in the shared webserver package. The package.json for our webserver looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "dependencies": {
    "issuu-productA": "1.0.2",
    "issuu-productB": "2.0.292",
    "issuu-productC": "1.0.x"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To follow the principle of least astonishment, most of our top-level packages are locked to a specific version of a page, but some packages like Marketing pages will always take the newest version.&lt;/p&gt;

&lt;p&gt;How did we migrate to this? After the initial serving infrastructure was ready, we made it up to the feature teams to take ownership of the old mothership codebase and turn it into a product/widget in the new world. Of course, the mothership still holds tight to some old products we never touch and that no team really owns. &lt;strong&gt;In the end, it is all about ownership.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After a few months, the old monolithic codebase is split into 45 packages. Oh, 46 now!&lt;/p&gt;

&lt;h2&gt;
  
  
  A new hope
&lt;/h2&gt;

&lt;p&gt;Instead of the old, frustrating technology lockdown, over the last six months a lot our feature teams have been innovating on the tools they have for building products. Most of the teams use the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makefiles for orchestrating everything why &lt;a href="https://algorithms.rdio.com/post/make/" rel="noopener noreferrer"&gt;reinvent the wheel&lt;/a&gt;?;&lt;/li&gt;
&lt;li&gt;Webpack for building assets;&lt;/li&gt;
&lt;li&gt;Babel for allowing us to write slick ES6 code that transpiles to ES5;&lt;/li&gt;
&lt;li&gt;a move to React and Redux;&lt;/li&gt;
&lt;li&gt;strict linting using (ESLint)[&lt;a href="http://eslint.org" rel="noopener noreferrer"&gt;http://eslint.org&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;and more as we go. Nothing stops a team from trying out TypeScript, CSS Modules, Elm, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are now able to work on isolated, vertical features without worrying about stepping on toes. Deployment time went from 30 minutes to just a few minutes, as we are rebuilding only what have changed and not the entire codebase. We went from a few weekly deploys to multiple times daily — continuous delivery for the win!&lt;/p&gt;

&lt;p&gt;The one constraint for a product is that it can be served by node. Heck, we are already talking about breaking the horizontal node server into smaller servers and letting the top-level routing logic reside in a proxy configuration. Ultimate autonomy to the team.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on sharing code, and lessons learned
&lt;/h2&gt;

&lt;p&gt;We want to make fast iterations on products and sustain team autonomy. Our new system is optimized for changes in issuu’s vertical products, not for making horizontal changes easier. It highlights clearly that we still have a lot of horizontal dependencies.&lt;/p&gt;

&lt;p&gt;In our old mothership repository, it is very easy to make a horizontal change and share a lot of code between products. One thing the code split has highlighted is that developers intuitively love to share code. Instead of copying and pasting small pieces, we would rather generalize it into shared components. This comes at a high cost: You now have yet another dependency, and &lt;strong&gt;dependencies slow you down&lt;/strong&gt;. You lose autonomy and make simple things complex.&lt;/p&gt;

&lt;p&gt;On the scale of a single product or feature, team code reuse and the &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;principle of DRY&lt;/a&gt; still make sense. But one should be careful about sharing code between products as shared dependencies are cumbersome. Of course, you never want to duplicate business logic, but I would much rather duplicate simple components than share them between verticals.&lt;/p&gt;

&lt;p&gt;Still, redundancy sucks, right? I’m going to end with a quote from the excellent post by &lt;a href="http://yosefk.com/blog/redundancy-vs-dependencies-which-is-worse.html" rel="noopener noreferrer"&gt;Yossi Kreinin&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Redundancy always means duplicated efforts, and sometimes interoperability problems. But dependencies are worse. The only reasonable thing to depend on is a full-fledged, real module, not an amorphous bunch of code. You can usually look at a problem and guess quite well if its solution has good chances to become a real module, with a real owner, with a stable interface making all its users happy enough. If these chances are low, pick redundancy. And estimate those chances conservatively, too. Redundancy is bad, but dependencies can actually paralyze you. I say kill dependencies first.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;This blog post was cross-posted from &lt;a href="https://skovhus.github.io/abandoning-the-mothership/" rel="noopener noreferrer"&gt;https://skovhus.github.io/abandoning-the-mothership/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It was originally posted at &lt;a href="https://engineering.issuu.com/2015/12/16/abandoning-mothership" rel="noopener noreferrer"&gt;issuu’s engineering blog&lt;/a&gt; and on &lt;a href="https://medium.com/@skovhus/abandoning-the-mothership-2d15b7e9313e" rel="noopener noreferrer"&gt;medium&lt;/a&gt;. This is the second part of our series “Toward a maintainable front-end”, the first part is &lt;a href="https://engineering.issuu.com/2015/09/15/mess-management.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microfrontend</category>
      <category>monolith</category>
      <category>velocity</category>
      <category>deployment</category>
    </item>
  </channel>
</rss>
