Code Review. How to modify an old commit.

Sometimes, when using Code review, you need to modify an old commit with the suggestions. I used to create a new commit for the modifications, but this is non clean, intuitive (if you wrap commits by task), nor backwards compatible.

There is a better way to this using git rebase, which basically allows you to change a commit and apply those changes to further commits.

In order to do that, we need to rebase the commit this way.
1º- Checkout the branch
2º- git rebase –interactive ‘xxxxxx^’
3º- In the editor, change ‘pitch’ to ‘edit’ on the commit we want to modify.
4º- Make the changes
​5º- git commit –all –amend –no-edit
6º- git rebase –continue
​7º- git push (–force) origin <branch_name>​
I hope it helps

From Java to Kotlin. Cheatsheet

I wanted to keep everything regarding the differences between Java and Kotlin on one place. That’s why I’ve created with Cheatsheet.
I hope it would be useful for you as well.

Printing

Java

System.out.print("Hello, World!");
System.out.println("Hello, World!");
Kotlin
print("Hello, World!")
println("Hello, World!")

Variables I

Java
final int x;
final int y = 1;
Kotlin
val x: Int
val y = 1

Variables II

Java
int w;
int z = 2;
z = 3;
w = 1;
Kotlin
var w: Int
var z = 2
z = 3
w = 1

Null I

Java
final String name = null;

String lastName;
lastName = null
Kotlin
val name: String? = null

var lastName: String?
lastName = null

var firstName: String
firstName = null // Compilation error!!

Null II

Java
if(text != null){
  int length = text.length();
}
Kotlin
val length = text?.length

val length = text!!.length // NullPointerException if text == null

Strings I

Java
String name = "John";
String lastName = "Smith";
String text = "My name is: " + name + " " + lastName;
String otherText = "My name is: " + name.substring(2);
Kotlin
val name = "John"
val lastName = "Smith"
val text = "My name is: $name $lastName"
val otherText = "My name is: ${name.substring(2)}"

Strings II

Java
String text = "First Line\n" +
              "Second Line\n" +
              "Third Line";
Kotlin
val text = """
        |First Line
        |Second Line
        |Third Line
""".trimMargin()

Ternary Operator

Java
String text = x > 5 ? "x > 5" : "x <= 5";
Kotlin
val text = if (x > 5)
              "x > 5"
            else "x <= 5"

Bits Operations

Java
final int andResult  = a & b;
final int orResult   = a | b;
final int xorResult  = a ^ b;
final int rightShift = a >> 2;
final int leftShift  = a << 2;
Kotlin
val andResult  = a and b
val orResult   = a or b
val xorResult  = a xor b
val rightShift = a shr 2
val leftShift  = a shl 2

Is As In

Java
if(x instanceof Integer){ }

final String text = (String) other;

if(x >= 0 && x <= 10 ){}
Kotlin
if (x is Int) { }

val text = other as String

if (x in 0..10) { }

Smart Cast

Java
if(a instanceof String){
  final String result = ((String) a).substring(1);
}
Kotlin
if (a is String) {
  val result = a.substring(1)
}

Switch / When

Java
final int x = // value;
final String xResult;

switch (x){
  case 0:
  case 11:
    xResult = "0 or 11";
    break;
  case 1:
  case 2:
    //...
  case 10:
    xResult = "from 1 to 10";
    break;
  default:
    if(x < 12 && x > 14) {
      xResult = "not from 12 to 14";
      break;
    }

    if(isOdd(x)) {
      xResult = "is odd";
      break;
    }

    xResult = "otherwise";
}



final int y = // value;
final String yResult;

if(isNegative(y)){
  yResult = "is Negative";
} else if(isZero(y)){
  yResult = "is Zero";
}else if(isOdd(y)){
  yResult = "is Odd";
}else {
  yResult = "otherwise";
}
Kotlin
val x = // value
val xResult = when (x) {
  0, 11 -> "0 or 11"
  in 1..10 -> "from 1 to 10"
  !in 12..14 -> "not from 12 to 14"
  else -> if (isOdd(x)) { "is odd" } else { "otherwise" }
}

val y = // value
val yResult = when {
  isNegative(y) -> "is Negative"
  isZero(y) -> "is Zero"
  isOdd(y) -> "is odd"
  else -> "otherwise"
}

For

Java
for (int i = 1; i < 11 ; i++) { }

for (int i = 1; i < 11 ; i+=2) { }

for (String item : collection) { }

for (Map.Entry&ltString, String&gt entry: map.entrySet()) { }
Kotlin
for (i in 1..10) { }

for (i in 1..10 step 2) {}

for (item in collection) {}
for ((index, item) in collection.withIndex()) {}

for ((key, value) in map) {}

Collections

Java
final List&ltInteger&gt numbers = Arrays.asList(1, 2, 3);

final Map&ltInteger, String&gt map = new HashMap&ltInteger, String&gt();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");


// Java 9
final List&ltInteger&gt numbers = List.of(1, 2, 3);

final Map&ltInteger, String&gt map = Map.of(1, "One",
                                        2, "Two",
                                        3, "Three");
Kotlin
val numbers = listOf(1, 2, 3)

val map = mapOf(1 to "One",
                2 to "Two",
                3 to "Three")

Collections

Java
for (int number : numbers) {
  System.out.println(number);
}

for (int number : numbers) {
  if(number > 5) {
    System.out.println(number);
  }
}
Kotlin
numbers.forEach {
    println(it)
}

numbers.filter  { it > 5 }
       .forEach { println(it) }

Collections

Java
final Map&ltString, List&ltInteger&gt&gt groups = new HashMap<>();
for (int number : numbers) {
  if((number & 1) == 0){
    if(!groups.containsKey("even")){
      groups.put("even", new ArrayList<>());
    }

    groups.get("even").add(number);
    continue;
  }

  if(!groups.containsKey("odd")){
    groups.put("odd", new ArrayList<>());
  }

  groups.get("odd").add(number);
}
Kotlin
val groups = numbers.groupBy {
                if (it and 1 == 0) "even" else "odd"
             }

Collections

Java
final List&ltInteger&gt evens = new ArrayList<>();
final List&ltInteger&gt odds = new ArrayList<>();
for (int number : numbers){
  if ((number & 1) == 0) {
    evens.add(number);
  }else {
    odds.add(number);
  }
}
Kotlin
val (evens, odds) = numbers.partition { it and 1 == 0 }

Collections

Java
final List&ltUser&gt users = getUsers();

Collections.sort(users, new Comparator&ltUser&gt(){
  public int compare(User user, User otherUser){
    return user.lastname.compareTo(otherUser.lastname);
  }
});

// or

users.sort(Comparator.comparing(user -> user.lastname));
Kotlin
val users = getUsers()
users.sortedBy { it.lastname }

 

How to create a REST API with Node.js and LoopBack

how to API REST tutorial

In this post, we are going to learn how to use LoopBack Node.js framework  to create a fully functional REST API over MongoDB.

We will follow these steps:

1- Define the models in the database

2- Define the relations between models

3- Define users access levels

PREREQUISITES

To follow this tutorial we will need NodeJS and MongoDB installed in our computer.

DATABASE SET UP

Install the LoopBack module.

sudo npm install loopback -g

Run Loopback and follow instructions.

slc loopback
[Node version -> 2.x, Stable version]
[Kind of application -> API server]

Move to the new folder.

cd "folder name"

We are going to do an e-commerce API for the example. We want to to store all date in a persistent way into a MongoDB database that will have Clients, Products and Comments.

In order to do so, we need to specify the route of the database. As it is not created yet, will create a new folder and connect it to MongoDB.

mkdir -p mongo/data
mongod --dbpath mongo/data

Then, in another terminal, we run the Loopback commands to create the database

We’ll call it “ecommerce”

slc loopback:datasource
? Enter the data-source name: MongoDB
? Select the connector for MongoDB: MongoDB (supported by StrongLoop)
Connector-specific configuration:
? Connection String url to override other settings (eg: mongodb://username:passw
ord@hostname:port/database):
? host: localhost
? port: 27017
? user:
? password:
? database: ecommerce
? Install loopback-connector-mongodb@^1.4 Yes

Once we generated the database, we can see the code generated by Loopback at the file model-config.json.

It is recommendable to change the attribute “dataSource”: “db” to the database we just created (“MongoDB”) at ACL,RoleMapping and Role.

1- DEFINE THE MODELS IN THE DATABASE

To create a new collection (what would be a table), we’ll use the following command.

slc loopback:model

The way to define the data will be as the following example:

? Enter the model name: Customer
? Select the data-source to attach Customer to: MongoDB (mongodb)
? Select model's base class User *
? Expose Customer via the REST API? Yes
? Custom plural form (used to build REST URL):
? Common model or server only? common

*In this case is not needed to define more attributes because we are extending the “User” class that already have username, password, email and other needed attributes.

Now we are going to define the “Product” collection.

slc loopback:model
? Enter the model name: Product
? Select the data-source to attach Product to: MongoDB (mongodb)
? Select model's base class PersistedModel
? Expose Product via the REST API? Yes
? Custom plural form (used to build REST URL):
? Common model or server only? common
? Property name: name
invoke loopback:property
? Property type: string
? Required? Yes
? Default value[leave blank for none]:
? Property name: description
invoke loopback:property
? Property type: string
? Required? Yes
? Default value[leave blank for none]:
? Property name: category
invoke loopback:property
? Property type: string
? Required? Yes
? Default value[leave blank for none]:
? Property name: image
invoke loopback:property
? Property type: string
? Required? No
? Default value[leave blank for none]:
? Property name: label
invoke loopback:property
? Property type: string
? Required? No
? Default value[leave blank for none]:
? Property name: price
invoke loopback:property
? Property type: number
? Required? Yes
? Default value[leave blank for none]:

Now, the comments:

slc loopback:model
? Enter the model name: Comments
? Select the data-source to attach Comments to: MongoDB (mongodb)
? Select model's base class PersistedModel
? Expose Comments via the REST API? Yes
? Custom plural form (used to build REST URL):
? Common model or server only? common

Let’s add some Comments properties now.

? Property name: rating
invoke loopback:property
? Property type: number
? Required? Yes
? Default value[leave blank for none]: 5
? Property name: comment
invoke loopback:property
? Property type: string
? Required? Yes
? Default value[leave blank for none]:

Now we have all the collections defined, it’s time to define the relation between them.

2- DEFINE THE RELATION BETWEEN MODELS

Let’s review what we have done up to now.

On the one hand, we have the e-commerce Users and on the other hand we have the Products.

We also want the Users to post Comments about our Products.

So these would be the relations:

1- A product can have several comments.

2- A product can have several users commenting about it.

3- A comment belongs to determined product.

therefore…

4- A user can post several comments.

and

5- A product can have several comments about it.

[insert schema here]

To define the relations between collections, we will use the following command:

slc loopback:relation

1- A product can have several comments.

slc loopback:relation
? Select the model to create the relationship from: Product
? Relation type: has many
? Choose a model to create a relationship with: Comments
? Enter the property name for the relation: comments
? Optionally enter a custom foreign key:
? Require a through model? No

2- A product can have several users commenting about it.

slc loopback:relation
? Select the model to create the relationship from: Product
? Relation type: has many
? Choose a model to create a relationship with: Customer
? Enter the property name for the relation: customers
? Optionally enter a custom foreign key:
? Require a through model? No

3- A comment belongs to determined product.

slc loopback:relation
? Select the model to create the relationship from: Comments
? Relation type: belongs to
? Choose a model to create a relationship with: Product
? Enter the property name for the relation: product
? Optionally enter a custom foreign key:

4- A user can post several comments.

slc loopback:relation
? Select the model to create the relationship from: Customer
? Relation type: has many
? Choose a model to create a relationship with: Comments
? Enter the property name for the relation: comments
? Optionally enter a custom foreign key: customerId
? Require a through model? No

5- A product can have several comments about it.

slc loopback:relation
? Select the model to create the relationship from: Comments
? Relation type: belongs to
? Choose a model to create a relationship with: Customer
? Enter the property name for the relation: customer
? Optionally enter a custom foreign key: customerId

With what we have done up to now

Up to this point, we already have the API and we can do some testing by this command.

node <project folder>/server/server.js

or

node .

Despite of this, we haven’t finished yet, as any user could use all the methods and CREATE and DELETE some data without any authentication, which drives us to the last step.

3- DEFINE USERS ACCESS LEVELS

The first thing that we are going to do in this section is to create the users “admin” and “kike” (although you can change the last one for your username) and we will give to the administrator privileges to the user “admin”.

Loopback allows us to include a script that will run whenever we start the service, so we will use that to introduce these two users into the database.

So, we create a file at <our project folder>/server/boot/script.js and copy the following code:

module.exports = function(app) {
  var MongoDB = app.dataSources.MongoDB;

  MongoDB.automigrate('Customer', function(err) {
    if (err) throw (err);
    var Customer = app.models.Customer;

  Customer.create([
    {username: 'admin', email: 'admin@admin.com', password: 'abcdef'},
    {username: 'kike', email: 'bodi.inf@gmail.com', password: 'abcdef'}
  ], function(err, users) {
  if (err) throw (err);
  var Role = app.models.Role;
  var RoleMapping = app.models.RoleMapping;

  //create the admin role
  Role.create({
    name: 'admin'
  }, function(err, role) {
    if (err) throw (err);
  //make admin
  role.principals.create({
    principalType: RoleMapping.USER,
    principalId: users[0].id
    }, function(err, principal) {
      if (err) throw (err);
      });
    });
  });
});

This will create two new users. A regular user (Kike) and an Admin user (obviously, admin). After that we create a Role admin and bind them together.

Now, let’s restrict the some accesses for Authenticated users:

We will use the Loopback Access Control List (ACL) by using this command:

slc loopback:acl

So first, let’s deny all kind of accesses:

slc loopback:acl
? Select the model to apply the ACL entry to: (all existing models)
? Select the ACL scope: All methods and properties
? Select the access type: All (match all types)
? Select the role All users
? Select the permission to apply Explicitly deny access

Once we have done this, let’s enable GET (READ) accesses for autheticated users:

slc loopback:acl
? Select the model to apply the ACL entry to: (all existing models)
? Select the ACL scope: All methods and properties
? Select the access type: Read
? Select the role Any authenticated user
? Select the permission to apply Explicitly grant access

And finally, allow Admins to perform all operations:

slc loopback:acl
? Select the model to apply the ACL entry to: (all existing models)
? Select the ACL scope: All methods and properties
? Select the access type: All (match all types)
? Select the role other
? Enter the role name: admin
? Select the permission to apply Explicitly grant access

Once we have done this, we finished and already have a fully functional REST API with Node.js.

We can run it and start playing with it with he following command:

node <project folder>/server/server.js

Cool, isn’t it? Now you can relax, take a cup of coffee and tell your coworkers how hard you have been working.

Cheers!

Improve your algorithms using the correct Data Structure

Algorithm complexity. Big O

 

We know that Object-oriented Programming can help us to design and build huge systems, but this is only the half history. Usually, we use computer programs because we need to manage huge amounts of data and do it within a reasonable amount of time.

Here is where algorithm design comes into play. The way we manage the data into the algorithm will determine the time that will take to solve the problem. (See above the Amount of data – Time correlation table)

Is this post, I want to talk about how using the correct data structure can help us to get a successful cost-effective algorithm.

When developing an algorithm, there are several things that we should take into account:

1- Amount of data

2- How we structure the data

3- How we manage the data

4- Time and space complexity

We assume that the main aim of our algorithm is to manage a big amount of data ( >1000 items ). The difference of time between two algorithms (let’s say O(x) vs O(x²)) for 10 elements is almost irrelevant.

Our work as a software engineers is to avoid unnecessary resource consumption and decrease the server costs.

The most important step when choosing a Data Structure is to know what kind of operations will be performed against that Data Structure.

Most common operations are Access, Search, Insertion and Deletion. Requirements may vary depending of each case but we base our research in those 4 as a first step.

Of course, the most valuable aspect of an algorithm is the programmer creativity. Let’s consider then, the following Data Structure table a cheatsheet for that.

 

Access Search Insertion Deletion Space
Array O(1) O(n) O(n) O(n) O(n)
Stack O(n) O(n) O(1) O(1) O(n)
Queue O(n) O(n) O(1) O(1) O(n)
List with PI O(n) O(n) O(1) O(1) O(n)
Hash table O(1)/O(n) O(1)/O(n) O(1)/O(n) >=O(n)

*as long as we overdimension the hash table there will be less collisions and we will get the item easily.

 

My plan is to get more deeply into the listed Data Structures. If you find interesting any other Data Structure, please comment below. I will appreciate any suggestion.