1

I am working on Java + Spring Boot example and have below code snippets.

Case-1

public class EmployeeRowMapper implements RowMapper<Employee>{

    @Override
    public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
        return Employee.builder()
                .firstName(rs.getString("FIRST_NAME"))
                .lastName(rs.getString("LASTN_AME"))
                .email(rs.getString("EMAIL"))
                .address(rs.getInt("ADDRESS")).build();
    }
}

Now, people (in code review comments) are suggesting me to create constants for FIRST_NAME, LAST_NAME, EMAIL and ADDRESS like below which I feel is absolutely not needed and doesn't bring any usefulness as per my knowledge and creating these constants will consume 4 bytes of memory and reference to these variable will never be garbage collected.

This is simple use-case I've shown using small code snippet of Spring Batch code, but this approach people do use when creating Controllers, Services or DAO/Repository layer in Java and where not.

Case-2

public class EmployeeRowMapper implements RowMapper<Employee>{
    public static final String FIRST_NAME = "FIRST_NAME";
    public static final String LAST_NAME = "LAST_NAME";
    public static final String EMAIL = "EMAIL";
    public static final String ADDRESS = "ADDRESS";

    @Override
    public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
        return Employee.builder()
                .firstName(rs.getString(FIRST_NAME))
                .lastName(rs.getString(LAST_NAME))
                .email(rs.getString(EMAIL))
                .address(rs.getInt(ADDRESS)).build();
    }
}

Note: Here I really need to understand which Case (i.e., Case-1 or Case-2) I need to follow and why ?

Also, people changing below controller to

@GetMapping(path = "/employee/{employeeId}")
public EmployeeDto getEmployee(@PathVariable Long employeeId) {
    return employeeIdService.getTridById(employeeId);
}

To

public static final String EMP_GET = "/employee/{employeeId}";

@GetMapping(path = EMP_GET)
public EmployeeDto getEmployee(@PathVariable Long employeeId) {
    return employeeIdService.getTridById(employeeId);
}

Say I've 100 Controllers and almost 500 endpoints in my modular application, so logically I am creating 500 String constants. Does this 500 constants doesnot occupy the memory area in the string constant pool?

PAA
  • 1
  • 46
  • 174
  • 282
  • The latter option creates less number of objects and causes less GC overhead. – Ravindra Ranwala Oct 15 '19 at 16:02
  • 1
    @RavindraRanwala does it really? Wouldn't the inline strings end up in the constants pool such that no object creations are necessary in both cases? – Jannik Oct 15 '19 at 16:04
  • There's no such pool. @Jannik – Ravindra Ranwala Oct 15 '19 at 16:05
  • 1
    There certainly is such a pool as it is mentioned in the Java Language Specification (3.10.5). I just wasn't sure how exactly the pool works. – Jannik Oct 15 '19 at 16:10
  • @RavindraRanwala are you sure speaking about Java??? actually I doubt that second snippet will use less memory – user85421 Oct 15 '19 at 16:13
  • 1
    I feel like this is more a style concern. If there's changes in the future or if you need access to the fields outside, it's easier to have them all declared at the same place (top of the file). Taking in consideration that it's Java, I don't think a bit of extra memory used (if it really does use more) is a big problem. – Simon Oct 15 '19 at 16:14
  • Possible duplicate of [when exactly are we supposed to use "public static final String"?](https://stackoverflow.com/questions/11677670/when-exactly-are-we-supposed-to-use-public-static-final-string) – Ryuzaki L Oct 15 '19 at 16:21
  • One thing I am not very clear is that, why to unnecessary clear variables just to use facility that Java provides of creating constants ? I have seen people are using `@RequestMapping` value of Spring REST annotation as a constant. Does this really required ? Will that reduced the readability ? – PAA Oct 15 '19 at 16:33
  • *"... it's only used once."* Until next month. Or next year. Don't be shortsighted. Use the same paradigm you'd use for constants that are used many times. – Andrew Henle Oct 15 '19 at 16:43
  • 1
    I am a c# guy, not a Java guy, but if I was faced with the same situation in c#, I probably wouldn't create constants. Does anyone who is touting option #2 have any concrete testing evidence to back up the performance gain? I would think it would be extremely trivial if any difference at all. – user2966445 Oct 15 '19 at 16:43
  • @AndrewHenle - If application grows, are you going to crate thousands of such String literals although its going to use only once ? – PAA Oct 15 '19 at 16:45
  • @PAA What does your workplace code standards say you're supposed to do? – Andrew Henle Oct 15 '19 at 16:48
  • @AndrewHenle - Yes, they're saying you supposed to do that, but I am not convince on that unless I dont have concrete reason of doing this way – PAA Oct 15 '19 at 17:07
  • 3
    Seems like this question would be a better fit on [Software Engineering SE](https://softwareengineering.stackexchange.com) than, here where it's already gathering votes to close as primarily opinion based. – Roddy of the Frozen Peas Oct 15 '19 at 17:41

2 Answers2

4

There are no "reasons" to do this, unless your team has an enforcement for readability (we have the same ones in our code reviews, I'll explain why later).

These are string literals in your case, so only one instance created; I hope people providing you comments are aware of this. But even if these would not be a single instance objects, from a performance perspective - this is ridiculous... On one hand you are using spring (proxies, proxies everywhere!) and your team is worried about String instances and GC pressure because of that? Well...

Why we enforce such a rule?

  • In my teams view - this is easier to read the code.

  • as soon as you use one constant at least twice in the same class, things are a lot more readable (in my teams view). i.e.:


Employee amp = Employee.builder()
                       .firstName(rs.getString(FIRST_NAME))
                       .lastName(rs.getString(LAST_NAME))
                       .email(rs.getString(EMAIL))

// ... later in the code re-use FIRST_NAME, LAST_NAME

In case you need to change "FIRST_NAME" - you replace it a in single place.

  • we provide all constants in the beginning of the class (again, this is subjective to my teams standards, may be yours does not).

What we don't do is to provide constants for spring controller mappings, it just creates too much noise and makes the path to read much more complicated.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Thanks. I do agree on the Controller part, because we've Swaggers and Rest API documentations, so creating constant for this can be avoided, however creating constants for the string variable which is again not getting used anywhere and probably will not, still you're suggesting to have constants in many API that we used from Spring ? – PAA Oct 15 '19 at 17:45
  • @PAA I am "suggesting" to follow a common, team-build pattern, whatever that is... – Eugene Oct 15 '19 at 17:49
  • I am at work right now and I can see real advantage for creating static field with path. You can use it simply in the test – Mateusz Oct 16 '19 at 09:27
2

In most cases, you shouldn't worry about memories. Readability in business applications is much more important

In the case with rest controllers it is easier to view and analyse all paths when they are grouped in one place instead of scattered in random places. Especially when you collect all routings in one file.

In the case with fields names, when you will name the field

private static final String ADDRESS_COLUMN_NAME = "ADDRESS";

You simply say that this is the name of the column in your database, not the field in the properties file. And of course you have it grouped in one place so you don't have to search the file.

Sometimes you can explain the weird API, lets say

String userName = response.get("benutzer").get("name");

or

private static final String USER_FIELD_IN_SOME_GERMANE_API = "benutzer";
private static final String USER_NAME_FIELD_IN_SOME_GERMANE_API = "benutzer";

String userName = response.get(USER_FIELD_IN_SOME_GERMANE_API).get(USER_NAME_FIELD_IN_SOME_GERMANE_API);

much better, isn't it?

Another example

if (error.equals("error 3214e.r") {
   // ...
}
// or
if (error.equals(USER_NOT_EXIST_ERROR_CODE) {
   // ...
}

While for me personally strings are not always a big problem, but always create variables with numbers (magic numbers)

for (int i = 0; i < 52; i++) 
   pickRandomCard()

// lol, why 52?

for (int i = 0; i < DECK_SIZE; i++) 
   pickRandomCard()
Mateusz
  • 690
  • 1
  • 6
  • 21
  • We've Swagger - REST API documentation, so I still not prefer to create not needed constants just to manage in all places, swagger is for that. This way we will keep creating many constants if you're using many modules like Spring Batch, Boot, Spring Rest, Spring HATEOAS, because each API has its significant use cases and for those API to use for our usecase, still not good to have thousands of constants in an application. Does it ? – PAA Oct 15 '19 at 17:30
  • Typo: *German* not *germane*. – Roddy of the Frozen Peas Oct 15 '19 at 17:38
  • I don't see any other reason that habits and standards in your company. In code review you can (or should) always ask your mates "why?" – Mateusz Oct 15 '19 at 17:38