JavaScript Functional Programming

Functional Programming in JavaScript:

JavaScript supports functional programming and functional programming represents data in our application.

Arrow functions:

const display = name => console.log(name)

Function as variable:


const person = {
name:"test data",
display(name){
console.log(name) }
}
person.display(person.name)

Function in array:


const person = ["Test one",
name => console.log(name),
"Test two",
name => console.log(name)]

person[1](person[0]) // Test one
person[3](person[2]) // Test two

Higher order functions, functions that either take or return other functions (i.e. more than one arrow):


const person = display => name => logger(name + !!!!!)

const showName = person(name => console.log(name))

showName("Test data") //Test data !!!!!

Notes:

  1. Functions can be saved, retrieved, or flow through your applications just like variables.
  2. Functional programming is a part of declarative programming.

Core concepts of functional programming:

  1. Immutablitiy: In functional programming, data is immutable. It never changes.
    let employee = {
    name: "Test",
    gender: "M",
    age: 23,
    grade: 'B'
    }
    
    const addGrade = (employee, grade) => ({...employee,grade})
    console.log(addGrade(employee,'A').grade) // A
    console.log(employee.grade) // 'B'
    
  2. Pure functions: A pure function is a function that returns a value that is computed based on its arguments.
    To create a pure function, try to follow the mentioned rules:
    – It should take in at least one argument.
    – It should return a value or another function.
    – It should not change or mutate any of its arguments.

    const addGrade = employee => ({
    ...employee,
    age: 30,
    grade: 'C'
    })
    
    console.log(addGrade(employee)) // {name:"Test", gender:"M", age:"30", grade:"C"}
    console.log(employee) // {name:"Test", gender:"M", age:"23", grade:"B"}
    
  3. Data Transformations: Functional programming is all about transforming data from one form to another. Two core functions with functional javascript – Arrays.map and Arrays.reduceFew useful javascript functions:

    Array.join :

    const fourWheelers = ["Car","Bus","Truck"]
    console.log(fourWheelers.join("-")) // Car-Bus-Truck
    

    Array.filter:

    const lmv = fourWheelers.filter(fourWheeler => fourWheeler === "Car")
    console.log(lmv) // Car
    

    Array.map:

    const fourWheelersName = fourWheelers.map(fourWheeler => '${fourWheeler} is Four wheeler.')
    
    console.log(fourWheelersName.join('/n'))
    /* Car Four Wheeler
    Bus Four Wheeler
    Truck Four Wheeler */
    
    console.log(fourWheelers.join('/n'))
    /* Car
    Bus
    Truck */
    
    const names = ["Test","Test1","Test2"]
    const editName = (oldName,newName,names) => names.map(name => (name === oldName)? newName : name)
    
    console.log(editName("Test","Test New", names)) //["Test New","Test1","Test2"]
    console.log(names) //["Test","Test1","Test2"]
    
    ** Object.keys is a method that can be used to return an array of keys from an object.
    
    

    Array.reduce/Array.reduceRight : These functions can be used to transform an array into any value including a number, string, Boolean, object or even a function.

    Reduce takes two arguments, a callback method and an original value.

    const scores = [23,3,12,14,34,1,25]
    const maxScore = scores.reduce((max,score) => (score > max)? score : max, 0)
    
    console.log(maxScore) //34
    

    ReduceRight works the same way as reduce, the difference is that it start reducing from the end of the array rather than the beginning.

    const values = [1,2,2,3,4,2,3,5,6]
    const distinctValues = values.reduce((newValues,value) => (newValues.indexOf(value) !== -1 ? newValues : [...newValues,value]),[])
    
    console.log(distinctValues)// [1,2,3,4,5,6]
    
  4. Higher-order functions: These are the functions that can manipulate other functions.
    const showTrue = () => console.log('Execute true function')
    const showFalse = () => console.log('Execute false function')
    const checkCondition = (condition, trueFn, falseFn) => (condition ? trueFn() : falseFn())
    
    console.log(checkCondition(true,showTrue,showFalse)) //Execute true function
    console.log(checkCondition(false,showTrue,showFalse)) //Execute false function
    
  5. Recursion: It is a technique that involves creating functions that recall themselves.
    const countdown = (maxvalue, showVal) => {
    showVal(maxvalue)
    return (maxvalue > 0) ? (countdown(maxvalue-1, showVal)) : maxvalue
    }
    
    countdown(10, value => console.log(value)); //10 9 8 7 6 5 4 3 2 1 0
    
    **Recursion should be used over loops but large amount of recursions can cause JavaScript errors.
    
  6. Composition: The goal of composition is to generate higher order function by combings simpler functions. It takes functions as arguments and return a single function.
    const name = person => appendSalutation(completeName(person))
    const name = compose(
    appendSalutation,
    completeName,
    )
    name(new Person())
    
    const compose = (...fns) => (args) => fns.reduce((composed,f) => f(composed), arg)
    

NOTE:
Follow these three simple rules to achieve functional programming :

  1. Keep data immutable.
  2. Keep functions pure – accept at least one argument, return data or another function.
  3. Use recursions over looping (wherever possible).

ES6 Basics

JavaScript Basics

1. Const : We cannot reset the value of constant variable.

const value = true;

2. let : with let keyword, we can limit the scope of a variable to any code block.

let topic = true;

3. Template String: with template string, we can create one string and insert the variable values by surrounding them with ${}

`${Salutation} ${firstName} ${lastName}`

4. Default Parameters: If a value is not provided for the argument, default value will be used. default argument can be any type.

function activity(name="Test"){
 console.log(`${name}`);
 }

5. Arrow Function: With arrow functions, you can create the functions without using the function keyword.

var showName = (firstName,lastName) =>`${firstName} ${lastName}` 
var displayRole = role => {
if(!role){
  throw new Error('Role is required');
}
return `${role}` 
}

Note: Arrow function protect the scope of this, but not block the scope of this.

6. Transpiling ES6: Not all browser supporting ES6, so we need to convert it to ES5 code before running it in browser.One of the popular tool for transpiling  is Babel.You can transpile the javascript directly in the browser using inline Babel transpiler. You just include the browser.js file and any script with type=”text/babel” will be converted.

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.js"> </script>
<script src="script.js" type="text/babel"></script>

Note: Transpiling approach is not a good idea for production because it will slow down the application.

ES6 Objects and Arrays:

1. Destructuring Assignment:

It allows us to locally scope fields within an object and to declare which values will be used.

  • Destructuring object having four keys and we only want to use two keys out of them.
 
var object= { salutation: "Mr.",
 firstName: "Test",
 lastName: "Data",
 role: "Developer"}

var {firstName,lastName} = object console.log(firstName,lastName); 
  • Destructuring incoming function argument:
var name = { firstName: "Test",
lastName: "Data" }

var showFirstName = ({firstName}) => console.log(`${firstName}`)
showFirstName(name)
  • Assign the specific element value of an array to a variable name:
var [salutation] = ["Salutation","FirstName","LastName"]
console.log(salutation) //Salutation
var [,,lastName] = ["Salutation","FirstName","LastName"]
console.log(lastName) //LastName 

2. Object Literal Enhancement:

It the process of restructuring or putting back together.

  • with object literal enhancement, we can grab variables from global scope and turn them into an object.
var firstName = "Test"
var lastName = "Data"
var name = {firstName,lastName}
console.log(name) // {firstName:"Test", lastName:"Data"} 
  • with object literal enhancement, we can create object method.
var print = () =>{ console.log(`${this.firstName} ${this.lastName}`)}
var name = {firstName, lastName, print}
name.print() // Test Data 
  • while defining object methods, it is no longer necessary to use the function keyword
const newName = { firstName,
lastName,
print(){
console.log(`${this.firstName} ${this.lastName}`);
},
printWithSalutation(salutation){
 console.log(`salutation ${this.firstName} ${this.lastName}`);}
}

3. The Spread Operator:

It represents with three dots(…) that performs several different tasks.

  • With Spread Operator, we can combine the contents of arrays.
 var fruits = ["Mango","Grapes","Banana"]
 var drinks = ["Mazza","Rani","Tropicana"]
 var fruitDrink = [...fruits,...drinks] 
 console.log(fruitDrink.join(",")) //Mango,Grapes,Banana,Mazza,Rani,Tropicana
 

Note: Spread Operator creates the copy of the array and then do the specified process.

  • Spread Operator can be used to get some, or the rest, of the items in the array
 var [first,...rest] = fruits
 console.log(rest.join(",")) //Grapes,Banana
 
  • Spread Operator can also be used to collect function arguments as an array.
function directions(...args){ 
var [start, ...remaining] = args
 var [finish, ...stops] = remaining.reverse()
 console.log(`drive through ${args.length} towns`)
 console.log(`start in ${start}`)
 console.log(`the destination is ${finish}`)
 console.log(`stopping ${stops.length} times in between.`) 
}
 directions("Hapur","Ghaziabad","Noida","Gurgaon")
  • Spread Operator can also be used for Objects.
var employee = { name: "Test", age: "20" }
var department = " Admin"
var company = { ...employee, department }
console.log(company) // { name:"Test", age:"20", department:"Admin" }

Promises:

It give us a way to make sense out of asynchronous behavior. It simplify back to a simple pass or fail.

Classes:

ES6 introduces class declaration, but javascript still works the same way. Functions are objects and inheritance is handled through the prototype.

class Person
{ 
constructor(name,age){
 this.name = name this.age = age
 }
 display(){
 console.log('My name is ${this.name} and I am ${this.age} years old.') }
}

Note: All types should be capitalized, due to that we will capitalize all class names.

  • We can create the new instance of the class using new keyword.
const personObj = new Person("Test data", 30);
 console.log(personObj.display()); //My name is Test data and I am 30 years old.

Simple Inheritance:

class UID extends Person{
 constructor(name, age, uniqueID){
 super(name,age)
 this.uniqueID = uniqueID 
}
 print(){
 super.print()
 console.log('And ${this.uniqueID} is my uniqueID.') }
 }

const personDtl = new UID("Test Data", 30, 1234567)
 console.log(personDtl.print()); //My name is Test data and I am 30 years old. And 1234567 is my uniqueID.

ES6 Modules:

JavaScript module is a piece of reusable code that can easily be incorporated into other javascript files.JavaScript module stored in separate file, one file per module.

  • Export multiple javascript object per module.
(script1.js)

export const display(name) => log(name, new Date())
export const log(name, timestamp) =>
console.log(`${timestamp.toString()} : ${name}`)
  • export default, using this we can export single javascript object from a module.
(script2.js)
const person = new Person("Test data", 26)
export default person
  • Modules can be consumed in other javascript file using import statement. Modules containing multiple export can take advantage of object destructuring.
import {display, log} from './script1'
import person from './script2'

display("display Test data details")
log("logging test data details")

person.print()
  • we can scope modules variables locally under different variable names.

import {display as d, log as l} from './script1'

p("display test data details")  l("logging test data details")

  • we can import everything into single  variable using *.

import * as prsn from './script'

CommonJS:

It is the module pattern that is supported by all versions of Node.js

  • with commonJS, object are exported using module.exports
module.exports = {display, log}
  • with commonJS, objects are imported using require function

const {display, log} = require('./script1')

Export Data in CSV/Excel Using Angular-Spring

Client Side Changes:

Step 1: HTML file implementation

html_impl

Step 2: Angular controller/service.js implementation in the respective download function

downloadPOCReport:

angular_impl

Server Side Changes:

Step 3: Controller/Resource.java implementation

controller_impl

Step 4: Service implementation

service_impl

Introduction to mongoDB

Overview of mongoDB

  • It is an open-source document database and leading NoSQL database.
  • It is written in C++.
  • It is a cross-platform, document oriented database that provides, high performance, high availability, and easy scalability.
  • It works on concept of database, collection and document.
    • Database:
      It is physical container for collections.
      A single mongoDB server might have multiple databases.
    • Collection:
      It represents a group of mongoDB documents.
      It is equivalent to RDBMS table.
      It exists within a single database.
    • Document:
      It is a set of key-value pairs

RDBMS                                                       MongoDB
Database                                                    Database
Table                                                           Collection
Tuple/Row                                                  Document
column                                                        Field
Table Join                                                    Embedded Documents
Primary Key                                                Primary Key (Default key _id provided by mongodb itself)

Note: Primary Key _id (12 bytes hexadecimal number) = Current timestamp(4 bytes) + Machine ID (3 bytes) + Process ID for MongoDB server (2 bytes) + incremental value (3 bytes)

Advantages of mongoDB :

  • It is a document database in which one collection holds different documents. Number of fields, content and size of the document can differ from one document to another.
  • It has a clear single object structure.
  • It doesn’t have complex joins.
  • It supports dynamic queries on documents using a document-based query language that’s nearly as powerful as SQL.
  • It is easy to scale.
  • In mongoDB Conversion/mapping of application objects to database objects not needed.
  • It used internal memory for storing the working set, enabling faster access of data.

Use of mongoDB:

  • It stored data in the form of JSON style documents.
  • It can put index on any attribute.
  • It has replication and high availability.
  • It has auto-sharding.
  • It has Rich queries.
  • It is fast in-place updates.

MongoDB is used basically in the following conditions:

  • Big Data.
  • Content Management and Delivery.
  • Mobile and Social Infrastructure.
  • User Data Management.
  • Data Hub.

MongoDB supports following datatype:

String, Integer, Boolean, Double, Min/ Max keys ?,  Arrays, Object, Null, Symbol, Date, Object ID, Binary data, Code, Regular expression

JUnit 5 Tutorial – New Features with Examples

What is JUnit?

It is an opensource testing framework which performs unit testing on Java based application. The current version is JUnit 5.

What’s New in JUnit 5?

Unlike its previous version, JUnit 5 is composed of several different modules from three different sub directories. (JUnit 5 requires Java 8 at run-time)

JUnit 5JUnit Platform + JUnit Jupiter + JUnit Vintage

1. JUnit Platform:

a) It serves as a foundation for launching testing frameworks on JVM.

b) It defines TestEngine API for developing testing framework that runs on the platform.

c) It provides console launcher to launch the platform from command line.

d) It provides build plugin for maven and Gradle as well as a JUnit4 based runner for running any TestEngine on platform.

2. JUnit Jupiter:

a) It is the combination of new programming model and extension model for writing tests and extensions.

b) It provides a TestEngine for running Jupiter based tests on platform.

3. JUnit Vintage:

a) It provides a TestEngine for running junit 3 and junit 4 based tests on platform.

Installation Guide of JUnit 5:

To install JUnit 5 in the application, please add the following maven dependencies in the respective pom.xml.


 <dependencies>
<!-- JUnit Platform -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-gradle-plugin</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.0.0-M2</version>
</dependency>

<!-- JUnit Jupiter -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.0.0-M2</version>
</dependency>

<!-- JUnit Vintage -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>4.12.0-M2</version>
</dependency>
</dependencies>

Example: FirstJunit5Test.java


/**
*
*/
package com.abhi.junit5.learning;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

/**
* @author Abhinav
*
*/
@RunWith(JUnitPlatform.class)
class FirstJunit5Test {

@Test
void testCaseFirst(){
assertEquals(2, 1+1);
}

@Test
@CustomTag
void failingTest() {
fail("Failing for failing's sake.");
}
}

JUnit 5 Annotations:

. @Test : It denotes that annoted method is a test method. It does not declare any attributes, since test extensions in junit jupiter operate based on their own annotations.

. @TestFactory : It denotes that annoted method is a test factory for dynamic tests*.

. @DisplayName : It declares the custom display names for the test class or test method. It could be the text with blank spaces, special characters, and even emojis.

. @BeforeEach : It denotes that the annoted method should be executed before each @Test annoted method. Such methods are inherited. Similar to junit 4 @Before.

. @AfterEach : It denotes that the annoted method should be executed after each @Test annoted method. Such methods are inherited. Similar to junit 4 @After.

. @BeforeAll : It denotes that the annoted method should be executed before all @Test annoted method. Such methods must be static and inherited. Similar to junit 4 @BeforeClass.

. @AfterAll : It denotes that the annoted method should be executed after all @Test annoted method. Such methods must be static and inherited. Similar to junit 4 @AfterClass.

. @Nested : It denotes that the annoted class is a nested, non static test class. @BeforeAll and @AfterAll annotations cannnot be used in @Nested test class.

. @Tag : It is used for filtering the test cases either at class or method level. Similar to junit 4 TestNG or categories.

. @Disabled : It is used to disable a test class or test method. Similar to junit 4 @ignore.

. @ExtendWith : It is used to register custom extensions*.

Meta Annotations and Composed Annotations:

In JUnit Jupiter you can define your own custom composed annotations that will automatically inherit the semantics of its meta-annotations.
Example: CustomTag.java

Sample Test Case example: BasicJUnit5Test.java


/**
 *
 */
package com.abhi.junit5.learning;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

/**
 * @author Abhinav
 *
 */
@RunWith(JUnitPlatform.class)
@DisplayName("Sample test class for showcasing the annotations")
class BasicJUnit5Test {

@BeforeAll
 static void beforeALL(){
 System.out.println("It will execute once before executing all the Test case");
 }

 @BeforeEach
 void beforeEach(){
 System.out.println("It will execute each time before executing the Test case");
 }

 @Test
 void passedTestCase(){
 System.out.println("Success Test case");
 }

 @Test
 void failedTestCase(){
 System.out.println("Failed Test case");
 }

 @Test
 @Disabled("For demo purpose")
 void disabledTestCase(){
 System.out.println("Ignored Test case");
 }

 @AfterEach
 void afterEach(){
 System.out.println("It will execute each time after executing any Test case");
 }

 @AfterAll
 static void afterAll(){
 System.out.println("It will execute once After executing all Test case");
 }
}

JUnit 5 Assertions:

JUnit 5 have many assertions methods packaged under JUnit Jupiter. Their are few new assertion methods introduce in JUnit 5 to support the Java 8 lambda expression feature. Else most of them are similar what we had in JUnit 4.

Example: AssertionsJunit5.java


/**
 *
 */
package com.abhi.junit5.learning;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import static org.junit.jupiter.api.Assertions.*;
/**
 * @author Abhinav
 *
 */
@RunWith(JUnitPlatform.class)
@DisplayName("Assertions in JUnit5")
public class AssertionsJunit5 {

@Test
 @DisplayName("Test case to show standard assertion methods.")
 void basicAssertions(){
 assertEquals("Abhi", "Abhi");
 assertNotEquals(4, 2, ()-&amp;amp;gt;"Assertion not equals message.");
 assertTrue(3&amp;amp;gt;2, ()-&amp;amp;gt;"Assertion messages can be lazily evaluated to avoid constructing complex messages unnecessarily.");
 }

 @Test
 @DisplayName("Test case to show Grouped assertion methods.")
 void newAssertion(){
 assertAll("Group Assertions",
 ()-&amp;amp;gt;assertEquals("Abhi", "Abhi"),
 ()-&amp;amp;gt;assertNotEquals(4, 3, ()-&amp;amp;gt;"Assertion not equals message."),
 ()-&amp;amp;gt;assertTrue(3&amp;amp;gt;2, ()-&amp;amp;gt;"Assertion messages can be lazily evaluated to avoid constructing complex messages unnecessarily.")
 );
 }

 @Test
 @DisplayName("Test case to show exception handle through assertion methods.")
 void exceptionAssertion(){
 Throwable exception = expectThrows(NullPointerException.class, ()-&amp;amp;gt;{ throw new NullPointerException("Got exception message");
 });

 assertEquals("Got exception message", exception.getMessage());
 }
}

JUnit 5 Assumptions:

Junit 5 have many assumption methods packaged under JUnit Jupiter. Their are few new assumption methods introduce to support the Java 8 lambda expression feature. Else most of them are similar what we had in JUnit 4.

Example: AssumptionsBasic.java


/**
 *
 */
package com.abhi.junit5.learning;

import static org.junit.jupiter.api.Assumptions.*;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

/**
 * @author Abhinav
 *
 */
@RunWith(JUnitPlatform.class)
@DisplayName("Assumptions in JUnit5")
public class AssumptionsBasic {

@BeforeAll
 static void setUp(){
 System.setProperty("TestEnv", "JUnit5");
 System.setProperty("Environment", "Stage");
 }

 @Test
 void showAssumeTrue(){
 assumeTrue("Stage".equals(System.getProperty("Environment")), ()-&amp;amp;gt; "Not on development environment");
 }

 @Test
 void showAssumptionBasic(){
 assumingThat("JUnit5".equals(System.getProperty("TestEnv")),
 ()-&amp;amp;gt;{
 assertEquals(2, 2);
 System.out.println("Inside assumption");
 });

 }
}

You can checkout/clone the JUnit 5 example repository from the mentioned path – https://github.com/erabhinavrana/my-junit5-learning