<?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: Udayakumar Rayala</title>
    <description>The latest articles on DEV Community by Udayakumar Rayala (@uday_rayala).</description>
    <link>https://dev.to/uday_rayala</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%2F81813%2F174e4316-6bf9-4efb-90e9-c107a2cc12ec.png</url>
      <title>DEV Community: Udayakumar Rayala</title>
      <link>https://dev.to/uday_rayala</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/uday_rayala"/>
    <language>en</language>
    <item>
      <title>Code review checklist</title>
      <dc:creator>Udayakumar Rayala</dc:creator>
      <pubDate>Wed, 04 Jul 2018 14:35:34 +0000</pubDate>
      <link>https://dev.to/uday_rayala/code-review-checklist-20c6</link>
      <guid>https://dev.to/uday_rayala/code-review-checklist-20c6</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F854%2F1%2AJyDMwcM4jfOAkg6UO6ChEw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F854%2F1%2AJyDMwcM4jfOAkg6UO6ChEw.jpeg"&gt;&lt;/a&gt;&lt;a href="http://blog.smartbear.com/wp-content/uploads/2015/09/Creating-Your-Code-Review-Checklist.jpg" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="http://blog.smartbear.com/wp-content/uploads/2015/09/Creating-Your-Code-Review-Checklist.jpg" rel="noopener noreferrer"&gt;http://blog.smartbear.com/wp-content/uploads/2015/09/Creating-Your-Code-Review-Checklist.jpg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have posted in my &lt;a href="https://dev.to/uday_rayala/code-reviews-vs-pair-programming-560i"&gt;last blog&lt;/a&gt; about how we do code reviews and compared it with pair programming.&lt;/p&gt;

&lt;p&gt;One thing I noticed is, every team and team members have a different list of things they look for while doing code review. In this post, I will list out the things I look for. This is no way a complete checklist. If there any checks which you think are missing, let us know by adding them in comments.&lt;/p&gt;

&lt;h4&gt;
  
  
  Design
&lt;/h4&gt;

&lt;p&gt;Depending on what programming language or platform you use, check whether the new code follows the right design.&lt;/p&gt;

&lt;p&gt;What is a right design is up to the team to agree upon? It is always best to have upfront discussions among developers when new abstractions are brought in and the new design is followed. Code reviews can be a way to make sure it is implemented as discussed. This will make sure there will not be a lot of rework. But this can be exempted when you want to implement something new and then get feedback on it. Make sure you write enough so the idea is conveyed.&lt;/p&gt;

&lt;p&gt;Following are some of the things you should check for (Thanks to &lt;a href="https://twitter.com/bhavinjavia" rel="noopener noreferrer"&gt;Bhavin Javia&lt;/a&gt; for contributing to most of this list):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify if coding conventions as per the designated style guide is being followed to maintain consistency and best practices.&lt;/li&gt;
&lt;li&gt;Check for Duplication inadvertently introduced by developers e.g due to lack of awareness about existing reusable components, misplaced logic/responsibilities, generic/reusable code not extracted and just copy/pasted elsewhere etc&lt;/li&gt;
&lt;li&gt;Identify Refactoring opportunities which were missed or deferred during earlier tech debt and code reviews. Often if the developer is working in that area, has a lot of context which makes it easier to include some refactoring tasks as part of the story/PR vs finding a dedicated block of time for refactoring.&lt;/li&gt;
&lt;li&gt;Spot and warn developers about potential dependencies or conflicts with other developer’s code e.g. when multiple features which touch same areas of the codebase are under development or review&lt;/li&gt;
&lt;li&gt;If there’s any non-standard feature or hack is being introduced, make sure it’s annotated with a #TODO or #FIXME tags along with an appropriate comment e.g. reference to the code snippet/patch being used with reason and what the ideal solution should be. e.g. #FIXME Patch to workaround bug # in &amp;lt;framework&amp;gt; &amp;lt;link&amp;gt;. Remove after upgrading to fixed version.&lt;/li&gt;
&lt;li&gt;Look out for new libraries introduced and see if they are required and are the latest version. Are there better alternatives for it?&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Tests
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;All the above checklist about code also applies to test code.&lt;/li&gt;
&lt;li&gt;Make sure all the code have tests written at all levels — unit, integration and functional.&lt;/li&gt;
&lt;li&gt;Check if all tests passing.&lt;/li&gt;
&lt;li&gt;Check if the tests are acting as documentation describing the intention of the code it is testing.&lt;/li&gt;
&lt;li&gt;Check if tests give proper error messages when they fail. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expect(subject).to include(:customer) #is better than:
expect(subject.key? :customer).to be\_true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Wear the QA hat&lt;/strong&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;This is something which most people miss or probably think not as important. Working of the code is as important as its quality. Even if you have a testing team, catching bugs at code review will reduce the cost of fixing it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Read the story description, ask questions to the BA or Product Owner and see if all the acceptance criteria is implemented as mentioned. I feel most bugs can be caught with just this check.&lt;/li&gt;
&lt;li&gt;Think about scenarios outside of what is mentioned in the story. Check if the usual user flows related to the new changes are still working as expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Cross functional requirements (Non Functional Requirements)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Also focus on cross functional requirements like Performance, Security, Analytics, Logging, Alerting etc.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check if the code can introduce any performance issues like N+1 query problem, or loading entire database into memory etc. Think about running this code in a production environment and anticipate what kind of problems might arise. Of course you can’t find all of them just by looking at the code but you might be able to identify some common mistakes from your past experience. Like doing Customer.all.&lt;/li&gt;
&lt;li&gt;Security is something which can be identified early. Check if data is accessed only by authorised users. Read about common security precautions which can be taken and share the same understanding with the team.&lt;/li&gt;
&lt;li&gt;If you already have integrated with some analytics system, check if the new functionality should integrate with it.&lt;/li&gt;
&lt;li&gt;Check if enough logging is done to be able to debug the application.&lt;/li&gt;
&lt;li&gt;Check if alerts are added when things break.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Continuous Delivery
&lt;/h4&gt;

&lt;p&gt;When you are following continuous delivery, you should make sure the new changes don’t break production data and functionality.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure data migration scripts are added and check if they execute as expected. Run them on your machine once if required. Don’t make changes which will result in data loss. Also, make sure the features going to production are auto-deployed to a staging or pre-production environment which has a replica of production data (obfuscated) to detected and fix potential issues.&lt;/li&gt;
&lt;li&gt;Check if feature toggles are added for any functionality which you don’t intend to release.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Other
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Check if the code under review is merged with the latest master branch code.&lt;/li&gt;
&lt;li&gt;Make sure instructions are added for any other teams to follow after integrating these changes. For example, informing the QA team what areas to run regression on if there are any major changes. Or informing any downstream consumer systems for any changes in the API contract. Or updating README for helping other developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, keep the changes to be reviewed small and raise pull requests soon to get feedback early.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please add your thoughts in the comments. And if you like the post, recommend it so others can find it and participate in the discussion.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>codereview</category>
    </item>
    <item>
      <title>How to create your own AWS Lambda Middleware framework in Node.js?</title>
      <dc:creator>Udayakumar Rayala</dc:creator>
      <pubDate>Wed, 06 Jun 2018 08:24:58 +0000</pubDate>
      <link>https://dev.to/uday_rayala/how-to-create-your-own-aws-lambda-middleware-framework-in-nodejs-2fkb</link>
      <guid>https://dev.to/uday_rayala/how-to-create-your-own-aws-lambda-middleware-framework-in-nodejs-2fkb</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F0Hi_fhw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/415/1%2AO4r5gQQQ37s0Lc4pTYbE3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F0Hi_fhw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/415/1%2AO4r5gQQQ37s0Lc4pTYbE3g.png" alt=""&gt;&lt;/a&gt;AWS Lambda Middlewares Framework&lt;/p&gt;

&lt;p&gt;We have around 25 lambdas and they share some common functionality like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrating with Sentry&lt;/li&gt;
&lt;li&gt;Removing unnecessary events&lt;/li&gt;
&lt;li&gt;Logging information about the event being processed&lt;/li&gt;
&lt;li&gt;Datadog tracing etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We needed a way to define these functionalities once and reuse them across lambdas. This post is about a middleware framework we wrote in Node.js to do this with very little code and no external libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Middleware Pattern
&lt;/h3&gt;

&lt;p&gt;We could have extracted each of these functionalities into a function and called it in the lambdas which would have allowed us to reuse the code. But we thought if we can bring in some convention, integrating/maintaining these common functionalities into lambdas would be much easier.&lt;/p&gt;

&lt;p&gt;Having working with a lot of web frameworks which have concepts like &lt;a href="http://www.oracle.com/technetwork/java/filters-137243.html"&gt;filters in java&lt;/a&gt;, &lt;a href="https://expressjs.com/en/guide/using-middleware.html"&gt;middlewares in Express&lt;/a&gt;, we felt a similar approach would work for us as well.&lt;/p&gt;

&lt;p&gt;The idea is to implement a lambda handler function as a core function and a set of middleware functions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Core function will do what the lambda is supposed to do like transforming the incoming data, writing the events to a data store etc.&lt;/li&gt;
&lt;li&gt;Each middleware will handle one functionality like integrating Sentry or logging etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the order in which the middlewares are called:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MiddleWare1 -&amp;gt; MiddleWare2 -&amp;gt; MiddleWareN-&amp;gt; CoreFunction
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Middlewares have the same signature as the lambda handler function with an additional argument of the &lt;em&gt;next&lt;/em&gt; middleware. In case of the last middleware, the &lt;em&gt;next&lt;/em&gt; argument will be the core function. If the core function returns some value, middlewares typically return the same value.&lt;/p&gt;

&lt;p&gt;And each middleware function can choose when to call the next middleware. This way we can divide a middleware function into three sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before Section — This code is executed before the core function. We can do things like filtering events, adding more data to context etc.&lt;/li&gt;
&lt;li&gt;Next Middleware Section — This could be the actual call to the core function. And the middleware has a choice to not call the core function at all and finish the lambda execution.&lt;/li&gt;
&lt;li&gt;After Section — This code is executed after the core function. We can do things like error handling, logging or returning a different response etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Promises instead of Callbacks
&lt;/h3&gt;

&lt;p&gt;Most of our lambda function code create or work with promises since they mostly query/write to external systems like Dynamodb, Elasticsearch etc. We thought it would be easier if our core function and middlewares work with promises instead of callbacks.&lt;/p&gt;

&lt;p&gt;A typical AWS lambda definition in Node.js v6.10 would look like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exports._myHandler_ = function(event, context, callback){
   // Do something
   // callback(null, "some success message");
   // or
   // callback("some error type");  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And this is how we wanted our handler functions to look like:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handlerFunction = (event, context) =&amp;gt; {
  return new Promise()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Node.js v8.10 supports async handlers which was not available when we wrote this middleware framework. This step might be redundant in Node.js v8.10.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Middleware Orchestrator
&lt;/h3&gt;

&lt;p&gt;Because we have a different signature than what lambda handler is expected to have, we created a function withMiddlewares.&lt;/p&gt;

&lt;p&gt;It takes the core function and an array of middlewares as input and returns a function which has the same signature as the lambda handler.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export._myHandler_ = withMiddlewares(
  handlerFunction, 
  [Middleware1(), Middleware2()]
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And this is the implementation of withMiddlewares:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Line 1: It has the same signature as the lambda middleware.&lt;/p&gt;

&lt;p&gt;Lines 2–14: chainMiddlewares returns a function which recursively calls each middleware and finally calls the handler. If there is an error thrown when calling the middleware, it will return a rejected promise.&lt;/p&gt;

&lt;p&gt;Lines 16–21: We call chainMiddlewares with all the middlewares and convert the resulting promise into a callback function.&lt;/p&gt;

&lt;h4&gt;
  
  
  Middleware Template
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Middleware = () =&amp;gt; {
  return (event, context, next) =&amp;gt; {
    // Before Logic
    return next(event, context)
      .then(result =&amp;gt; {
        // After Logic
        return result
      })
      .catch(error =&amp;gt; {
        // Error Handling
        return Promise.reject(error)
      })
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 1: Sentry Middleware
&lt;/h3&gt;

&lt;p&gt;Integrating Sentry typically involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before Section — Initialising raven library&lt;/li&gt;
&lt;li&gt;After Section — Reporting errors to Sentry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the trimmed down version of how this middleware definition would look like:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;captureExceptionAndReturnPromisewill wait for Sentry request to complete since it is returned as promise.&lt;/p&gt;

&lt;p&gt;If we are not able to send the request to Sentry for various reasons like Sentry is down or network error, we currently bubble up the error. But we can also log the error and return the original error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 2: Dynamodb Insert/Modify Events Filter
&lt;/h3&gt;

&lt;p&gt;Some of our lambdas want to ignore Dynamodb delete events and execute only on the insert/modify events.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before Section — Remove delete events from event.Records&lt;/li&gt;
&lt;li&gt;After Section — No after actions&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;We are modifying the event.Records here. Another option is to clone the event with filtered records if we want immutability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 3: Lambda Handler
&lt;/h3&gt;

&lt;p&gt;This is how a lambda handler would look like using the above defined middlewares. The order of the middlewares is important. SentryMiddleware should be the first middleware to catch errors in downstream middlewares too.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Implementing this pattern made our code more readable and testable. You can find the full implementation with tests and sample middlewares &lt;a href="https://github.com/siroop-ch/nodejs-lambda-middleware"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Team who worked on this:&lt;/em&gt; &lt;a href="https://github.com/uvesten"&gt;&lt;em&gt;Petter Uvesten&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://github.com/linuxbasic"&gt;&lt;em&gt;Linus Basig&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://github.com/barrborra"&gt;&lt;em&gt;Barbora Brockova&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://github.com/Kjir"&gt;&lt;em&gt;Stéphane Bisinger&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;


</description>
      <category>awslambda</category>
      <category>designpatterns</category>
      <category>middlewarepattern</category>
      <category>node</category>
    </item>
    <item>
      <title>Incremental refactoring using Scientist</title>
      <dc:creator>Udayakumar Rayala</dc:creator>
      <pubDate>Thu, 09 Mar 2017 04:47:50 +0000</pubDate>
      <link>https://dev.to/uday_rayala/incremental-refactoring-using-scientist-30pm</link>
      <guid>https://dev.to/uday_rayala/incremental-refactoring-using-scientist-30pm</guid>
      <description>

&lt;p&gt;In one of my recent projects, we had to replace a part of the code which calculates price with a new pricing service that has more functionality.&lt;/p&gt;

&lt;p&gt;Calculating price being one of the most critical part of our service, we were faced with the following questions—&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do we know if the new pricing service is doing same as calculations we have?&lt;/li&gt;
&lt;li&gt;If it is not working as expected, what are the inputs for which it is not working?&lt;/li&gt;
&lt;li&gt;How do we know if we have integrated with the new service correctly ?&lt;/li&gt;
&lt;li&gt;What is the performance impact of calling the new service? Is it better or worse?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We could have tested with a bunch of scenarios with known inputs but production is all about unexpected situations. We wanted a way to test the integration before we can release the changes to the users. That is when we came across &lt;a href="https://github.com/github/scientist"&gt;Scientist&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/github/scientist"&gt;Scientist&lt;/a&gt; is a small ruby library which gives necessary framework to test your new code without releasing it. The main building block is an Experiment. It has two blocks of code &lt;strong&gt;control&lt;/strong&gt; and &lt;strong&gt;candidate&lt;/strong&gt;. Both blocks are executed every time an experiment is called. But only the result from control block is returned. Exceptions in candidate block will be rescued. And at the end, results from both the blocks can be compared and logged for further analysis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea was to create a Scientist experiment with control block as the existing local price calculation and candidate block as the call to the new pricing service. And compare the results before we can go live.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparation
&lt;/h3&gt;

&lt;p&gt;Couple of things we wanted to do before using Scientist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refactor the existing code into one class. This way we can use Class Polymorphism to switch between using existing implementation, new implementation or the scientist experiment. We use Figaro for managing application configuration. So this refactoring to using class polymorphism would help us pass the class to use as a configuration to our service. I will show below how we did that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After refactoring, our existing pricing calculations were moved into the LocalPricingEngine with estimate method:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;We needed a place to log the input params, what the control/candidate blocks returned, and the time it took to execute each block. There are number of places we can log this information like Redis, Postgres DB etc. But we chose to log it in our log file. We already had json logging using &lt;a href="https://github.com/roidrage/lograge"&gt;Lograge&lt;/a&gt;. So putting in log file would make it easy to retrieve this information in one line.&lt;/li&gt;
&lt;li&gt;Although low level information of logging per input difference is useful, it would be hard to get a summarised view of what happened. We need to be able to find out how many mismatches happened and at what time of the day (our price calculation varies by time of the day). We already use DataDog for monitoring/alerting and it made sense to put this information right there. I will show code snippets on how we did this later.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;We created three polymorphic implementations of PricingEngine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LocalPricingEngine&lt;/strong&gt;  — Existing implementation of price calculations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PricingServiceEngine&lt;/strong&gt;  — New implementation which calls the pricing service for calculations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ExperimentalEngine&lt;/strong&gt;  — Scientist experiment which calls the above classes for control and candidate blocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And also a factory which would choose the right implementation based on our environment configuration:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;We replaced the call to LocalPricingEngine with the call to PricingEngineFactory.engine.&lt;/p&gt;

&lt;p&gt;So this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LocalPricingEngine.new.estimate(...)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;changed to:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PricingEngineFactory.engine.estimate(...)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We now have the ability to change the pricing engine from our environment variable PRICING_ENGINE. It would have one of these values: LocalPricingEngine or PricingServiceEngine or ExperimentalEngine. And not having this environment variable would choose LocalPricingEngine by default.&lt;/p&gt;

&lt;p&gt;This is how the ExperimentalEngine looked like:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;I trimmed down the variable names for better formatting. e represents an experiment object and p1, p2, p3 are param1, param2, param3 respectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Publishing Results
&lt;/h3&gt;

&lt;p&gt;This is the step I spent most time to figure our inspite of Scientist’s good documentation.&lt;/p&gt;

&lt;p&gt;By default Scientist doesn’t publish the results anywhere. If we want to publish the results, we can do so by creating a new Scientist::Experiment and overriding publish method.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, we want to log two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Experiment results to log file.&lt;/li&gt;
&lt;li&gt;Summaries to DataDog.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We needed a way to communicate the experiment results to Lograge. And since Lograge custom options can only be passed at controller level, we used RequestStore as a way to pass the results from Experiment to Controller.&lt;/p&gt;

&lt;p&gt;This is how the controller configuration looked like:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;We used &lt;a href="https://github.com/reinh/statsd"&gt;statsd&lt;/a&gt; client to publish the summaries to DataDog.&lt;/p&gt;

&lt;p&gt;This is how the experiment class looked like. You can replace MyService in MyServiceExperiment with your service or application name:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;There are two methods to implement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;enabled? — This controls whether the candidate block should run or not. In our case, we always enabled since we controlled this behaviour from the class polymorphism we implemented.&lt;/li&gt;
&lt;li&gt;publish — This method is called after both control and candidate blocks are run. We are publishing the results to DataDog and to Lograge through RequestStore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we needed to tell Scientist to use this new experiment we created. You can do so with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;You can put this in initializers folder if you are using Rails.&lt;/p&gt;

&lt;h3&gt;
  
  
  Outcome
&lt;/h3&gt;

&lt;p&gt;Using Scientist for this use case helped us in the following ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test whether the new service can handle the load. Our new service was production ready, so decided to take the entire load. But if you dont want to take all the load, you can use the run_if or enabled?block to control how much percentage of load you want to run the experiments for. More info &lt;a href="https://github.com/github/scientist#ramping-up-experiments"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Uncover edge cases. We had a rule to increase the prices at certain time of the day. We misconfigured the new service to stop increase of price one minute early. We uncovered this when we saw a lot of mismatches only during this one minute. There was also a rounding issue on how the final price was rounded. Although it was small for one price calculation, it would add up to a lot when thousands of calculations were made.&lt;/li&gt;
&lt;li&gt;It helped us give instant feedback about the difference in prices when changes were made either in local price calculation or in the new service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Things to look out for
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;control and candidate blocks run sequentially. So this would increase the overall execution time. It would have been nice if they could run in parallel.&lt;/li&gt;
&lt;li&gt;control and candidate results are compared using ==. You can override this behaviour by defining e.compare method. More info &lt;a href="https://github.com/github/scientist#controlling-comparison"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;We migrated to the new service without resulting any user issues and with greater confidence. We incrementally built the integration releasing one or two times every day without the risk of causing any inconvenience to the users. We caught bugs early and our production started giving us feedback as we built.&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://github.com/github/scientist"&gt;Scientist&lt;/a&gt; was pretty smooth. It is a very small library. You can read through its code in less than an hour. And the documentation is pretty good which covers most of the commonly asked questions.&lt;/p&gt;





</description>
      <category>rails</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>refactoring</category>
    </item>
    <item>
      <title>Code Reviews vs Pair Programming</title>
      <dc:creator>Udayakumar Rayala</dc:creator>
      <pubDate>Fri, 08 Jan 2016 11:29:53 +0000</pubDate>
      <link>https://dev.to/uday_rayala/code-reviews-vs-pair-programming-560i</link>
      <guid>https://dev.to/uday_rayala/code-reviews-vs-pair-programming-560i</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqeJ0VmSemcroGPakiuihcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqeJ0VmSemcroGPakiuihcg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARWH6NqKGeRb9Vn_UgHv8QA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARWH6NqKGeRb9Vn_UgHv8QA.png"&gt;&lt;/a&gt;Code Reviews vs Pair Programming&lt;/p&gt;

&lt;p&gt;I’ve spent nine years working in teams which religiously follow pair programming. I’m used to working that way and appreciate the benefits it brings.&lt;/p&gt;

&lt;p&gt;We didn’t have the luxury of pair programming all the time in my last project. This required us to do code reviews to ensure the quality of the code we delivered. This post is an attempt to consolidate the upsides and downsides of doing code reviews instead of pair programming in my three months of experience.&lt;/p&gt;

&lt;h4&gt;
  
  
  How do we do it?
&lt;/h4&gt;

&lt;p&gt;We use Github as our source code repository. The master branch is always considered to contain production-ready code. Each story is developed on an independent branch, a pull request is created, reviewed and merged back into the master.&lt;/p&gt;

&lt;p&gt;We use &lt;a href="https://github.com/reenhanced/gitreflow" rel="noopener noreferrer"&gt;git-reflow&lt;/a&gt; to facilitate code review. Working on a story typically involves three steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start&lt;/strong&gt;  — You do a &lt;code&gt;git reflow start&lt;/code&gt; on master. This creates a new branch with whatever is on the master branch. You can continue working on this branch and it should not affect what is released to production since only changes that are in master go to production. Our CI(Teamcity) was configured to run the build on every branch that is created. So as and when changes were made, the tests were run and verified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review&lt;/strong&gt;  — After completing your changes and reviewing them yourself, you can raise a pull request by running &lt;code&gt;git reflow review&lt;/code&gt;. This will create a pull request (PR) on Github. You can then ask any of your team members or a particular person to review. They will put their suggestions/comments as inline comments on the PR. You can have a conversation on whether any changes are required. This generally goes back and forth between the developer and the reviewer. Once all the required changes are done, the reviewer marks that the PR can be merged by adding an ‘LGTM’ comment on the PR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliver&lt;/strong&gt;  — You can now merge the PR into the master branch. You might have conflicts if someone else has merged and made similar changes. After a successful merge, you have to make sure the expected functionality is working on master and all the tests pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find more information about git-reflow in these posts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://guides.github.com/introduction/flow/" rel="noopener noreferrer"&gt;https://guides.github.com/introduction/flow/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://scottchacon.com/2011/08/31/github-flow.html" rel="noopener noreferrer"&gt;http://scottchacon.com/2011/08/31/github-flow.html&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Upsides
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specialist feedback&lt;/strong&gt; — Although it is encouraged to have more generalists in an Agile team, it is often advantageous to have some specialists or people who are experts in some areas like CSS, database, or rails. And having a setup like this helps in getting their feedback on the code before merging. This encourages sharing of knowledge. I’ve found this to be more scalable than getting the specialists to pair with each member of the team. This also applies to teams where there are more junior developers than senior developers who may need feedback on the code written.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No keyboard hogging&lt;/strong&gt;  — Pair programming is useful as a way of sharing knowledge. But I have seen sometimes people with more experience dominate the pairing. Although it is great in the beginning to share knowledge, it doesn't help junior folks build the confidence to work on their own. Even if they are given a chance to navigate while pairing, they might feel some pressure because they are wasting their pair’s time to keep up to their pace. When following code reviews, junior folks can work on the stories by themselves. They can get occasional help if required and also spend more time reading outside core working hours without the guilt of wasting their pair’s time. They might initially take more time to deliver a story but it helps in building their confidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suits distributed teams&lt;/strong&gt;  — I have done a lot of remote pairing. Even though it works well, you often have timezone and bandwidth challenges. Since code reviews with pull requests are done asynchronously, they also allow team members to follow working hours that are convenient to them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversations are archived&lt;/strong&gt;  — Pull request comments are useful for someone to know why things are done in a certain way later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Highly collaborative&lt;/strong&gt;  — The conversations in a code review are visible to the entire team. If there is something I can provide input on, I can jump into the conversation. This happens in pair programming when the entire team is sitting in one place and conversations can be overheard. But it’s not always possible for distributed teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Downsides
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Working on stories which have dependencies is hard &lt;/strong&gt; — There might be an in-progress branch from which you need changes, but you can’t get them onto your branch because they haven’t been merged to master. This requires the developers on dependent stories to work very closely and a lot of git merges and rebasing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time lag between story development and review &lt;/strong&gt; — This often happens because people are busy developing their own stories. You sometimes have to follow up with people multiple times to get the review done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reviewing big changes is hard &lt;/strong&gt; — &lt;strong&gt; &lt;/strong&gt; If there are a lot of changes, it takes a lot of time and effort to review them thoroughly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delayed feedback from CI pipelines &lt;/strong&gt; — CI pipelines for every new branch works great only at one level. If you have a second level build which runs end-to-end tests on multiple services, you cannot run them on all the new branches. Hence, the feedback is delayed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;This doesn’t mean we shouldn’t do pair programming at all. It still helps to pair when you’re on-boarding new people or setting up a new code base. And I feel it is still useful to do some form of code review in teams that follow pair programming. But make sure you keep the stories small and don’t end up having long-lived branches.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please add your thoughts in the comments. And if you like the post, recommend it so others can find it participate in the discussion.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>softwaredevelopment</category>
      <category>pairprogramming</category>
      <category>codereview</category>
    </item>
  </channel>
</rss>
