I need your recommendations. which way is the best in terms of software engineering (Readability, Usability )
I have object person
public class Person {
private String name;
private String surname;
public Person(String name, String surname) {
super();
this.name = name;
this.surname = surname;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
I have method savePerson.
First way is to set request parameters to variable before initialise object.
public void handle(Map<String, Object> map, HttpServletRequest request) throws Exception {
String name = request.getParameter("name");
String surname = request.getParameter("surname");
Person person = new Person(name, surname);
personService.savePerson(person);
}
Second way is to set request parameters set them as constructors parameters.
public void handle(Map<String, Object> map, HttpServletRequest request) throws Exception {
Person person = new Person(request.getParameter("name"), request.getParameter("surname"));
personService.savePerson(person);
}
You have to consider that the compiler transforms your operations in a sort of binary version that is a little optimized.
Your second version is less readable but it has only one code line.
The compiler will do it for you, so you can choose your version according to your writing style.
If you have to share your code with other persons, the first method will probably be the best because it is more simple, and in a scenario where the execution efficiency is the same, it can become your discriminant.
The first way is more readable and easy to debug, than the second one. Moreover, if you add other fields in your Person object the second way will be totally messy.
In order to simply even more the code you can use Lombok to avoid writting Getter and Setter for your Person class
First one for sure. It is readable and the instructions are clearly visible. It being basic can be understood by any junior level developer as well so if someone else works on this code, it will be easy for him/her to make the necessary changes.
Always the code that is readable must be used so as to keep the things structured and more manageable.
Related
Consider the below DTO. In SonarQube scan it says the fields name and age are duplicated in getters and setters. Why is this even an issue? Can someone tell me how to fix this, as I have a ton of DTOs with the same issue?
public class Employee {
String name;
int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age= age;
}
public int getAge() {
return age;
}
}
The point is, if you have multiple DTOs that all have the same "name" and "age" property, it would make sense to define a "Person" class with those properties and have Employee extend from that.
In any case, SonarQube issues are just issues. It certainly does not say "it must be removed". You are free to interpret the severity of the problem in your own context. There is no doubt that duplicated code and properties can be a maintenance problem. If you choose to ignore it, that's up to you.
I have always been programming in java, and recently i started learning some c++.
In C++ it is conventional to set setter params as const, why don't we see this as much in java ?
I mean are there any disadvantages to creating a setter like so:
public void setObject(final Object o){ this.o=o; }
vs
public void setObject(Object o){ this.o=o; }
The first one should enforce for Object param o to stay constant through the whole set function, not ?
Edit:
A final param would enforce this NOT to happen :
public void setName(String name){
name="Carlos";
this.name=name;
}
The user will never be able to set the name different from "Carlos"
There's little advantage to setting a Java method parameter as final since it does not stop someone from changing the parameter reference's state within the method. All it prevents is the re-assignment of the parameter variable to something else, which does nothing to the original reference, and it allows for use of the parameter in anonymous inner classes. If you wanted true safety in this situation, you'd strive to make your parameter types immutable if possible.
Edit
You've posted:
public void setObject(Object o){
o++; // this does not compile
this.o=o;
}
Which mixes primitive numeric and reference type. It only makes sense if o is an Integer or other numeric wrapper class, and even so, making it final would not prevent someone from creating:
private void setI(final Integer i) {
this.i = 1 + i;
}
But neither your code nor this code above would affect the parameter object on the calling code side.
Edit
OK now you've posted:
public void setName(String name){
name="Carlos";
this.name=name;
}
But then someone could write
public void setName(final String name){
this.name= name + " Carlos";
}
Here's where the danger comes and where final doesn't help. Say you have a class called Name:
public class Name {
private String lastName;
private String firstName;
public Name(String lastName, String firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
And then a class, Foo, with a Name field and a setter. This is dangerous code:
class Foo {
private Name name;
public void setName(final Name name) {
name.setFirstName("Carlos");
this.name = name;
}
}
Because not only does it change the state of the field, it changes the state of the Name reference in the calling code, and the final modifier won't help one bit. The solution: make Name immutable.
e.g.,
import java.util.Date;
// class should be declared final
public final class BetterName {
private String lastName;
private String firstName;
private Date dateOfBirth;
public BetterName(String lastName, String firstName, Date dob) {
this.lastName = lastName;
this.firstName = firstName;
// make and store a private copy of non-immutable reference types
dateOfBirth = new Date(dob.getTime());
}
// only getters -- no setters
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
public Date getDateOfBirth() {
// return copies of non-immutable fields
return new Date(dateOfBirth.getTime());
}
}
Okay, a final parameter/variable cannot be assigned to. As the java compiler needs to be capable to determine if a variable/parameter is actually final (for anonymous inner classes), optimization is no factor AFAIK.
It is more that C++ has a larger tool set, which java tried to reduce. Hence using C++ const string& is important, saying
The string is passed by pointer, access is automatically dereferenced.
If the actual argument is a variable, the variable itself is not changed.
Mind there might be a conversion operator for passing something else than a const string&.
Now java:
Java does not allocate objects on the stack, only keeps primitive types and object handles on the stack.
Java has not output parameters: a variable passed to a method call will never change its immediate value.
Back to your question:
As a setter in java mostly would not benefit from a final parameter.
A final will be a contract to not use the variable for a second assignment.
However:
public final void setXyz(Xz xyz) {
this.xyz = xyz;
}
is more useful: this method cannot be overriden, and hence may be safely used in a constructor. (Calling an overriden method in a constructor would be in a context of a still not initialized child instance.)
Both methods work, however which is the proper way to do it?
Method one:
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object(String name){
this.name = name;
}
}
Method two:
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//Changed this.name = name to setName(name)
public Object(String name){
setName(name);
}
}
I've searched around but couldn't find an exact question that referred to this. If there is one, free to post the link and I'll remove the question
My first thought was to use the setter in the constructor. So if you want to change how the name is stored, or if you want to add any other behavior while setting the name, you just have to change it once.
But thinking just a bit more on this, I think using direct access to the variable is better if the class is not final and the method is not private. Otherwise someone could extend your, override the method, causing your constructor to call their method with unpredictable behavior.
Rule of thumb: If the class is not final, you should only call private methods in the constructor.
While using a setter in the constructor reduces code duplication, calling overrideable methods (ie non final / non private methods) in a constructor is discouraged - it can lead to weird bugs when extending a class.
Consider the following case (based off of your example):
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//Changed this.name = name to setName(name)
public Object(String name){
setName(name);
}
}
With the following subclass:
public class SubObject extends Object {
private String Id;
#Override
public void setName(String name) {
super.setName(name + Id);
}
public SubObject(String name){
super(name);
this.id = "1";
}
}
Creating an instance of SubObject will cause a null pointer, as setName() is called in the constructor, but the implementation of setName() relies on the Id field having been initialized.
Someone extending a class should not have to go check the source code of the super class to ensure the constructor isn't calling overrideable methods.
If all the setter and constructor do is a simple assignment, it doesn't matter which of the two ways you choose.
However, if you need to perform some validations before assigning the new value to the member, it makes sense to have that logic in a single place, which means calling the setter method from the constructor is the better option.
I would NOT use the setter in the constructor. This because if someone added any other behavior while setting the name in the setter, I'd consider it a collateral effect.
If setName() coontains some inner logic about how the name should be set, then I would choose 2. On the other hand, if setName() contains some aditional code that needs to be run when name is set, i would choose 1.
Let me make a bit more complex situation so I can express my point:
class Person {
private String firstName;
private String lastName;
private boolean wasRenamed;
//getters...
public Person(String fullName) {
???
}
public void setFullName(String fullName) {
???
}
}
Here we have Persons with first and last names, also we want to keep record who was renamed and who not. Let's say fullName contains first and last name separated by space. Now let's look at 2 different approaches you provided in your question:
Not call setFullName() in costructor: This will lead to code duplicity (spliting fullName by space and assigning it to first and last name.
Do call setFullName() in costructor: This will add extra trouble with the wasRenamed flag, since setFullName() has to set this flag. (This could be solved by simply resetting the flag back to false in constructor after calling setFullName(), but let's say we don't want to do that)
So I would go with a combination of 1 and 2, and split the inner logic of setting the name and the additional code that needs to run before/after name is set into different methods:
class Person {
private String firstName;
private String lastName;
private boolean wasRenamed;
//getters...
private void setFullName0(String fullName) {
//split by space and set fields, don't touch wasRenamed flag
}
public Person(String fullName) {
setFullName0(fullName);
}
public void setFullName(String fullName) {
setFullName0(fullName);
wasRenamed = true;
}
}
I am having a doubt with method creations in a class for setting information.
creating separate methods for setting each attribute
class Address{
private String name;
private String city;
public setName(String name) { ... }
public setCity(String name) { ... }
}
creating single method for setting all attributes
class Address{
private String name;
private String city;
public setAddress(String name,String city) { ... }
}
from above two ways which is preferable in memory point of view?
Common practice is to use JavaBean style
class Address {
private String name;
private String city;
public setName(String name){
this.name = name;
}
public String getName() {
return name;
}
public setCity(String city){
this.city = city;
}
public getCity() {
return city;
}
}
Another common practise, which is quite similar to you second approach is to create immutable object. Parameters are passed to constructor instead of big setter method.
class Address {
private final String name;
private final String city;
public Address(String name, String city) {
this.name = name;
this.city = city;
}
public String getName() {
return name;
}
public getCity() {
return city;
}
}
From memory point of view, difference would be that second example is setting all attributes in constructor and all those attributes are immutable. In general, object constructed this way are safer when used by multiple threads.
In second example, there is no need for synchronization. You'd need to handle synchronization/memory issues when multiple threads using standard JavaBean object.
I can't see how the two approaches would be any different memory-wise.
Choose the approach that makes most sense to have in the interface of the class.
I would recommend to go with approach 2 only if both properties are logically strongly related, or if there is some class invariant that you don't want to temporarily break (even temporarily).
In your Address example, I would definitely go with two setter methods, since when talking about addresses, the name and city are quite unrelated.
For methods in general I'd say that whether or not you split a method up in two has little effect on memory consumption. Each object doesn't get its own set of methods allocated. The memory containing the methods is shared between all instances of a class.
Rule of thumb: Strive to make the interface of your class clean and logical.
Why not to use method #2
Your second example is not recommended because if you added a new field to the Address class, then do you add it into the existing setter method or do you create a new setter method? If you add it into the existing setter method, then any classes that called that method would be broken. And if you created a new setter method, then it is confusing for anyone who wants to use that class why certain fields are grouped together that way while others are not.
Using a separate setter method for each field that you wish to expose
The common practice is to have a single setter method for each field in your class that you wish to expose (i.e. your first example). Whether or not this is a good practice is debatable because it forces a class to be mutable. It is best to make an object immutable, if possible, for a number of reasons.
Initializing your fields using a constructor
One way to make a class immutable is by getting rid of the setter methods and instead making your fields settable via your class constructor, as below. The downside to implementing it this way is that if your class has a lot of fields, it may potentially lead to large, unreadable constructor calls.
public class Address {
public String name;
public String city;
private Address(String name, String city) {
this.name = name;
this.city = city;
}
}
Initializing your fields using the Builder pattern
Below is a completely alternative implementation (inspired by this article) that is a variation of the Builder pattern. It simulates object mutability without sacrificing readability.
public class Address {
public String name;
public String city;
private Address() {}
private void setName(String name) {
this.name = name;
}
private void setCity(String city) {
this.city = city;
}
static class Builder {
private Address address = new Address();
public Builder name(String name) {
address.setName(name);
return this;
}
public Builder city(String city) {
address.setCity(city);
return this;
}
public Address build() {
return address;
}
}
}
With the above class, you could create an immutable instance of the Address class as follows:
Address address = new Address.Builder()
.name("Mansoor's address")
.city("Toronto")
.build();
Which approach uses more memory?
From a memory point of view, there shouldn't be any difference since the size of a class in memory is dependent on the fields in the class. Since all three implementations have the same fields, they should take the same amount of space in memory, regardless of which approach you use.
This is not a clear question. Do you mean, would you rather have two methods like setFoo(String) and setBar(int), or one method like setFooBar(String, int)? It really depends on whether these are logically different properties, in which case you want individual methods, or whether it often (or only) makes sense to set them together. You could provide both.
Neither has any impact on memory, no.
The JavaBean standard is to have getters and setters for each property: http://en.wikibooks.org/wiki/Java_Programming/Java_Beans. If you don't want to follow that standard convention, its what makes the most sense for your shop. As per other answers on this thread, there probably is a minimal memory delta, if any.
Nb.1 without a doubt.
And you don't write that code by hand, only declare your fields.
Then you let Eclipse do the rest for you.
In Eclipse use Source --> generate getters and setters.
A very similar construct as #2 is done in the objects constructor.
The updated question with regards to memory. Don't worry one second in production code for the memory difference between those two ways.
You generally write a setter and a getter method for each attribute.
I don't really see the case when one method is enough for setting all the attributes. In this case, all attributes should have the same value? Or you always would have to pass parameters for all attributes. Both cases are not really what you want. So you should clearly prefer your first approach.
I am asking myself how to design an object-oriented address book in Java.
Let's say a contact can have several contact details, like addresses, phone numbers and e-mail addresses.
One way to implement this would be to give every contact an ArrayList for every type. But there must be a better and more object-oriented solution. What is it?
The most OOP suggestion I can give you is to create a class for every item/piece of information. For example:
public abstract class ContactInfo { /* ... */ }
public class Address extends ContactInfo { /* ... */ }
public class PhoneNumber extends ContactInfo { /* ... */ }
public class EmailAddress extends ContactInfo { /* ... */ }
public class Contact {
private String name;
private Set<ContactInfo> info;
// ...
}
and finally,
public class AddressBook {
List<Contact> contacts;
// ...
}
This may or may not be overkill for your specific case, but as a thought experiment, it's the way to go. It obviously takes care of the literal part of OOP — using objects — but also lays groundwork for encapsulation, abstraction and inheritance, which are closely related principles.
You're on the right track. The only thing I would do differently would be to use a List interface instead of an ArrayList collection to reference the contacts' attribute collections. This is advice based on the code-to-interfaces rule-of-thumb as described in this article and many others.
I don't think that's particularly un-object oriented. If your domain is such that a Person can have zero or more EmailAddresses, then you've almost exactly described the situation to use a list.
The only alternative approach I can think of would be to have fields such as
WorkEmail
PersonalEmail
OtherEmail1
OtherEmail2
OtherEmail3
but in my opinion that's worse, because:
You simply cannot support more than five email addresses (well, you could add more fields, but that increases the pain of the latter points and still imposes some finite limit.)
You're implying some extra semantics than may be present (what if the same address is used for work and personal? What if neither applies, can you just fill the Other ones? What if you don't know the purpose?)
You now have to test each field manually to see which is null, which is going to involve a non-trivial amount of duplication in Java. You can't use nice features like the enhanced-for loop to apply the same block to every email address, and you can't trivially count how many addresses there are
The list of properties that a Person has is now much less clean. I suppose you could package these properties into an EmailContactDetails class or something, but now you've got an extra level of indirection (more conceptual complexity) for no real gain.
So, if a person has a possibly-empty, unbounded list of email addresses, what's wrong with representing that as a list?
You can also use a Map, and then get specific values e.g. via myMap.get("emailAdress1") or iterate over the whole map like you would do with a list via myMap.entrySet().
One simple way to handle most of the use cases can be like this
public class AddressBook {
private Map<String, Contact> contacts;
AddressBook(){
contacts = new HashMap<String, Contact>();
}
public boolean addContact(Contact contact) {
if(contacts.containsKey(contact.getName())) {
System.out.println("Already exists");
return false;
}
contacts.put(contact.getName(), contact);
return true;
}
public boolean updateContact(Contact contact) {
contacts.put(contact.getName(), contact);
return true;
}
}
class Contact{
private String name;
private String email;
private String phone;
private Address address;
public Contact(String name) {
this.name = name;
}
public Contact(String name, String email, String phone, Address address) {
this.name = name;
this.email = email;
this.phone = phone;
this.address = address;
}
// getters and setters
#Override
public String toString() {
return "name is "+name+" and address is "+address;
}
}
class Address{
private String street1;
private String street2;
private String city;
private int zipcode;
public Address() {}
// getters and setters
#Override
public String toString() {
return "street1 is "+street1+" and zipcode is "+zipcode;
}
}