Welcome To Fusebes - Dev & Programming Blog

Kotlin Properties, Backing Fields, Getters and Setters
07
Mar
2021

Kotlin Properties, Backing Fields, Getters and Setters

You can declare properties inside Kotlin classes in the same way you declare any other variable. These properties can be mutable (declared using var) or immutable (declared using val).

Here is an example –

// User class with a Primary constructor that accepts three parameters
class User(_id: Int, _name: String, _age: Int) {
    // Properties of User class
    val id: Int = _id         // Immutable (Read only)
    var name: String = _name  // Mutable
    var age: Int = _age       // Mutable
}

You can get or set the properties of an object using the dot(.) notation like so –

val user = User(1, "Jack Sparrow", 44)

// Getting a Property
val name = user.name

// Setting a Property
user.age = 46

// You cannot set read-only properties
user.id = 2	// Error: Val cannot be assigned

Getters and Setters

Kotlin internally generates a default getter and setter for mutable properties, and a getter (only) for read-only properties.

It calls these getters and setters internally whenever you access or modify a property using the dot(.) notation.

Here is how the User class that we saw in the previous section looks like with the default getters and setters –

class User(_id: Int, _name: String, _age: Int) {
    val id: Int = _id
        get() = field
    
    var name: String = _name
        get() = field
        set(value) {
            field = value
        }
    
    var age: Int = _age
        get() = field
        set(value) {
            field = value
        }
}

You might have noticed two strange identifiers in all the getter and setter methods – field and value.

Let’s understand what these identifiers are for –

1. value

We use value as the name of the setter parameter. This is the default convention in Kotlin but you’re free to use any other name if you want.

The value parameter contains the value that a property is assigned to. For example, when you write user.name = "Bill Gates", the value parameter contains the assigned value “Bill Gates”.

2. Backing Field (field)

Backing field helps you refer to the property inside the getter and setter methods. This is required because if you use the property directly inside the getter or setter then you’ll run into a recursive call which will generate a StackOverflowError.

Let’s see that in action. Let’s modify the User class and refer to the properties directly inside the getters and setters instead of using the field identifier –

class User(_name: String, _age: Int) {
    var name: String = _name
        get() = name		  // Calls the getter recursively

    var age: Int = _age
        set(value) {
            age = value		  // Calls the setter recursively
        }
}

fun main(args: Array<String>) {
    val user = User("Jack Sparrow", 44)

    // Getting a Property
    println("${user.name}") // StackOverflowError

    // Setting a Property
    user.age = 45           // StackOverflowError

}

The above program will generate a StackOverflowError due to the recursive calls in the getter and setter methods. This is why Kotlin has the concept of backing fields. It makes storing the property value in memory possible. When you initialize a property with a value in the class, the initializer value is written to the backing field of that property –

class User(_id: Int) {
    val id: Int	= _id   // The initializer value is written to the backing field of the property
}

A backing field is generated for a property if

  • A custom getter/setter references it through the field identifier or,
  • It uses the default implementation of at least one of the accessors (getter or setter). (Remember, the default getter and setter references the field identifier themselves)

For example, a backing field is not generated for the id property in the following class because it neither uses the default implementation of the getter nor refers to the field identifier in the custom getter –

class User() {
    val id	// No backing field is generated
        get() = 0
}

Since a backing field is not generated, you won’t be able to initialize the above property like so –

class User(_id: Int) {
    val id: Int = _id	//Error: Initialization not possible because no backing field is generated which could store the initialized value in memory
        get() = 0
}

Creating Custom Getters and Setters

You can ditch Kotlin’s default getter/setter and define a custom getter and setter for the properties of your class.

Here is an example –

class User(_id: Int, _name: String, _age: Int) {
    val id: Int = _id

    var name: String = _name 
        // Custom Getter
        get() {     
            return field.toUpperCase()
        }     

    var age: Int = _age
        // Custom Setter
        set(value) {
            field = if(value > 0) value else throw IllegalArgumentException("Age must be greater than zero")
        }
}

fun main(args: Array<String>) {
    val user = User(1, "Jack Sparrow", 44)

    println("${user.name}") // JACK SPARROW

    user.age = -1           // Throws IllegalArgumentException: Age must be greater that zero
}

Conclusion

Thanks for reading folks. In this article, You learned how Kotlin’s getters and setters work and how to define a custom getter and setter for the properties of a class.

Micro-frontends: The path to a scalable future — part 1
26
Mar
2021

Micro-frontends: The path to a scalable future — part 1

Introduction

We have all heard the term microservices and perhaps have worked with them in the backend world. Before microservices, there were monolith applications. Back then, team and application growth was leading monolithic applications into a non-scalable dead-end. The codebase was growing, and technologies were getting older. All of this has made migrations and upgrades incredibly painful and frustrating.

An increase in project growth meant that multiple teams would unwittingly create further bottlenecks and inter-team dependencies. Deployments and releases were being micro-managed, but the growing amount of unmanaged technical debt would cause problems further down the line.

The same problems were present in the front-end world too. Again, you can structure the fanciest framework/library at that time and build your application with the best intentions. However, several years later, your tiny little application will inevitably become huge and force you to increase the size of your team. Eventually, this work will be split between multiple teams that will find themselves spending hours defining a release management schedule.

It’s around this time that you will hear about another cool library trending in the industry. Exploring the complexities of how to migrate to a new library while maintaining the old one typically leads to paranoia and eventually makes you give up on the idea because it’s just too much hassle. But you are also faced with a shrinking number of engineers who are willing to work with deprecated technologies. The chosen path has led you to a non-scalable dead-end.

A path to scalability

Try to imagine what the outcome would have looked like would we bravely decide to choose a different path. First, we should know that everything comes with a price, and with great power comes great responsibility. That power is the implementation of micro-frontends, which is

an architectural pattern to develop and maintain web application as a composition of small front-end applications

With back-end microservices, we had completely separate services with their separate DB and API. Microservices can be divided by business logic. For example, in an e-commerce app, we can have different microservices for a product catalog, user’s shopping cart, orders, etc. Without micro-frontend applications, it would have been a monolithic front-end application communicating with different back-end microservices (Fig. 1).

Figure 1. Application with monolith front-end and back-end microservices.

By splitting up the front-end into micro-frontends, we can align front-end and back-end architecture approaches and have a more robust and elegant full-stack architecture (Fig. 2).

Figure 2. End-to-end front-end and back-end microservices.
Figure 2. End-to-end front-end and back-end microservices.

With this approach, we can reach several significant benefits:

  • Team and technology autonomy: each team would have its own mission on the product and could select its own technology stack;
  • Small, maintainable, and de-coupled codebases: each team’s codebase would remain small and isolated from others’ codebases;
  • Independent release management: each team would be able to independently release its own part of the application saving a lot of time on inter-team communication and release schedule;
  • Painless upgrades and migrations: having small codebases and being free of inter-team dependency would lead to painless and independent upgrades of application technologies as well as migrations from the old one to a new one;

With the mentioned benefits, there are also challenges attached to implementing the micro-frontends architecture. There will still remain some issues and concerns that will be shared between teams such as web performance, a common design system, etc.

Even though the idea behind micro-services and micro-frontends is very similar, the implementation challenges are slightly different, and we will discuss them in the next section.

Micro-frontends integration concepts

There are three main concepts and problems to be taken into consideration when implementing the micro-frontend architecture.

Routing and page transition

This is one of the most important concepts. Regardless of how many micro-frontends are implemented in our application, it is crucial to handle transitions between micro-frontends (Fig. 3) properly. That said, users must never notice a switch from one micro-frontend application to another when navigating in the application.

Figure 3. The transition from one micro-frontend to another.

Page transition, which is also known as routing, can be either server or client-side. Let’s briefly go over each of them.

  • Server routing: on each transition (usually triggered by a click), there is a request to a server to obtain and serve the whole HTML document to the user. This method eventually leads to a full page reload, which is also known as a hard transition. It has several pros and cons and was a traditional way to handle transitions before the client-side routing evolution.
  • Client routing: on each transition, only some part of the application is being reloaded and operated by JavaScript in the browser on the client-side. Compared to server routing, there is no full page reload and is also known as soft transition. It brings a much better user experience and is implemented in almost all modern web applications.

There is an excellent article that covers server and client routing in more detail. With micro-frontends, the problem has various solutions starting from simple link transitions (the way routing was being handled in the 90’s and early 2000’s) into multi-layered client-side routings(a very modern way of having one top-level routing for the whole application, and several low-level routings per each micro-frontend). They differ by their implementation complexity, so the selection should be made based on the needs of our application.

Composition

It might be necessary to have a page owned by one team, but it will include fragments from other teams. This means we should consider the composition of multiple micro-frontends within each other (Fig. 4). For example, we could have an e-commerce web application and a product detail page owned by one team. We should also show the shopping cart content, which is owned by another team.

Figure 4. Composition of multiple micro-frontends.

Composition is a rendering concern which, similarly to routing, can be client and/or server-side:

  • Server-side rendering (SSR): with SSR or Universal rendering, our page document is being constructed and rendered on the server and served to the user. It is beneficial on the initial page load of an application as it is much more performant than rendering it on the client-side.
  • Client-side rendering (CSR): With CSR, our application page content is being constructed, rendered, and loaded on the client-side, operated by JavaScript. This type of rendering is used with all modern libraries and frameworks.

There are many cases when having just SSR or CSR will not be enough to meet our app needs (for example, when we need good SEO, a smooth user experience, and a fast content load). In these cases, the application uses both server and client-side rendering.

In most cases, the most relevant and essential content is being rendered server-side. It is being served to the user first, and afterward, the rest and more dynamic content is being handed over to JavaScript, which renders it on the client-side. There is much more to say about CSR, SSR but it is out of our topic for now. I highly recommend reading this article to learn more about these concepts and differences.

Tip: Again, most of the applications use both client and server-side rendering. But there is an easy life-hack that can help you check which parts of an application are rendered on the server-side and which parts on the client-side. Simply go to your browser settings and turn off JavaScript. Then open your desired website, and you will see the content which is loaded on the server-side. Then by turning on JS again, reloading the page will allow JS to render the other parts handed over to the client-side.

As with routing, there are also many different techniques both server-side(SSI, Zalando, Podium, etc.) and client-side(iframe, Ajax, Web Components, etc.) to handle micro-frontends composition. Which of these to go with depends on our application requirements.

Communication

The last concept of micro-frontend integration is the communication between our micro-frontends (Fig. 5).

Figure 5. Communication between micro-frontends.

Remember that we can have multiple micro-frontends on one page, and interaction with one can eventually lead to others’ changes. For example, let’s imagine we are on the product detail page of an e-commerce application, and we want to add a product to our shopping cart.

On the header (which is another micro-frontend fragment application), there is an icon of our cart, which also has an indicator — the number of added items. Adding the product on the details page should also update the number of items on our header’s shopping cart icon. There can be multiple communication scenarios like parent to fragment, fragment to parent, as well as fragment to fragment, and each communication is being handled differently.

  • Parent to fragment: This case is similar to handling communication between the parent component to the child components. It can be done by passing the data to children via props/attributes. So if our fragment/child is implemented with web components technology, it should be getting some attributes when they are being loaded, and data change in parent micro-frontend can trigger changed data passing to the fragment/child micro-frontends;
  • Fragment to parent: In this case, we can use the browser’s native CustomEvents API. So, on the parent side, there can be a subscribed event listener, while inside a fragment, we emit/publish an event on data change. The event emitter will bubble up the data to the listener on the parent side, which will then be handled on the parent micro-frontend.
  • Fragment to fragment: In this case, we can use the combination of the previous two techniques by emitting events to the parent fragment, which will listen to the changes and pass them to another fragment via props/attributes.

Another way of micro-frontends communication is Broadcast Channel API, which is an implementation of the Publisher/Subscriber design pattern just like the Custom Events API.

What’s next?

So, we have learned how beneficial micro-frontends can be and what problems they can solve. We also learned what challenges and problems we might face when implementing the micro-frontend architecture. We saw that based on the described three concepts, some various technologies and patterns could be used to achieve a full micro-frontend integration.

This should be enough to understand the main concepts and the big picture of micro-frontend architecture. This article is the first part of the series of 3 articles. The next article will be focused on high-level micro-frontend architecture types starting from the simplest and ending with the most complex one. We will also learn the concepts that will help us go with the architecture type that best fits our needs. So, stay tuned.

Layered Architecture
14
May
2021

What is a Layered Architecture?

One of the most common, and efficient, models deployed by enterprises is the Layered Architecture, also called the n-tiered pattern. It packs similar components together in a horizontal manner and is self-independent. What does that mean? 

It implies that the layers of the model are interconnected to each other but not interdependent. Similar components stay at the same level allowing the layers to be separated inadvertently based on the nature of the code. It is this isolation, that lends the software layers an independent nature. 

Consider an instance, wherein you’d want to switch from an Oracle database to an SQL. This shift may cause you to upend the database layer but will not have a domino effect on any other layer. 

Evidently, it serves a challenge for an enterprise software architect to create layers that separate from each other. Nevertheless, since the roles of each layer are clearly distinct, it accredits this software development architecture the following qualities:

  • It is easily maintainable as enterprise software developers with limited, or should we say pertinent, knowledge can be assigned to operate on a single layer.
  • You can test changes in layers separately from each other. 
  • Upgraded versions of the software can be implemented effortlessly. 

The flow of code is top-down, meaning it enters the presentation layer first and trickles down to the bottom-most layer that is the database layer. Each layer has a designated task based on the nature of the components it preserves. These could be checking the consistency of values within the code or reformatting the code altogether. 

Refactoring – a key  – way to lower frontend maintenance cost is a software development process by which developers change the internal shape and size of the code. They do it without affecting its external attributes can also be carried out in an n-tiered model.

Layered Architecture

This software development architecture can be customized to add layers to the presentation, business, persistence, and database levels. Such a model is called a Hybrid Layered architecture.

Benefits

  • Amongst the various types of software architecture, the layered variant suits enterprises that don’t want to go overboard with experimenting and want to stick to the traditional software architecture design patterns. 
  • Testing components become relatively easier as inter-dependencies are negligible in this format of software development engineering.
  • Considering many software frameworks were built with the backdrop of an n-tiered structure, applications built with them, as a result, happen to be in the layered format as well. 

Potential Drawbacks 

  • Larger applications tend to be resource-intensive if based on this format, therefore for such projects, it is advised to overlook the layered pattern. 
  • Although the layers are independent, yet the entire version of the software is installed as a single unit. Therefore, even if you update a single layer, you would have to re-install the entire apparatus all over again. 
  • Such systems are not scalable due to the coupling between the layers. 

Ideal For

The Layered architecture pattern suits the niche of LOB i.e. Line of Business Applications. These are applications that are essential to the functioning of the business itself. For instance, the accounts department of an organization needs software such as QuickBooks, Xero, Sage or Wave Accounting for keeping financial data. 

Similarly, the marketing team would demand a customer relationship management software slash tool to help them cope with the volume of interactions. In short, applications that do more than just CRUD (create, read, update, and delete) operations are suited to the layered architecture pattern. 

Remove Duplicates from Sorted Array
06
Feb
2021

Remove Duplicates from Sorted Array

Remove Duplicates from Sorted Array

Given a sorted array, remove the duplicates from the array in-place such that each element appears only once, and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Example

Given array [1, 1, 1, 3, 5, 5, 7]

The output should be 4, with the first four elements of the array being [1, 3, 5, 7]

Remove Duplicates from Sorted Array solution in Java

Given that the array is sorted, all the duplicate elements will appear together.

We can solve the problem in O(n) time complexity by using two pointer sliding window pattern. We’ll keep two pointers (indexes) –

  • One index i, to iterate over the array, and
  • Another index j, to keep track of the number of unique elements found so far. This index will move only when we modify the array in-place to include a new non-duplicate element.
class RemoveDuplicatesSortedArray {

  private static int removeDuplicates(int[] nums) {
    int n = nums.length;

    /*
     * This index will move only when we modify the array in-place to include a new
     * non-duplicate element.
     */
    int j = 0;

    for (int i = 0; i < n; i++) {
      /*
       * If the current element is equal to the next element, then skip the current
       * element because it's a duplicate.
       */
      if (i < n - 1 && nums[i] == nums[i + 1]) {
        continue;
      }

      nums[j++] = nums[i];
    }

    return j;
  }

  public static void main(String[] args) {
    int[] nums = new int[] { 1, 1, 1, 3, 5, 5, 7 };
    int newLength = removeDuplicates(nums);

    System.out.println("Length of array after removing duplicates = " + newLength);

    System.out.print("Array = ");
    for (int i = 0; i < newLength; i++) {
      System.out.print(nums[i] + " ");
    }
    System.out.println();
  }
}
# Output
Length of array after removing duplicates = 4
Array = 1 3 5 7 

Liked the Article? Share it on Social media!

Building Restful APIs with Kotlin, Spring Boot, Mysql, JPA and Hibernate
05
Mar
2021

Building Restful APIs with Kotlin, Spring Boot, MySQL , JPA and Hibernate

Kotlin has gained a lot of popularity in recent times due to its productivity features and a first class support in Android.

Owing to the increasing popularity of Kotlin, Spring framework 5 has also introduced a dedicated support for Kotlin in Spring applications.

In this article, You’ll learn how to build a Restful CRUD API with Kotlin and Spring Boot 2.x, which is based on Spring framework 5.

So Stay tuned!

What will we build?

In this blog post, we’ll build Restful APIs for a mini blog application. The blog has a list of Articles. We’ll write APIs for creating, retrieving, updating and deleting an Article. An Article has an id, a title and some content.

We’ll use MySQL as our data source and JPA & Hibernate to access the data from the database.

All right, Let’s now create the application.

Creating the Application

We’ll use Spring initializr web tool to bootstrap our application. Follow the steps below to generate the application :

  1. Go to http://start.spring.io
  2. Select Kotlin in the language section.
  3. Enter Artifact as kotlin-demo
  4. Add WebJPA, and MySQL dependencies.
  5. Click Generate to generate and download the project.
Kotlin Spring Boot Restful CRUD API Example

Once the project is generated, unzip it and import it into your favorite IDE. Here is the Project’s directory Structure for your reference.

Kotlin Spring Boot Restful CRUD API Example Directory Structure

Configure MySQL

We’ll need to configure MySQL database url, username, and password so that Spring Boot can create a Data source.

Open src/main/resources/application.properties file and add the following properties to it –

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/kotlin_demo_app?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
spring.datasource.username = root
spring.datasource.password = root


## Hibernate Properties

# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

Please don’t forget to change spring.datasource.username and spring.datasource.password as per your MySQL installation.

Note that, I’ve set spring.jpa.hibernate.ddl-auto property to update. This property updates the database schema whenever you create or modify the domain models in your application.

Creating the Domain Model

Let’s now create the Article domain entity. Create a new package called model inside com.example.kotlindemo package, and then create a new Kotlin file called Article.kt with the following contents –

package com.example.kotlindemo.model

import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.validation.constraints.NotBlank

@Entity
data class Article (
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0,

    @get: NotBlank
    val title: String = "",

    @get: NotBlank
    val content: String = ""
)

The Entity class is so small and concise, right? That’s because A Kotlin class doesn’t need getters and setters like Java. Moreover, I have used a data class here. A data class automatically generates equals()hashcode()toString() and copy() methods.

Note that, I’ve assigned a default value for all the fields in the Article class. This is needed because Hibernate requires an entity to have a no-arg constructor.

Assigning default values to all the member fields will let hibernate instantiate an Article without passing any argument. It Works because Kotlin supports Default Arguments 🙂

Creating the Repository

Let’s now create the repository for accessing the data from the database. First, create a package called repository inside com.example.kotlindemo package, and then create a Kotlin file named ArticleRepository.kt with the following contents –

package com.example.kotlindemo.repository

import com.example.kotlindemo.model.Article
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface ArticleRepository : JpaRepository<Article, Long>

That’s all we need to do here. Since we’ve extended ArticleRepository from JpaRepository interface, all the CRUD methods on Article entity is readily available to us. Spring boot automatically plugs-in a default implementation of JpaRepository called SimpleJpaRepository at runtime.

Creating the controller End-points

Finally, Let’s create the controller end-points for all the CRUD operations on Article entity.

First, create a new package called controller inside com.example.kotlindemo package and then create a new kotlin file called ArticleController.kt inside controller package with the following contents –

package com.example.kotlindemo.controller

import com.example.kotlindemo.model.Article
import com.example.kotlindemo.repository.ArticleRepository
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import java.util.*
import javax.validation.Valid

@RestController
@RequestMapping("/api")
class ArticleController(private val articleRepository: ArticleRepository) {

    @GetMapping("/articles")
    fun getAllArticles(): List<Article> =
            articleRepository.findAll()


    @PostMapping("/articles")
    fun createNewArticle(@Valid @RequestBody article: Article): Article =
            articleRepository.save(article)


    @GetMapping("/articles/{id}")
    fun getArticleById(@PathVariable(value = "id") articleId: Long): ResponseEntity<Article> {
        return articleRepository.findById(articleId).map { article -> 
            ResponseEntity.ok(article)
        }.orElse(ResponseEntity.notFound().build())
    }

    @PutMapping("/articles/{id}")
    fun updateArticleById(@PathVariable(value = "id") articleId: Long,
                          @Valid @RequestBody newArticle: Article): ResponseEntity<Article> {

        return articleRepository.findById(articleId).map { existingArticle ->
            val updatedArticle: Article = existingArticle
                    .copy(title = newArticle.title, content = newArticle.content)
            ResponseEntity.ok().body(articleRepository.save(updatedArticle))
        }.orElse(ResponseEntity.notFound().build())

    }

    @DeleteMapping("/articles/{id}")
    fun deleteArticleById(@PathVariable(value = "id") articleId: Long): ResponseEntity<Void> {

        return articleRepository.findById(articleId).map { article  ->
            articleRepository.delete(article)
            ResponseEntity<Void>(HttpStatus.OK)
        }.orElse(ResponseEntity.notFound().build())

    }
}

The controller defines APIs for all the CRUD operations. I have used Kotlin’s functional style syntax in all the methods to make them short and concise.

Running the Application

You can run the application by typing the following command in the terminal –

mvn spring-boot:run

The application will start at Spring Boot’s default port 8080.

Exploring the Rest APIs

1. POST /api/articles – Create an Article

curl -i -H "Content-Type: application/json" -X POST \
-d '{"title": "How to learn Spring framework", "content": "Resources to learn Spring framework"}' \
http://localhost:8080/api/articles

# Output
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:25:59 GMT

{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}

2. GET /api/articles – Get all Articles

curl -i -H 'Accept: application/json' http://localhost:8080/api/articles

# Output
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:25:29 GMT

[{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}]

3. Get /api/articles/{id} – Get an Article by id

curl -i -H 'Accept: application/json' http://localhost:8080/api/articles/1

# Output
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:27:51 GMT

{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}

4. PUT /api/articles/{id} – Update an Article

curl -i -H "Content-Type: application/json" -X PUT \
-d '{"title": "Learning Spring Boot", "content": "Some resources to learn Spring Boot"}' \
http://localhost:8080/api/articles/1

# Output
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:33:15 GMT

{"id":1,"title":"Learning Spring Boot","content":"Some resources to learn Spring Boot"}

5. DELETE /api/articles/{id} – Delete an Article

curl -i -X DELETE http://localhost:8080/api/articles/1

# Output
HTTP/1.1 200 
Content-Length: 0
Date: Fri, 06 Oct 2017 03:34:22 GMT

Conclusion

That’s all folks! In this article, You learned how to use Kotlin with Spring Boot for building restful web services.

You can find the entire code for the application that we built in this article in my github repository. Consider giving a star on github if you find the project useful.

Thank you for reading folks! See you next time 🙂

10 Common Software Architectural Patterns in a nutshell
18
Mar
2021

10 Common Software Architectural Patterns in a nutshell

Ever wondered how large enterprise scale systems are designed? Before major software development starts, we have to choose a suitable architecture that will provide us with the desired functionality and quality attributes. Hence, we should understand different architectures, before applying them to our design.

What is an Architectural Pattern?

According to Wikipedia,

An architectural pattern is a general, reusable solution to a commonly occurring problem in software architecture within a given context. Architectural patterns are similar to software design pattern but have a broader scope.

In this article, I will be briefly explaining the following 10 common architectural patterns with their usage, pros and cons.

  1. Layered pattern
  2. Client-server pattern
  3. Master-slave pattern
  4. Pipe-filter pattern
  5. Broker pattern
  6. Peer-to-peer pattern
  7. Event-bus pattern
  8. Model-view-controller pattern
  9. Blackboard pattern
  10. Interpreter pattern

1. Layered pattern

This pattern can be used to structure programs that can be decomposed into groups of subtasks, each of which is at a particular level of abstraction. Each layer provides services to the next higher layer.

The most commonly found 4 layers of a general information system are as follows.

  • Presentation layer (also known as UI layer)
  • Application layer (also known as service layer)
  • Business logic layer (also known as domain layer)
  • Data access layer (also known as persistence layer)

Usage

  • General desktop applications.
  • E commerce web applications.
Layered pattern

2. Client-server pattern

This pattern consists of two parties; a server and multiple clients. The server component will provide services to multiple client components. Clients request services from the server and the server provides relevant services to those clients. Furthermore, the server continues to listen to client requests.

Usage

  • Online applications such as email, document sharing and banking.
Client-server pattern

3. Master-slave pattern

This pattern consists of two parties; master and slaves. The master component distributes the work among identical slave components, and computes a final result from the results which the slaves return.

Usage

  • In database replication, the master database is regarded as the authoritative source, and the slave databases are synchronized to it.
  • Peripherals connected to a bus in a computer system (master and slave drives).
Master-slave pattern

4. Pipe-filter pattern

This pattern can be used to structure systems which produce and process a stream of data. Each processing step is enclosed within a filter component. Data to be processed is passed through pipes. These pipes can be used for buffering or for synchronization purposes.

Usage

  • Compilers. The consecutive filters perform lexical analysis, parsing, semantic analysis, and code generation.
  • Workflows in bioinformatics.
Pipe-filter pattern

5. Broker pattern

This pattern is used to structure distributed systems with decoupled components. These components can interact with each other by remote service invocations. A broker component is responsible for the coordination of communication among components.

Servers publish their capabilities (services and characteristics) to a broker. Clients request a service from the broker, and the broker then redirects the client to a suitable service from its registry.

Usage

Broker pattern

6. Peer-to-peer pattern

In this pattern, individual components are known as peers. Peers may function both as a client, requesting services from other peers, and as a server, providing services to other peers. A peer may act as a client or as a server or as both, and it can change its role dynamically with time.

Usage

Peer-to-peer pattern

7. Event-bus pattern

This pattern primarily deals with events and has 4 major components; event sourceevent listenerchannel and event bus. Sources publish messages to particular channels on an event bus. Listeners subscribe to particular channels. Listeners are notified of messages that are published to a channel to which they have subscribed before.

Usage

  • Android development
  • Notification services
Event-bus pattern

8. Model-view-controller pattern

This pattern, also known as MVC pattern, divides an interactive application in to 3 parts as,

  1. model — contains the core functionality and data
  2. view — displays the information to the user (more than one view may be defined)
  3. controller — handles the input from the user

This is done to separate internal representations of information from the ways information is presented to, and accepted from, the user. It decouples components and allows efficient code reuse.

Usage

  • Architecture for World Wide Web applications in major programming languages.
  • Web frameworks such as Django and Rails.
Model-view-controller pattern

9. Blackboard pattern

This pattern is useful for problems for which no deterministic solution strategies are known. The blackboard pattern consists of 3 main components.

  • blackboard — a structured global memory containing objects from the solution space
  • knowledge source — specialized modules with their own representation
  • control component — selects, configures and executes modules.

All the components have access to the blackboard. Components may produce new data objects that are added to the blackboard. Components look for particular kinds of data on the blackboard, and may find these by pattern matching with the existing knowledge source.

Usage

  • Speech recognition
  • Vehicle identification and tracking
  • Protein structure identification
  • Sonar signals interpretation.
Blackboard pattern

10. Interpreter pattern

This pattern is used for designing a component that interprets programs written in a dedicated language. It mainly specifies how to evaluate lines of programs, known as sentences or expressions written in a particular language. The basic idea is to have a class for each symbol of the language.

Usage

  • Database query languages such as SQL.
  • Languages used to describe communication protocols.
Interpreter pattern

Comparison of Architectural Patterns

The table given below summarizes the pros and cons of each architectural pattern.

Comparison of Architectural Patterns

Hope you found this article useful. I would love to hear your thoughts. 😇

Thanks for reading. 😊

Cheers! 😃

How to format Date and Time in Java
03
Mar
2021

How to format Date and Time in Java

In this article, you’ll learn how to format Date and Time represented using Date, LocalDate, LocalDateTime, or ZonedDateTime to a readable String in Java.

Format LocalDate using DateTimeFormatter

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class LocalDateFormatExample {
    public static void main(String[] args) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");

        LocalDate localDate = LocalDate.of(2020, 1, 31);

        System.out.println(localDate.format(dateTimeFormatter));

    }
}
# Output
31/01/2020

Format LocalDateTime using DateTimeFormatter

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeFormatExample {
    public static void main(String[] args) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("E, MMM dd yyyy, hh:mm:ss a");

        LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 31, 10, 45, 30);

        System.out.println(localDateTime.format(dateTimeFormatter));

    }
}
# Output
Fri, Jan 31 2020, 10:45:30 AM

Format ZonedDateTime using DateTimeFormatter

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class ZonedDateTimeFormatExample {
    public static void main(String[] args) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("E, MMM dd yyyy, hh:mm:ss a (VV)");

        ZonedDateTime zonedDateTime = ZonedDateTime.of(
                LocalDateTime.of(2020, 1, 31, 10, 30, 45),
                ZoneId.of("America/New_York"));
        
        System.out.println(zonedDateTime.format(dateTimeFormatter));

    }
}
# Output
Fri, Jan 31 2020, 10:30:45 AM (America/New_York)

Format Date and Time using SimpleDateFormat

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormatExample {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

        Date date = new Date();

        System.out.println(sdf.format(date));

    }
}
# Output
24/02/2020

Let’s see another example with a more complex pattern:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateFormatExample {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("E, MMM dd yyyy, hh:mm:ss a");

        Calendar calendar = Calendar.getInstance();
        calendar.set(2020, 1, 26, 15, 30, 45);

        Date date = calendar.getTime();

        System.out.println(sdf.format(date));

    }
}
# Output
Wed, Feb 26 2020, 03:30:45 PM
A Guide on How to Write a Clean Code
18
Mar
2021

A Guide on How to Write a Clean Code

In this article, I’m going to talk about writing clean code in general and then end up with some examples. As an Android developer having a clean code has always been challenging for me which needs lots of effort and that’s just coding and coding.

Rules We Should Follow

  1. Ignore duplication (imply DRY principle-Don’t Repeat Yourself)
  2. Minimize entities, classes, and functions (avoid repetition)
  3. It should be readable and simple
  4. Be testable as it makes your code flexible and maintainable
  5. Follow SOLIDprinciples

S = Single-responsibility principle: A class should only have one purpose.

O = Open-closed principleA class should be open for extension, but closed for modification.

L = Liskov substitution principleAbstraction should be able to provide all needs of child class.

I = Interface segregation principleSmall interface is better than big one.

D = Dependency Inversion Principle: A class should depend on abstraction, not implementation.

6. Be careful with dependencies

As many as possible try to have one-directional dependency. When dependency goes in multiple directions, things get much more complicated which makes hard to update and change.

7. Don’t hardcode

Define constant or use variables instead of hardcoding the values which will not only help readability but also make it easy to change if it is being used at multiple places.

Now let’s start writing Clean Code 🚀 …

Valid Names

Naming is one of the hardest parts of programming and may take time to choose, but it is a strong way to convey your code’s intent to other developers who read them in the future which must show the purpose of that class, function, or variable and even tell what is going to do. Don’t append prefixes or type information. I always have a checklist in my mind as listed below which assures me that a name has been chosen well:

  • Are the variables named according to the convention (camelCase, PascalCase, etc)?.
  • Does the name have an appropriate length to ensure that no one will be confused by it?.
  • Are the name of variables clear about what they hold?.
  • Are the names meaningful, searchable, and easy to pronounce?.

Class names should not only be names (not verbs) but also should have the PascalCase convention. On the other hand, method names should be verbs or phrase verbs and follow the camelCase convention. The same rules apply to variable names.

Functions and Methods

Following S from SOLID principles, let functions and methods perform only one task which should be small. If the function arguments are too many, you should review your code and maybe pack them into an object or divide that task between some other functions. Prefer possible exceptions to return error codes and extract error handling try catch into their own function.

Comments

We should use comments only when it is necessary, not to explain bad code. Writing lengthy comments will not help us in changing our code into a clean one. If the code is bad, we should solve it by improving the code, not by adding instructions on how to use it, but it doesn’t mean that you shouldn’t use comments at all, sometimes it is important such as dealing with third party APIs where you need to explain some behavior.

Code Appearance

It might look unimportant at first glance, but it is of high importance to write your code with a well-organized format which makes it readable such as:

  • Do not write everything in a single line. Give proper whitespace, indentation, or line breaks in your code.

Indentation styles assist in identifying control flow and blocks of code. In some programming languages, indentation is used to delimit logical blocks of code; correct indentation in these cases is more than a matter of style. In other languages, indentation and white space do not affect function, although logical and consistent indentation makes code more readable. (Inspired by WIKIPEDIA)

  • Instance variables should be declared at the top of the class.
  • If functions are calling each other (dependent functions) they should be close while putting the caller at first.
  • It is often helpful to align similar elements vertically, to make typo-generated bugs more obvious.

Tests

The importance of Test code is equal to producing the code and of course, while writing tests you might find some bugs. However, it can sometimes be quite difficult to write a good test for a particular piece of code which is a result of a badly designed and untestable code. Testing is almost like coding for the second time so follow all the previous rules for writing a good test as well which should be as per below :

  • One assert and single concept per test
  • Easy to write and readable (simplicity)
  • Fast
  • Independent

To conclude, I hope this article could be helpful to write a better code although it is important to keep practicing and learning in this field 😃 …

Three Number Sum Solution
06
Feb
2021

Three Number Sum Solution

Three Number Sum Problem Statement

Given an array of integers, find all triplets in the array that sum up to a given target value.

In other words, given an array arr and a target value target, return all triplets a, b, c such that a + b + c = target.

Example:

Input array: [7, 12, 3, 1, 2, -6, 5, -8, 6]
Target sum: 0

Output: [[2, -8, 6], [3, 5, -8], [1, -6, 5]]

Three Number Sum Problem solution in Java

METHOD 1. Naive approach: Use three for loops

The naive approach is to just use three nested for loops and check if the sum of any three elements in the array is equal to the given target.

Time complexity: O(n^3)

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

class ThreeSum {

  // Time complexity: O(n^3)
  private static List<Integer[]> findThreeSum_BruteForce(int[] nums, int target) {
    List<Integer[]> result = new ArrayList<>();
    for (int i = 0; i < nums.length; i++) {
      for (int j = i + 1; j < nums.length; j++) {
        for (int k = j + 1; k < nums.length; k++) {
          if (nums[i] + nums[j] + nums[k] == target) {
            result.add(new Integer[] { nums[i], nums[j], nums[k] });
          }
        }
      }
    }
    return result;
  }

  public static void main(String[] args) {
    Scanner keyboard = new Scanner(System.in);

    int n = keyboard.nextInt();
    int[] nums = new int[n];

    for (int i = 0; i < n; i++) {
      nums[i] = keyboard.nextInt();
    }
    int target = keyboard.nextInt();

    keyboard.close();

    List<Integer[]> result = findThreeSum_Sorting(nums, target);

    for(Integer[] triplets: result) {
      for(int num: triplets) {
        System.out.print(num + " ");
      }
      System.out.println();
    }
  }
}

METHOD 2. Use Sorting along with the two-pointer sliding window approach

Another approach is to first sort the array, then –

  • Iterate through each element of the array and for every iteration,
    • Fix the first element (nums[i])
    • Try to find the other two elements whose sum along with nums[i] gives target. This boils down to the two sum problem.

Time complexity: O(n^2)

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

class ThreeSum {

  // Time complexity: O(n^2)
  private static List<Integer[]> findThreeSum_Sorting(int[] nums, int target) {
    List<Integer[]> result = new ArrayList<>();
    Arrays.sort(nums);
    for (int i = 0; i < nums.length; i++) {
      int left = i + 1;
      int right = nums.length - 1;
      while (left < right) {
        if (nums[i] + nums[left] + nums[right] == target) {
          result.add(new Integer[] { nums[i], nums[left], nums[right] });
          left++;
          right--;
        } else if (nums[i] + nums[left] + nums[right] < target) {
          left++;
        } else {
          right--;
        }
      }
    }
    return result;
  }
}

METHOD 3. Use a Map/Set

Finally, you can also solve the problem using a Map/Set. You just need to iterate through the array, fix the first element, and then try to find the other two elements using the approach similar to the two sum problem.

I’m using a Set in the following solution instead of a Map as used in the two-sum problem because in the two-sum problem, we had to keep track of the index of the elements as well. But In this problem, we just care about the element and not its index.

Time complexity: O(n^2)

import java.util.Set;
import java.util.Scanner;
import java.util.HashSet;

class ThreeSum {

  // Time complexity: O(n^2)
  private static List<Integer[]> findThreeSum(int[] nums, int target) {
    List<Integer[]> result = new ArrayList<>();
    for (int i = 0; i < nums.length; i++) {
      int currentTarget = target - nums[i];
      Set<Integer> existingNums = new HashSet<>();
      for (int j = i + 1; j < nums.length; j++) {
        if (existingNums.contains(currentTarget - nums[j])) {
          result.add(new Integer[] { nums[i], nums[j], currentTarget - nums[j] });
        } else {
          existingNums.add(nums[j]);
        }
      }
    }
    return result;
  }
}

Liked the Article? Share it on Social media!