<?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: Arminas Katilius</title>
    <description>The latest articles on DEV Community by Arminas Katilius (@arminaskatilius).</description>
    <link>https://dev.to/arminaskatilius</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%2F51285%2F6c57b5a1-1a5f-40b0-a73f-3d5fdfc6dff4.jpg</url>
      <title>DEV Community: Arminas Katilius</title>
      <link>https://dev.to/arminaskatilius</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arminaskatilius"/>
    <language>en</language>
    <item>
      <title>Why TDD is Not Working For You</title>
      <dc:creator>Arminas Katilius</dc:creator>
      <pubDate>Mon, 18 Mar 2019 13:42:47 +0000</pubDate>
      <link>https://dev.to/arminaskatilius/why-tdd-is-not-working-for-you-2hbd</link>
      <guid>https://dev.to/arminaskatilius/why-tdd-is-not-working-for-you-2hbd</guid>
      <description>&lt;p&gt;Test Driven Development seems such a simple technique, yet it causes a wide range of reactions towards it. From people thinking it’s making you &lt;a href="https://www.researchgate.net/publication/3248924_Professionalism_and_Test-Driven_Development"&gt;more professional&lt;/a&gt;, to people thinking &lt;a href="https://dhh.dk/2014/tdd-is-dead-long-live-testing.html"&gt;it’s dead&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overall I think too strong push from TDD enthusiasts does more harm than good. It's great when you are excited about good coding practice, but when you start forcing others, it can have the opposite reaction. There is even a psychological term for it - &lt;a href="https://en.wikipedia.org/wiki/Reactance_(psychology)"&gt;Reactance theory&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reactances can occur when someone is heavily pressured to accept a certain view or attitude. Reactance can cause the person to adopt or strengthen a view or attitude that is contrary to what was intended, and also increases resistance to persuasion.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think this somewhat affects that developers are more likely to express and share an opinion on why TDD is not working for them. &lt;br&gt;
TDD is a specific technique and it is naive to think that it can be applied for everyone. And nobody should feel bad or unprofessional for not using TDD. However maybe TDD is the right technique for you, but multiple coincidences lead you to the conclusion that it's too hard and impractical. Here I will share a few ideas that might help you rethink your TDD experience. Some of them are ideas about how to apply the rules alternatively and some of them how to improve test experience, even if you are not using TDD.&lt;/p&gt;

&lt;h2&gt;
  
  
  You follow rules too strictly
&lt;/h2&gt;

&lt;p&gt;This comes from all tutorials and books, where the rules are laid out strictly. First &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd"&gt;law of TDD&lt;/a&gt; states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are not allowed to write any production code unless it is to make a failing unit test pass.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From such strong wording, it might seem that following the rules strictly is a must. While all 3 laws describe TDD process accurately and some developers do follow them strictly, it should be treated as material for initial learning.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn the rules, THEN break them&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For TDD it means that once you grasp how it works, you can apply it whenever you feel it works. Initially, strict process teaches you how to write testable code. But later you might find it more comfortable to build structure first and start writing TDD tests for logic then. &lt;/p&gt;

&lt;h2&gt;
  
  
  You are only using it for unit tests
&lt;/h2&gt;

&lt;p&gt;It's a common misconception, that TDD == unit tests. Actually, even the name is "Test Driven Development", not "Unit Test Driven Development". Unit tests are mostly used in TDD examples and tutorials, and usually, TDD works really great with pure unit testable functions. But in reality, the technique works with any kind of tests. &lt;/p&gt;

&lt;p&gt;For example, I have written a lot of SQL queries using TDD. Sometimes I am not sure what SQL I need to write, but I just need to create a test that inserts few database rows and expects some result. And then I can try out different SQL queries until it works. And same with API tests. You might need to fix bug where JSON output is a wrong format. Instead of testing manually with Postman, you can write an API test case and then start fixing the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your testing infrastructure is too slow
&lt;/h2&gt;

&lt;p&gt;The great benefit of TDD is that it actually can make you faster. Here is how. &lt;/p&gt;

&lt;p&gt;Writing a new functionality, or fixing existing one process could be oversimplified into two steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create/Update code&lt;/li&gt;
&lt;li&gt;Check if it works as intended&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TDD lets you optimize the speed of the "Check if it works as intended". You need not to wait for an app to be rebuilt, you need not open a browser, create test data and see if the code works as you expected. With TDD you see the result instantaneously.&lt;/p&gt;

&lt;p&gt;However, if tests execution is slow, that just breaks the flow. Some say &lt;a href="https://blog.ploeh.dk/2012/05/24/TDDtestsuitesshouldrunin10secondsorless/"&gt;tests should run in 10 seconds or less&lt;/a&gt;. &lt;br&gt;
And I can partly agree because TDD felt best for me when a test suite was fast. However, I would not agree that it's bad to run part of a test suite in order to be faster if you have a big test suite. But before using that technique, there are other ways to improve speed.&lt;/p&gt;

&lt;p&gt;First, it’s essential to find out why tests are slow. Integration tests might slow down if there is redundant data initialization, or if the database is being rebuilt each time. Each case is unique. And it is the same with unit tests, it varies depending on the stack or tools you are using. Find out their limitations and best practices and see if you can improve the speed in any way. &lt;/p&gt;

&lt;p&gt;And if there is no other way to improve speed (for example IT tests are naturally slower than unit). You can apply this technique, which allows running tests fast. Run a different amount of tests in a specific frequency:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Execute a single test most often, when you do small code changes&lt;/li&gt;
&lt;li&gt;After a certain time, or if you think you have made a large change, run all tests for a particular function/method&lt;/li&gt;
&lt;li&gt;After a certain time, run multiple related tests (might be all tests for the same class/module)&lt;/li&gt;
&lt;li&gt;Finally, run all test suit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is not an exact science and you should find what works best. But try not to think too much about which tests you should need to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your testing infrastructure is inconvenient
&lt;/h2&gt;

&lt;p&gt;It closely relates to the previous statement about speed. To be efficient at TDD, you have to use comfortable tools (same applies to be efficient at writing tests without TDD as well). &lt;/p&gt;

&lt;p&gt;As an example I can mention two qualities of testing infrastructure, that I think are really important:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;How easy is to execute all tests vs single test?&lt;/strong&gt;
Best case is that you can execute needed tests with a single button click or keyboard shortcut. Going to console and typing regex to match test you want to run is just tedious.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How clear are assertion errors?&lt;/strong&gt; You should not need to decipher why the test failed. Failure message like &lt;em&gt;"Expected true to be false"&lt;/em&gt;, when you were expecting certain item in an array is no good.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The list can go on, but the main goal is to minimize thinking about routine actions. This instead allows thinking more about the actual problem that you need to solve. If testing infrastructure gets in the way and makes you think too much about how to start writing or write test, it will be really hard to be efficient at TDD. This way tests will become annoying chore no matter if you write them after or before.&lt;/p&gt;

&lt;h2&gt;
  
  
  You apply TDD for simple cases only
&lt;/h2&gt;

&lt;p&gt;Writing tests for simple logic, especially if mocking is involved, can feel a bit awkward. You need to write setup code, initialize mock objects, add assertions for method calls, etc. And finally, the actual code is just "if" statement and few function calls. And this can feel a bit underwhelming.&lt;/p&gt;

&lt;p&gt;I am not saying you should not use TDD for simple cases. While learning it certainly helps. But applying for simple cases only might not reveal it's full potential. When I started using TDD, it seemed that I can only apply it to a new code, and only to certain functions. But I have started to use it when fixing new bugs or adding new functionality to existing code and it really helped me to understand how to apply it in different cases.&lt;/p&gt;

&lt;p&gt;TDD feels best when you have complex logic to implement. You do not even know how to implement it, but it allows you to chip away requirements and finally get fully working solution. And also it adds a lot of confidence to refactor while you do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  You are testing too much implementation details
&lt;/h2&gt;

&lt;p&gt;Good tests are clear and easy to understand. And with TDD it should be simple to think of what test to write upfront. However, if you are trying to cover internal behavior too much, it might be too hard to write test upfront.&lt;/p&gt;

&lt;p&gt;For example that happens a lot when a lot of stubbing and mocking involved. These kind of tests are hard to write because they involve assertions like "this method should be called 3 times with these arguments", etc.&lt;/p&gt;

&lt;p&gt;Another example I can remember is writing React tests using &lt;a href="https://airbnb.io/enzyme/"&gt;Enzyme&lt;/a&gt;. I sometimes ended up with tests that were checking internal state, checking how component renders children components and etc. And when I have started using &lt;a href="https://github.com/kentcdodds/react-testing-library"&gt;React Testing Library&lt;/a&gt; it become much easier to use TDD. You do not have access to internal details and it forces you to think about components testing differently. You do not care what child components are being rendered and what props are passed to them. Instead, you can write tests that expect certain text being rendered, and such tests are definitely easier to write upfront. &lt;/p&gt;

</description>
      <category>tdd</category>
      <category>testing</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Writing Javascript Codemods and Understanding AST Easily</title>
      <dc:creator>Arminas Katilius</dc:creator>
      <pubDate>Tue, 05 Mar 2019 20:36:12 +0000</pubDate>
      <link>https://dev.to/arminaskatilius/writing-javascript-codemods-and-understanding-ast-easily-48fc</link>
      <guid>https://dev.to/arminaskatilius/writing-javascript-codemods-and-understanding-ast-easily-48fc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally posted in my &lt;a href="https://katilius.dev/writing-js-codemods/"&gt;personal blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the big advantages when using statically typed language is ease of refactoring. Different IDE tools can easily rename class or method across hundreds of files with hundreds of usages. And given the nature of Javascript, some of the refactorings are hard, or even impossible.&lt;/p&gt;

&lt;p&gt;Despite that, different tools, that modify or inspect Javascript code still emerge. And in some cases, they are even better than ones in statically typed languages ecosystem. &lt;strong&gt;Prettier&lt;/strong&gt;, &lt;strong&gt;Eslint&lt;/strong&gt;, &lt;strong&gt;React Codemods&lt;/strong&gt; to name a few.&lt;/p&gt;

&lt;p&gt;They all have one in common - they all analyze or modify parsed Abstract Syntax Tree of the code. Basically, AST let you traverse source code using a tree structure. AST is a general programming languages term and not specific to Javascript. I will not go into the theory about AST here, but I will show a concrete example of how to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notable tools and libraries
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://astexplorer.net/"&gt;AST Explorer&lt;/a&gt; - one of the most useful tools while learning. You paste JS code and see AST representation in different AST specs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/facebook/jscodeshift"&gt;jscodeshift&lt;/a&gt; - a tool by Facebook, that helps writing code modification scripts.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/benjamn/ast-types/"&gt;AST Types&lt;/a&gt; - type specification on which jscodeshift is based.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/reactjs/react-codemod"&gt;react-codemod&lt;/a&gt; - collection of scripts, written for jscodeshift that convert React code in different ways. There are some good examples to look into.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/cpojer/js-codemod"&gt;js-codemod&lt;/a&gt; - Similar collection of scripts, that are not React specific. Also, help to learn by example.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up codemod project for TDD workflow
&lt;/h2&gt;

&lt;p&gt;Codemod is textbook sample where TDD works. You have an input file, you run the script and you get output. Thus I would really recommend using TDD for codemod projects. Not only it makes codemods more stable, but having projects with test workflow setup, will help you learn. Because you can experiment just by running the same test over and over again. &lt;/p&gt;

&lt;p&gt;Here is how to create codemod project from scratch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create empty npm project (&lt;code&gt;npm init sample-codemod&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Install codeshift &lt;code&gt;npm i -S jscodeshift&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install jest &lt;code&gt;npm i -S jest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy over test utils from jscodeshift library &lt;a href="https://github.com/facebook/jscodeshift/blob/595b15cda4f52673cad8fe3ae65c12e334966dbf/src/testUtils.js"&gt;src/testUtils.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Modify &lt;code&gt;testTest.js&lt;/code&gt;, by replacing &lt;code&gt;require('./core')&lt;/code&gt; with &lt;code&gt;require('jscodeshift')&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create initial folder structure:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-- src
|   +-- __testfixtures__  - put sample files for transformation, use suffixes .input.js and .output.js
|   +-- __tests__ -simplicity-in-technology.markdown
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After that, you can create a test file and start adding tests. Test utils from &lt;code&gt;jscodeshift&lt;/code&gt; allow you to create 2 type tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inline, where input and output is defined as string &lt;code&gt;defineInlineTest(transformFn, options, input, output)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Using files, where you define path to input and output files &lt;code&gt;defineTest(__dirname, transformName, options, testFilePrefix)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have created a repo with this sample in &lt;a href="https://github.com/katilius/sample-js-codemod"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps to create codemod
&lt;/h2&gt;

&lt;p&gt;Essentially codemods could be oversimplified to just 2 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the tree node&lt;/li&gt;
&lt;li&gt;Replace with new one or modify&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since there are many ways to write the same logic in JS. You will need to think of all ways developer could write the thing you want to replace. For example, even finding imported value is not that trivial. You can use &lt;code&gt;require&lt;/code&gt; instead of &lt;code&gt;import&lt;/code&gt;, you can rename named import, you can do same import statement multiple times and etc.&lt;/p&gt;

&lt;p&gt;At start I would suggest to think only about the simplest case and not think about edge cases. That's why I think TDD is essential, you can gradually add more complex cases, while not breaking initial functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample codemod
&lt;/h2&gt;

&lt;p&gt;Let's write simple codemod using this workflow. First let's define a simple test case, as we are trying to work with TDD.&lt;/p&gt;

&lt;p&gt;We want to convert this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we are using file approach for jscodeshift. It would be defined this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;arrow-to-function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&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;defineTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;arrow-to-function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;defaultExportedArrow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once we have this sample, we can launch &lt;a href="https://astexplorer.net/"&gt;AST Explorer&lt;/a&gt; and inspect how to input code is parsed as AST (make sure you use esprima spec):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lJUUccJd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zm28eoi504t24vic5a34.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lJUUccJd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zm28eoi504t24vic5a34.png" alt="Arrow AST"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From explorer it's clear that we need to find the node of type &lt;code&gt;ArrowFunctionExpression&lt;/code&gt;. And based on the highlight, we care about arrow function &lt;code&gt;body&lt;/code&gt; and &lt;code&gt;params&lt;/code&gt; fields.&lt;br&gt;
After analyzing what to find, we also need to find out what we need to build, here AST explorer helps as well. Just paste output code to it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DSrHYwpT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1hqhiz38wur7n5d98lz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DSrHYwpT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1hqhiz38wur7n5d98lz9.png" alt="Function AST"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the structure, it's clear, that regular functions are a bit more complex. We need to add a block statement and return statement.&lt;/p&gt;

&lt;p&gt;Let's start with finding arrow functions. To create codeshift transformation you need to create file and export single function. That function will receive three arguments: fileInfo, API, options. Currently, we mostly care about &lt;code&gt;api.jscodeshift&lt;/code&gt; (usually, it is defined as &lt;code&gt;j&lt;/code&gt;) and &lt;code&gt;fileInfo&lt;/code&gt;. Finding all arrow functions is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jscodeshift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ArrowFunctionExpression&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will return the collection instance, which we can iterate and replace nodes. Let's replace all arrow functions with regular functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jscodeshift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ArrowFunctionExpression&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replaceWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodeValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// get value from NodePath&lt;/span&gt;

      &lt;span class="c1"&gt;// whole node will be replaced with newly built node:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionDeclaration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nx"&gt;nodeValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blockStatement&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;returnStatement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodeValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toSource&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Each item is an instance of &lt;code&gt;NodePath&lt;/code&gt;, which allows you get parent node, therefore in order to access actual node you need to use &lt;code&gt;p.value&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;If you access jscodeshift field starting with &lt;strong&gt;uppercase&lt;/strong&gt;, it will return type (&lt;code&gt;j.ArrowFunctionExpression&lt;/code&gt;). It is used to filter and check nodes.&lt;/li&gt;
&lt;li&gt;If you access jscodeshift field starting with &lt;strong&gt;lowercase&lt;/strong&gt;, it will return build instance. Which allows creating code blocks. Check &lt;a href="https://github.com/benjamn/ast-types/"&gt;AST Types&lt;/a&gt; repo to see what fields are supported using each builder. For example, if you would open &lt;code&gt;core.ts&lt;/code&gt; file and look for &lt;code&gt;FunctionExpression&lt;/code&gt;, it has following definition: &lt;code&gt;build("id", "params", "body")&lt;/code&gt;. Which means that you need to pass id, params, and body.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that's pretty much it. If you follow these steps, it's not that hard to write more complex codemod. Just constantly check &lt;strong&gt;AST Explorer&lt;/strong&gt; and gradually you will become more familiar with the structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further improvements
&lt;/h3&gt;

&lt;p&gt;The current implementation is extremely naive and &lt;strong&gt;should not be run on actual code base&lt;/strong&gt;. Yet, if you would like to work further on this example to learn, here are some suggestions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle arrow functions with block statement &lt;code&gt;{}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Do not convert arrow functions that call &lt;code&gt;this&lt;/code&gt;. Arrow functions handle &lt;code&gt;this&lt;/code&gt; differently and current codemod would break working code.&lt;/li&gt;
&lt;li&gt;Convert arrow function declaration into named functions, for example &lt;code&gt;const sum = (a, b) =&amp;gt; a + b&lt;/code&gt; could be converted to named function &lt;code&gt;function sum(){...}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Running on codebase
&lt;/h3&gt;

&lt;p&gt;I have mentioned previously that this code should not be run on the real codebase, however, if you would build fully working codemod, here is how to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx jscodeshift -t script-path.js pathToFiles
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Dealing with complexity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Extract custom predicates. For example, if you are dealing a lot with JSX, you might create predicates like &lt;code&gt;hasJsxAttribute&lt;/code&gt;, &lt;code&gt;isNativeElement&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;Extract builder functions. If you keep creating import statements, create a function that would return the node with the import statement. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using Typescript
&lt;/h3&gt;

&lt;p&gt;It takes a bit of guessing when using jscodeshift API if you are not familiar with it. Typescript can simplify this process, it works with &lt;strong&gt;AST Types&lt;/strong&gt; mentioned at the start of the post. With Typescript it's a bit easier, to guess what parameters to use in a builder, or how to access certain values. However since parsing is really dynamic in nature, time saved by getting type info is sometimes lost dealing with Typescript type system and defining types manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jscodeshift recipes
&lt;/h2&gt;

&lt;p&gt;Here I will share some code snippets, that might help you do some tasks while writing your own codemod. They are not 100% error prone, but at least they show some different modifications you can do. &lt;/p&gt;

&lt;h3&gt;
  
  
  Create function call statement
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// will generate this:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableDeclaration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;const&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableDeclarator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;literal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;literal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Find imports in file
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;findImportsByPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;importPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;defaultImportUsed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;namedImports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ImportDeclaration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;importPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodePath&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;nodePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;specifiers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;specifier&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ImportDefaultSpecifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;specifier&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultImportUsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// specifier interface has both local and imported fields&lt;/span&gt;
                    &lt;span class="c1"&gt;// they are the same unless you rename your import: import {test as b}&lt;/span&gt;
                    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;namedImports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;specifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imported&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Rename JSX attribute
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jscodeshift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JSXAttribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodePath&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;nodePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;className&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;toSource&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>codemod</category>
      <category>ast</category>
      <category>jscodeshift</category>
    </item>
    <item>
      <title>Improving Code Quality using Pull Requests</title>
      <dc:creator>Arminas Katilius</dc:creator>
      <pubDate>Sat, 19 Jan 2019 17:54:23 +0000</pubDate>
      <link>https://dev.to/arminaskatilius/improving-code-quality-using-pull-requests-2e9i</link>
      <guid>https://dev.to/arminaskatilius/improving-code-quality-using-pull-requests-2e9i</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted in company &lt;a href="https://www.devbridge.com/articles/improving-code-quality-using-pull-requests/"&gt;blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pull requests are a bit like writing automated tests. First, the usefulness of them is hard to measure, since each project is different. At the same time using both become industry standard. Yet, there is still a lot of skeptics. They think that tests/pull requests slow developers from delivering functionality faster. Finally, both lose meaning, if they are used just for the sake of using.&lt;/p&gt;

&lt;p&gt;Another interesting thing is how tests and pull requests, besides their main purpose, improve other areas. For example, tests and especially TDD can help improve code quality and design. In this post, I will try to provide good practices for pull requests. And I will also try to mention how they can improve other areas.&lt;/p&gt;

&lt;p&gt;Before starting, one could ask why do pull requests at all. I will not go deep into it, each team can decide why pull requests are important, or why they are not. Yet, these are the things where pull requests are useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Giving confidence for the author, that the code is good enough for merging&lt;/li&gt;
&lt;li&gt;Sharing knowledge and understanding&lt;/li&gt;
&lt;li&gt;Making ourselves less lazy&lt;/li&gt;
&lt;li&gt;Noticing bugs&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  How to prepare Pull Request better
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Keep it small
&lt;/h2&gt;

&lt;p&gt;That is one of the most common problems with PRs, and it can affect overall experience while using pull requests. It's hard to understand changes and notice problems when there are a lot of files. Depending on team members, that usually results in two situations:&lt;/p&gt;

&lt;p&gt;reviewers just skim through files and approve without reading&lt;br&gt;
review drags on because it causes multiple discussions and the author must fix a lot of files&lt;br&gt;
There are different techniques to reduce the size of PR. What you can do depends on the type of project and release cycles. You could first introduce a partially working solution, and then with following pull requests expand it. For example, if you need to implement a data table with filtering and sorting, you could start with just a table, then add sorting with other pull requests and finally filtering. Or if you have a single repository for the project, you could introduce API changes first, and UI later.&lt;/p&gt;

&lt;p&gt;If you do not want to merge partially working functionality into a common branch, there are other techniques. You could introduce pull requests into the feature branch. With this technique, you need to create branches from your main feature branch and create pull requests back to it. It does add overhead and playing around with branches, but it might work for you.&lt;/p&gt;

&lt;p&gt;There are other ways how to split a large problem into smaller ones, and it depends on how each person tackles it. But by trying to split it into smaller chunks you can at the same time improve your problem-solving skills. This, in turn, helps in task estimation and other areas, because even before coding, you can split a task into easy to digest parts better.&lt;/p&gt;

&lt;p&gt;All things considered, think if large pull requests are not a symptom of too big tasks/stories. All these techniques are rarely needed if tasks are small enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactor with separate Pull Request
&lt;/h2&gt;

&lt;p&gt;This tightly relates to the previous tip about small pull requests, but I wanted to mention it because it is a good technique for development even without using pull requests. The general rule states: &lt;em&gt;“First refactor to make it easy to add new functionality, and only then add new functionality “&lt;/em&gt;. It's a great technique because instead of over-engineering, you allow new functionality guide design of the system.&lt;/p&gt;

&lt;p&gt;If you follow this rule, you can create simpler pull requests for your team to review. This adds a lot of benefits. It automatically splits huge pull request into few smaller ones. At the same time, if refactoring affects a lot of files, you introduce them sooner, rather than later. I have not always followed this rule, and it often caused painful merge conflicts, because other team members were editing the same files.&lt;/p&gt;

&lt;p&gt;The only downside of this approach might be if you introduce refactoring tightly to new feature you are implementing and for some reason, the feature is no longer added to the codebase, and you are left with code refactored and prepared for functionality that is not needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use git commit messages wisely
&lt;/h2&gt;

&lt;p&gt;Another general programming tip that translates well to pull requests is good to commit messages. It documents code and all the changes in a pull request. Think of it this way: instead of creating description where you list changes you have made, commit messages will document that. And in pull request description you can write other relevant information. And as a side effect, I really liked the description, I heard from colleague: &lt;em&gt;“Writing meaningful commit messages, makes you structure tasks better and divide your work into meaningful parts.”&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comment code yourself
&lt;/h2&gt;

&lt;p&gt;If you have doubts about the implementation of a feature, better discuss them before start coding and not do that in a pull request. But sometimes it might be less important things you are not sure of. For example - naming method or class. You can mention that in the pull request and somebody might suggest another name that you like better.&lt;/p&gt;

&lt;p&gt;Another way you might help reviewers is by commenting important places of the code or even explaining why you have done the things you have done. You can use it to guide reviewers to the changes you have made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduce new ideas with PRs
&lt;/h2&gt;

&lt;p&gt;As I've mentioned earlier, it is better to discuss things before starting to code. But sometimes you might end up in the situation, where it's just hard to imagine if the suggested solution would work without seeing the actual code. In this case, you can create proof of concept solution and create a pull request for it. It doesn't have to be merged, but PR review page is a good place to discuss that solution.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Review Pull Request Better:
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Do not approve PRs blindly
&lt;/h2&gt;

&lt;p&gt;One of the worst practices to do if you are doing pull requests. If multiple developers approve requests without reading them, it means that you aren't actually doing code reviews and pull requests, you are just creating an illusion.&lt;/p&gt;

&lt;p&gt;At the beginning I have mentioned, that one of the qualities of a pull request process is created confidence that your code is good enough to merge. You get this confidence because you know that other developers reviewed requirements against code, and checked readability. Reasonably sized pull request was approved 5 seconds after creation, you have a problem.&lt;/p&gt;

&lt;p&gt;If you are busy at the time, better leave pull request for others to review and come back to it later. I would rather wait longer for my pull request to be approved, but at least then I would know that somebody looked into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be polite, ask first
&lt;/h2&gt;

&lt;p&gt;Sometimes you do not know why the certain code was written the way it was, and you might tell someone to fix a certain problem. Sometimes it is polite to first ask the question and then suggest improvement. For example: Why have you iterated list four times instead of one?&lt;/p&gt;

&lt;p&gt;When you really are familiarized with code, go ahead and suggest improvement. But don't forget to be polite as well. There is a difference how you can communicate the same information:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Split this method into three smaller ones&lt;/em&gt; vs.&lt;br&gt;
&lt;em&gt;It would increase readability if you would split this method into 3 smaller ones.&lt;/em&gt;&lt;br&gt;
A thing to remember is that people reading your comments do not see your facial expression. And you might have best intentions with your suggestion, but once it becomes text, it might seem mean or rude. And I had many situations where I wanted to just be concise and clear, but the person receiving the suggestion was not happy about that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use code snippets
&lt;/h2&gt;

&lt;p&gt;When I started doing code reviews, I often wrote things like &lt;em&gt;“This could be simplified”&lt;/em&gt;, &lt;em&gt;“You could use lodash here”&lt;/em&gt;, etc. But then the author was not sure what I mean or did not know how to implement the suggestion. Gradually, I replaced generic messages with code snippets. It does take more time, but at the same time, it's much easier to compare the current code with suggested improvements and see if it's even worth doing. Also, the snippet might not be 100% accurate, the main goal is to convey information to the author more clearly.&lt;/p&gt;

&lt;p&gt;The thing to remember is that this suggestion is not a hard rule. If you feel that some part of the code is hard to read, you can express that in different ways. Sometimes just stating concern about complexity might be enough. It might help the author notice a problem and improve the code on his own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review the code even if you are new
&lt;/h2&gt;

&lt;p&gt;Often new team members are not sure who's pull requests they can review or even when they can review PRs at all. Each team can have a different agreement when a person can &lt;em&gt;“approve“&lt;/em&gt; pull requests, but you should start reading and even commenting pull requests right away. You might even add questions for the author about general ways of coding in the project and learn best practices.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Improve Overall Pull Request Process
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Make use of static analysis tools
&lt;/h2&gt;

&lt;p&gt;One of the things reviewers tend to notice is code style. It might be multiple empty lines, unused variables, and functions etc. Pull requests help to align different styles of code across developers. It does not mean that one style is better than another but having a consistent style across codebase is better compared to random style for each file. However, using pull request for that has multiple problems. One is that developers are just humans, and they will not always notice these problems. &lt;/p&gt;

&lt;p&gt;Another is that comments about code style can take quite a lot of pull request review. They are for sure easy to fix, but when there-there are ten comments about style and one about readability, then the most important can get lost easily.&lt;/p&gt;

&lt;p&gt;All things considered, I am not saying that it’s not worth to mention style problems in PR, but if you notice certain problems too often, consider using linting tool to notice those before pull request. If a robot can do things for you and even better, why do it yourself? Moreover, it’s easier when the robot notices problems - you cannot take offense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Have a checklist for things to require before approving
&lt;/h2&gt;

&lt;p&gt;Each developer decides if a pull request is ready to be merged, or not. But if the reviewer is stubborn, he could avoid approving pull request, even though there are no major problems with it. When you start noticing, that kind of behavior, discuss and agree on common values for the code. Then using values as a basis, decide on things required for the pull request to be approved. For example, if tests are important, make a rule that bug fix requires a new test or existing test fix. Having list of required things before approve really helps for new team members and reduces the number of discussions when PR is not being approved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop large threads of discussions sooner than later
&lt;/h2&gt;

&lt;p&gt;Programmers love their code. Imagine you have worked all day on the particular algorithm and somebody just starts to dissect it and tells to do things differently. Even worse, the reviewer might not be particularly polite about that. He might be wrong, or he might be right, but the point is that this could cause long discussion thread, where you exchange arguments why one or another way is better. Even if the conversation is polite, you should stop it before it gets too long and has a live discussion about that. Sometimes it’s enough to just go to other developer desk and chat, and sometimes you might need to schedule a meeting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gamify process
&lt;/h2&gt;

&lt;p&gt;When you find trouble making developers commit to reviewing pull requests, instead of adding rules immediately, try adding some fun to the process. If you have a TV in office box that shows stats, add a new section which shows some information about pull requests. For example, you could show requests, that are pending for quite some time and are not reviewed. Additionally, you could have stats like &lt;em&gt;“Reviewer that added most comments this month”&lt;/em&gt; or other fun statistics, that would encourage people to commit to reviewing. There are many other creative ways to improve the process and encourage the developer to participate. &lt;/p&gt;

</description>
      <category>pullrequest</category>
      <category>codereview</category>
    </item>
  </channel>
</rss>
