Tips for hiring Java Developer and a hands-on guide to Java 14
They say that experience is the best teacher — after all, reading “8 years of experience” on an applicant’s résumé is quite promising for many hiring officers. However, when it comes to hiring IT professionals, not all their skills and qualifications will be laid out on paper.
A candidate’s CV only tells half the story — essential skills (sometimes referred to as soft skills) are often left out in the application. On paper, some will oversell their technical know-how, some might downplay their problem-solving and related skills, while others might embellish their years of stagnation working only with one technology and never going beyond their given workload.
As with any hiring process, you need to be smart with your hiring efforts to find the right person for the job. Here are some tips and guidelines on how to go about the hiring process properly.
As DevsData and other trusted IT consulting companies will tell you, for a project to be successful, you have to make sure you are getting only the top-notch people involved. In the case of hiring a freelance Java developer, you will need to weed out the candidates who are not a fit for your project and organization. Here is where to start:
Experience as a tech freelancer does not always mean excellence in all projects. Software development is not a defined, static process, which means different IT professionals will have their own areas of expertise in the development process.
Fifteen years of experience may not always equate to a successful partnership and project. As explained in this blog by DevsData, there are many aspects to web development. Look for the ones who have extensive background in the type of development work you need.
More than the technical skills, also check their background working in different industries. Pharmaceutical, banking and finance, retail, and other sectors will have specific requirements and their own set of rules, which means developing an app for them will also require you to follow a lot of special requests and guidelines.
Seasoned freelance developers will always have feedback and testimonials from previous clients and colleagues. Check for their online presence on their personal website, GitHub, LinkedIn, Behance, Dribbble, or some other online platforms. This should give you a good idea of their works, style and expertise, and experience — and on the contrary, if their accounts are updated and you do not see anything substantial, it should also tell you something about them.
See if you can get in touch with clients they have worked with, as well as previous employers, to ask a few questions and for a quick background check about the candidate.
More often than not, IT professionals with a good track record will have good working relationships with previous clients and employers, even after the completion of a project or their employment.
If you are not an expert in the tech development project that your business needs, find someone who does. Get a senior Java consultant to speak with and assess the candidates. Ask them to go through each candidate’s application, especially the technical part. More on this in a previous blog about app development for non-technical founders. As the old saying goes, “Leave it to the experts.”
Taking off from the previous tip and during the interview process, be sure to ask about seemingly random things not on their résumé. Pick their brain about the latest tech news they have read about Java, Big Data, Spark, and the like. Inquire about the last time they upskilled or their recently-acquired skills in development.
This part of the interview can help them become more at ease before you dive into the more technical and detailed part of the interview. It also gives you a chance to gauge their communication skills, as well as their interest in and passion for their line of work.
One of the most reliable ways to test a candidate’s skills is by putting these to the test. Prepare a mini test or mini hackathon of sorts (preferably a paid one) that would include some scenarios and problems they may encounter at any point of the development process. The way they tackle the challenge and address problems should tell you a lot about their technical, creativity, and problem-solving skills.
A good thing to keep in mind here is to not confuse problem-solving skills for algorithmic knowledge. In our view, you should not put too much weight on algorithmic knowledge, since it mostly applies to very specific cases and thus, is not something used regularly.
Instead, test for their reasoning process, how they think on their feet, and how they come up with appropriate solutions under pressure. When we conduct that stage internally at DevsData, and if there are any algorithms involved, oftentimes we even explicitly explain upfront how the algorithm or a data structure works, and then expect the candidate to use that knowledge and apply his reasoning to solve a particular problem.
The next time you are hiring a developer, try throwing them a curveball by asking them questions that will surely get them rattled and thinking. Below are some of the questions we ask at DevsData. They will help you sift through the candidate pool and leave you with the cream of the crop.
Please remember that the knowledge test is only one of many stages in the process and should never be used alone. While it can be argued that the knowledge questions are more suitable for junior candidates, the senior ones should be well-versed in them. On top of that, it is very advisable to pose open-ended questions about a broader picture and potential implications of this very specific engineering decision, as well as a broader system architecture suitable for larger enterprise solutions. When a candidate is really determined, the knowledge can be gained rapidly.
On the other hand, what cannot be gained quickly is broader system understanding, and the ability to quickly solve problems under pressure. It is not uncommon to see engineers with 15 or 20 years of experience reluctant to learn about deep language technicalities, new approaches to software development, new frameworks, or likewise reluctant and even afraid of taking a problem-solving challenge. And that is one of the differentiating factors that perhaps should not be ignored.
Of the three, LinkedList is generally going to give you the best performance.
ArrayList and Vector each use an array to store the elements of the list. As a result, when an element is inserted into (or removed from) the middle of the list, the elements that follow must all be shifted accordingly. Vector is synchronized, so if a thread-safe implementation is not needed, it is recommended to use ArrayList rather than Vector.
LinkedList, on the other hand, is implemented using a doubly-linked list. As a result, inserting or removing an element only requires updating the links that immediately precede and follow the element being inserted or removed.
However, if performance is that critical, it is better to just use an array and manage it yourself, or use one of the high-performing third-party packages such as Trove or HPPC.
In Java, Strings are immutable and are stored in the String pool. Meaning that, once a String is created, it stays in the pool in memory until being garbage collected. Therefore, even after you are done processing the string value (e.g., the password), it remains available in memory for an indeterminate period of time thereafter (again, until being garbage collected) which you have no real control over. Therefore, anyone having access to a memory dump can potentially extract sensitive data and exploit it.
In contrast, if you use a mutable object like a character array, for example, to store the value, you can set it to blank once you are done with it with confidence that it will no longer be retained in memory.
Nevertheless, we advise avoiding operations on sensitive information in a plain text – they should be encrypted whenever humanly possible.
If a collection backs another, it means that changes in one are reflected in the other and vice-versa. For example, suppose we want to create a whitelist function that removes invalid keys from a Map. This can be achieved far easier with Map.keySet, which returns a set of keys backed by the original map. When we remove keys from the key set, they are also removed from the backing map:
public static <K, V> Map<K, V> whitelist(Map<K, V> map, K… allowedKeys) {
Map<K, V> copy = new HashMap<>(map);
copy.keySet().retainAll(asList(allowedKeys));
return copy;
}
retainAll writes through to the backing map, and allows us to easily implement something that would otherwise require iterating over the entries in the input map, comparing them against allowedKey, etcetera.
Note that it is important to consult the documentation of the backing collection to see which modifications will successfully write through. In the example above, map.keySet().add(value) would fail, because we cannot add a key to the backing map without a value.
Do you have IT recruitment needs?
The main distinction between fail-fast and fail-safe iterators is whether or not the collection can be modified while it is being iterated. Fail-safe iterators allow this, fail-fast iterators do not
In Java, each thread has its own stack, including its own copy of variables it can access. When the thread is created, it copies the value of all accessible variables into its own stack. The volatile keyword basically says to the JVM “Warning, this variable may be modified in another Thread”.
In all versions of Java, the volatile keyword guarantees global ordering on reads and writes to a variable. This implies that every thread accessing a volatile field will read the variable’s current value instead of (potentially) using a cached value. In Java 5 or later, volatile reads and writes establish a happens-before relationship, much like acquiring and releasing a mutex.
Using volatile may be faster than a lock, but it will not work in some situations. The range of situations in which volatile is effective was expanded in Java 5; in particular, double-checked locking now works correctly. The volatile keyword is also useful for 64-bit types like long and double since they are written in two operations. Without the “volatile” keyword you risk stale or invalid values.
One common example for using volatile is for a flag to terminate a thread. If you have started a thread, and you want to be able to safely interrupt it from a different thread, you can have the thread periodically check a flag (i.e., to stop it, set the flag to true). By making the flag volatile, you can ensure that the thread that is checking its value will see that it has been set to true without even having to use a synchronized block. For example:
public class Foo extends Thread {
private volatile boolean close = false;
public void run() {
while(!close) {
// do work
}
}
public void close() {
close = true;
// interrupt here if needed
}
}
Oracle has been releasing a new Java version every six months since 2017. The latest version, Java 14, was released on 17 March 2020 and it introduced 16 JEPs (JDK Enhancement Proposals). You can quickly get acquainted with the most interesting ones.
About changes in previous releases, you can read on the official Oracle documentation page.
Scala’s complex features promote better coding and improved performance. Functions, macros, and tuples are just a few of the advancements Scala offers. It incorporates functional and object-oriented programming into a powerful language.
Developers, and those who hire them, need to take advantage of Scala’s strengths as a language to fully appreciate the functionality it offers. The language was developed to remove the restrictiveness of Java, offering a well-organized and cleaner language.
Building complex applications is inherently difficult. A monolithic architecture better suits simple, lightweight applications. It is important to understand monolithic architecture since it is the basis for microservices architecture where each service by itself is implemented according to monolithic architecture.
The microservice pattern is a better choice for complex, evolving applications. This approach focuses on handling a complex system, but in order to do so, it introduces its own set of complexities and implementation challenges.
Overall, it is a good practice to divide the application into microservices, but it obviously takes more engineering work to do so. That is why many startups build their MVP as a monolith.
Overall, it is a good practice to divide the application into microservices, but on the flip side, it obviously takes more engineering work to do so. That is why many startups build their MVP as a monolith.
Java developers have access to a wide range of open-source big data tools: Apache Hadoop, Apache Spark and many more. Most Java engineers can easily take on a new big data tool since it is like learning a new API, plus some of the core modules of these tools are written in Java, or in Scala.
You can find out more about Big Data in Financial Services and get acquainted with the basic terms related to Big Data and Data Analytics in our other blog posts.
If possible, try to use tools and approaches such as Docker, infrastructure-as-a-code (Kubernetes, Terraform), and continuous integration in your projects. By 2022 the DevOps market will reach $6.6 billion, so it is fair to say that new practices and modern technologies will shape the tech market. Are you eager to have faster and more efficient deployments? If so, applying automation should be at the top of your list.
We know that everyone holds Java 7 or 8 dear to their hearts, but now is time to move to the newest version. Oracle no longer supports Java 8, so it is up to you to download and install newly added features and encourage your team to take this step now. Each update has many features and enhancements that you could use in your project.
When updating an old application, it is good to consider careful gradual updates reinforced by extensive automated and manual system testing. This includes the components, core features, and interconnected applications.
It is best to update as soon as possible (i.e., now) for systems running on Java 8 or older, and most especially with way older Java systems — we have recently worked on a corporate project that still uses Java 4(!).
Updating it will, for sure, be a challenge, and you will need engineers of the highest caliber, but nothing that a good hiring, planning, and implementation will not solve.
The longer you wait, the worse it will get, so take action now.
It is crucial that the documentation is ready from Day 1 and is regularly updated. The documents should contain all the necessary information to facilitate software analysis and the possible implementation of new employees.
And even later on, when the system is being integrated with other modules, or APIs (either external or internal), the process should be also well-documented. It is not a separate application anymore, but rather a live ecosystem of IT solutions that coexist and communicate together. Think, 5 years from now, how much more expensive and difficult would it be to make any changes, if we don’t take action and document the changes now.
Avoid swallowing the exceptions. The stack trace is the most valuable troubleshooting information. In the production system, where the priority is to bring the system up and then find the root cause, these exceptions are gold, as, without them, you will never be able to find what happened with your application at that moment. On the other hand, do not print the stack trace multiple times. Printing a stack trace is a resource-intensive process and should be controlled i.e. you print more information while running on DEBUG or INFO mode and only print essential information while running in PRODUCTION mode.
This is one of the most common reasons for production issues in the last decade. Make sure you always close the database connection, so that it is released back to the pool. This is also one of the JDBC best practices. A common mistake is not closing the connection in the finally block of a try catch. If there is a connection pool leak, your connection pool will be exhausted soon and your user will experience immediate slowness.
Notably, what you should not do in your project is to use a production database for system testing – that should leverage mocks. Funny enough, some time ago we contracted for an investment bank that did just that. As a result, the tests were very resource consuming, were making an impact on the performance of the production system, and their coverage was tiny (supposedly as a tradeoff for performance). That is something that should be avoided.
This is one of the common mistakes made by beginners and intermediate Java programmers who do not know about paging or pagination. You simply cannot load every record e.g. order or trade from the database in one call. In some cases, obviously, you will run out of memory and it is also a waste of network bandwidth, CPU and memory as the user might not need all of those data. Secondly, you just cannot keep the data in your application forever because it may become stale hence you need to load it again.
So, instead of loading all records in one go, implement some sort of pagination or lazy loading so that you do not have to load everything in the beginning.
There is hardly a code where something is not hard-coded – especially when there is time pressure in the project or tight budget restrictions – yet doing so to values such as URLs, directory locations, usernames/passwords, cache sizes, log levels, etc in the code results in a product that is hard to maintain, not portable, and hard to customize. Instead of hard-coding configuration parameters, you must externalize them in a property file – YAML format is one of the popular choices. It is not only easily parsable by the machine, but also clearly legible for a human being (even if not technical).
Even though Java is platform-independent, if you are not careful you could end up making your Java application platform dependent. Programmers should not code anything that is related to the local operating system, but rather aim to abstract away things making them portable, more universal and much more maintainable.
Packaging utility jar files in several places, especially various versions of the same utility jar in various locations is the cause of many production issues. You must have a clean build and versioning processing, especially for internal applications. Consider using Maven for dependency management, it makes life a lot easier than keeping versioned JAR files in the lib folder.
These small things can make a big difference when it comes to developing and maintaining a real-world Java application. Paying attention to these details will help you proceed forward with your project more strongly. A good Java architect will ensure that the application is both easy to maintain and support.
Effectively hiring freelance Java developer is not a walk in the park. It requires you to devote a lot of time and effort to find the best candidates from a vast pool of talent. We hope that the above guidelines will help you streamline the entire process so that you end up with only exceptional minds working for you. Also, you can check our other article about Java development in German.
Frequently asked questions (FAQ)
DevsData – a premium technology partner
DevsData is a boutique tech recruitment and software agency. Develop your software project with veteran engineers or scale up an in-house tech team with developers with relevant industry experience.
Free consultation with a software expert
🎧 Schedule a meeting
“DevsData LLC is truly exceptional – their backend developers are some of the best I’ve ever worked with.”
Nicholas Johnson
Mentor at YC,
Ex-Tesla engineer,
Serial entrepreneur
Categories: Big data, data analytics | Software and technology | IT recruitment blog | IT in Poland | Content hub (blog)
general@devsdata.com
“I interviewed about a dozen different firms. DevsData LLC is truly exceptional – their backend developers are some of the best I’ve ever worked with. I’ve worked with a lot of very well-qualified developers, locally in San Francisco, and remotely, so that is not a compliment I offer lightly. I appreciate their depth of knowledge and their ability to get things done quickly. “
Nicholas Johnson
CEO of Orange Charger LLC,
Ex-Tesla Engineer,
Mentor at YCombinator