2
\$\begingroup\$

I'm learning Java JDK 1.8 since one day and I'm using Java's methods to the first time. I have never used Java before because I'm a Python/Django developer.

I created a method which let to get energy in function of two parameters: mass and light speed. I would like to know if my method is well-written or if I made some mistakes about method, call, etc.

import java.util.Scanner;

public class methodes {

    public static double Energie(double m, double c)
      {
       return (double) (m*Math.pow(c, 2));
      }

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int C = 300000 ;
        double m ;

        System.out.println("Valeur de la masse en kg : ");
        m = sc.nextDouble();

        double E = Energie(m,C);
        System.out.println("Pour " + m + " kg donné, l'énergie équivaut à " + E + " Joules");

    }

}
\$\endgroup\$
  • 1
    \$\begingroup\$ When you run it, does it work as it should? Why are you using Java 1.5 when the latest version is Java 1.8 ? \$\endgroup\$ – Simon Forsberg Apr 13 '17 at 8:54
  • \$\begingroup\$ Yes it seems to work pretty well. It's Java 1.8 yes not 1.5. My questions are : Is the script well-written ? Is it possible to get a script more simple than mine ? \$\endgroup\$ – Essex Apr 13 '17 at 8:58
  • 3
    \$\begingroup\$ If you are expressing the answer in Joules, the SI unit of Energy, why are you setting the speed of light as 300000 km per second and not 300000000 m per second. I believe you won't get the correct answer. \$\endgroup\$ – TheRandomGuy Apr 13 '17 at 13:14
  • \$\begingroup\$ Yes, even if I have an Astrophysic degrees, I was focus on Java's syntax ;) \$\endgroup\$ – Essex Apr 13 '17 at 17:38
4
\$\begingroup\$

The implementation looks fine. Only the conventions on capital letters and spacing might be a bit different in the java community.

A class name always starts with a capital letter

public class Methodes

General utility classes are usually called Util but Methodes is fine depending on your own project preference. Especially when you're not native English it might change depending on who you work with, and how well you know the language.

Method names start with a lower case. And the opening { is placed at the same line as the method name

public static double energie(double m, double c) {
    return (double) (m*Math.pow(c, 2));
}

If you really want to place { at the line after the method name that's fine as long as you're consistent. So either do it always, or do it never. (big discussion in general about which is better, the community overal prefers on the same line).

Variables start with a lower case letter and are camel case, constants are written full uppercase and separated with _. Preferably use meaningful names, although m, C and e in this context are already pretty decent.

public class ExampleClass {
    //this is a constant. Since java 7 (?) you can also use _ in numbers to read easier.
    public static final int SPEED_OF_LIGHT = 300_000;

    public static int calculateEnergy(double mass) {
        return (double) (mass*Math.pow(SPEED_OF_LIGHT , 2));
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println("Valeur de la masse en kg : ");
        double mass = sc.nextDouble();

        double energy = calculateEnergy(mass);
        System.out.println("Pour " + mass + " kg donné, l'énergie équivaut à " 
                          + energy + " Joules");
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Thank you so much for your point of view and what is correct or not with Java ! I still have Python habits but I am trying to forget a little Python and just think about Java Syntax. I will take into account your advices ! \$\endgroup\$ – Essex Apr 13 '17 at 12:35
  • \$\begingroup\$ You're welcome. It's probably a good idea to use a popular (and free) IDE like IntelliJ or Eclipse (to name a few, there are others as well). These can propose some code style improvements as well. And even autocorrect most of the style issues with a simple key combination (like ctrl+shift+L in IntelliJ). \$\endgroup\$ – Imus Apr 13 '17 at 14:11
  • \$\begingroup\$ You can find the Java Naming Conventions here: oracle.com/technetwork/java/codeconventions-135099.html \$\endgroup\$ – Timothy Truckle Apr 13 '17 at 17:44
  • \$\begingroup\$ @Deadpool I'd suggest to have a look at Google Conventions as they're much more detailed than those by Sun. They differ a bit, but only in details. \$\endgroup\$ – maaartinus Apr 15 '17 at 6:45
4
\$\begingroup\$

The answer of Imus is good but I'd like to add some points and stress some concepts which are shown in his example but not metioned:

Naming

Conventions

beside the constraints of the Java Naming Conventions (http://www.oracle.com/technetwork/java/codeconventions-135099.html) let method names start with a verb. Variable and class names should classes start with / be nouns. And interface names should be adjectives.

Single letter names

You define a variable with a single letter name C. This name does make sense to you while you're writing this code. But when you read this in 3 month again you may have used the name C in some other programs for some other entity. Then it may not be so easy to get the right meaning of C in this context.

On the other hand there is no penalty for long identifier names. If you use an IDE like eclipse, IntellyJ, JDeveloper or alike you have intelli senses which keeps you from typing existing identifier names youreself when using them.

Therfore you should avoid single letter names and (uncommon) abbreviations. Your variable C should be named speedOfLight.

Physical quantities

Your variable C holds a physical quantity.

Physical quantities consit of value and unit.

There have been lots of accidents cause by the diffent unit coders implied when using a variable. (e.g.: https://en.wikipedia.org/wiki/Mars_Climate_Orbiter#Cause_of_failure)

So always explicitly add the unit of the quantity to you identifiers dealing with physical quantities:

 int speedOfLightInKmPerSecond = 300000;

 public static double calculateEnergy(double massInKg, int speedOfLightInKmPerSecond) {

Of cause this does not guarantee that no one passes a value in the wrong unit but the chances to do it right raise dramatically.

Utility classes

Utility classes are quite common, but I dislike that concept for a couple of reasons.

  • The main reason is that you cannot apply dependency injection to utility classes. That makes the code using them inflexible. When you need a different version of the utility class you have to change every other code in need to using this new version.

    If you use ordinary a class instead and inject an object of it into the using code you can simply subclass the "utility" and inject a subclass object into the using code which does not know if it uses the base class or the subclass (polymorphism).

  • Methods of utility classes cannot be overridden in subclasses, since they are static.

  • Java is an object oriented language. Therefore you are encuraged to use objects and avoiding them feels somewhat strange to me.

  • In java there is (almost) no performance penalty when creating (a few) short living objects. That means performance is no justification for utility classes.

\$\endgroup\$
  • \$\begingroup\$ Great complementary answer :) I only disagree with your reasoning on Utility classes. You make some valid points, but they don't mean to never use utility classes. They only dictate when to use them. That is, if it's a certain helper function that will never change. Things like Math.pow() or Physics.calculateEnergy(...) for example. Dependency injection makes absolutely no sense in this context. Making object is cheap but unnecessary overhead. And java beïng an OO language does not imply everything has to be objects. \$\endgroup\$ – Imus Apr 14 '17 at 7:04
  • \$\begingroup\$ Here is an interesting article about replacing utility classes with OO approach: yegor256.com/2014/05/05/oop-alternative-to-utility-classes.html \$\endgroup\$ – Piotr Aleksander Chmielowski Apr 14 '17 at 12:24
  • \$\begingroup\$ @PiotrAleksanderChmielowski Let me respectfuly disagree entirely with that article. It's always nice if the auther himself later on in a comment explains: "It's terrible performance wise, but that's a bug in Java/C#/Ruby/etc, not in OOP.". \$\endgroup\$ – Imus Apr 15 '17 at 7:49
  • \$\begingroup\$ What do you disagree with? \$\endgroup\$ – Piotr Aleksander Chmielowski Apr 15 '17 at 8:45
  • \$\begingroup\$ @Imus >It's always nice if the auther himself later on in a comment explains: "It's terrible performance wise, but that's a bug in Java/C#/Ruby/etc, not in OOP."< Usually performance problems are not caused by certain programming paradigms but by poor algorithms. Therefore performance related decisions should only be made if the code in question has been proved to be a bottleneck. \$\endgroup\$ – Timothy Truckle Apr 16 '17 at 16:15
0
\$\begingroup\$

Step 1. Decrease the distance between variable usages

Look at these lines:

    Scanner sc = new Scanner(System.in);

    System.out.println("Valeur de la masse en kg : ");
    double mass = sc.nextDouble();

You have to jump from the first to the last line of the snippet to follow sc variable. Try to rewrite it as:

    System.out.println("Valeur de la masse en kg : ");

    Scanner sc = new Scanner(System.in);
    double mass = sc.nextDouble();

Now it is easy to track sc variable. BTW. it is true also for energy.

Step 2. Remove unnecessary variables.

Let's go further:

    System.out.println("Valeur de la masse en kg : ");

    double mass = new Scanner(System.in).nextDouble();

What is the benefit of this transformation? Now we are sure that sc is not used anywhere further in the code. Before it, we had to check it by ourselves.

Step 3. Use constants.

What if we want to track the value of m variable? We have to find its declaration and all value assigments. However this is an easy way to send a message "you don't habe to track the value of m - it won't change" for anyone who read the code:

    final double m = sc.nextDouble();

Moreover, there is one more benefit of this approach! If your intention is to keep m constant, compiler will warn anyone who will try to change its value.

Finally, how I'd design main

(Notice, I've renamed calculateEnergy to energy)

    System.out.println("Valeur de la masse en kg : ");
    final double mass = new Scanner(System.in).nextDouble();

    System.out.println("Pour " + mass + " kg donné, l'énergie équivaut à " 
                      + energy(mass) + " Joules");
\$\endgroup\$
  • \$\begingroup\$ I think someone have a valid reason to downvote the answer, so don't be shy and share the reason with us. \$\endgroup\$ – Piotr Aleksander Chmielowski Apr 15 '17 at 8:48
  • \$\begingroup\$ "I think someone have a valid reason to downvote the answer" I did not downvote but I'm OK with it. The reason is: while your suggestion is good in general in this particular case it is not. IMHO dependency injection is the higher value to preserve. With your suggestion it becomes harder to achieve DI when refactoring that code. \$\endgroup\$ – Timothy Truckle Apr 16 '17 at 16:23
  • \$\begingroup\$ @TimothyTruckle "With your suggestion it becomes harder to achieve DI" - how? \$\endgroup\$ – Piotr Aleksander Chmielowski Apr 17 '17 at 10:43
  • 1
    \$\begingroup\$ "There is a known rule called YAGNI," There are other concepts called separation of concerns and single responsibility and I argue that the instantiation of a dependency it a responsibility of a businesss object. There is also the open closed principle (OCP) which states, that your code should be open for extension but closed to changes (by other code). Those concepts are contradictive to YAGNI and you have to decide which is more important in your eyes. When in doupt I usually choose the others. Since I practice TDD I need DI to replace the dependencies with test doubles anyway... \$\endgroup\$ – Timothy Truckle Apr 19 '17 at 9:05
  • 1
    \$\begingroup\$ @TimothyTruckle I agree 100% with your last comment and it's true that, for example, instantiating a Scanner shall be done outside our class. And for sure it has to be a next step of refactoring. My answer covers one step before and I'm sure, that steps I've proposed are valid, because introduction of DI is not harder when there are no variables! Modern IDEs have extract parameter refactoring option and we don't have to intruduce unnecessary coupling between lines of code just to make future refactoring easier. It will be equally easy without it. \$\endgroup\$ – Piotr Aleksander Chmielowski Apr 22 '17 at 14:35
-1
\$\begingroup\$

Since you are a physicist, you should know the exact value of the speed of light and that 300,000 km/s is way too much. You must use the correct values for constants.

Depending on what you use this speed of light constant for, you may have to take into account that this constant is only valid in vacuum.

\$\endgroup\$
  • 1
    \$\begingroup\$ This site is about code, not about physics. Please edit your answer to provide some coding related value or delete it. \$\endgroup\$ – Timothy Truckle Apr 18 '17 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.