Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Wednesday, October 31, 2018

Feature Toggling Graphql Service with LaunchDarkly

For a project I was working on, we have a graphql service that retrieves clients positions from a SQL database. Under the hood there are some complex SQL stored procedures joining multiple SQL tables and complex data processing before they are finally in a usable shape. We want to move all this complexity to a Hive Big Data project which is more suitable to handle this type of data massaging and have our project consumed a Hive REST API.

The plan is to make sure that once the Hive REST API is live or even during UAT, the consumers of our graphql service do not notice any difference. And if something goes wrong with Hive, we can switch back to good old SQL with very minimal code change. This is where I think LaunchDarkly comes in handy as a fallback scenario. Fortunately I have some prior experience working with it.


The Toy Example

Now to illustrate what I'm dealing with, I have created a toy graphql service. Suppose we have a graphql query that retrieve clients positions defined as:

   type Query {
      positions: [String]
   }

Suppose the result of the query sourced from SQL is:

   {
     "data": {
       "positions": [
         "Sql1",
         "Sql2",
         "Sql3"
       ]
     }
   }

We want to be able to switch to Hive on the fly so that the same query returns:

   {
     "data": {
       "positions": [
         "Hive1",
         "Hive2",
         "Hive3"
       ]
     }
   }

Without feature toggling management, one way to achieve this is to introduce a boolean flag ie. use Hive vs use SQL. The graphql query definition becomes something like this:

   type Query {
      positions(useHive:Boolean!): [String]
   }

This solution isn't always possible because this means we have to change our public API. With LaunchDarkly there's no need to alter our public API, all the code needed for feature toggling happens internally.

Source Code

Using LaunchDarkly

If you're new to LaunchDarkly, see my other post for some background information how to get started.

Create a new feature flag and call it 'position-hive'. When this feature is switched ON, we'll make the positions query returning data from Hive. We can also target a specific set of users who are allowed to use this feature and another set who aren't.

Since I'm using node.js to build this graphql service, we will need LaunchDarkly SDK for Node.js. Install the Node.js SDK with npm:

    npm install ldclient-node --save

We want to make sure that LaunchDarkly client and user are initialised only once when the graphql service started. Once they are initialised, we passed them into the graphql context so we can retrieve these back when needed. Now in the real world there's usually user authentication and authorisation before we can use a service. I'm not going to cover that here, I'm just assuming that's already happening automagically and we can get the user id and name from the graphql request argument.

According to LaunchDarkly SDK documentation, the LaunchDarkly client will emit a 'ready' event when it has been initialized and can serve feature flags. waitForInitialization() function is an alternative to this 'ready' event. If your application uses promises to manage asynchronous operations, which is the case here, this is the recommended way to interact with the SDK. When LaunchDarkly client is ready and can serve feature flags then retrieving a flag setting for a given user can be done this way:

   ldClient.variation(FEATURE_KEY, ldUser, FEATURE_DEFAULT)
     .then(function(featureValue) {
         // application code
     });
The FEATURE_KEY is 'position-hive' and FEATURE_DEFAULT is either true or false. I set it to false in our case as I want our graphql service to use SQL data by default.

Source Code

https://github.com/velianarie/graphql-launchdarkly

Saturday, March 31, 2018

JavaScript Spread Operator and Destructuring

I just found out about this amazing (now rather old) feature of ES6 while googling of ways to clone an object then excluding some of the properties. We basically can do this by combining spread operator with destructuring.

So supposed we have this recipe object and we want to turn this recipe into an alcohol free recipe ie. taking the rum and kirsch out of the recipe.

Output:

   Original recipe: {"egg":45,"butter":60,"sugar":150,"rum":10,"kirsch":10,"milk":120,"flour":150}
   Alcohol free recipe: {"egg":45,"butter":60,"sugar":150,"milk":120,"flour":150}

Friday, November 17, 2017

[Learning Notes]: TDD for React/Redux in an Isomorphic Application by Hany Elemary

I felt lucky I managed to watch this video before our Safari Books Online subscriptions were discontinued.

History

Hany Elemary begins with a little history of how isomorphic applications came to be. They evolve roughly as follows:
  1. Full-page refresh
    • Thin client (DOM manipulation, form validation, animations)
    • Rich server (routing, views, application logics, storage)
  2. Rich Internet application with AJAX request
    • Rich client (DOM manipulation, form validation, animations + views, application/display logic)
    • Thin server (initial bootstrap, API, storage)
  3. Single Page Application Isomorphic
    • Client (DOM manipulation, form validation, animations)
    • Shared code (routing, views, application/display logic) => runs client-side or server-side based on the request's context
    • Server (API, storage)
To make it easier for beginners to understand the differences between these developments, Hany mentions an analogy of a server in a restaurant and what they do when a customer orders a dish:
  1. Full-page refresh
    • First order: go buy pots pans, groceries, come back, cook & serve
    • Subsequent orders: go buy pots pans, groceries, come back, cook & serve
  2. Rich internet application with AJAX request
    • First order: go buy pots pans, come back, go get groceries, come back, cook & serve
    • Subsequent orders: go get groceries, come back, cook & serve
  3. Single Page Application Isomorphic
    • First order: go buy pots pans, get groceries, come back, cook & serve
    • Subsequent orders: go get groceries, come back, cook & serve

Sequence diagram of isomorphic application

Initial request
  1. User enters URL in browser
  2. Browser requests data from server
  3. Server fetches data from API/Database
  4. API/Database returns data to server eg. JSON
  5. Server generates & serves markup back to browser
  6. Browser render page
Subsequent requests
  1. User navigates in browser
  2. Browser fetches data straight from API/Database
  3. API/Database returns data to browser
  4. Browser renders page

React/Redux Overview

Paradigm shift in front-end development

  • React is library NOT framework
  • React only handles view layer eg. no AJAX, no Promises, no event system, etc. So why do we need it? Well sometimes we only need small composable library rather than a big ecosystem where you only use a tiny fraction of it. Get rid of libraries you don't need and get new libraries when you need it
  • React is component-based architecture: reusable components
  • Web developers often told not to mix HTML with JavaScript because HTML cannot be minified and it also cluttered your components. React uses HTML within JavaScript (JSX). JSX is pre-processor step that compiles your HTML into JavaScript so it could be minified.
  • Virtual DOM and diffing algorithm. Virtual DOM is in-memory representation of the real DOM, it has no knowlege to browser or environment it's run in, it's essentially a data structure. Diffing algorithm makes sure only the difference between virtual and real DOM is committed to the real DOM.

Deterministic view rendering

We know exactly which view is rendered first. In asynchronous function we won't know, whichever request got a response first, it'll be rendered first (race condition) ie. it's non-deterministic.

Event Sourcing

Event sourcing is technique that cares about sequences of events that lead to a specific outcome rather than the outcome itself. We want to store all events that occurred through our system as opposed to the outcomes that have happened. Characteristic: no update, no delete, it's an append-only log of events. In accounting terms: general ledger. Your book of records becomes stream of events, your source of truth. Advantages:
  • We have audit trail of all events that have happened in our system
  • You can replay a sequence of events to bring the application to a very specific state

Redux was inspired by Event Sourcing

  • Single source of truth: Redux Store
  • State is read-only/immutable. We only appending things, we're not updating or deleting things
  • Changes (ie. actions not events!) are made with pure functions (reducers). Reducers: given the same parameters will always output the same result, no side effect, no network operation, etc

Developer's workflow

  1. Write action / action creator
  2. Write component reducer to return the new state
  3. Determine the shape of your state / data - root reducer
  4. Write component that dispatches your action
  5. Connect component to store to subscribe to changes

TDD with React/Redux - Simple Components

Test pyramid

  1. UI
  2. Driven through the browser. Ensure the app is healthy in very high level, only test business critical features that represent overall workflows. Tend to be very slow and very expensive to maintain.
  3. Service (service level test, contract test)
  4. Expecting specific response for API given specific request. If API changes, test should fail. Protecting your application from changes in downstream dependencies or if your application is dependent on an API that you don't own.
  5. Unit
  6. Responsible for example display logic, behaviour, integration between components. Should be very fast and inexpensive to maintain.

Testing framework

  • Mocha - Test framework: assertions, expectations
  • Sinonjs - Stubbing framework: fake and spy on function calls
  • Mochawesome - Reporting: HTML reports that generate with each run, important to integrate with CI/CD pipeline
  • Enzyme - React test utility: rendering mechanism, access to components instances and children
  • Istanbul - Reporting: code coverage

TDD with React/Redux - Async Operation

Redux Saga

  • A library that aims to make side-effects easier and better.
  • What is side effects? network / asynchronous operations like fetching data. We can't guarantee that the same request will always be successful.
  • Reads like synchronous code. Think of Redux Saga as separate thread in your application.
  • ES6 generators makes an asynchronous code appears synchronous.
  • Redux Saga is a middleware. (PS: middleware is some code you can put between the framework receiving a request and the framework generating a response eg. logging)

Testing frameworks

  • Nock - HTTP mocking: useful for testing components integration with APIs, E2E tests
  • Mountebank - HTTP stubbing over the wire: useful for testing components integration with APIs, E2E tests, simulating failure modes.
  • Mountebank allows you to create an actual server and then mock the HTTP request and response. You can do pattern matching ie. if I see this pattern in the request then return this particular response. Another feature is latency ie. this request will return this response after n seconds. This can be used to simulate loading in your application.

Wednesday, February 1, 2017

JavaScript First Impressions - From a C# Developer POV

The company I work for has recently decided to do web development and as someone who has mostly done desktop development and not much experience in any web development, I'm quite excited about it. I decided to start with the basic, JavaScript. I'll list some of the things I like or find interesting and also things I don't quite like or seem counter-intuitive about JavaScript. I'll put a disclaimer here that this is all my personal opinion and first impressions as a C# developer who's never had any commercial exposure to JavaScript and I might be seriously biased towards C# and unconsciously comparing it with C# with a love-hate feeling and quite possibly more hate in this case.

Like

Syntax-wise similar to C#

C# JavaScript
Variable declaration
            var x = "bla bla";
            
             var x = "bla bla";
            
Object initialisation
            var x = new 
            {
                Name = "John",
                LastName = "Doe"
            };
            
             var x = {
                name: “John”,
                lastName: “Doe”
             };
            
Class declaration
            class MyClass : MyBaseClass
            {
                ...
            }
            
            class MyClass extends MyBaseClass {
                ...
            }
            
And many others I cannot list here.

No property declaration needed

> var myObject = new Object();
> myObject.NewProperty = "hello";
hello


Dislike

Equality operators

JavaScript has two kinds of equality operators:

  • strict equality using ===
  • loose equality using ==

Both equality compares two values for equality. The == operator is called loose because two values may be considered the same even if they are of different type. The == equality converts both values to a common type (type coercion) before comparing the values. This can potentially hide bugs and many JavaScript basic tutorial articles recommends to always use === operator. If this is the case, why bother having two equality operators in the first place? I'm sure there's a reason why the == equality is introduced, but I haven't made it my priority to look into it.


Usage of this keyword

In C# this keyword would refer to the current object. A function that wants to access the value of this should be defined inside the class. All variables in C# is lexically scoped. In JavaScript this is not always the case. The value of this is determined by how a function is called i.e. the same function will have different this value depending on how it's called.

> var myObject = new Object();
> myObject.x = 0;
>
> var myFunction = function() { 
>  this.x = 55; // what is "this" here?
> };  
>
> myObject.CallFunction = myFunction;  // Now 'myObject' has a method called 'CallFunction', which is 'myFunction'.
> myObject.CallFunction();  // This executes 'myFunction', "this" now belongs to 'myObject'
> myObject.x; 
55

Weak typing

We can add number and string together for example.

> var x = "5" + 1 + 2
512
> var y = 1 + 2 + "5" + 6
356

Here we see that if we put a number in quotes, the rest of the numbers will be treated as strings and concatenated, while the previous numbers are treated as numbers. This is actually an interesting behaviour. JavaScript is smart enough to figure out what type of data we have and then make the necessary adjustments so that we don't have to redefine it. However, coming from a strongly typed language like C#, this behaviour irks me. In a strong typed language environment, the compiler will tell me right away that I'm trying to operate on two different data types. With JavaScript, I won't get any compilation error, but I could get a different result than what I expected. I know this is a rather weak argument. Developers should know the behaviour of the language they're using, but this kind of problem seems appropriate for this blog.



Conclusion

The syntax similarity to C# in my case is unfortunately misleading because it distorts my expectations of how easy it is to switch between the two languages. This is in some way reminds me of my experience learning English and Dutch as they're quite similar to me when I first started. It's quite easy to mix both English and Dutch words in a single sentence without even realising I was doing this or thinking in English while trying to speak or construct sentences in Dutch (or the other way around). Like any language, it is up to us to learn how to use the language as it's meant to be used. We should avoid falling into the trap of thinking in one language we feel more comfortable with, while we should be thinking in the other. It is a painful process, but I believe that when we invest time to become familiar with it and stop lamenting over what it is not or what it should've been, we'll start seeing the power of the language and with experience we can easily decide which language is better suited for a specific problem we're trying to solve.