How to show more detailed output when using Gradle?

If you are used to Maven, the number of printed messages/logs might surprise you when you are using Gradle for the first time. With the default settings, Gradle just prints some very minimalistic details of the build. Something like this:

$ gradle clean build

BUILD SUCCESSFUL in 4s
6 actionable tasks: 6 executed

You can add the -i or --info flag to enable INFO level logging, which will contain much more details and should be enough most of time times. Here are the first lines of the output when using the flag:

$ gradle clean build -i
Initialized native services in: C:\Users\Adam_Soltesz\.gradle\native
The client will now receive all logging from the daemon (pid: 1724). The daemon log file: C:\Users\Adam_Soltesz\.gradle\daemon\4.10.2\daemon-1724.out.log
Starting 7th build in daemon [uptime: 1 hrs 36 mins 16.459 secs, performance: 100%]
Using 12 worker leases.
Starting Build
Settings evaluated using settings file 'C:\projects\misc\gradle-spring-boot-example\settings.gradle'.
Projects loaded. Root project using build file 'C:\projects\misc\gradle-spring-boot-example\build.gradle'.
Included projects: [root project 'demo']

> Configure project :
Evaluating root project 'demo' using build file 'C:\projects\misc\gradle-spring-boot-example\build.gradle'.
Applying dependency management to configuration 'annotationProcessor' in project 'demo'
Applying dependency management to configuration 'apiElements' in project 'demo'
Applying dependency management to configuration 'archives' in project 'demo'
Applying dependency management to configuration 'bootArchives' in project 'demo'
Applying dependency management to configuration 'compile' in project 'demo'
Applying dependency management to configuration 'compileClasspath' in project 'demo'
...

If you need even more details, you can use the -d or --debug flag to enable DEBUG level logging.

$ gradle clean build -d
12:56:22.570 [INFO] [org.gradle.internal.nativeintegration.services.NativeServices] Initialized native services in: C:\Users\Adam_Soltesz\.gradle\native
12:56:22.636 [DEBUG] [org.gradle.internal.nativeintegration.services.NativeServices] Native-platform posix files integration is not available. Continuing with fallback.
12:56:22.917 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClient] Executing build a0ae13db-2334-4861-bfa0-c8720c0d71d1 in daemon client {pid=2760}
12:56:23.077 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Software Loopback Interface 1
12:56:23.078 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? true
12:56:23.080 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a multicast interface? true
12:56:23.080 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding loopback address /127.0.0.1
12:56:23.080 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding loopback address /0:0:0:0:0:0:0:1
12:56:23.080 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding loopback multicast interface Software Loopback Interface 1
12:56:23.080 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft 6to4 Adapter
12:56:23.081 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
12:56:23.083 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a multicast interface? true
12:56:23.083 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding loopback multicast interface Microsoft 6to4 Adapter
12:56:23.085 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Hyper-V Virtual Switch Extension Adapter
12:56:23.086 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
12:56:23.088 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a multicast interface? true
12:56:23.088 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding loopback multicast interface Hyper-V Virtual Switch Extension Adapter
12:56:23.088 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (Network Monitor)
...

As you can see, this is usually too detailed, but may come in handy sometimes.

 

How to use the switch statement in JavaScript with logical expressions?

The switch statement in JavaScript is usually used as a way of performing different operations depending on the value of an expression. In the usual case, you specify it in the following way:

var number = 1;

switch (number) {
    case 1:
        console.log("One");
        break;
    case 2:
        console.log("Two");
        break;
    case 3:
        console.log("Three");
        break;
    default:
        console.log("Something else");
}

You can see that you provide the expression in parenthesis after the switch keyword and then the different values after the case keyword.

By only seeing this structure, it might not be obvious how to convert the following code to use a switch statement:

var number = 16;

if (number >= 1 && number <= 5) {
    console.log('Between 1 and 5.');
} else if(number >= 6 && number <= 10) {
    console.log('Between 6 and 10.');
} else if (number >= 11 && number <= 15) {
    console.log('Between 11 and 15.');
} else {
    console.log('Some other number.');
}

The situation is not easy because you are doing different things based on number ranges and not based on single values. One option would be to add a bunch of cases to the switch like this:

var number = 16;

switch (number) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        console.log('Between 1 and 5.');
        break;
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
        console.log('Between 6 and 10.');
        break;
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
        console.log('Between 11 and 15.');
        break;
    default:
        console.log('Some other number.');
}

This can result in a very long code if there are larger numbers at play. Luckily, we have a nice trick which can be used to simplify this:

var number = 55;

switch (true) {
    case number >= 1 && number <= 5:
        console.log('Between 1 and 5.');
        break;
    case number >= 6 && number <= 10:
        console.log('Between 6 and 10.');
        break;
    case number >= 11 && number <= 15:
        console.log('Between 11 and 15.');
        break;
    default:
        console.log('Some other number.');
}

As you can see, we are putting true into the switch parenthesis so a case will match if it evaluates to true. So it is doing the same as the if statement. Some people better like this syntax, some people not. It’s your choice which one you use, although the use of if is more widespread.

Variable in JavaScript has value without specifying it

In JavaScript for certain variable names, a quite confusing situation can happen due to the various scopes present in the language. Let’s start off with some examples where we see the expected outcome and reach some interesting points from there. We have placed all the example code at the root of a JS file (so it is not inside any block).

var firstName = 'John';
var lastName;
console.log(firstName);
console.log(lastName);

The output of this is not surprisingly the following.

John
undefined

The first one contains a string we have specified and the second one prints undefined as we have not specified any value.

What if I declare a variable called “name”, but don’t assign a value to it?

var name;
console.log(name);

Surprisingly, it will contain an empty string. We’ll see why at the end, but until that let’s see another example.

What happens if I assign “John Doe” to the variable, and rerun my program?

var name = 'John doe';
console.log(name);

It will, of course, print “John Doe”. Nothing surprising. But what if I update the code to the following and refresh the page?

var name;
console.log(name);

This is what we see after the refresh:

John Doe

Wow! Our variable has the value we have previously set, although it’s not even in our code anymore.

Explanation

The first surprising outcome happened because the window object has a property called “name”, which contained an empty string. This is what is returned because we were using the “name” variable from the global scope. So what is the window object exactly?

The window object is supported by all browsers. It represents the browser’s window. All global JavaScript objects, functions, and variables automatically become members of the window object. Global variables are properties of the window object.

So, even before one line of our code executed, the “name” global variable already had an empty string as value. That is what we got back.

The other weird outcome is also because of the window object’s “name” property. This property is persisted between page refreshes and it is only cleared when the browser window is closed. This is why it still contained the value we have removed.

The conclusion we can draw here is that besides the JavaScript keywords (e.g. delete, var) that you cannot use for variable names, there are some other names that should not be used because of their unexpected side effects.

Of course, using global variables is not a good idea 99% of the time. But this won’t stop anyone from using them. They are especially common for practice code when we just quickly trying out something, and this is a good opportunity for beginners to have some headaches due to the above issue. So guys, be careful with your variable naming!

What is the DRY principle? Why is it useful to follow?

DRY stands for Don’t Repeat Yourself.

It is a very general principle that everyone should keep in mind when writing software. It means that we should avoid repetitions in our code as much as possible. By repetitions we do not necessarily refer to a set of lines or whole lines, it could just mean a string literal, a number, or any smaller fragment of code.

Let’s see a simple example where we use a short formula to calculate a value.

int result = (pointsInFirstRound + pointsInSecondRound) * bonusMultiplier;

It is possible that this formula will be used in multiple places. In order to follow DRY, you should extract it to a method.

private int calculateResult(int pointsInFirstRound, int pointsInSecondRound, int bonusMultiplier) {
    return (pointsInFirstRound + pointsInSecondRound) * bonusMultiplier;
}

You can call this method any number of times.

Advantages of DRY

Less work

By not repeating code, you have less work to do. If you have a logic that spans 10 lines and you extract it to a method. You will need 1 line instead of 10 lines at every occasion where you use it.

Better maintainability

There is always a chance that your code will need to be changed because a bug is found and you need to fix it or a change request came in. If you have the code in only one place, it’s much easier to modify as you only have to do it once.

Less chance to break the code

If you have to do a change in 10 places, there is a chance that you’ll make a mistake. If the logic is only in 1 place, you have a much higher chance of getting it right.

Better testability

If you extract a piece of code to a well-separated and reusable unit, then unit testing it is easy. You can you test the extracted code and you can mock that logic at every occurrence.

If you have that block of code in several places then you have to take it into account at all of its occurrences. So using DRY makes testing easier.

Better readability

As a result of following DRY, you will have less and better-structured code that is easier to follow.

Disadvantages of DRY

DRY is a great principle to follow but if it is overused it can be a source of issues. If you are trying too hard to make sure that nothing is repeated, it is possible that your code will become too complicated and hard to understand.

You have to weigh the benefits of DRY. Sometimes it’s better to repeat some code if it clearly helps readability a lot.

Soft Skill Interview Questions About Junior Developers in the Team

You are the coach for several juniors developers. What practices do you use to improve them?

The techniques that can be used could differ based on a lot of factors including the experience of the junior or how much time do they have for training, but let’s see some general tips that can be used.

Teach them how to teach themselves

For a junior developer often the biggest roadblock is not knowing where to find the required information. Developers should be already familiar with the use of Google and even know about some commonly used sites like StackOverflow. However, it might not always be obvious how to search for the required information, what keywords to use, which information sources are the best, and which should be avoided. Giving some tips on these topics, helping in some concrete cases can show them the right direction.

Point them in the right direction

In case of a question or issue, don’t always tell them the exact solution, but rather point them into the right direction. Of course, it depends on the deadlines how far you can go with this mindset.

Encourage collaboration

If there are more of them, encourage collaboration between them. Tell them to share their ideas and be ready to help each other whenever needed.

Be available

Because their lack of experience there will be roadblocks where they would be stuck for a long time without outside help. Make sure that you are available as much as possible and let them know when you are busy (e.g. in a meeting).

Be prepared to be interrupted often. Most good leaders can free up time for questions usually immediately or in a few minutes.

Delegate simple questions

Developers have different levels of skills. Each has areas where he is more knowledgeable than others, even if they are junior.  If it is probable that another developer can help out in a question, delegate it to him. This way you save time and encourage collaboration as well.

Project knowledge bases

If they are already on a project, share information about project knowledge bases with them as early as possible. Call their attention to the most useful pages/articles for starting out and also mention what information should be avoided because it’s outdated (this happens in every project…).

Do code reviews regularly

Inexperienced developers can make mistakes that require a big part of the solution to be rewritten. It’s best if these turn out as soon as possible and not after 5 days of work. Do code reviews as often as it makes sense.

Involve everyone in the code reviews

In the beginning, probably you will be the one who is giving the most feedback on their code reviews but make sure that they check each other’s code as well to learn from their mistakes and incorporate new ideas to their code.

Always explain

If they did something the wrong way, always explain to them why is your proposed solution is better, what are the advantages of it. Try not to make comments on code reviews too short. You may understand each other from short sentences with someone you have been working with for a long time, but for a new developer, a more thorough explanation can prevent further questions.

You are the technical lead on a new project and got only junior co-workers. What kind of problems do you see? How do you handle them?

Basically, you can use some of the ideas above to improve their skillset, but here are some sections from the problems perspective.

Missing experience

They will have limited experience, so they will need more time to implement tasks. Make sure you take this into account when estimating the length of the tasks. If you give ample time to implement a good solution and learn in the meantime, their skills will improve rapidly.

Organize knowledge transfer meetings if possible.

Missing domain knowledge

Refer them to good documentation and make sure that they understand what they are working on.

Organize knowledge transfer meetings if possible.

Not understanding client requests

We all know that clients don’t always express themselves clearly. Call the attention of the new guys to always ask if something is not clear in the requirements because wasting time on a different implementation can be hurt the project.

Unfamiliarity with processes

At every project, there are some processes that everyone needs to follow. Like what branching strategy to use, or how to handle tickets (which state means what, etc.). Be sure to collect these processes and give the new colleagues a detailed overview of them as soon as possible. It’s best to have it in written form as well, where they can get a refresher is something is not clear.

Review their code thoroughly

You are responsible for making sure that the code committed is in a good shape. Spend extra time on the code reviews, even try out the functionalities manually if needed. Double check if tests are implemented correctly.

Hitting blockers

Make sure to check regularly how they are progressing. Tell them to ask for help if they are blocked on something.

Going on vacation

If you are going on vacation, there will be no one to provide leadership. In the beginning of the project be sure not to go on longer vacations. Shorter ones are much easier to survive without you. Determine the most fitting person to be your deputy and teach them how to lead the team when you are away.

How can you build a team from just junior developers?

If you absolutely must build a team from just juniors, then check the above problems you can face and how to solve them.

Otherwise, if possible try to do some negotiation with other projects/teams if they are able to substitute a team member with a junior guy and give you a more experienced developer. For a team that is going on for a long period of time, getting one new colleague is not that big of a deal because the existing ones can get him up to speed really fast.