I'm debating myself whether it is a bad practice to trim the input String arguments of a method? I personally don't like modifying the input arguments but wondering if trimming is Ok?
I've code something like below
private Order retrieveOrderDetails(String productId, String cardNumber, Date purchaseDate) {
validateInputs(trim(productId), trim(cardNumber), purchaseDate);
List<Order> orders = pullOrdersByCardNumber(trim(cardNumber));
return retrieveOrderDetails(orders, trim(productId), purchaseDate);
}
Instead of using trim() in multiple places, is it acceptable to do something like below?
private Order retrieveOrderDetails(String productId, String cardNumber, Date purchaseDate) {
productId = trim(productId);
cardNumber = trim(cardNumber);
validateInputs(productId, cardNumber, purchaseDate);
List<Order> orders = pullOrdersByCardNumber(cardNumber);
return retrieveOrderDetails(orders, productId, purchaseDate);
}
The strings should already be trimmed by the time they reach retrieveOrderDetails().
Needing to trim strings implies that they're coming from user input: form fields, a configuration file, etc. Trimming whitespace from user input is a job for user interface code or file reading code. You should not be mixing layers of abstraction, handling both UI and business logic in the same function.
Don't trim the strings here, and don't check that they're trimmed. Don't worry about trimming at all. It's the caller's problem, not this function's.
If you want to be really pure you could even replace the strings with domain-specific classes. You already have Date purchaseDate rather than String purchaseDate. Do the same thing for the other two parameters. Then where trimming belongs becomes clear: not here.
Order retrieveOrderDetails(ProductId productId, CardNumber cardNumber, Date purchaseDate) {
...
}
Orthogonal to John's point (which is "you shouldn't need to do this here"), you seem to be asking if it is acceptable to modify a method parameter variable.
It really comes down to readability. Which of these three versions do >>you<< think is more readable?
public void test(String arg) {
// repeat the trim computation
use(trim(arg));
use2(trim(arg));
}
public void test(String arg) {
// modify the argument
arg = trim(arg);
use(arg);
use2(arg);
}
public void test(String arg) {
// use a local variable
String trimmedArg = trim(arg);
use(trimmedArg);
use2(trimmedArg);
}
Your answer will probably depend on the context.
But really, it is up to you to make your own judgement. We can't tell you which version you will find more readable. It is readability for you and your colleagues that matters. After all, you will be the ones who (may) need to read this code in N years time.
There will be small performance differences, but that should not be your primary criteria or deciding, unless you have strong evidence that this code is performance critical.
If your business function doesn't change if the input is trimmed or not so trimming is fine.
But if there is a different logic between trim and with-out trim, so you can't do that by default.
Related
I really like the addition of records in Java 14, at least as a preview feature, as it helps to reduce my need to use lombok for simple, immutable "data holders". But I'm having an issue with the implementation of nullable components. I'm trying to avoid returning null in my codebase to indicate that a value might not be present. Therefore I currently often use something like the following pattern with lombok.
#Value
public class MyClass {
String id;
#Nullable String value;
Optional<String> getValue() { // overwrite the generated getter
return Optional.ofNullable(this.value);
}
}
When I try the same pattern now with records, this is not allowed stating incorrect component accessor return type.
record MyRecord (String id, #Nullable String value){
Optional<String> value(){
return Optional.ofNullable(this.value);
}
}
Since I thought the usage of Optionals as return types is now preferred, I'm really wondering why this restriction is in place. Is my understanding of the usage wrong? How can I achieve the same, without adding another accessor with another signature which does not hide the default one? Should Optional not be used in this case at all?
A record comprises attributes that primarily define its state. The derivation of the accessors, constructors, etc. is completely based on this state of the records.
Now in your example, the state of the attribute value is null, hence the access using the default implementation ends up providing the true state. To provide customized access to this attribute you are instead looking for an overridden API that wraps the actual state and further provides an Optional return type.
Of course, as you mentioned one of the ways to deal with it would be to have a custom implementation included in the record definition itself
record MyClass(String id, String value) {
Optional<String> getValue() {
return Optional.ofNullable(value());
}
}
Alternatively, you could decouple the read and write APIs from the data carrier in a separate class and pass on the record instance to them for custom accesses.
The most relevant quote from JEP 384: Records that I found would be(formatting mine):
A record declares its state -- the group of variables -- and commits
to an API that matches that state. This means that records give up a
freedom that classes usually enjoy -- the ability to decouple a
class's API from its internal representation -- but in return, records
become significantly more concise.
Due to restrictions placed on records, namely that canonical constructor type needs to match accessor type, a pragmatic way to use Optional with records would be to define it as a property type:
record MyRecord (String id, Optional<String> value){
}
A point has been made that this is problematic due to the fact that null might be passed as a value to the constructor. This can be solved by forbidding such MyRecord invariants through canonical constructor:
record MyRecord(String id, Optional<String> value) {
MyRecord(String id, Optional<String> value) {
this.id = id;
this.value = Objects.requireNonNull(value);
}
}
In practice most common libraries or frameworks (e.g. Jackson, Spring) have support for recognizing Optional type and translating null into Optional.empty() automatically so whether this is an issue that needs to be tackled in your particular instance depends on context. I recommend researching support for Optional in your codebase before cluttering your code possibly unnecessary.
Credits go to Holger! I really like his proposed way of questioning the actual need of null. Thus with a short example, I wanted to give his approach a bit more space, even if a bit convoluted for this use-case.
interface ConversionResult<T> {
String raw();
default Optional<T> value(){
return Optional.empty();
}
default Optional<String> error(){
return Optional.empty();
}
default void ifOk(Consumer<T> okAction) {
value().ifPresent(okAction);
}
default void okOrError(Consumer<T> okAction, Consumer<String> errorAction){
value().ifPresent(okAction);
error().ifPresent(errorAction);
}
static ConversionResult<LocalDate> ofDate(String raw, String pattern){
try {
var value = LocalDate.parse(raw, DateTimeFormatter.ofPattern(pattern));
return new Ok<>(raw, value);
} catch (Exception e){
var error = String.format("Invalid date value '%s'. Expected pattern '%s'.", raw, pattern);
return new Error<>(raw, error);
}
}
// more conversion operations
}
record Ok<T>(String raw, T actualValue) implements ConversionResult<T> {
public Optional<T> value(){
return Optional.of(actualValue);
}
}
record Error<T>(String raw, String actualError) implements ConversionResult<T> {
public Optional<String> error(){
return Optional.of(actualError);
}
}
Usage would be something like
var okConv = ConversionResult.ofDate("12.03.2020", "dd.MM.yyyy");
okConv.okOrError(
v -> System.out.println("SUCCESS: "+v),
e -> System.err.println("FAILURE: "+e)
);
System.out.println(okConv);
System.out.println();
var failedConv = ConversionResult.ofDate("12.03.2020", "yyyy-MM-dd");
failedConv.okOrError(
v -> System.out.println("SUCCESS: "+v),
e -> System.err.println("FAILURE: "+e)
);
System.out.println(failedConv);
which leads to the following output...
SUCCESS: 2020-03-12
Ok[raw=12.03.2020, actualValue=2020-03-12]
FAILURE: Invalid date value '12.03.2020'. Expected pattern 'yyyy-MM-dd'.
Error[raw=12.03.2020, actualError=Invalid date value '12.03.2020'. Expected pattern 'yyyy-MM-dd'.]
The only minor issue is that the toString prints now the actual... variants. And of course we do not NEED to use records for this.
Don't have the rep to comment, but I just wanted to point out that you've essentially reinvented the Either datatype. https://hackage.haskell.org/package/base-4.14.0.0/docs/Data-Either.html or https://www.scala-lang.org/api/2.9.3/scala/Either.html. I find Try, Either, and Validation to be incredibly useful for parsing and there are a few java libraries with this functionality that I use: https://github.com/aol/cyclops/tree/master/cyclops and https://www.vavr.io/vavr-docs/#_either.
Unfortunately, I think your main question is still open (and I'd be interested in finding an answer).
doing something like
RecordA(String a)
RecordAandB(String a, Integer b)
to deal with an immutable data carrier with a null b seems bad, but wrapping recordA(String a, Integer b) to have an Optional getB somewhere else seems contra-productive. There's almost no point to the record class then and I think the lombok #Value is still the best answer. I'm just concerned that it won't play well with deconstruction for pattern matching.
I have a key value arrays
String[] fields = {"firstName", "middleName", "id"};
String[] fieldValues = {"first name", "middle name", "student id"};
I have a method that compares two beans and returns a array of String with different field values.
public static String[] beanCompare(Object A, Object B,
String[] fields, String[] fieldValue);
Example If I pass a Studentbean with different firstName and id.
It will return
["first name", "student id"].
I need to compare 100's of beans.
The return value updates an activity log table. Let say, the firstName field is updated. We display
the first name has been updated
in the UI. It's for auditing.
Is there a readable and maintainable way to represent such key-value pair?
Correct me if I'm wrong, but it seems that (passing field names and field values this way) you're trying to build custom objects dynamically.
If that's your purpose, then you're in full XY problem, since you've figured out this solution to your problem, and then you're trying to tune up this solution, while you should go back to the problem, which has a standard, engineered, best practice solution: the Builder Pattern.
If you have many fields on an object, but you need to use only a portion of them in some cases and another portion in other cases, then use a Builder, set only the fields you need, then invoke the build() method, and get your object without the need to do what you're doing or permute all the constructors.
Here is an example of this pattern in Java.
So, enum worked for me.
public enum FieldEnum {
firstName("first name"), middleName("middle name"), id("student id");
String value;
FieldEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
Its more readable and maintainable.
I would like to know a simple method to write this SPARQL query in Java Code:
select ?input
?string
(strlen(?match)/strlen(?string) as ?percent)
where {
values ?string { "London" "Londn" "London Fog" "Lando" "Land Ho!"
"concatenate" "catnap" "hat" "cat" "chat" "chart" "port" "part" }
values (?input ?pattern ?replacement) {
("cat" "^x[^cat]*([c]?)[^at]*([a]?)[^t]*([t]?).*$" "$1$2$3")
("Londn" "^x[^Londn]*([L]?)[^ondn]*([o]?)[^ndn]*([n]?)[^dn]*([d]?)[^n]*([n]?).*$" "$1$2$3$4$5")
}
bind( replace( concat('x',?string), ?pattern, ?replacement) as ?match )
}
order by ?pattern desc(?percent)
This code is contained in the discussion To use iSPARQL to compare values using similarity measures.
The purpose of this code is to find the resources similar to a given word on DBPedia.
This method takes into consideration that I know in advance the strings and the length of it. I would like to know how I can write this query in a parameterized method that, regardless of the word and the length of it, it returns to me the similarity measures.
Update: ARQ - Writing Property Functions is now part of the standard Jena documentation.
It looks like you'd enjoy having a syntactic extension to SPARQL that performs the more complex portions of your query. For example:
SELECT ?input ?string ?percent WHERE
{
VALUES ?string { "London" "Londn" "London Fog" "Lando" "Land Ho!"
"concatenate" "catnap" "hat" "cat" "chat" "chart" "port" "part" }
VALUES ?input { "cat" "londn" }
?input <urn:ex:fn#matches> (?string ?percent) .
}
ORDER BY DESC(?percent)
In this example, it's assumed that <urn:ex:fn#matches> is a property function that will automatically perform the matching operation and calculate the similarity.
The Jena documentation does a great job explaining how to write a custom filter function,
but (as of 07/08/2014) does little to explain how to implement a custom property function.
I will make the assumption that you can convert your answer into java code for the purpose of calculating string similarity, and focus on the implementation of a property function that can house your code.
Implementing a Property Function
Every property function is associated with a particular Context. This allows you to limit the availability of the function to be global or associated with a particular dataset.
Assuming you have an implementation of PropertyFunctionFactory (shown later), you can register the function as follows:
Registration
final PropertyFunctionRegistry reg = PropertyFunctionRegistry.chooseRegistry(ARQ.getContext());
reg.put("urn:ex:fn#matches", new MatchesPropertyFunctionFactory);
PropertyFunctionRegistry.set(ARQ.getContext(), reg);
The only difference between global and dataset-specific registration is where the Context object comes from:
final Dataset ds = DatasetFactory.createMem();
final PropertyFunctionRegistry reg = PropertyFunctionRegistry.chooseRegistry(ds.getContext());
reg.put("urn:ex:fn#matches", new MatchesPropertyFunctionFactory);
PropertyFunctionRegistry.set(ds.getContext(), reg);
MatchesPropertyFunctionFactory
public class MatchesPropertyFunctionFactory implements PropertyFunctionFactory {
#Override
public PropertyFunction create(final String uri)
{
return new PFuncSimpleAndList()
{
#Override
public QueryIterator execEvaluated(final Binding parent, final Node subject, final Node predicate, final PropFuncArg object, final ExecutionContext execCxt)
{
/* TODO insert your stuff to perform testing. Note that you'll need
* to validate that things like subject/predicate/etc are bound
*/
final boolean nonzeroPercentMatch = true; // XXX example-specific kludge
final Double percent = 0.75; // XXX example-specific kludge
if( nonzeroPercentMatch ) {
final Binding binding =
BindingFactory.binding(parent,
Var.alloc(object.getArg(1)),
NodeFactory.createLiteral(percent.toString(), XSDDatatype.XSDdecimal));
return QueryIterSingleton.create(binding, execCtx);
}
else {
return QueryIterNullIterator.create(execCtx);
}
}
};
}
}
Because the property function that we create takes a list as an argument, we use PFuncSimpleAndList as an abstract implementation. Aside from that, most of the magic that happens inside these property functions is the creation of Bindings, QueryIterators, and performing validation of the input arguments.
Validation/Closing Notes
This should be more than enough to get you going on writing your own property function, if that is where you'd like to house your string-matching logic.
What hasn't been shown is input validation. In this answer, I assume that subject and the first list argument (object.getArg(0)) are bound (Node.isConcrete()), and that the second list argument (object.getArg(1)) is not (Node.isVariable()). If your method isn't called in this manner, things would explode. Hardening the method (putting many if-else blocks with condition checks) or supporting alternative use-cases (ie: looking up values for object.getArg(0) if it is a variable) are left to the reader (because it's tedious to demonstrate, easily testable, and readily apparent during implementation).
I know that the Javadocs says:
Returns a string representation of the object. In general, the
toString method returns a string that "textually represents" this
object. The result should be a concise but informative representation
that is easy for a person to read. It is recommended that all
subclasses override this method.
But when should I spend time overriding the toString method for my classes? Should it be one of the first things I do along with overriding equals and hashCode? Or should I wait until it's actually needed?
I know Eclipse can auto generate toString methods for you, so should I just have Eclipse auto generate them once I know the fields for my class?
Josh Bloch gives a good explanation in Effective Java, in item 10.
[...] providing a good toString implementation makes your class much more pleasant to use.
It really makes it easier to output debugging traces, or makes better logging messages, since you can use the object's string representation provided by toString() directly; you don't have to manually build a string that gives the information needed on the object.
As stated in the book, you should include all the interesting information in the resulting String. You should also document properly your method; you may document the resulting String format or not, but you should at least document your intent (whether the format is subject to change, or not likely to change).
In the end, it is up to you (and your company's standards) to decide if overriding it in every class should be part of your habits or not. Personally, I don't override toString () in every classes, only in the ones which are most at risk of being used in a debuging trace.
I would implement toString() method on any class that holds human understandable non confidential data. Ex: Transfer Object, Beans, Data Object, Wrappers. For such classes just go on to implement 'toString()' method.
Classes that represent a service, process with transient states need not implement the method.Here, You can wait until it is actually needed.
Make sure you do not expose any variables with "transient" keyword in 'toString()'!
Typically, I override it when I want to assign a default format of displaying an object, often formatting a compact/digestable display of relevant attributes. So that I can simply, for example, display it in debug or log by doing:
MyClass myClsInst = new MyClass();
...
System.out.println(myClsInst);
In general, It's used to show or see what the object has.
For instance, Let's say there is a Student class and you created objects.
Student class has age, grade, gpa, name, country, address.
class Student{
private int age;
private int grade;
private double gpa;
private String name;
private String country;
private String address;
Student(...){
// ...
}
public String toString(){
String str = "age is "+age+ ", grade is " + grade + ...
return str;
}
}
And you created A student, and B student ( and maybe more )
You just need to 'toString()' for checking its inside like this:
System.out.println(aStudent.toString());
System.out.println(bStudent.toString());
or You can just write the object name, it automatically calls 'toString()'
System.out.println(aStudent);
System.out.println(bStudent);
It removes the redundant works & faster.
Then, you will see like this:
Output:
age is 13, grade is 3, ...
age is 15, grade is 5, ...
It's useful when you see what A student or B student has when you debug.
And also, It's useful when you make your own form like JSON.
It will be easier to manipulate its data with JSON format.
I am trying to demonstrate in simple way.
package com.web.doamin;
public class User {
String name;
long id;
/*#Override
public String toString() {
return "User [user = " + name + ", id="+ id + "]";
}*/
public static void main(String[] args) {
User user = new User();
System.out.println(" : user : " + user );
}
}
If we did't Override toString() method we will get Object Hash code in sysout
O/P without Override toString() method - com.web.doamin.User#7852e922
if We Override the ToString() method we will get O/P - User [user = null, id=0]
Note - It is a good idea to override toString() as we get get proper output when an object is used in System.out.println();
I want my data structures to be custom formatted.
e.g. I have a DS
Address {
string house_number,
string street,
string city,
long pin_code,
}
Now, I want to associate certain conversion specifiers with each of these fields.
e.g. house_number -> H
street -> S,
city -> C,
pin_code -> P
...
So that something like
myPrintWriter.printf("Mr A lives in %C", address_instance)
yields "Mr A lives in boston" (if address_instance.city = boston) etc..
It seems there is no easy way to do this. java.util.Formatter seems to be final. The only customization it provides is via the interface Formattable, but that helps in customizing the 's' conversion specifier only.
Is there a way to add our custom conversion specifiers? Any help will be much appreciated.
Thanks,
It seems there is no easy way to do this. java.util.Formatter seems to be final.
That's true, but you can still use composition. I would do something like the following:
class ExtendedFormatter {
private Formatter defaultFormatter;
// provide the same methods like the normal Formatter and pipe them through
// ...
// then provide your custom method, or hijack one of the existing ones
// to extend it with the functionality you want
// ...
public Formatter format(String format, Object... args) {
// extract format specifiers from string
// loop through and get value from param array
ExtendedFormattable eft = (ExtendedFormattable)args1;
String specifierResult = eft.toFormat(formatSpecifier); // %C would return city
// use specifierResult for the just queried formatSpecifier in your result string
}
}
The hard part is to know how to attach the different format specifiers to the fields you want to output. The first way I can think of, is to provide your own ExtendedFormattable interface that each class that should be used with the ExtendedFormatter can implement, and return the according values for your custom format specifiers. That could be:
class Address implements ExtendedFormattable {
public String toFormat(String formatSpecifier) { // just an very simple signature example
// your custom return values here ...
}
}
There's also annotations, but I think that's not a very viable way.
A sample call would look like:
ExtendedFormatter ef = new ExtendedFormatter();
ef.format("Mr A lives in %C", address_instance);
I believe you will need to write your own formatter which works the way you want.