Pass variable vs access class field - java

I have got a question regarding program style. Within a class, is it better to pass a variable to a method or to access the field inside a method?
public class NumberTest{
private int num;
public NumberTest (int num){
this.num = num;
calculateX(num);
calculateY();
}
private void calculateX(int num){
System.out.println (num);
}
private void calculateY(){
System.out.println(num)
}
}

I'll differ from the others here...
Where it is at all reasonable, I like to pass in the argument. This very slightly decouples the method from the class implementation, and makes it easier to unit test. For example, sometimes it is a pretty complex process to set this.num to 94404 due to other constraints.
e.g. this is a Zip Code but your business logic requires that it must match the State and Country field. Or, in practice this field is read from a Database, a Web Site, etc...
If you pass the argument, your unit test can shortcut and just pass in the value. And, in the off chance you might have a future special case where you don't want to use what's in the class field, you can do it.
Now, if you are using 27 class fields, you obviously don't want to pass in 27 arguments. But, IMO, if it's 1 or 2, I like to pass them in.
Minor Noted added after acceptance:
There is another possible difference between passing in the arg and using a field. In a multi-threaded environment, using a passed in argument may be safer that reading from a field. The field might get changed in the middle of the function, while a passed in argument, depending on type and usage, is less likely to change. In this example, a passed in int num will never change unexpectedly, but this.num might.

You're already passing the object (as this) when you call a member function anyway. You don't gain anything from having to explicitly specify the argument too, unless you need to be able to use that same function with values other than this.num.
Short version: Use the latter, unless you need to calculateX(some_whole_other_number).

those methods might look kinda similar to you, since they give you the same result, but they're actually very very different from each-other.
For instance, suppose your NumberText method looked like
public NumberTest (int num){
this.num = num;
calculateX(num * 2);
calculateY();
}
calculateX wouldn't actually take the field, but it can take something completely different.
A general rule of thumb is
If it makes sense to pass in something other than num to calculateX than you probably should pass it in. otherwise, don't
also, if you do this
private void calculateX(int num){
System.out.println (num);
}
change the parameter name to something other than num

Is num some state of NumberTest? Will you need it later? If so, make it a field.
Does NumberTest just provide function calculateX for many nums? If so make calculateX static.

Related

How to name a variable that is a copy of a parameter?

I have a method that will process a Collection<Nodes> that is passed in as a parameter. This Collection will be modified, therefore I thought it would be good to first make a copy of it. How do I name the parameter and local variable, e.g. nodes in the example below?
List<Nodes> process(Collection<Nodes> nodes) {
List<Nodes> nodes2 = new ArrayList<>(nodes);
...
}
As another example consider the following where the variable is an int parsed from a String parameter:
public void processUser(final String userId) {
final int userId2 = Integer.parseInt(userId);
...
A good approach to the name variables problem is to use names that suggest the actual meaning of the variable. In your example, you are using names that do not say anything about the method functionality or variables meaning, that's why it is hard to pick a name.
There are many cases like yours in the JDK, e.g. Arrays#copyOf:
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
#SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
In this case they call the parameter original and the local variable copy which perfectly expresses that the returned value is a copy of the parameter. Precisely, copying is what this method does and it is named accordingly.
Using the same reasoning for your case (consider refactoring to give more meaningful names to your method and variables) I would name your local copy of nodes something like processedNodes, to express what that variable is and to be consistent with your method's name.
Edit:
The name of the new method you added in your edit does not provide hints about what it does either. I'll assume that it modifies some properties (maybe in a database) of the user whose id is passed via parameter.
If that is the case (or similar), I think that an appropriate approach you
could apply would be that every method should have a single responsibility. According to your method's name it should process the user, for that you need an int userId. The responsibility of parsing an String userId should be out of the scope of this method.
Using the proposed approach has, among others, the following advantages:
Your class won't change if you have to add additional validation to your input.
Your class won't be responsible for handling NumberFormatException which must be the application responsibility.
Your processUser method won't change if you have to handle different types of inputs (e.g. float userId).
It ultimately comes down to what you want to communicate to future programmers. The computer obviously doesn't care; it's other people you're talking to. So the biggest factor is going to be what those people need to know:
What is the logical (abstract, conceptual) meaning of this variable?
What aspects of how this variable is used could be confusing to programmers?
What are the most important things about this variable?
Looking at your first example, it's kind of hard to understand enough about your program to really choose a good name. The method is called process; but methods generally speaking implement computational processes, so this name really doesn't tell me anything at all. What are you processing? What is the process? Who are you processing it for, and why? Knowing what the method does, and the class it's in, will help to inform your variable name.
Let's add some assumptions. Let's say you're building an application that locates Wi-fi access points in a building. The Node in question is a wireless node, with subclasses Repeater, AccessPoint, and Client. Let's also say it's an online-processed dataset, so the collection of nodes given may change at any time in response to a background thread receiving updates in what nodes are currently visible. Your reason for copying the collection at the head of the method is to isolate yourself from those changes for the duration of local processing. Finally, let's assume that your method is sorting the nodes by ping time (explaining why the method takes a generic Collection but returns the more specific List type).
Now that we better understand your system, let's use that understanding to choose some names that communicate the logical intention of your system to future developers:
class NetworkScanner {
List<Node> sortByPingTime(Collection<Node> networkNodes) {
final ArrayList<Node> unsortedSnapshot;
synchronized(networkNodes) {
unsortedSnapshot = new ArrayList<>(networkNodes);
}
return Utils.sort(unsortedSnapshot, (x,y) -> x.ping < y.ping);
}
}
So the method is sortByPingTime to define what it does; the argument is networkNodes to describe what kind of node we're looking at. And the variable is called unsortedSnapshot to express two things about it that aren't visible just by reading the code:
It's a snapshot of something (implying that the original is somehow volatile); and
It has no order that matters to us (suggesting that it might have, by the time we're done with it).
We could put nodes in there, but that's immediately visible from the input argument. We could also call this snapshotToSort but that's visible in the fact that we hand it off to a sort routine immediately below.
This example remains kind of contrived. The method is really too short for the variable name to matter much. In real life I'd probably just call it out, because picking a good name would take longer than anyone will ever waste figuring out how this method works.
Other related notes:
Naming is inherently a bit subjective. My name will never work for everyone, especially when multiple human languages are taken into account.
I find that the best name is often no name at all. If I can get away with making something anonymous, I will--this minimizes the risk of the variable being reused, and reduces symbols in IDE 'find' boxes. Generally this also pushes me to write tighter, more functional code, which I view as a good thing.
Some people like to include the variable's type in its name; I've always found that a bit odd because the type is generally immediately obvious, and the compiler will usually catch me if I get it wrong anyway.
"Keep it Simple" is in full force here, as everywhere. Most of the time your variable name will not help someone avoid future work. My rule of thumb is, name it something dumb, and if I ever end up scratching my head about what something means, choose that occasion to name it something good.
I used to give names, which reflect and emphasize the major things. So a potential reader (including myself after a couple of months) can get immediately, what is done inside the method just by its signature.
The API in discussion receives an input , does some processing and returns the output. These are the three main things here.
If it is not important, what processing is done and what is the type of input, the most generic is this form:
List<Nodes> process(Collection<Nodes> input) {
List<Nodes> output = new ArrayList<>(input);
...
}
and
public void process(final String input) {
final int output = Integer.parseInt(input);
...
If it is important to provide more information about processing and type of an input, names like: processCollection, inputCollection and processUser, inputUserId are more appropriate, but the local variable is still the output - it is clear and self-explained name:
List<Nodes> processCollection(Collection<Nodes> inputCollection) {
List<Nodes> output = new ArrayList<>(inputCollection);
...
}
and
public void processUser(final String inputUserId) {
final int output = Integer.parseInt(inputUserId);
...
It depends on the use case and sometimes it is even more appropriate to elaborate the processing, which is done: asArray or asFilteredArray etc instead of processCollection.
Someone may prefer the source-destination terminology to the input-output - I do not see the major difference between them. If this serves telling the method story with its title, it is good enough.
It depends on what you are going to do with the local variable.
For example in the first example it seems that is likely that variable nodes2 will actually be the value returned in the end. My advice is then to simply call it result or output.
In the second example... is less clear what you may want to achieve... I guess that userIdAsInt should be fine for the local. However if an int is always expected here and you still want to keep the parameter as a String (Perhaps you want to push that validation out of the method) I think it is more appropriate to make the local variable userId and the parameter userIdAsString or userIdString which hints that String, although accepted here, is not the canonic representation of an userId which is an int.
For sure it depends on the actual context. I would not use approaches from other programming languages such as _ which is good for instance for naming bash scripts, IMO my is also not a good choice - it looks like a piece of code copied from tutorial (at least in Java).
The most simple solution is to name method parameter nodesParam or nodesBackup and then you can simply go with nodes as a copy or to be more specific you can call it nodesCopy.
Anyway, your method process has some tasks to do and maybe it is not the best place for making copies of the nodes list. You can make a copy in the place where you invoke the method, then you can simply use nodes as a name of your object:
List<Nodes> process(Collection<Nodes> nodes) {
// do amazing things here
// ...
}
// ...
process(new ArrayList<>(nodes))
// ...
Just my guess, you have got a collection and you want to keep the original version and modify the copy, maybe a real solution for you is to use java.util.stream.Stream.
Simply put, when naming the variable, I consider a few things.
How is the copy created? (Is it converted from one type to another?...)
What am I going to do with the variable?
Is the name short, but/and meaningful?
Considering the same examples you have provided in the question, I will name variables like this:
List<Nodes> process(Collection<Nodes> nodes) {
List<Nodes> nodesCopy = new ArrayList<>(nodes);
...
}
This is probably just a copy of the collection, hence the name nodesCopy. Meaningful and short. If you use nodesList, that can mean it is not just a Collection; but also a List (more specific).
public void processUser(final String userId) {
final int userIdInt = Integer.parseInt(userId);
...
The String userId is parsed and the result is an integer (int)! It is not just a copy. To emphasize this, I would name this as userIdInt.
It is better not to use an underscore _, because it often indicates instance variables. And the my prefix: not much of a meaning there, and it is nooby (local will do better).
When it comes to method parameter naming conventions, if the thing a method parameter represents will not be represented by any other variable, use a method parameter name that makes it very clear what that method parameter is in the context of the method body. For example, primaryTelephoneNumber may be an acceptable method parameter name in a JavaBean setter method.
If there are multiple representations of a thing in a method context (including method parameters and local variables), use names that make it clear to humans what that thing is and how it should be used. For example, providedPrimaryTelephoneNumber, requestedPrimaryTelephoneNumber, dirtyPrimaryTelephoneNumber might be used for the method parameter name and parsedPrimaryTelephoneNumber, cleanPrimaryTelephoneNumber, massagedPrimaryTelephoneNumber might be used for the local variable name in a method that persists a user-provided primary telephone number.
The main objective is to use names that make it clear to humans reading the source code today and tomorrow as to what things are. Avoid names like var1, var2, a, b, etc.; these names add extra effort and complexity in reading and understanding the source code.
Don't get too caught up in using long method parameter names or local variable names; the source code is for human readability and when the class is compiled method parameter names and local variable names are irrelevant to the machine.

Why do we need parameter(s) in a method(if it involves giving parameter), I mean what does a parameter do?

When we say
public static void task(int number)
{
(you can give any example)
}
what is the function of parameter there ? I understand that when we give task.subtring(0,5) here the parameters are telling us the place value of the character. How does it work in "int"..
If you are confused about the general idea of parameters, they are a message you pass to a method. Think of a method or a function for that matter as a labeled block of code the you can execute somewhere else using that label. Now, parameters are a way of giving a different input to that block of code. They are variables that get used inside that block of code and that you can set from outside of it by passing in a different value when you use that label. For example, I can pass an int (integer number) to a method that multiplies it by 2 and returns the result:
int multiplyBy2(int number){
return number*2;}
Now, I can pass different numbers into that method and get different outputs. What could be confusing about that method you've shown is that it doesn't return a value and can't access class fields, so it might seem useless. However, that method can be doing a lot of other stuff with that integer. A few examples: the method can be printing some string to the screen that changes based on the integer, it could be writing to a file, it could be modifying static fields, and many other possible tasks.
In the example you posted you would pass in the value of a single int; maybe to get a single character, maybe to read a specific line from a file; anything that needs that single int. In the example you understand there are two int parameters.
Your question is for the idea of parameters at all, aren't you? Parameters make methods more dynamic. for example you want to add a number to an existing int in an object. you will do it in this way (it is only a part of a class):
int all;
....
public void add(int i){
all += i;
}

getter method vs directly using input param

I have come across this code (simplified of course) in the project I have been assigned to.
Method Option 1
public myType getSomething(final int pTeamId) {
this.teamId = pTeamId;
final ClassABC classABC = new ClassABC(pTeamId);
...
return myType;
}
Notice how the input parameter pTeamId is being assigned to the private data member teamId in the first line of the method. Please note that there are getter and setter methods for this teamId data member (Which I have not bothered to include for simplicity's sake. Just know they are a standard getter/setter pair).
So I suppose I could write this method differently where I call the getter of the data member I just set instead of using the input parameter passed in directly as in Method Option 1:
Method Option 2
public myType getSomething(final int pTeamId) {
this.teamId = pTeamId;
final ClassABC classABC = new ClassABC(this.getTeamId());
...
return myType;
}
I realize this question may seem trivial and/or stupid to some, but I am encountering this situation frequently in a large code base I am modifying, so I am curious about which is the "correct" way to approach this, Method option 1 or Method option 2.
I came across this thread, but it targets JavaScript: speed of getter function vs direct access
My first inclination is to use Method Option 1, but I really do not have a good reason why, besides that "it looks faster...".
Can someone else provide a better reason(s)?
Specifically,
1) Is there is a proper/preferred convention/technique/practice in this scenario?
and
2) WHY is one option better than the other? Are they equal? Are there performance issues? etc.
Are there questions I am not asking? (or is this all an over-analysis)?
Any insight would be appreciated.
The getter could have logic in it like not returning null but an empty string instead.
same with the setter.
when you manipulate the variable directly you don't execute that logic.
this can also be a problem if someone overrides the getter and setter logic. (you can forbidd this by making them final) but this is not a common doing! (i would go one step further and call it an anti-pattern)
i would suggest always calling the getters/setters. and there is no real performance loss

Programming conventions in java

I have a simple question about one aspect about so called programming conventions in java.
Simply - if I pass a local variable in one method to a another (helper) method - should I keep the name of it to 100 percent or try to rename it slightly?
Look at the example - should I rename the variable totalAmount in the helpermethods signature to something similar (for instance total_amount or theTotalAmount)?
private void myMethod() {
int totalAmount = 0;
// calculations where totalAmount is involved.
myHelperMethod(totalAmount); // send totalAmount to a another method.
}
private void myHelperMethod(int totalAmount) {
// use totalAmount here .....
}
There's absolutely no obligation to keep the same variable name.
Just choose a name that fits the local context.
In your example, your myHelperMethod could potentially receive any amount as a parameter, not necessarily a totalAmount. Let's just name it amount, or anything else that describes its actual role in this method.
No, you need not. Its like pouring water from one glass to another, the value(water) will remain the same, the glass(holder) will change.
Even in cases when the call is a variable-for-variable (it could be expression-for-variable) the two names represent conceptually different things, so you should not be naming them the same unless they really mean the same thing.
Formal parameters represent variables with names meaningful inside the function, while variables that you pass represent variables with names meaningful outside the function. Here is an example:
// Function definition
static double computeDiscount(double originalPrice, double discountPercentage, double cap) {
...
}
// Function calls
double priceClothing = computeDiscount(clothingOrigPrice, discountPercentage, clothingDiscountCap);
double priceAccessories = computeDiscount(accessoriesOrigPrice, discountPercentage, accessoriesDiscountCap);
It's your choice to decide about the names. Conventions don't tell what name you should keep. Use names which reflects the entity the best. And also avoid using the confusing names. In your case if both the 'totalAmount' are actually representing the totalAmount, then you made the right choice. If not, then reconsider changing the names.

How do I pass a primitive data type by reference?

How can I pass a primitive type by reference in java? For instance, how do I make an int passed to a method modifiable?
There isn't a way to pass a primitive directly by reference in Java.
A workaround is to instead pass a reference to an instance of a wrapper class, which then contains the primitive as a member field. Such a wrapper class could be extremely simple to write for yourself:
public class IntRef { public int value; }
But how about some pre-built wrapper classes, so we don't have to write our own? OK:
The Apache commons-lang Mutable* classes:
Advantages: Good performance for single threaded use. Completeness.
Disadvantages: Introduces a third-party library dependency. No built-in concurrency controls.
Representative classes: MutableBoolean, MutableByte, MutableDouble, MutableFloat, MutableInt, MutableLong, MutableObject, MutableShort.
The java.util.concurrent.atomic Atomic* classes:
Advantages: Part of the standard Java (1.5+) API. Built-in concurrency controls.
Disadvantages: Small performance hit when used in a single-threaded setting. Missing direct support for some datatypes, e.g. there is no AtomicShort.
Representative classes: AtomicBoolean, AtomicInteger, AtomicLong, and AtomicReference.
Note: As user ColinD shows in his answer, AtomicReference can be used to approximate some of the missing classes, e.g. AtomicShort.
Length 1 primitive array
OscarRyz's answer demonstrates using a length 1 array to "wrap" a primitive value.
Advantages: Quick to write. Performant. No 3rd party library necessary.
Disadvantages: A little dirty. No built-in concurrency controls. Results in code that does not (clearly) self-document: is the array in the method signature there so I can pass multiple values? Or is it here as scaffolding for pass-by-reference emulation?
Also see
The answers to StackOverflow question "Mutable boolean field in Java".
My Opinion
In Java, you should strive to use the above approaches sparingly or not at all. In C it is common to use a function's return value to relay a status code (SUCCESS/FAILURE), while a function's actual output is relayed via one or more out-parameters. In Java, it is best to use Exceptions instead of return codes. This frees up method return values to be used for carrying the actual method output -- a design pattern which most Java programmers find to be more natural than out-parameters.
Nothing in java is passed by reference. It's all passed by value.
Edit: Both primitives and object types are passed by value. You can never alter the passed value/reference and expect the originating value/reference to change. Example:
String a;
int b;
doSomething(a, b);
...
public void doSomething(String myA, int myB) {
// whatever I do to "myA" and "myB" here will never ever ever change
// the "a" and "b"
}
The only way to get around this hurdle, regardless of it being a primitive or reference, is to pass a container object, or use the return value.
With a holder:
private class MyStringHolder {
String a;
MyStringHolder(String a) {
this.a = a;
}
}
MyStringHolder holdA = new MyStringHolder("something");
public void doSomething(MyStringHolder holder) {
// alter holder.a here and it changes.
}
With return value
int b = 42;
b = doSomething(b);
public int doSomething(int b) {
return b + 1;
}
Pass an AtomicInteger, AtomicBoolean, etc. instead. There isn't one for every primitive type, but you can use, say, an AtomicReference<Short> if necessary too.
Do note: there should very rarely be a need to do something like this in Java. When you want to do it, I'd recommend rethinking what you're trying to do and seeing if you can't do it some other way (using a method that returns an int, say... what exactly the best thing to do is will vary from situation to situation).
That's not possible in Java, as an alternative you can wrap it in a single element array.
void demo() {
int [] a = { 0 };
increment ( a )
}
void increment( int [] v ) {
v[0]++;
}
But there are always better options.
You can't. But you can return an integer which is a modified value
int i = 0;
i = doSomething(i);
If you are passing in more than one you may wish to create a Data Transfer Object (a class specifically to contain a set of variables which can be passed to classes).
Pass an object that has that value as a field.
That's not possible in Java
One option is to use classes like java.lang.Integer, then you're not passing a primitive at all.
On the other hand, you can just use code like:
int a = 5;
a = func(a);
and have func return the modified value.

Categories

Resources