Freelance Java Developer

Tips for hiring Java Developer and a hands-on guide to Java 14

freelance java2

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.

Battle-tested hiring tips that will help you find the best freelance Java developer

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:

Look for experience relevant to your needs

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.

Check references and testimonials

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.

Seek an expert’s experience

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.”
Freelance Java DeveloperExperienced freelance developers are bound to have feedback from previous clients or even testimonials from fellow developers.

Have a short tech talk

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.

Test their skills and brainpower

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.
freelance javaDetermine his level of interest in the industry through this talk because their passion for learning speaks a lot about his capabilities as well.

Challenging Java questions you may ask during an interview

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.

ArrayList, LinkedList, and Vector are all implementations of the List interface. Which of them is most efficient for adding and removing elements from the list? Explain your answer, including any other alternatives you may be aware of.

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.

Is it more secure to store sensitive data (such as a password, social security number, etc.) in a character array rather than in a String? Why or why not?

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.

What does it mean for a collection to be “backed by” another? Give an example of when this property is useful.

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.
freelance java developerDo not forget to evaluate the quality of work that the freelancer dished out during the exams. Analyze his degree of creativity and approach towards the situation.

Describe and compare fail-fast and fail-safe iterators. Give examples.

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

  • Fail-fast iterators operate directly on the collection itself. During iteration, fail-fast iterators fail as soon as they realize that the collection has been modified (i.e., upon realizing that a member has been added, modified, or removed) and will throw a ConcurrentModificationException. Some examples include ArrayList, HashSet, and HashMap (most JDK1.4 collections are implemented to be fail-fast).
  • Fail-safe iterates operate on a cloned copy of the collection and therefore do not throw an exception if the collection is modified during iteration. Examples would include iterators returned by ConcurrentHashMap or CopyOnWriteArrayList

What is the volatile keyword? How and why would you use it?

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

}

}

DevsData provides engineers of the highest caliber
Contact us

Java trends for 2020 and beyond

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.

Java 14 – changes

  • Switch is extended so it can be used as either a statement or an expression so that both forms can use either traditional case … : labels (with fall through) or new case … -> labels (with no fall through), with a further new statement for yielding value from a switch expression.
  • G1 is enhanced to improve allocation performance on non-uniform memory access (NUMA) memory systems.
  • JDK Flight Recorder data is now available as a data stream allowing for continuous monitoring.
  • New JDK-specific file mapping modes have been added so that the FileChannel API can be used to create MappedByteBuffer instances that refer to non-volatile (NVM) memory.
  • Allows currencies to be formatted with locale-specific accounting formats, for example, ($3.27) instead of -$3.27
  • Enhanced com.sun.management.OperatingSystemMXBean to ensure that it reports values based on the current operating environment, such as a container environment. The MXBean for tools to get information on the operating system has been improved for container environments.

About changes in previous releases, you can read on the official Oracle documentation page.

Scala

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.

Microservice architecture vs monolith

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.

Hadoop, Spark and Big Data ecosystem – development of custom Big Data solutions

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.

Keeping Up with DevOps

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.

Update your Java 7 application, sooner than later

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.

Tips for maintaining an old, production Java application

Keep your documentation up to date

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.

Do not swallow exceptions

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.

Close Database Connections

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.

Avoid loading large result sets from the database

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.

Avoid hard coding Configuration Parameters

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).

Do not write platform-specific code

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.

Avoid packing multiple versions of same JAR files

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.

Tips for Java application maintenance – summary

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.

Conclusions

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.

DevsData – a premium technology partner

DevsData is a boutique software and recruitment agency. Get your software project done by Google-level engineers or scale up an in-house tech team with developers with experience relevant to your industry.

Free consultation with a software expert

Contact Us

Online Reviews

DevsData LLC is truly exceptional – their backend developers are some of the best I’ve ever worked with.”

Nicholas Johnson

MENTOR AT YC,
SERIAL ENTREPRENEUR

Got a project idea?

Let's have a call to:

Got a project idea?

Quote mark

Best back-end engineers I've ever worked with.​

“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. Their depth of knowledge and their ability to get things done quickly."

Nicholas Johnson

CEO OF ORANGE CHARGER LLC;

MENTOR AT YCOMBINATOR

Success

Thank you


We'll get back to you within 1 bussiness day.