I know it is provocative to put complex business logic in plain English to easily explain the logic, or Jira id/bug Id as a future reference in the codebase, but with time, the codebase evolves, methods are refactored but we forgot to refactor comments and your comment will be out of sync and gives a wrong interpretation about the method/code/business logic, undoubtedly a code smell, if you need to put bug id for future reference put as a commit message but avoid comments remember clean code is self-explanatory.
Home » Posts filed under java
Clean code Tips1:: Urge to put comments? refrain to do it.
in
cleancodetips,
code smell,
design pattern,
java
- on November 16, 2020
- No comments
Bounded Context in my view
in
DDD,
design pattern java,
design principles in java,
java,
Microservice
- on April 28, 2018
- No comments
In this article, I will share my view about Bounded Context,
What does it mean,?
Why is it required?
The connection between Bounded context and Microservices.
I will try to keep it simple, and this article targeted to that audience who will hear the term Bounded Context while developing Microservices but having a hard time to understanding the Bounded context concept.
Before deep dive into Bounded Context in terms of DDD(Domain Driven Design), Let's understand what is the meaning of that in the real world.
We know the human is the most intelligent species and created different countries for the ruling. But Question is Why they created different countries or Logical Boundaries? In what basis Boundary has been drawn between two countries, before Human civilization, in the Earth, we only have land there is no concept of country.
One compelling answers come to my mind is that to separate the administration, culture, laws, economics, so each country abstracted its people from other countries unless it is an impossible task to create one Unified culture, language as in ancients time different tribes has there own languages and cultures.
In the same country, there are some predefined rules, language, style every citizen follows. They understand the common language, aware of laws, currency, style so as a brief I can say, Citizens are sync with each other in a country and country has one Unified culture which every citizen follows and understand.
In programming, We apply Bounded context in the same manner, to separate different models/subdomains from each other in a Domain/Problem space, In a Domain-driven design --Strategic design part, we introduce Bounded context so in a certain context a model has a certain meaning like the countries where for a particular country--ceratin language, currency has specific meaning, But in a different country that currency or language is not understandable, Because it has no meaning/different meaning respect to that country. Like the word Fool, In English it means Stupid but in Bengali it means Flower !!!!
So If we consider Country as a Bounded context, and language/currencies as a Model inside that context we can easily map the concept of the domain model in a certain bounded context. The model has some meaning for a Bounded context but the same model has no meaning/different meaning for another Bounded context, So by Bounded context, we create a logical boundary where the model and business terms have a certain meaning and the Bounded context separate/hide the models from the outer world. All communication should be done via API. So it is obvious that under a Bounded context -- model and business logic maintains a certain law and maintain its own persistence storage and that is not directly accessible to other Bounded Context.
BoundedContext Communication: Any design has two common parts, abstraction of the data model and communicates with other parts of the system. By Bounded context we separate the data model in a simple term abstracting the commonalities in the business but How one Bounded context communicate with others?
Here the concept of Context Map stepped in, Using Context map we can discover How one Context depends on other Bounded Context, Like are two Context has strong dependencies. or one domain sends a confirmation message to another domain(Conformist) or may use a shared kernel/Shared model, I will talk about Context map later in a separate article, But as of now, you can think context map is for communicating clearly between Bounded Contexts.
At this point, I believe you have a fair bit of idea what is a Bounded context, But still, if you have questions How it fits in Architecture? go to the next paragraph.
Let say we have to design Online Student management system where Student can register to the site choose course accordingly, Pay the Course fee and then he will be tagged to a batch and Teacher & Student is notified about the batch start date and time slot.
As an Architect, you have to identify the bounded context of the different domain related to this business logic.
If we divide the business logic based on related functionality we can found four basic functionality
1. Registration process: Which takes care of Registration of Student.
2. Payment System: Which will process the Course fee and publish online payment status.
3. Batch Scheduling: Upon confirmation of payment, this function checks the Teacher availability, batch availability and based on that create a batch and assign the candidates or update an existing batch with the candidate.
4. Notification System: It will notify Teacher and Student about the timings and slot information.
So, There are 4 bounded contexts Registration, Payments, Scheduler, and Notification.
Now let's dig down How each Module represents Teacher and Student and Course Models.
Registration process: It only wants the Student information and it needs it demographic information like Name, age, sex, address and which course student chooses.
There is no mean of Teacher in this context
Payment System : It treats Student as Candidates In Payment System only Student/Candidates financial information is required like Account number and based on the course fees it deduct the amount from given account, So here perspective of a student is totally different, Information needed in payment Service is totally different from Registration although Payment system may need few pieces of information like name, address of the student those are very minimal information.
The term "Teacher" is not valid here, In payment System Teacher treated as Faculty and they can be permanent or Contractor based on the Faculty type Payment System choose the payment calculation either per hour basis or per anum basis.
Batch Scheduling: In case of Batch Scheduling System, it needs bare minimum information from Teacher and Student like name, Address etc. But it needs detailed information, of Course, Batches under the Courses etc.
Notification System: For Notification System, we just need the Teacher and Student email address or Phone number and name nothing else, And it needs the name of the Student management system and Course details, here Student management site acts as Sender and Teacher and Student denotes as Reciever.
Till now we have seen, same Domain Objects Teacher, Student, Course have different meaning and use-cases for different Context, This is the beauty of Bounded Context ,we have multiple canonical models for same domain Object based on different context, So developers, Business, user are always in the same page when they are talking about a context, the concept of ubiquitous language is woven here, using ubiquitous language DDD create a unified system where every participant understand the language based on the context.
Now, the common question is why the Bounded context term is so popular in Microservices?
To answer this questions first we have to understand that DDD is applicable for Monolith as well as in Microservice, But in case of Monolith, it is vaguer and more of a logical segregation so only good developers can see it. The main reason is in monolith we have a single giant codebase, may we break it multimodule based on DDD create ACL/Translator when one module talks to another but still it needs other modules as dependent jars to invoke its method. Another point is as this is a single code base and multiple coders working on them so some not so skillfull coder can pollute the boundary or domain Object, Architecht can't create a physical boundary based on Bounded Context, But in Microservice architechture it is inherent as Microservice said that rather than a large code base we can create Small services which have it own code base and services are talk to each other through API or messaging, so It clearly says that understand the Business Domain break the Business logic in to multiple Bounded Contexts and each Bounded Context will be a separte codebase and they comuunicate through Context Map, To design the Context map you have to design API carefully, may you can use Port and Hub architechture So your code under the Bounded context is not comminicate with Outerworld and never polluted. Microservice offers this type of strong segregation of Bounded Context. Bounded Context is more visible and understandable in the context of Microservice.
Conclusion: Bounded Context is the basic needs, when you are trying to break a large business logic it helps you to understand how different part of the system use domain objects in a different manner with different terminology. Bounded Context is just a view to properly organize the business logic based on functionality but to make the business logic works -- communication between Bounded context needed, and it uses Context Map for the same. In my next article, I will discuss Context Map.
What does it mean,?
Why is it required?
The connection between Bounded context and Microservices.
I will try to keep it simple, and this article targeted to that audience who will hear the term Bounded Context while developing Microservices but having a hard time to understanding the Bounded context concept.
Before deep dive into Bounded Context in terms of DDD(Domain Driven Design), Let's understand what is the meaning of that in the real world.
We know the human is the most intelligent species and created different countries for the ruling. But Question is Why they created different countries or Logical Boundaries? In what basis Boundary has been drawn between two countries, before Human civilization, in the Earth, we only have land there is no concept of country.
One compelling answers come to my mind is that to separate the administration, culture, laws, economics, so each country abstracted its people from other countries unless it is an impossible task to create one Unified culture, language as in ancients time different tribes has there own languages and cultures.
In the same country, there are some predefined rules, language, style every citizen follows. They understand the common language, aware of laws, currency, style so as a brief I can say, Citizens are sync with each other in a country and country has one Unified culture which every citizen follows and understand.
In programming, We apply Bounded context in the same manner, to separate different models/subdomains from each other in a Domain/Problem space, In a Domain-driven design --Strategic design part, we introduce Bounded context so in a certain context a model has a certain meaning like the countries where for a particular country--ceratin language, currency has specific meaning, But in a different country that currency or language is not understandable, Because it has no meaning/different meaning respect to that country. Like the word Fool, In English it means Stupid but in Bengali it means Flower !!!!
So If we consider Country as a Bounded context, and language/currencies as a Model inside that context we can easily map the concept of the domain model in a certain bounded context. The model has some meaning for a Bounded context but the same model has no meaning/different meaning for another Bounded context, So by Bounded context, we create a logical boundary where the model and business terms have a certain meaning and the Bounded context separate/hide the models from the outer world. All communication should be done via API. So it is obvious that under a Bounded context -- model and business logic maintains a certain law and maintain its own persistence storage and that is not directly accessible to other Bounded Context.
BoundedContext Communication: Any design has two common parts, abstraction of the data model and communicates with other parts of the system. By Bounded context we separate the data model in a simple term abstracting the commonalities in the business but How one Bounded context communicate with others?
Here the concept of Context Map stepped in, Using Context map we can discover How one Context depends on other Bounded Context, Like are two Context has strong dependencies. or one domain sends a confirmation message to another domain(Conformist) or may use a shared kernel/Shared model, I will talk about Context map later in a separate article, But as of now, you can think context map is for communicating clearly between Bounded Contexts.
At this point, I believe you have a fair bit of idea what is a Bounded context, But still, if you have questions How it fits in Architecture? go to the next paragraph.
Let say we have to design Online Student management system where Student can register to the site choose course accordingly, Pay the Course fee and then he will be tagged to a batch and Teacher & Student is notified about the batch start date and time slot.
As an Architect, you have to identify the bounded context of the different domain related to this business logic.
If we divide the business logic based on related functionality we can found four basic functionality
1. Registration process: Which takes care of Registration of Student.
2. Payment System: Which will process the Course fee and publish online payment status.
3. Batch Scheduling: Upon confirmation of payment, this function checks the Teacher availability, batch availability and based on that create a batch and assign the candidates or update an existing batch with the candidate.
4. Notification System: It will notify Teacher and Student about the timings and slot information.
So, There are 4 bounded contexts Registration, Payments, Scheduler, and Notification.
Now let's dig down How each Module represents Teacher and Student and Course Models.
Registration process: It only wants the Student information and it needs it demographic information like Name, age, sex, address and which course student chooses.
There is no mean of Teacher in this context
Payment System : It treats Student as Candidates In Payment System only Student/Candidates financial information is required like Account number and based on the course fees it deduct the amount from given account, So here perspective of a student is totally different, Information needed in payment Service is totally different from Registration although Payment system may need few pieces of information like name, address of the student those are very minimal information.
The term "Teacher" is not valid here, In payment System Teacher treated as Faculty and they can be permanent or Contractor based on the Faculty type Payment System choose the payment calculation either per hour basis or per anum basis.
Batch Scheduling: In case of Batch Scheduling System, it needs bare minimum information from Teacher and Student like name, Address etc. But it needs detailed information, of Course, Batches under the Courses etc.
Notification System: For Notification System, we just need the Teacher and Student email address or Phone number and name nothing else, And it needs the name of the Student management system and Course details, here Student management site acts as Sender and Teacher and Student denotes as Reciever.
Till now we have seen, same Domain Objects Teacher, Student, Course have different meaning and use-cases for different Context, This is the beauty of Bounded Context ,we have multiple canonical models for same domain Object based on different context, So developers, Business, user are always in the same page when they are talking about a context, the concept of ubiquitous language is woven here, using ubiquitous language DDD create a unified system where every participant understand the language based on the context.
Now, the common question is why the Bounded context term is so popular in Microservices?
To answer this questions first we have to understand that DDD is applicable for Monolith as well as in Microservice, But in case of Monolith, it is vaguer and more of a logical segregation so only good developers can see it. The main reason is in monolith we have a single giant codebase, may we break it multimodule based on DDD create ACL/Translator when one module talks to another but still it needs other modules as dependent jars to invoke its method. Another point is as this is a single code base and multiple coders working on them so some not so skillfull coder can pollute the boundary or domain Object, Architecht can't create a physical boundary based on Bounded Context, But in Microservice architechture it is inherent as Microservice said that rather than a large code base we can create Small services which have it own code base and services are talk to each other through API or messaging, so It clearly says that understand the Business Domain break the Business logic in to multiple Bounded Contexts and each Bounded Context will be a separte codebase and they comuunicate through Context Map, To design the Context map you have to design API carefully, may you can use Port and Hub architechture So your code under the Bounded context is not comminicate with Outerworld and never polluted. Microservice offers this type of strong segregation of Bounded Context. Bounded Context is more visible and understandable in the context of Microservice.
Conclusion: Bounded Context is the basic needs, when you are trying to break a large business logic it helps you to understand how different part of the system use domain objects in a different manner with different terminology. Bounded Context is just a view to properly organize the business logic based on functionality but to make the business logic works -- communication between Bounded context needed, and it uses Context Map for the same. In my next article, I will discuss Context Map.
Change Method Call On the Fly:: CallSite
in
java,
java interview questions for experienced
- on March 12, 2018
- No comments
In my previous article, I talked about invokeDynamic, In this article, I will show you the coding how you can leverage the power of invokedynamic.
We all know that to load a class dynamically and call a method at runtime we use Java Reflection, Framework developers are often used Reflection to load class runtime and call a method at runtime. But Reflection has a performance cost as it does the security checking each time, On the other hand, invokeDynamic solves that problem and we can use invokeDynamic to runtime call the method.
To call the method runtime we need Method handle, Mow the interesting thing is we also change the underlying method call based on some parameters, It is a very powerful thing to do, the Same call can invoke different implementation on runtime based on parameter !!!
I try to explain you by a simple example, Say there are two methods call bark and mewaoo, Now based on the animal passed I want to call the corresponding method dynamically?
I will show you the code first then explain the code,
package com.example.methodhandle;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;
public class MethodHandleExample {
MutableCallSite callSite = null;
public void bark() {
System.out.println("I am a Dog :: So barking");
}
public void mewaoo() {
System.out.println("I am a Cat :: So Mewaooing");
}
public MethodHandle findMethodHandle(String command) throws NoSuchMethodException, IllegalAccessException {
MethodHandle mh = null;
if ("DOG".equalsIgnoreCase(command)) {
mh = createMethodHandle(MethodType.methodType(void.class), "bark");
} else if ("CAT".equalsIgnoreCase(command)) {
mh = createMethodHandle(MethodType.methodType(void.class), "mewaoo");
} else {
throw new RuntimeException("Give a Proper Command");
}
return mh;
}
public CallSite createCallSite(String command) throws NoSuchMethodException, IllegalAccessException {
if (callSite == null) {
callSite = new MutableCallSite(findMethodHandle(command));
} else {
callSite.setTarget(findMethodHandle(command));
}
return callSite;
}
public MethodHandle createMethodHandle(MethodType methodType, String methodName)
throws NoSuchMethodException, IllegalAccessException {
return MethodHandles.lookup().findVirtual(this.getClass(), methodName, methodType);
}
public static void main(String[] args) {
MethodHandleExample example = new MethodHandleExample();
try {
example.createCallSite("DOG").dynamicInvoker().invoke(example);
example.createCallSite("CAT").dynamicInvoker().invoke(example);
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
If I run this code output will be
I am a Dog :: So barking
I am a Cat :: So Mewaooing
Explanation:: To call bark and mewaoo method dynamically based on the passing parameter, We first need to create MethodHandle for each method.
MethodHandle is such an Object which stores the metadata about the method, Such as the name of the method signature of the method etc.
So here, I create a generic method called createMethodHandle, which returns a method handle.
To create a Method handle we need two major thing name of the method and the MethodType Object, MethodType Object says about the signature of the method. name parameter denotes the name of the method.
I create a generic method called findMethodHandle, This method passes the required parameters to the createMethodHandle method based on the passed command, If the command is a dog, this method pass the method name as bark and method type as void as bark takes nothing and return nothing (Signature of bark method).
Now , to change the invocation of the method we need a Calliste --Which actually flips the call, For two methods we have two different method handle, Calliste bound with a Method handle and actually call underlying Method handle , MutableCallsite can change the underlying Method handle Object (Strategy), so Callsite change the MethodHandle based on the command given.
Here I create a method called createCallSIte, which create a single instance of a Callsite Object, and based on the command, Callsite change the target aka MethodHandle.
Conclusion: This is a simple example but using Callsite and Methodhandle you can create a factory of Strategy and based on the situation you can choose the optimum one, so developers perspective it just a method call but ad framework developer you can choose what to call when like lambda in java8 maintained LambdaMewtaFactory.
Java:: What is invokeDynamic
in
java,
java interview,
java interview questions
- on February 19, 2018
- No comments
In my previous article,
I discussed --How JVM determines which methods to call at runtime?Also,
we learned that In bytecode level, java compiler uses 4 special opcodes
for method invoking
invokestatic,invokeinterface,invokevirtual,invokespecial.
Now, the question arises if all types of methods invoking (interface, static method, instance method, constructor etc.) are covered by 4 opcodes, why there is another opcode invokeDynamic has been introduced?
Why invokeDynamic?
To understand why invokedymic is required let dig down to a real problem, for a moment think you are building a framework where based on the command passed from UI you load a class runtime and invoke a particular method of that class.
Say you are building a Web framework like Struts -- Now based on the URL you have to map a java class and invoke a specific method so you will create an XML(like struts-config.xml) where developer explicitly put the strategy -- which URL map to which class and which method to be called.
Let's see the prototype of the XML.
Think how you can design the same in java, what is the weapon available in java to implement the same, Of course, by the Reflection mechanism-- By the reflection you are able to load the Employee controller class and based on the parameter you can invoke the appropriate method.
Pseudocode will be like that.
This is the one reason to introduce invokeDynamic in the place of reflection, it facilitates dynamic programming -- where type checking and method resolution done at runtime. So by that you can add remove methods programmatically -- You can do bytecode engineering runtime I mean, you can insert a new method which is not in the class definition !!! or override a method runtime!!! invokeDynamic provides this type of flexibility, unlike reflection.
invokeDynamic is as fast as other opcodes, but to introducing invoke dynamic in Java is not an easy task.
Java is a statically type so type checking is done at compile time also compiler checks a method is available in the class or not if the method is not available it throws compiler error so the questions is
How can we trick compiler in such a way where we can introduce a new method at runtime to be specific type checking and method resolution done at run-time?
How invokeDyamic works internally?
To work the invokeDynamic opcode correctly two important components are MethodHandle and CallSite
MethodHandle: Method handles wraps the metadata about a method-- It holds the method signature so by invoking it you can invoke a method on an Object at runtime.
CallSite : Callsite can hold Method handle and if the Call site is mutable we can change the Method handle time to time, so based on the parameter we can change the MethodHandle and as Method handle holds the method so runtime we can change the method call without altering the bytecode instruction that is invoked dynamic, so same method invocation can execute different methods based on the parameters.
Actually when the invokeDynamic instruction is read by the interpreter following procedure happens underhood-- invokedynamic instruction is associated with a special method called the bootstrap method (BSM). When the invokedynamic instruction is read by the interpreter, the BSM is invoked. It returns an object called Callsite (hold a method handle) that indicates which method actually execute.
So, Calliste works like the subline in the Train track-- Trani always runs on a straight track but when it needs to change it's direction Line Engineers are pull the liver of subline so it joins with another line according to the needs and Train just pass on that line and change the track, Calliste mimic the same methodology when based on parameter it changes the underlying method handle and same method invocation call diffrent method at runtime.
Let see the diagram,
Conclusion: invokeDynamic is a valuable inclusion in terms of framework level developer, By invokedynamic we can get the real essence of Dynamic programming in JVM, Many languages which run on JVM uses the invokedynamic to achieve dynamic type checking also Lamda uses invokedynamic, In my next tutorial I will show you how to write Callsite and MethodHandle and How you can changeMethodHandle under Callsite dynamically.
invokestatic,invokeinterface,invokevirtual,invokespecial.
Now, the question arises if all types of methods invoking (interface, static method, instance method, constructor etc.) are covered by 4 opcodes, why there is another opcode invokeDynamic has been introduced?
Why invokeDynamic?
To understand why invokedymic is required let dig down to a real problem, for a moment think you are building a framework where based on the command passed from UI you load a class runtime and invoke a particular method of that class.
Say you are building a Web framework like Struts -- Now based on the URL you have to map a java class and invoke a specific method so you will create an XML(like struts-config.xml) where developer explicitly put the strategy -- which URL map to which class and which method to be called.
Let's see the prototype of the XML.
<controller url="/employee" class="com.java.example.EmployeeController">
<param key="add" method="executeAdd">
<param key="update" method="executeUpdate">
<param key="delete" method="executeDelete">
<goto key="success" path="/success.jsp">
<goto key="faliure" path="/error.jsp">
</controller>
Seeing,
this configuration XML one thing is clear, based on the action taken by
the user in UI, different method will be called for EmployeController
class, If user performs an add then internally an 'add' parameter will be passed and framework checks that which method has to call for 'add' parameter and found it is executeAdd.
Until User does not take an action no one can tell which method will
be called, so all the decision has to be taken at runtime based on the
parameters passed(add, edit, delete).<param key="add" method="executeAdd">
<param key="update" method="executeUpdate">
<param key="delete" method="executeDelete">
<goto key="success" path="/success.jsp">
<goto key="faliure" path="/error.jsp">
</controller>
Think how you can design the same in java, what is the weapon available in java to implement the same, Of course, by the Reflection mechanism-- By the reflection you are able to load the Employee controller class and based on the parameter you can invoke the appropriate method.
Pseudocode will be like that.
Class controller = Class.forname("com.example.EmployeeController");
Controller empController = controller.newInstance();
Class inputParams[] = {javax.servlet.http.HttpRequest,javax.servlet.http.HttpResponse};
String methodSuffix = makeFirstLetterCapital(empController.getParam());//add to Add
Method tobeInvoked= Class.declaredMethod("execute"+methodSuffix,inputParams);
tobeInvoked.invoke(empController,request,response);
This
runs very well, It will take the decision on runtime except for one
problem. Reflection has huge performance penalties because it is always
checking security constraints like what is the method access specifiers,
is the caller has permission to call the method etc, so for this
reflection is bit slow.Controller empController = controller.newInstance();
Class inputParams[] = {javax.servlet.http.HttpRequest,javax.servlet.http.HttpResponse};
String methodSuffix = makeFirstLetterCapital(empController.getParam());//add to Add
Method tobeInvoked= Class.declaredMethod("execute"+methodSuffix,inputParams);
tobeInvoked.invoke(empController,request,response);
This is the one reason to introduce invokeDynamic in the place of reflection, it facilitates dynamic programming -- where type checking and method resolution done at runtime. So by that you can add remove methods programmatically -- You can do bytecode engineering runtime I mean, you can insert a new method which is not in the class definition !!! or override a method runtime!!! invokeDynamic provides this type of flexibility, unlike reflection.
invokeDynamic is as fast as other opcodes, but to introducing invoke dynamic in Java is not an easy task.
Java is a statically type so type checking is done at compile time also compiler checks a method is available in the class or not if the method is not available it throws compiler error so the questions is
How can we trick compiler in such a way where we can introduce a new method at runtime to be specific type checking and method resolution done at run-time?
How invokeDyamic works internally?
To work the invokeDynamic opcode correctly two important components are MethodHandle and CallSite
MethodHandle: Method handles wraps the metadata about a method-- It holds the method signature so by invoking it you can invoke a method on an Object at runtime.
CallSite : Callsite can hold Method handle and if the Call site is mutable we can change the Method handle time to time, so based on the parameter we can change the MethodHandle and as Method handle holds the method so runtime we can change the method call without altering the bytecode instruction that is invoked dynamic, so same method invocation can execute different methods based on the parameters.
Actually when the invokeDynamic instruction is read by the interpreter following procedure happens underhood-- invokedynamic instruction is associated with a special method called the bootstrap method (BSM). When the invokedynamic instruction is read by the interpreter, the BSM is invoked. It returns an object called Callsite (hold a method handle) that indicates which method actually execute.
So, Calliste works like the subline in the Train track-- Trani always runs on a straight track but when it needs to change it's direction Line Engineers are pull the liver of subline so it joins with another line according to the needs and Train just pass on that line and change the track, Calliste mimic the same methodology when based on parameter it changes the underlying method handle and same method invocation call diffrent method at runtime.
Let see the diagram,
Conclusion: invokeDynamic is a valuable inclusion in terms of framework level developer, By invokedynamic we can get the real essence of Dynamic programming in JVM, Many languages which run on JVM uses the invokedynamic to achieve dynamic type checking also Lamda uses invokedynamic, In my next tutorial I will show you how to write Callsite and MethodHandle and How you can changeMethodHandle under Callsite dynamically.
How does method dispatch happen in Java?
in
java,
java interview,
java interview questions
- on January 23, 2018
- No comments
Have you ever wondered when you call a method like a list.add("Shamik"), How the actual method invoke in runtime?
If you want to discover the How part then you are in the right place else you can easily skip the article as it is not related to coding perspective. we know in Java we maintain two steps process
Compiler compiles and make the bytecodes
The interpreter takes bytecode and changes the instruction to machine code.
But think, When your code compiles to bytecode how the method call looks like and in the runtime how the dynamic linking happens, In a simple word how JVM find the actual method and call that method.
In this tutorial, we will discuss the same.
In java(till Java7) we have four types of method
1. Static methods.
2. private, package private or public methods
3. Interface methods declaration.
4. Some special methods like the constructor, super etc.
Now, as the actual method call happens at runtime, somehow at compile time(bytecode) we have to instruct JVM where to find the method or location of the method. But for some cases it is not possible to tell earlier(compile time) which method will be invoked( like in case of overriding, Polymorphism) so compiler has to defer the lookup of the method until runtime, so there are different types of opcodes are used by compiler to tell JVM what to do in runtime.
At runtime, JVM maintains a runtime table called vtable where each entry represents the precise location of the method. The help of this vtable, JVM actually dispatches the call to an actual method.
opcodes
In bytecode, java uses 4 opcodes still java6 but in java7 there is a new opcode introduced called invokedynamic, I will write a separate article on invokedynamic opcode but in this article, we will discuss the other opcodes.
invokestatic: invokestatic opcode is used at compile time to dispatch static methods.
invokevirtual: invokevirtual used to dispatch instance methods.
invokespecial: invokespecial is used to dispatch special methods like constructor or super or for the private method.
invokeinterface: invokeinterface is used to dispatch a method call via an interface.
Now, we will write a java example and try to see the bytecode representation of that example.
package com.example.methodcall;
import java.util.ArrayList;
import java.util.List;
public class MethodCall {
public void addCity() {
List<String> city = new ArrayList<String>();
city.add("Kolkata");
}
public void addState() {
ArrayList<String> state = new ArrayList<String>();
state.add("WestBengal");
}
public static void main(String[] args) {
MethodCall target = new MethodCall();
target.addCity();
target.addState();
}
}
Now I want to see the bytecode representation of the above java program so I will run the following command
javap -c MethodCall.class
Bytecode will look like following
public class com.example.methodcall.MethodCall {
public com.example.methodcall.MethodCall();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public void addCity();
Code:
0: new #15 // class java/util/ArrayList
3: dup
4: invokespecial #17 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #18 // String Kolkata
11: invokeinterface #20, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: return
public void addState();
Code:
0: new #15 // class java/util/ArrayList
3: dup
4: invokespecial #17 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #31 // String WestBengal
11: invokevirtual #33 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
14: pop
15: return
public static void main(java.lang.String[]);
Code:
0: new #1 // class com/example/methodcall/MethodCall
3: dup
4: invokespecial #39 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #40 // Method addCity:()V
12: aload_1
13: invokevirtual #42 // Method addState:()V
16: return
}
Deep dive into the bytecode Representation :
In the above bytecode representation, except invokestatic all opcodes has been used.
If you noticed the bytecode minutely you can explore that for each method a section is entitled and each java line converted to a command. Let go through each method section
com.example.methodcall.MethodCall(): This is the constructor of MethodCall class, here you can find an invokespecial call because this opcode is used for calling a special method like constructor or super etc. if you pay attention to the commented line beside the invokespecial call you will find the method details
// Method java/lang/Object."<init>":() V: This says constructor can be found in java.lang.object which is detonated by a special symbol <init> and it takes nothing as an argument
public void addCity(): In this section bytecode use invokeinterface opcode for the line
List<String> city = new ArrayList<String>();
city.add("Kolkata");
and it is commented
as
// InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z which means add is an interface method which is in java.util.List and it takes Object as an input argument.
Here invokeInterface opcode is used because, as we did the polymorphic assignment so at the compile time there is no way to know where is the actual add method implementation, so compiler has to put such opcode which will instruct JVM to dispatch the call to exact method from Vtable at runtime, so method resolution happens at runtime.
public void addState():
In this section bytecode use invokevirtual opcode for the line
ArrayList<String> state = new ArrayList<String>();
state.add("WestBengal");
and it is commented as
// Method java/util/ArrayList.add:(Ljava/lang/Object;)Z which means add can be found in java.util.ArrayList and it takes Object as an input argument.
There, is very subtle difference in coding -- we use ArrayList instead of List so it is not a polymorphic assignment so it creates a huge difference in bytecode now bytecode knows the exact class where to find the add method at compile-time but still call will be dispatched in runtime as if some other class can extend ArrayList. But it uses Invokevirtual opcode which is used for calling an instance method.
public static void main(java.lang.String[]): The last section is entitled to the main method where we call two instance methods addCity and addState so it uses invokevirtual opcode.
Conclusion : In this article we have a fair bit of an idea how method call is happened using different opcodes, But in Java7 an important opcode has been added that is invokeDynamic, which opens the door to allow dynamic type language in JVM, so other languages which run on top of JVM uses this invokeDynamic opcode to make them dynamic language certain extent also Lambda Expression in Java8 uses the invokedynamic opcode, In my next tutorial I will give a detailed overview on -- invokeDynamic opcode.
If you want to discover the How part then you are in the right place else you can easily skip the article as it is not related to coding perspective. we know in Java we maintain two steps process
Compiler compiles and make the bytecodes
The interpreter takes bytecode and changes the instruction to machine code.
But think, When your code compiles to bytecode how the method call looks like and in the runtime how the dynamic linking happens, In a simple word how JVM find the actual method and call that method.
In this tutorial, we will discuss the same.
In java(till Java7) we have four types of method
1. Static methods.
2. private, package private or public methods
3. Interface methods declaration.
4. Some special methods like the constructor, super etc.
Now, as the actual method call happens at runtime, somehow at compile time(bytecode) we have to instruct JVM where to find the method or location of the method. But for some cases it is not possible to tell earlier(compile time) which method will be invoked( like in case of overriding, Polymorphism) so compiler has to defer the lookup of the method until runtime, so there are different types of opcodes are used by compiler to tell JVM what to do in runtime.
At runtime, JVM maintains a runtime table called vtable where each entry represents the precise location of the method. The help of this vtable, JVM actually dispatches the call to an actual method.
opcodes
In bytecode, java uses 4 opcodes still java6 but in java7 there is a new opcode introduced called invokedynamic, I will write a separate article on invokedynamic opcode but in this article, we will discuss the other opcodes.
invokestatic: invokestatic opcode is used at compile time to dispatch static methods.
invokevirtual: invokevirtual used to dispatch instance methods.
invokespecial: invokespecial is used to dispatch special methods like constructor or super or for the private method.
invokeinterface: invokeinterface is used to dispatch a method call via an interface.
Now, we will write a java example and try to see the bytecode representation of that example.
package com.example.methodcall;
import java.util.ArrayList;
import java.util.List;
public class MethodCall {
public void addCity() {
List<String> city = new ArrayList<String>();
city.add("Kolkata");
}
public void addState() {
ArrayList<String> state = new ArrayList<String>();
state.add("WestBengal");
}
public static void main(String[] args) {
MethodCall target = new MethodCall();
target.addCity();
target.addState();
}
}
Now I want to see the bytecode representation of the above java program so I will run the following command
javap -c MethodCall.class
Bytecode will look like following
public class com.example.methodcall.MethodCall {
public com.example.methodcall.MethodCall();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public void addCity();
Code:
0: new #15 // class java/util/ArrayList
3: dup
4: invokespecial #17 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #18 // String Kolkata
11: invokeinterface #20, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: return
public void addState();
Code:
0: new #15 // class java/util/ArrayList
3: dup
4: invokespecial #17 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #31 // String WestBengal
11: invokevirtual #33 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
14: pop
15: return
public static void main(java.lang.String[]);
Code:
0: new #1 // class com/example/methodcall/MethodCall
3: dup
4: invokespecial #39 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #40 // Method addCity:()V
12: aload_1
13: invokevirtual #42 // Method addState:()V
16: return
}
Deep dive into the bytecode Representation :
In the above bytecode representation, except invokestatic all opcodes has been used.
If you noticed the bytecode minutely you can explore that for each method a section is entitled and each java line converted to a command. Let go through each method section
com.example.methodcall.MethodCall(): This is the constructor of MethodCall class, here you can find an invokespecial call because this opcode is used for calling a special method like constructor or super etc. if you pay attention to the commented line beside the invokespecial call you will find the method details
// Method java/lang/Object."<init>":() V: This says constructor can be found in java.lang.object which is detonated by a special symbol <init> and it takes nothing as an argument
public void addCity(): In this section bytecode use invokeinterface opcode for the line
List<String> city = new ArrayList<String>();
city.add("Kolkata");
and it is commented
as
// InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z which means add is an interface method which is in java.util.List and it takes Object as an input argument.
Here invokeInterface opcode is used because, as we did the polymorphic assignment so at the compile time there is no way to know where is the actual add method implementation, so compiler has to put such opcode which will instruct JVM to dispatch the call to exact method from Vtable at runtime, so method resolution happens at runtime.
public void addState():
In this section bytecode use invokevirtual opcode for the line
ArrayList<String> state = new ArrayList<String>();
state.add("WestBengal");
and it is commented as
// Method java/util/ArrayList.add:(Ljava/lang/Object;)Z which means add can be found in java.util.ArrayList and it takes Object as an input argument.
There, is very subtle difference in coding -- we use ArrayList instead of List so it is not a polymorphic assignment so it creates a huge difference in bytecode now bytecode knows the exact class where to find the add method at compile-time but still call will be dispatched in runtime as if some other class can extend ArrayList. But it uses Invokevirtual opcode which is used for calling an instance method.
public static void main(java.lang.String[]): The last section is entitled to the main method where we call two instance methods addCity and addState so it uses invokevirtual opcode.
Conclusion : In this article we have a fair bit of an idea how method call is happened using different opcodes, But in Java7 an important opcode has been added that is invokeDynamic, which opens the door to allow dynamic type language in JVM, so other languages which run on top of JVM uses this invokeDynamic opcode to make them dynamic language certain extent also Lambda Expression in Java8 uses the invokedynamic opcode, In my next tutorial I will give a detailed overview on -- invokeDynamic opcode.
Oogways on Value Types(Project Valhalla)
in
java
- on January 09, 2018
- No comments
Oogways promised us to give a demonstration on Project Valhalla, which is in roadmap of Oracle, Project Valhalla mainly focus on two features
1. Value types
2. Generic Specialization.
In this Article, I will cover the talk on Value type given by Oogways.let us get started what Oogways told us-- me and 5 Ninja warriors.
Oogways : we all know, to support primitives in Collection API--The Wrapper Object concept is created and java5 introduced autoboxing /unboxing feature, basically the motto of Autoboxing is to uplift primitives as an Object, so we can treat them as Object and Object's methods(equals, hashcode,toString) can be inherited to the Boxed Object so it can act as an Object and user(coder) does not have to bother about Boxing the primitives in a wrapper class, It will be done automatically and Vice versa.
So in developer's perspective, it is a huge improvement as you can play with collections and primitives and under the hood, all primitives get promoted to Object(Wrapper class, int->Integer). But in case of performance, it is not so good, to make developer happy Oracle compromised on the performance. Let us take a detailed look why the performance is degraded.
Case of Boxed Time elapsed:: 9
Case of primitive Time elapsed:: 6
So, Just in case of traversing boxed version and primitive version, there is a 3 Ms lag for 1000 elements. Not only in traversal there is also the side effect of memory consumption.
Why this performance degradation in case of Boxed version?
The performance degradation occurs due to the following reasons
Memory consumption : One of the differences between Java primitives and Object is --there is a cost associated with Object, just to box an int to Integer , it has to create a header(8-16 byte) and reference(4-8 bytes) in case of a reachable object, so instead of 4 bytes(int-4 bytes) it takes 4+8+4=16 bytes minimum. Imagine the same for 1000 elements each, so heap space is consumed rapidly as the elements in the array are increased (Not considering JIT optimization).
Traversing for Payload: When we wrap primitives into a wrapper class, it will act as Object so now array of Integers stores the pointers unlike the array of primitives where array store the value itself, so there is an unnecessary cost to traverse through the pointer to fetch the actual value/payload. It will certainly take much more time than storing the value directly in the array.
Lack of Inherent Locality : Think about the Java memory model map , in case of primitives , value will get stored in register and is pushed to stack memory. In case of array of primitives it will occupy same contiguous memory , so cache hits is bigger than cache miss and traversal will be optimized and faster. On the another hand in case of Object (Wrapper class) it will get stored in heap memory and we don't know where it belongs in heap memory as JVM there are different spaces like young generation, eden etc and Objects are moved to that spaces so there will no contiguous memory allocated for array of Objects. So the array of objects lacks the inherent locality and also cache miss is greater than cache hits, so traversing through pointer will take more time than directly find value from a contiguous location.
Due to the above reasons, Boxing is bad in terms of performance. But in Java, there are many use cases where we use Boxing to achieve some functionality which can't be achieved by only primitives.
I will tell you what are those areas where we use unnecessary boxing and compromise performance to achieve some programmatic design decision.
Value Types : In java, Often we design some Object which just carrier of some data, its primary goal represents a data structure nothing else, It does not hold any state so there is no identity check once the values are same we can say two objects are same , so they are only caring for value, not the reference and state. think about a Point object or a Money Object or a Pin Code Object, which are the associations of some primitives / Objects, If the value is same we can say those two objects are equal, think about Money Object, it is the combination of currency and value which is char and double respectively.
Wrapper Object: All primitives Wrapper types are degrading the performance.
Iterator: Iterator creates a snapshot of the collections to be traversed so it wraps the collection into an Iterator Objects which is nothing but a wrapper and degrades the performance.
Multi valued returns : Some time we need to return more than one value and those are heterogeneous type( like int, char,Object etc) from a method , in other languages we can do it by Tuples concept but in case of java we have to wrap the return value in to an object and return that Object, say I have a method which returns Address of a customer, and Address contains flat number, location, zip code, city, country -- so we have to create a wrapper Object which contains all these properties and return the Address so here Address Object acts as wrapper/boxed Object.
In the all above cases, we see a common problem to associate heterogeneous types we have to wrap it into a Object which act as Boxed type and compromise the performance as there is no other way in Java we can achieve Class like behavior (tied data and behaviors) but act as primitive type so we can benefit local inherent, less memory and fast performance.
Java architects addressed these problems and came up with a remarkable idea called Value Type under Project Valhalla.
The slogan of the project is “Codes like a class, works like an int!”
Seeing this slogan we can understand what they want to achieve. They want to create a new Datatype -- From developer's perspective, this act as a class and they can tie data and method together but in JVM it will act as primitive-- means it has no reference and stays in Stack memory !!!
If they really build this new datatype, it will solve performance issue without compromising the encapsulation because all the heterogeneous types act as user-defined primitives and store into the register so no pointer traversing is needed for getting payload.
Although, it is a remarkable idea and solves all design issues stated earlier without compromising performance but the road is not smooth-- there are many assumptions involved to create the new Value type-- which code like a class and act as an int.
I will try to give an overview of what considerations are needed to create a new Datatype.
Equality Check: As Value type does not has a pointer, so how you check the equality for two value Objects, As Value Object is a composite data Structure so a probable solution will call equals or == for all associated components.
Null keyword: We know for Object null is the default value, but Value type is not an Object so what will be its default value? Probable solution would be default Value of ValueObject is setting the default value to all is sub-fields/association that is the initial state of ValueObject and that is set when Value Object initialized. And the null keyword for ValueObject should be disallowed.
Reference Cast: Value type is not an Object so it is not Reference type and it is not pointed by a reference, But to support those APIs which play with Reference casting is needed, Value type should able to upgrade to reference type and vice versa as we do in the case with primitive boxing and unboxing.
Polymorphism: One of the powerful features of java is Polymorphism where parent reference can hold all the subtypes, but this is valid for only reference types which have a pointer. So at runtime pointer points to the corresponding subclass implementation. As Value type is pointer less and immutable in nature so the question is, should Value type allow Polymorphism? The Answer is no, it is Just a Value type. Although you are coding it like a class, inheritance should be disallowed as Valuetype does not carry any header information and used for flattening the associated Objects.
Cloning: Value type carry only information so Cloning does not make sense but it can be used as Identity transformation.
Till now, we have found various use cases for using Value types, Now we will see how a Value Type may look like
Next Question will come How we instantiate Value types.
Probably in the following way
So it flattens the Money Value type.
As Value type is neither Object and nor primitive we have still some questions about equality check. Let's see How Valuetype treats equality check.
But if it ends here that would be fine but still, it has some advanced things to deal with and the probable answer to those questions are.
Subtyping:
Value type can extends Reference type? No, because it is not an Object this is a new type.
Reference type extends a value type? No, because Valuetype does not have reference/pointer.
Can a Value type class extend another value type? No, because value types are final.)
Can a value type be abstract or non-final? No abstract value type seems not worthwhile
Can a value type implement interfaces? Yes. Boxing may occur when we treat a value type as an interface instance.
Can values participate in inheritance-based subtyping? No, polymorphism not allowed.
Containment :
Can a value class contain a field of the reference type? Yes because of a value type code like a class.
Can a reference class contain a field of value type? Yes because it is just another type.
Can a value type contain a component field of value type? Yes it is work like a class
Can an array contain elements of value type? Yes works like an int. And the array itself is an object.
Can a value class contain a non-final field? No as Value type is immutable.
Can values have member types? Yes. Non-static member types have hidden fields that record containing values.
Can values be member types? Yes. If non-static, they have hidden fields that point to containing objects.
Compatibility
Are values objects? No, although they can be boxed into objects.
Are primitives values? Possibly. (Value classes named int, boolean, etc., would provide good successors to the existing wrapper types.
Can value types be serialized? Not by default, since that would violate encapsulation.
Conclusion: Value type is a rich concept, Oracle is working hard to release this concept to efficiently manage the memory wasted for tiny objects which are acting as a wrapper or as the data carriers.
1. Value types
2. Generic Specialization.
In this Article, I will cover the talk on Value type given by Oogways.let us get started what Oogways told us-- me and 5 Ninja warriors.
Oogways : we all know, to support primitives in Collection API--The Wrapper Object concept is created and java5 introduced autoboxing /unboxing feature, basically the motto of Autoboxing is to uplift primitives as an Object, so we can treat them as Object and Object's methods(equals, hashcode,toString) can be inherited to the Boxed Object so it can act as an Object and user(coder) does not have to bother about Boxing the primitives in a wrapper class, It will be done automatically and Vice versa.
So in developer's perspective, it is a huge improvement as you can play with collections and primitives and under the hood, all primitives get promoted to Object(Wrapper class, int->Integer). But in case of performance, it is not so good, to make developer happy Oracle compromised on the performance. Let us take a detailed look why the performance is degraded.
package com.example.valhalla;
public class PerformanceTest {
Integer[] boxedArray = new Integer[1000];
int[] primitiveArray = new int[1000];
public void insert() {
for (int i = 0; i < 1000; i++) {
boxedArray[i] = i;
primitiveArray[i] = i;
}
}
public void traveseBoxedArray() {
Long start = System.currentTimeMillis();
for(int i=0;i<boxedArray.length;i++) {
System.out.print(i);
}
System.out.println();
Long end = System.currentTimeMillis();
System.out.println("Time elapsed :: " + (end-start));
}
public void travesePrimitiveArray() {
Long start = System.currentTimeMillis();
for(int i=0;i<primitiveArray.length;i++) {
System.out.print(i);
}
System.out.println();
Long end = System.currentTimeMillis();
System.out.println("Time elapsed :: " + (end-start));
}
public static void main(String[] args) {
PerformanceTest test = new PerformanceTest();
test.insert();
test.traveseBoxedArray();
test.travesePrimitiveArray();
}
}
Output : Case of Boxed Time elapsed:: 9
Case of primitive Time elapsed:: 6
So, Just in case of traversing boxed version and primitive version, there is a 3 Ms lag for 1000 elements. Not only in traversal there is also the side effect of memory consumption.
Why this performance degradation in case of Boxed version?
The performance degradation occurs due to the following reasons
Memory consumption : One of the differences between Java primitives and Object is --there is a cost associated with Object, just to box an int to Integer , it has to create a header(8-16 byte) and reference(4-8 bytes) in case of a reachable object, so instead of 4 bytes(int-4 bytes) it takes 4+8+4=16 bytes minimum. Imagine the same for 1000 elements each, so heap space is consumed rapidly as the elements in the array are increased (Not considering JIT optimization).
Traversing for Payload: When we wrap primitives into a wrapper class, it will act as Object so now array of Integers stores the pointers unlike the array of primitives where array store the value itself, so there is an unnecessary cost to traverse through the pointer to fetch the actual value/payload. It will certainly take much more time than storing the value directly in the array.
Lack of Inherent Locality : Think about the Java memory model map , in case of primitives , value will get stored in register and is pushed to stack memory. In case of array of primitives it will occupy same contiguous memory , so cache hits is bigger than cache miss and traversal will be optimized and faster. On the another hand in case of Object (Wrapper class) it will get stored in heap memory and we don't know where it belongs in heap memory as JVM there are different spaces like young generation, eden etc and Objects are moved to that spaces so there will no contiguous memory allocated for array of Objects. So the array of objects lacks the inherent locality and also cache miss is greater than cache hits, so traversing through pointer will take more time than directly find value from a contiguous location.
Due to the above reasons, Boxing is bad in terms of performance. But in Java, there are many use cases where we use Boxing to achieve some functionality which can't be achieved by only primitives.
I will tell you what are those areas where we use unnecessary boxing and compromise performance to achieve some programmatic design decision.
Value Types : In java, Often we design some Object which just carrier of some data, its primary goal represents a data structure nothing else, It does not hold any state so there is no identity check once the values are same we can say two objects are same , so they are only caring for value, not the reference and state. think about a Point object or a Money Object or a Pin Code Object, which are the associations of some primitives / Objects, If the value is same we can say those two objects are equal, think about Money Object, it is the combination of currency and value which is char and double respectively.
package com.example.valhalla;
public final class Money {
public final double value;
public final char currency;
public Money(double value,char currency) {
this.currency=currency;
this.value=value;
}
public final void display() {
System.out.println(value + currency);
}
}
So, Money is immutable in nature and we wrap the value and currency into a Money Object which acts as Wrapper Object, But this Money does not do anything apart from encapsulating the primitives values. So performance got affected as Money is an Object rather than a collection of primitives, and we can't store value and currency into an array as those are the heterogeneous types and array support homogeneous typing.To support heterogeneous type we have to opt for an object and compromise the performance.Wrapper Object: All primitives Wrapper types are degrading the performance.
Iterator: Iterator creates a snapshot of the collections to be traversed so it wraps the collection into an Iterator Objects which is nothing but a wrapper and degrades the performance.
Multi valued returns : Some time we need to return more than one value and those are heterogeneous type( like int, char,Object etc) from a method , in other languages we can do it by Tuples concept but in case of java we have to wrap the return value in to an object and return that Object, say I have a method which returns Address of a customer, and Address contains flat number, location, zip code, city, country -- so we have to create a wrapper Object which contains all these properties and return the Address so here Address Object acts as wrapper/boxed Object.
In the all above cases, we see a common problem to associate heterogeneous types we have to wrap it into a Object which act as Boxed type and compromise the performance as there is no other way in Java we can achieve Class like behavior (tied data and behaviors) but act as primitive type so we can benefit local inherent, less memory and fast performance.
Java architects addressed these problems and came up with a remarkable idea called Value Type under Project Valhalla.
The slogan of the project is “Codes like a class, works like an int!”
Seeing this slogan we can understand what they want to achieve. They want to create a new Datatype -- From developer's perspective, this act as a class and they can tie data and method together but in JVM it will act as primitive-- means it has no reference and stays in Stack memory !!!
If they really build this new datatype, it will solve performance issue without compromising the encapsulation because all the heterogeneous types act as user-defined primitives and store into the register so no pointer traversing is needed for getting payload.
Although, it is a remarkable idea and solves all design issues stated earlier without compromising performance but the road is not smooth-- there are many assumptions involved to create the new Value type-- which code like a class and act as an int.
I will try to give an overview of what considerations are needed to create a new Datatype.
Equality Check: As Value type does not has a pointer, so how you check the equality for two value Objects, As Value Object is a composite data Structure so a probable solution will call equals or == for all associated components.
Null keyword: We know for Object null is the default value, but Value type is not an Object so what will be its default value? Probable solution would be default Value of ValueObject is setting the default value to all is sub-fields/association that is the initial state of ValueObject and that is set when Value Object initialized. And the null keyword for ValueObject should be disallowed.
Reference Cast: Value type is not an Object so it is not Reference type and it is not pointed by a reference, But to support those APIs which play with Reference casting is needed, Value type should able to upgrade to reference type and vice versa as we do in the case with primitive boxing and unboxing.
Polymorphism: One of the powerful features of java is Polymorphism where parent reference can hold all the subtypes, but this is valid for only reference types which have a pointer. So at runtime pointer points to the corresponding subclass implementation. As Value type is pointer less and immutable in nature so the question is, should Value type allow Polymorphism? The Answer is no, it is Just a Value type. Although you are coding it like a class, inheritance should be disallowed as Valuetype does not carry any header information and used for flattening the associated Objects.
Cloning: Value type carry only information so Cloning does not make sense but it can be used as Identity transformation.
Till now, we have found various use cases for using Value types, Now we will see how a Value Type may look like
package com.example.valhalla;
public final _ByValue class Money {
public final double value;
public final char currency;
public Money(double value,char currency) {
this.currency=currency;
this.value=value;
}
public final void display() {
System.out.println(value + currency);
}
public boolean equals(Money that) {
return this.currency == that.currency && this.currency == that.currency;
}
}
Here, a new keyword _ByValue is used to instruct JVM to treat the class as a Value type so instead of pointing the Money Object it extracts Money's all component and create a space in the stack.Next Question will come How we instantiate Value types.
Probably in the following way
Money money = __MakeValue(100, '$')
It will create a value type and store the currency and value properties into a stack.So it flattens the Money Value type.
As Value type is neither Object and nor primitive we have still some questions about equality check. Let's see How Valuetype treats equality check.
Money money1 = __MakeValue(100, '$);
Money money2 = __MakeValue(100, '$);
now
money1 == money2 (Do the Value equality check)
money1.equals(money2) (Do the Value equality check)
Object moneyWrapper1 = money1// Reference type
Object moneyWrapper2 = money2// Reference type
moneyWrapper1 == moneyWrapper2 // Refrence check
moneyWrapper1.equals(moneyWrapper2) // call Money Value types equals
Ok, we are got a fair bit of idea what are the challenges and how Oracle architects are trying to deal with the same to offer Value type in Java.But if it ends here that would be fine but still, it has some advanced things to deal with and the probable answer to those questions are.
Subtyping:
Value type can extends Reference type? No, because it is not an Object this is a new type.
Reference type extends a value type? No, because Valuetype does not have reference/pointer.
Can a Value type class extend another value type? No, because value types are final.)
Can a value type be abstract or non-final? No abstract value type seems not worthwhile
Can a value type implement interfaces? Yes. Boxing may occur when we treat a value type as an interface instance.
Can values participate in inheritance-based subtyping? No, polymorphism not allowed.
Containment :
Can a value class contain a field of the reference type? Yes because of a value type code like a class.
Can a reference class contain a field of value type? Yes because it is just another type.
Can a value type contain a component field of value type? Yes it is work like a class
Can an array contain elements of value type? Yes works like an int. And the array itself is an object.
Can a value class contain a non-final field? No as Value type is immutable.
Can values have member types? Yes. Non-static member types have hidden fields that record containing values.
Can values be member types? Yes. If non-static, they have hidden fields that point to containing objects.
Compatibility
Are values objects? No, although they can be boxed into objects.
Are primitives values? Possibly. (Value classes named int, boolean, etc., would provide good successors to the existing wrapper types.
Can value types be serialized? Not by default, since that would violate encapsulation.
Conclusion: Value type is a rich concept, Oracle is working hard to release this concept to efficiently manage the memory wasted for tiny objects which are acting as a wrapper or as the data carriers.
Techniques for reducing Tight Coupling
in
design pattern,
design pattern in java,
java
- on October 09, 2017
- No comments
“Tight Coupling is Bad” How many times you have heard this word from your seniors. Probably many many times.
But why Coupling is bad what are the implications comes if you do tight coupling?
What is actually a Tight coupling?
How we can fight with it.?
In this tutorials, we will dig the answers.
Coupling: In a simple term coupling is when a Class or Interface dependent on another class/interface i.e has a HAS-A relationship.
Example :
Class Vehicle{
private Wheel wheel =new Wheel();
}
In above example, Vehicle is dependent on Wheel, Which means without creating Wheel Object we can’t create Vehicle Object if anything goes wrong while creating Wheel Object vehicle will never be created. Also if we need to test Vehicle, first Wheel Object has to be created then Vehicle can be tested. Without, Wheel Vehicle has no existence. This type of coupling is called Tight Coupling, We know Vehicle must contain Wheel, To make the statement more generic sometimes we have requirements where a class must have to contains other classes to fulfill its purpose, they can't-do thing independently. So Coupling is inevitable, it can not be avoided but by programming technique we can make it pluggable in such a way so that we can reduce the degree of coupling so Dependable and Dependent class/interface can be changed without impacting each other. We called this technique as Loose coupling. I will show you some techniques which reduce the coupling between Objects.
Creation of Objects : Often while we doing coding we direct create the dependable Object instance, either in a init method or in Constructor or supply it through setter/constructor. But it is always risky. Once you have done that, Then you lose the flexibility if requirement changes in future you have to change the Dependent Object to accommodate the change in dependable Object. Let say All Ford cars use MRF Wheel So they are dependent on MRF wheel, Now if they change the mind and want to use Another company’s wheel then they have to change all car's Wheel Object creation so it is against the Open-Close principle.
Ex.
public Class Ford{
MRFWheel wheel;
Ford(MRFWheel wheel){
this.wheel =wheel;// replaced by new JKWheel()
}
}
So the best practices would be If you think dependent object will be changed frequently or may have multiple implementations always create an Interface and use that interface as a reference so anytime you can change the implementation without affecting the dependent class. But if you are sure about the dependent Objects behavior will not change then unnecessary don’t create interface it again against YAGNI and KISS.
IWheel{
//wheel related methods
}
public class Ford{
IWheel wheel;
Ford(IWheel wheel){
this.wheel =wheel;// replaced by new JKWheel()
}
}
Assuming MRFWheel and JKWheel are the subclasses of the IWheel
new Ford(new MRFWheel());
new Ford(new JKWheel())
Use Static factory method for creating Object : While creating an Interface for multiple implementations is good as you can change implementation dynamically. But if the dependable Object implementation is changed then again you have to change the all dependant Object which again breaks the Open/close principle.
Say Now Wheel take Air Pressure as a Constructor arguments then the caller of the Ford car has to change its logic, as multiple cars have dependencies on Wheel every implementation will break due to this change.
new Ford(new MRFWheel(AirPressure pressure));
new Ford(new JKWheel(AirPressure pressure))
The problem is we do not centralize the Object creation so all the caller has a responsibility to create the Objects and when the project grows it is a tedious job to find all references and fix them in case of a change in business logic in dependable Object. We certainly reduce our effort, if we use a Static Factory method to create the instances, So we centralize the creation of dependable object all dependent objects refer static factory method to get the dependable Object.So if any implementation details change it will only affect the Static factory method, Unless the method signature of the Static factory method is changed.
public static IWheel createWheel(WHEEL wheel){
if(WHEEL.mrf.equals(wheel)
new MRFWheel(AirPressure pressure)
}
else if(WHEEL.JK.equals(wheel)
new JKWheel(AirPressure pressure)
}else{
New DumyWheel(AirPressure pressure)
}
calling:
new Ford(WheelFactory.createWheel(WHEEL.mrf)));
new Ford(WheelFactory.createWheel(WHEEL.JK)));
Don’t take dependable Object Responsibility : Often knowingly or unknowingly, caller take the responsibility of dependable Object, which is breaking the encapsulation and it is the most common coding mistake I have seen, Not judging the Cohesion properly and it breaks another principle Tell Don’t Ask. Which increases unnecessary coupling and gradually your code not welcoming any future changes. Let's take a Simple example how we take dependable Object responsibility. Say Ford car has a method which shows the specifications of the car in very detail manner. So when it shows the Wheels Specifications often we do code like this in Ford Class.
public void FordSpecification(){
//Ford car specific specifications
//then
wheel.getAirPressure();
wheel.getManufactureDate();
wheel.getBrandName();
}
But it has a severe problem if in future Wheel specification is changed if it adds or removes any attribute it has a direct impact on Ford class, So all Ford Car classes have to be changed to incorporate the specification changes of the wheel.
It is wheel specification changes so why Ford class would be the sufferer?
Because while coding we did not understand the Wheel class responsibility, It is wheel class responsibility to provide specification through a specification method which uses by the Ford.
In Wheel class
public void specification(){
wheel.getAirPressure();
wheel.getManufactureDate();
wheel.getBrandname();
}
In Ford Class
public void FordSpecification(){
//Ford car specific specifications
//then
wheel.specification();
}
If wheel specification changes it does not impact the Ford class.
Try to reduce Hide-coupling :
Hide Coupling means from the API, you can’t understand there is and Dependency inside it.
It is a common programming technique where we hide the coupling from the user, Like create necessary Objects inside init method or constructor. I am not saying this is bad but , When you hide a Coupling think very carefully , If the Object is a kind of Utility, Connection pools, Worker thread that is fine but if it is a normal business Object, always provide an option for setting the Object from Outside, So user can set a Dummy or Mock Object while testing, Unless as a developer it is very hard to track down why the Object is not created as user does not aware of hiding coupling
Take the first example again
Public Class Ford{
MRFWheel wheel;
Ford(){
this.wheel =new MRFWheel();
}
}
From the API of Ford, it is impossible to say Ford has a dependency on MRFWheel. You will discover it in runtime if MRFWheel Object is not created from the stack trace. But if you change the implementation.
Public Class Ford{
IWheel wheel;
Ford(IWheel wheel){
this.wheel =wheel;// replaced by new JKWheel()
}
}
Then we can inject a DummyWheel while unit testing the Ford specific method.
Conclusion : Tight Coupling always creates a Big Ball of Mud. And gradually loses the flexibility to incorporate changes. Always take a closer look for coupling while writing code-- A silly mistake can cost you very much in near future. If you take above best practices most of the time you will be on safer side.