Wednesday, March 30, 2016

Handling non-functional requirements in scrum

Product owners defines application functionalities and requirements about what application should do. Such requirements are called functional requirements.

There use to be some inherent requirements of a system like performance,scalability, manageability, which the software architect needs to identify and define.These are called non-functional requirements of a system.Non functional requirements defines the quality or constraints of a system.If these are not taken care during software architecture phase, application ends up with technical debt, which leads to high cost of maintenance, enhancement and support.

The distinction between functional and non-functional requirement can be understood from a ticket booking application. The functional requirement would be that users should be able to book the tickets between two locations. Whether the application should remain available all the time or can be brought down for some time weekly or monthly for maintenance would be a non-functional requirement.

Some examples of non-functional requirements of an application are as following -
  1. Scalability (Capability to handle growing amount of work)
  2. Performance
  3. Usability (Easy to use, learn and fit for purpose)
  4. Manageability (Easy to configured, deployed, controlled and supervised)
  5. Security
  6. Documentation
  7. Extensibility (Ability to be extended with minimal or no change in existing code/behaviour)
  8. Portability (Usability in different environment)
  9. Reliability (Ability to function under stated condition for specified period of time)
  10. Robustness (Ability to cope up with error or erroneous input during execution)
  11. Availability (Ratio of time of application at operable/committed level to total time)
  12. Resilience (Ability to provide accepted level on service in case of faults, natural disasters or targeted attacks)
  13. Configuration management (Track and control changes in software)
  14. Disaster recovery (Procedures to recover from natural or human made disasters)
In scrum, such non functional requirements, can be handled in following ways-

Creating the stories and getting the product-owners buy-in for prioritization -In this approach, we talk to product owner to get the non-functional requirements considered as user stories. The example of such story with acceptance criteria might be "As a user, I want the application to remain available 24*7. It should not need to be brought down for upgrades" . The limitation of this approach is that some of the times, such stories might not be prioritized by product owners for a long time. The positive side of this approach is that whenever its picked up, we would have complete buy-in from product-owners.

Considering the non-functional requirements part of functional story itself - In this approach, the non-functional requirements gets implemented along with the story itself, but it would have impact on the estimation of stories. While following this approach, the estimation would be higher than it would have been without non-functional requirements

In this article, I explained the way to understand and manage the non-functional requirements. Please let us know,your experience as well about managing and handling non-functional requirements

Monday, March 7, 2016

Direct vs Seda vs Direct-Vm vs VM end points in Apache Camel

Apache camel is a rule based routing and mediation engine. It provides facility to perform seamless integration of various type of components via routes and endpoints.

Camel comes up with four camel aware end points.These end points have following similarities-
1. All of these end points accept camel exchange message only.
2. All of these end points are in-memory. Message in these queues would get lost in case of abrupt shutdown of system.

All of these queues provide better performance than other end points because no camel message transformation is performed by the end point.

Despite having multiple similarities, the purpose of each and every end point is different.The exact nature of difference can be noticed from the following matrix -


With In Same Camel Context
Across Camel contexts in a Single JVM
Synchronous
direct
direct-vm
Asynchronous
seda
vm

Synchronous communication refers to the communication, where the sender sends the message and proceed ahead only when response is retrieved back. In this case, all further processing happens on the received message.

Asynchronous communication refers to the kind of communication, where sender sends a copy of message to the receiver and proceeds without waiting for the processing at receiver to be completed.

In the following example, I will show you the behavior of direct end point and let you use the same example to test and understand the behavior of seda, direct-vm and vm end points. In case of any difficulty, you can download the complete project with the example of all of the end points from the following git hub location.-


Technology used -
java version "1.8.0_73"
Apache Camel 2.16.2
Apache Maven 3.0.4

pom.xml -
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>camel</groupId>
 <artifactId>CamelAwareEndPoints</artifactId>
 <packaging>jar</packaging>
 <version>1.0-SNAPSHOT</version>
 <dependencies>
  <dependency>
   <groupId>org.apache.camel</groupId>
   <artifactId>camel-core</artifactId>
   <version>2.16.2</version>
  </dependency>
  <dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-simple</artifactId>
   <version>1.6.4</version>
  </dependency>
 </dependencies>
</project>
Project Structure

DirectEndPointRouter.java-
package com.salil.camelawareendpoints.router;

import org.apache.camel.builder.RouteBuilder;

public class DirectEndPointRouter extends RouteBuilder  {

 public static final String DIRECT_END = "direct:End";
 public static final String DIRECT_START = "direct:start";

 @Override
 public void configure() throws Exception {
  from(DIRECT_START).routeId("StartRouteId")
  .setBody().simple("Start Message")
  .to(DIRECT_END)
  .log("Message at start route completion = ${body}");
  
  
  from(DIRECT_END).routeId("EndRouteId")
  .setBody().simple("End Message")
        .log("message after end-route completion = ${body}");
 }

}

DirectEndPointBehaviorExample.java-
package com.salil.camelawareendpoints.ContextExample;

import com.salil.camelawareendpoints.router.DirectEndPointRouter;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.impl.DefaultCamelContext;

/**
 * Created by Salil on 29-02-2016.
 */
public class DirectEndPointBehaviorExample {

    public static void main(String[] args) throws Exception {
        CamelContext camelContext = new DefaultCamelContext();
        camelContext.addRoutes(new DirectEndPointRouter());
        camelContext.start();

        ProducerTemplate producerTemplate=camelContext.createProducerTemplate();
        producerTemplate.sendBody(DirectEndPointRouter.DIRECT_START, "Initial Message");
    }
}

Execution output-
427 [main] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.16.2 (CamelContext: camel-1) is starting
429 [main] INFO org.apache.camel.management.ManagedManagementStrategy - JMX is enabled
843 [main] INFO org.apache.camel.impl.converter.DefaultTypeConverter - Loaded 182 type converters
973 [main] INFO org.apache.camel.impl.DefaultRuntimeEndpointRegistry - Runtime endpoint registry is in extended mode gathering usage statistics of all incoming and outgoing endpoints (cache limit: 1000)
1280 [main] INFO org.apache.camel.impl.DefaultCamelContext - AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn this option off as it may improve performance.
1280 [main] INFO org.apache.camel.impl.DefaultCamelContext - StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
1441 [main] INFO org.apache.camel.impl.DefaultCamelContext - Route: StartRouteId started and consuming from: Endpoint[direct://start]
1451 [main] INFO org.apache.camel.impl.DefaultCamelContext - Route: EndRouteId started and consuming from: Endpoint[direct://End]
1451 [main] INFO org.apache.camel.impl.DefaultCamelContext - Total 2 routes, of which 2 is started.
1459 [main] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.16.2 (CamelContext: camel-1) started in 1.031 seconds
1501 [main] INFO EndRouteId - message after end-route completion = End Message
1501 [main] INFO StartRouteId - Message at start route completion = End Message

In this case, we can notice following things
1- The output of end route got printed before the completion of start route
2- Both start route and end route had the same message in the body of the message at the time of printing
3- All the execution happens on the main thread only

This behavior appears because of synchronous nature of direct end point, where at the call of '.to(DIRECT_END)', the execution of first route stopped & it resumed again on receiving of the message with body 'End Message'

Let us know whether you could understand the behavior of seda, direct-vm and vm points, or faced any difficulty even after executing the examples at following git hub location

Tuesday, March 1, 2016

Lamda expression vs Anonymous class in java

Lamda expression are anonymous methods, which can be assigned to a variable, passed as an argument or returned as a value of function call.

Lamda expression in java 8 comes as a big relief from writing the boiler plate code needed to implement single method interfaces like comparable, comparator, runnable or callable etc. For writing such methods using anonymous class it use to take minimum six to seven lines of code. The same can be written in a single line while using Lamda expression.

In the following example, we are trying to print 'Salil Verma' using thread. we can notice that Lamda expression is very concise and anonymous class contains boiler plate code.

Anonymous class approach -

public class ThreadAnonymousClassExample {
   
 public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Salil Verma");
            }
        };
        new Thread(runnable).start();
    }
}

Lamda expression approach -

public class ThreadLamdaExample {
   
 public static void main(String[] args) {
        new Thread(()->System.out.println("Salil Verma")).start();
    }
}

Although Lamda expression looks very handy and concise in writing, it has got limitations. This expression can be used only on the situations where we are using single method interface. On situations where interface or abstract class has got more than one methods, Anonymous class is the way to go.

In short, Lamda expression should be preferred over anonymous class where we are implementing single method interface otherwise anonymous class is the way to go.