I'm a little bit confused on what is the right way to use setters.
Is the preferable method to create a setters with only 1 parameter of the same object type like this one ?
public void setWebsite(String website) {
if(website ==null){
this.website = "";
}else {
this.website = website;
}
}
But i have 2 setters where i'm doubting about
public void setAddressClientList(List<AddressClient> addressClientList,Client client) {
//Here we add the customer to the address
if (!addressClientList.isEmpty()) {
for (AddressClient addressClient : client.getAddressClientList())
{
addressClient.setClient(this);
this.addressClientList.add(addressClient);
}
}
}
and
public void setProfessional(String companyName,String vatNumber ) {
this.professional = !(companyName == null || vatNumber == null);
}
this is the constructor
public Client(Client client,Company company,Client lastInsertClient) throws ClientException {
setCompany(company);
setActive(true);
setCustomField(client.customField);
setWebsite(client.website);
setVatNumber(client.vatNumber);
setPhoneNumber(client.phoneNumber);
setCurrency("notImplementedYet");
setFaxNumber(client.faxNumber);
setCompanyName(client.companyName);
setSalutation(client.salutation);
setLastName(client.lastName);
setEmail(client.email);
setFirstName(client.firstName);
setClientNumber(lastInsertClient);
setProfessional(client.companyName,client.vatNumber);
setAddressClientList(client.addressClientList,client);
}
Can someone explain if this what the best way to use the setters. And if the last 2 setters are not correct what would you suggest ?
Maybe you shouldn't use setters, maybe you should. Setters are mostly used to set a field of the Object that you want. Usually you set a single value at a time (or get it if that is the case), but there can be cases where values should be manipulated in pairs etc. This is a strictly semantic and almost philosophical question, but if you want to do it according to the best practices that people use, I suggest that you rename the method to something more descriptive to avoid confusion if somebody else works with your code. If this is a solo project, you might as well just comment it properly and be on your merry way.
Related
I am currently using HibernateConstraintValidator to implement my validations. But my reviewer is not fine with having if/else in code or ! operators. Which design pattern can I use to remove the if/else in my validation logic?
public class SomeValidatorX implements ConstraintValidator<SomeAnnotation, UUID> {
#Autowired
SomeRepository someRepository;
#Override
public boolean isValid(UUID uuid, ConstraintValidationContext context) {
return !(uuid!=null && someRepository.existsById(uuid)); //The reviewer doesn't want this negation operator
}
}
And in below code, he doesn't want if/else
public class SomeValidatorY implements ConstraintValidator<SomeAnnotation, SomeClass> {
#Autowired
SomeRepository someRepository;
#Override
public boolean isValid(SomeClass someObject, ConstraintValidationContext context) {
if(someObject.getFieldA() != null) { //He doesn't want this if statement
//do some operations
List<Something> someList = someRepository.findByAAndB(someObject.getFieldA(),B);
return !someList.isEmpty(); //He doesn't want this ! operator
}
return false; // He was not fine with else statement in here as well
}
}
Side Note: We have to use Domain Driven Design (if it helps)
A long time ago, in the beginning of time. There was a guideline that said that methods should only have one exit point. To achieve that, developers had to track the local state and use if/else to be able to reach the end of the method.
Today we know better. By exiting a method as early as possible it's much easier to keep the entire flow in our head while reading the code. Easier code means less mistakes. Less mistakes equals less bugs.
In my opinion, that's why the reviewer doesn't like the code. It's not as easy to read as it could be.
Let's take the first example:
public boolean isValid(UUID uuid, ConstraintValidationContext context) {
return !(uuid!=null && someRepository.existsById(uuid)); //The reviewer doesn't want this negation operator
}
What the code says is "not this: (uuid should not be empty and it must exist)". Is that easy to understand? I think not.
The alternative: "Its OK if uuid do not exist, but if it do, the item may not exist".
Or in code:
if (uuid == null) return true;
return !someRepository.existsById(uuid);
Much easier to read, right? (I hope that I got the intention correct ;))
Second example
if(someObject.getFieldA() != null) { //He doesn't want this if statement
//do some operations
List<Something> someList = someRepository.findByAAndB(someObject.getFieldA(),B);
return !someList.isEmpty(); //He doesn't want this ! operator
}
return false; // He was not fine with else statement in here as well
Ok. Here you are saying:
If field A is not null:
Build a list where A and b is found
If that list is not empty fail, otherwise succeed.
Otherwise fail
A easier way to conclude that is to simply say:
It's ok if field A is not specified
If field A is specified it must exist in combination with B.
Translated to code:
if (someObject.getFieldA() == null)
return true;
return !someRepository.findByAAndB(someObject.getFieldA(),B).isEmpty();
In C# we have Any() which is opposite to isEmpty which I would prefer in this case as it removes the negation.
Sometimes negations are required. It doesn't make sense to write a new method in the repository to avoid it. However, if findByAAndB is only used by this I would rename it to ensureCombination(a,b) so that it can return true for the valid case.
Try to write code as you talk, it makes it much easier to create a mental picture of the code then. You aren't saying "Im not full, lets go to lunch", are you? ;)
You can check the Null-object pattern.
The general pattern is to ban null completely from your code. This eliminates the ugly null checks. In this point I agree with your code reviewer.
Following the below recommendations will result in:
public boolean isValid(SomeClass someObject, ConstraintValidationContext context) {
return someRepository.containsAAndB(someObject.getFieldA(), B);
}
Avoid null checks
Before introducing the Null-object pattern, simply apply the pattern or convention to enforce initialization of all references. This way you can be sure that there are no null references in your entire code.
So when you encounter a NullPointerException, you don't solve the issue by introducing a null check, but by initializing the reference (on construction) e.g., by using default values, empty collections or null objects.
Most modern languages support code analysis via annotations like #NonNull that checks references like arguments and will throw an exception, when a parameter is null/not initialized. javax.annotation for instance provides such annotations.
public void operation(#NonNull Object param) {
param.toString(); // Guaranteed to be not null
}
Using such annotations can guard library code against null arguments.
Null-Object Pattern
Instead of having null references, you initialize each reference with a meaningful value or a dedicated null-object:
Define the Null-object contract (not required):
interface NullObject {
public boolean getIsNull();
}
Define a base type:
abstract class Account {
private double value;
private List<Owner> owners;
// Getters/setters
}
Define the Null-object:
class NullAccount extends Account implements NullObject {
// Initialize ALL attributes with meaningful and *neutral* values
public NullAccount() {
setValue(0); //
setOwners(new ArrayList<Owner>())
#Override
public boolean getIsNull() {
return true;
}
}
Define the default implementation:
class AccountImpl extends Account implements NullObject {
#Override
public boolean getIsNull() {
return true;
}
}
Initialize all Account references using the NullAccount class:
class Employee {
private Account Account;
public Employee() {
setAccount(new NullAccount());
}
}
Or use the NullAccount to return a failed state instance (or default) instead of returning null:
public Account findAccountOf(Owner owner) {
if (notFound) {
return new NullAccount();
}
}
public void testNullAccount() {
Account result = findAccountOf(null); // Returns a NullAccount
// The Null-object is neutral. We can use it without null checking.
// result.getOwners() always returns
// an empty collection (NullAccount) => no iteration => neutral behavior
for (Owner owner : result.getOwners()) {
double total += result.getvalue(); // No side effect.
}
}
Try-Do Pattern
Another pattern you can use is the Try-Do pattern. Instead of testing the result of an operation you simply test the operation itself. The operation is responsible to return whether the operation was successful or not.
When searching a text for a string, it might be more convenient to return a boolean whether the result was found instead of returning an empty string or even worse null:
public boolean tryFindInText(String source, String searchKey, SearchResult result) {
int matchIndex = source.indexOf(searchKey);
result.setMatchIndex(matchIndex);
return matchIndex > 0;
}
public void useTryDo() {
SearchResult result = new Searchresult();
if (tryFindInText("Example text", "ample", result) {
int index = result.getMatchIndex();
}
}
In your special case, you can replace the findByAAndB() with an containsAAndB() : boolean implementation.
Combining the patterns
The final solution implements the Null-Object pattern and refactors the find method. The result of the original findByAAndB() was discarded before, since you wanted to test the existence of A and B. A alternative method public boolean contains() will improve your code.
The refactored implementation looks as followed:
abstract class FieldA {
}
class NullFieldA {
}
class FieldAImpl {
}
class SomeClass {
public SomeClass() {
setFieldA(new NullFieldA());
}
}
The improved validation:
public boolean isValid(SomeClass someObject, ConstraintValidationContext context) {
return someRepository.containsAAndB(someObject.getFieldA(), B);
}
You can try this
return Optional.ofNullable(uuid)
.map(someRepository::existsById)
.orElse(false);
StudentDTO class having around 20 string attributes and each need to validate whether mandatory or not based on the logic given below in comments. This will make update method lengthy with too many if else's. Exception message should change based on the property evaluating. This code use Java 11.
// all fields except lastUpdated are string
public Student populateStudent(final StudentDTO studentDTO) {
Student student = new Student();
boolean dataUpdated = false;
/*
If mandatory parameter is:
1.) null : parameter is not updating
2.) empty : validate and throw an exception
3.) blank : validate and throw an exception
*/
if (isEmptyOrBlank(studentDTO.getName())) {
handleBadParam("Bad student name");
} else {
if (studentDTO.getName() != null) {
student.setName(studentDTO.getName());
dataUpdated = true;
}
}
if (isEmptyOrBlank(studentDTO.getBirthday())) {
handleBadParam("Bad student birthday");
} else {
if (studentDTO.getBirthday() != null) {
student.setBirthday(studentDTO.getBirthday());
dataUpdated = true;
}
}
// .... 20 other similar if-else statements later ....
// if atleast one parameter updated then date should update
if (dataUpdated) {
student.setLastUpdated(new Date());
}
return student;
}
private boolean isEmptyOrBlank(String name) {
return name != null && (name.isEmpty() || isBlank(name));
}
private void handleBadParam(String messgae) {
throw new IllegalArgumentException(messgae);
}
private boolean isBlank(String name) {
return (name.trim().length() == 0);
}
It seems you are validating your object.
I will not share any code example, I will just share an design opinion. By the way while designing your application, you should follow a design principle. So SOLID design principles is the commonly accepted, and you can apply these principles to your app while designing it.
You may create a class like StudentValidator so it's job must be only validating the Student object. So you realize first principle of solid's single responsibility.
And also that StudentValidator class will have methods which validations you need. And after all that implementations, you can cover in a method for each validation or you may call them when needed line.
Also there are many design patterns to avoid if-else statements via implementing patterns. Like command pattern, using enums etc.
I would strongly recommend to use the Java environment JSR 303 Bean Validation.The javax.validation packages provide developers with a standardized way of doing so. Fields that have to fulfill certain criteria receive the corresponding annotations, e.g. #NotNull, and these are then evaluated by the framework. Naturally, for checking more specific conditions, there is the possibility of creating custom annotations and validators.
You could refer to this https://dzone.com/articles/bean-validation-made-simple.
In the last time I often write long functions that have several parameters but use only one of them and the functionality is only different at a few keypoints that are scattered around the function. Thus splitting the function would create too many small functions without a purpose. Is this good style or is there a good general refactoring pattern for this? To be more clear, an example:
public performSearch(DataBase dataBase, List<List<String>> segments) {performSearch(dataBase,null,null,segments);}
public performSearch(DataBaseCache dataBaseCache,List<List<String>> segments) {performSearch(null,dataBaseCache,null,segments);}
public performSearch(DataBase dataBase, List<String> keywords {performSearch(dataBase,null,keywords,null);}
public performSearch(DataBaseCache dataBaseCache,List<String> keywords) {performSearch(null,dataBaseCache,keywords,null);}
/** either dataBase or dataBaseCache may be null, dataBaseCache is used if it is non-null, else dataBase is used (slower). */
private void performSearch(DataBase dataBase, DataBaseCache dataBaseCache, List<String> keywords, List<List<String>> segments)
{
SearchObject search = new SearchObject();
search.setFast(true);
...
search.setNumberOfResults(25);
if(dataBaseCache!=null) {search.setSource(dataBaseCache);}
else {search.setSource(dataBase);}
... do some stuff ...
if(segments==null)
{
// create segments from keywords
....
segments = ...
}
}
This style of code works but I don't like all those null parameters and the possibilities of calling methods like this wrong (both parameters null, what happens if both are non-null) but I don't want to write 4 seperate functions either... I know this may be too general but maybe someone has a general solution to this principle of problems :-)
P.S.: I don't like to split up a long function if there is no reason for it other than it being long (i.e. if the subfunctions are only ever called in that order and only by this one function) especially if they are tightly interwoven and would need a big amount of parameters transported around them.
I think it is very bad procedural style. Try to avoid such coding. Since you already have a bulk of such code it may be very hard to re-factor it because each method contains its own logic that is slightly different from other. BTW the fact that it is hard is an evidence that the style is bad.
I think you should use behavioral patterns like
Chain of responsibilities
Command
Strategy
Template method
that can help you to change your procedural code to object oriented.
Could you use something like this
public static <T> T firstNonNull(T...parameters) {
for (T parameter: parameters) {
if (parameter != null) {
return parameter;
}
}
throw new IllegalArgumentException("At least one argument must be non null");
}
It does not check if more than one parameter is not null and they must be of the same type, but you could use it like this:
search.setSource(firstNonNull(dataBaseCache, database));
Expecting nulls is an anti-pattern because it litters your code with NullPointerExceptions waiting to happen. Use the builder pattern to construct the SearchObject. This is the signature you want, I'll let you figure out the implementation:
class SearchBuilder {
SearchObject search = new SearchObject();
List<String> keywords = new ArrayList<String>();
List<List<String>> segments = new ArrayList<List<String>>();
public SearchBuilder(DataBase dataBase) {}
public SearchBuilder(DataBaseCache dataBaseCache) {}
public void addKeyword(String keyword) {}
public void addSegment(String... segment) {}
public void performSearch();
}
I agree with what Alex said. Without knowing the problem I would recommend following structure based on what was in the example:
public interface SearchEngine {
public SearchEngineResult findByKeywords(List<String> keywords);
}
public class JDBCSearchEngine {
private DataSource dataSource;
public JDBCSearchEngine(DataSource dataSource) {
this.dataSource = dataSource;
}
public SearchEngineResult findByKeywords(List<String> keywords) {
// Find from JDBC datasource
// It might be useful to use a DAO instead of datasource, if you have database operations other that searching
}
}
public class CachingSearchEngine {
private SearchEngine searchEngine;
public CachingSearchEngine(SearchEngine searchEngine) {
this.searchEngine = searchEngine;
}
public SearchEngineResult findByKeywords(List<String> keywords) {
// First check from cache
...
// If not found, then fetch from real search engine
SearchEngineResult result = searchEngine.findByKeywords(keywords);
// Then add to cache
// Return the result
return result;
}
}
Could anubody explain how to use set methods? Problem:
class Sonum {
private int prior;
public Sonum(int prior) {
this.prior = prior;
}
public int getPrior() {
return prior;
}
public void setPrior(int prior) {
this.prior = prior;
}
class Tel {
// Please explain how can I set the value for prior? (for example 2)
}
Well, first you need an instance of Sonum on which you want to set the prior value. For example:
class Test {
public void foo() {
Sonum sonum = new Sonum(5);
// Use it with a prior of 5
// ...
sonum.setPrior(10);
// Now use it with a prior of 10
}
}
Sonum mySonum = new Sonum(1); //prior is currently 1
mySonum.setPrior(2); //now prior is 2
Take a deep breath. The Java Tutorial. Read it. You will understand.
Refer
Creating Objects & Using Objects
http://download.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
"Setter methods" aren't magic. They're just regular methods. You need an instance of that class, and then you can call the methods on it. Just like any other Java object.
set method deal with a private value that we would like to prevent the direct way to him using our client, therefor there are get \ set method.
The biggest advantage of get \ set methods is the control ability !
We can for example control a minimum age when we want to set an age, and many other simple examples.
Example:
setAge (int age)
{
if ( age < 0 )
{
System.out.println ( "Wrong age !!" );
}
}
Now I think you can easily understand this HW :)
I'm a bit new to Guava and it's style. I'm definitely digging it, but one thing I keep tripping over is the order of chained methods. Where I seem to have this problem the most is when using compound Orderings. I have to keep asking myself questions like:
Where does the natural go?
Where does the nullFirst (or last) go?
Which nullsFirst does what? (In the example below, one for host, one for last name, one for first name?)
Here's an example of one that I was just working on. It looks cumbersome, and I'm just not sure if I put it all together right. I have some JUnits to test it, and it seems okay, but there are always those quirky boundary cases.
Ordering<Host> lastNameThenFirstNameOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
public String apply(Host host) {
return host.getLastName();
}}).compound(Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
public String apply(Host host) {
return host.getFirstName();
}})).nullsFirst();
As for an actual question: Is there a well-defined rule for how these things get executed? It seems to be last-to-first, but I'm having trouble telling that.
edit: Just wanted to point out the large, ugly code I was trying to replace:
Ordering<Host> ordering2 = new Ordering<Host>() {
public int compare(Host host1, Host host2) {
if (host1 == null || host2 == null) {
return host1 == host2 ? 0 : ((host1 == null) ? -1 : 1);
}
if(host1.getLastName() != null || host2.getLastName() != null){
if (host1.getLastName() == null) {
return -1;
} else if (host2.getLastName() == null) {
return 1;
}
if (host1.getLastName().compareTo(host2.getLastName()) != 0) {
return host1.getLastName().compareTo(host2.getLastName());
}
}
if (host1.getFirstName() == null) {
return -1;
} else if (host2.getFirstName() == null) {
return 1;
}
return host1.getFirstName().compareTo(host2.getFirstName());
}};
I think what you do is correct, but awfully ugly. Try this for readability:
Use an Enum
Move the functions to an enum that implements Function<Host, String>. Each of the enum items can provide it's own implementation.
enum HostFunctions implements Function<Host, String>{
GETFIRSTNAME{
#Override
public String apply(final Host host){
return host.getFirstName();
}
},
GETLASTNAME{
#Override
public String apply(final Host host){
return host.getLastName();
}
}
}
Indent your Code
Now reference those enum functions and indent your code properly. This is what it will look like:
final Ordering<Host> orderingByLastAndFirstName =
Ordering
.natural()
.nullsFirst()
.onResultOf(HostFunctions.GETLASTNAME)
.compound(
Ordering
.natural()
.nullsFirst()
.onResultOf(HostFunctions.GETFIRSTNAME))
.nullsFirst();
I'd say that makes everything much more understandable.
IDE Configuration
Regarding proper indentation (at least if you use Eclipse), see this question:
How to indent the fluent interface
pattern “correctly” with eclipse?
Enums as Functions
Regarding the enum: this is called the enum singleton pattern. The Guava guys use it all over their code base. Read about it on wikipedia or in Effective Java, Item 3. Although those sources both talk about single-item enums, the approach is almost the same here.
Each chaining call is "wrapping" the previous ordering into a new one, so you're right, the execution order can be thought of as "backwards".
I wrote and reviewed the Ordering class and I still regularly have to stop and scratch my head over the correct interleaving of nullsFirst(), and onResultOf() and reverse()!
The following would be my preference for doing this, assuming you must be able to handle null hosts, first names and last names. To me, it seems like a non-null first name and last name ought to be a requirement of the Host class. And you should generally try to avoid allowing collections to contain null objects.
Ordering<Host> lastNameFirstNameOrdering = new Ordering<Host>() {
#Override public int compare(Host left, Host right) {
return ComparisonChain.start()
.compare(left.getLastName(), right.getLastName(), Ordering.natural().nullsFirst())
.compare(left.getFirstName(), right.getFirstName(), Ordering.natural().nullsFirst())
.result();
}
}.nullsFirst();
Alternatively, I'd take an approach similar to Sean's but break things down for readability.
Ordering<Host> lastNameOrder = Ordering.natural().nullsFirst()
.onResultOf(Host.LAST_NAME);
Ordering<Host> firstNameOrder = Ordering.natural().nullsFirst()
.onResultOf(Host.FIRST_NAME);
Ordering<Host> orderingByLastAndFirstName =
lastNameOrder.compound(firstNameOrder).nullsFirst();
Keep in mind that you could also make these individual orderings static final fields of the class, allowing you to easily use them anywhere when sorting like Host.LAST_NAME_ORDER.