I apologize for inventing the null reference at the 2009 conference.
That's my mistake, worth a billion dollars.
Null This is a hate problem that developers who use insecure languages are always plagued with. Computer scientist [Antony Hoare | wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%B3%E3%83%88%E3%83%8B% As E3% 83% BC% E3% 83% BB% E3% 83% 9B% E3% 83% BC% E3% 82% A2) said above, it is a technical debt woven into the language. It is no exaggeration to say.
In modern new development, null insecure languages are no longer legacy languages | Qiita The idea of avoiding null insecure languages themselves as in the article There will be. However, there are still situations where you have to choose a language that is not Null-safe for a variety of reasons.
So, this time, I will think about the method for facing Null in Java.
――The countermeasure plan has a "recommendation level", but it is a personal impression based on experience. ――The recommendation level when incorporating in a team is shown in 3 stages (: star: ~: star :: star :: star :)
JSR-305 A group of annotations defined for Software Defect Detection as a Java specification.
Therefore, it is not an annotation expected to work in Runtime, but a specification defined as a ** auxiliary function ** at the time of development (for example, support in IDEs such as Find Bugs and IntelliJ).
null
Recommendation level:: star :: star:: star:
import javax.annotation.Nullable;
@Nullable
public String createText() {
// ...
import javax.annotation.Nonnull;
@Nonnull
public String createText() {
// ...
It is very important to be able to use the check support function, but I felt that the effectiveness would be maximized in the following points when working as a team.
--The intention of each method of the designer / implementer can be clearly left. -Improved quality at the time of review as a side effect --Reduces the effort of implementers using methods to consider null --Reduced unnecessary null checks
null
in the argumentRecommendation level:: star:
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
public String createText(@Nonnull String id,
@Nullable String option) {
// ...
While you can get the same advantages as "declare whether the return type is null
", the following disadvantages are conspicuous for the team.
--It is troublesome to add all the arguments ――Because it is troublesome, it is easy to become a mere corpse --The argument goes into the annotation festival state, and visibility drops.
suggests
null` as the return typeRecommendation level:: star:
import java.util.Optional;
public Optional<String> getText() {
// ...
Java 8 ʻOptional` is mentioned in many articles, so I won't go into details. The reasons why we do not recommend it here are as follows.
--ʻOptional` type is not a Serializable class, so its usage is limited. --Rules are likely to break in cases where libraries (especially O / R Mapper type) are not supported.
■ Reference
-Java 8 "Optional" ~ How to deal with null in the future ~ -Summary of stories and usage of Optional not Serializable
"Assertion programming" that checks the preconditions introduced in Master Programmer. It's very valuable because it allows you to leave the designer / implementer's "higher level concept" as code.
Recommendation level:: star :: star:
private String createText(String id) {
assert (id != null) : "id must not be null.";
// ...
A typical example of assertive programming in Java is ʻassert`. However, you should be aware of the following points in the code (Programming with assertions | oracle.com Excerpt from assert.html)
■ Enable and disable assertions ** By default, assertions are disabled ** at run time. You can use the two command line switches to enable / disable assertions. Use the -enable assertions or -ea switches to enable assertions at various levels of detail.
It can be read that ʻassert` is just an auxiliary means for the implementer's assertion, not for raising an exception in the runtime of the product code. Also, if you read the official document carefully, it will contain important information such as treatments that have side effects, so you need to think carefully about what points to use when adopting.
Recommendation level:: star :: star:: star:
import org.springframework.util.Assert;
public String createText(String id) {
Assert.notNull(id, "ID must not be null.");
// ...
For Spring framework ʻorg.springframework.util.Assert` Use is that.
Unlike Java Assertion, it raises an exception even at Runtime. It's a simplification of null checking, but it also works with the Runtime, so you can leave a very strong statement of intention in your code.
null
defensefinal
to make it ImmutableRecommendation level:: star :: star:
public String createText(final String id) {
// ...
public String createText(String id) {
final String prefix = something(id);
// ...
The use of final
does not seem to be directly related to null
.
However, in combination with the non-null
guarantee in Assertion, you can almost completely guarantee non-null in your method. As a result, you can confidently delete unnecessary processing such as "I don't know what will come, so check" null
for the time being "in the intermediate processing.
Recommendation level:: star :: star:
import java.util.Collections;
public String createText() {
List immutables = Collections.singletonList("value1", "value2");
// ...
import java.util.Collections;
public String createText() {
Map<String, String> immutables = Collections.singletonMap("key1", "value1");
// ...
import java.util.Collections;
public List<Store> fetchStores() {
List<Store> stores = findAll();
return Collections.unmodifiableCollection(stores);
import com.google.common.collect.ImmutableMap;
public String createText() {
Map<String, String> immutables = ImmutableMap.of("key1", "value1", "key2", "value2");
// ...
import com.google.common.collect.ImmutableList;
public String createText() {
List<String> immutables = ImmutableList.of("value1", "value2");
// ...
It's a fairly local defense when it comes to immutable collections.
It reduces the risk of mixing null
elements into a collection once created, with the goal of caring for null
exceptions in subsequent intermediate processing.
It's sober, but it should be incorporated as much as possible.
Let's see how much the amount of information actually differs before / after application.
before
public class StoreService {
public Store fetchStore(String storeId){
// ...
}
public List<Store> fetchSisterStores(String storeId){
// ...
}
public List<Coupon> fetchCoupons(String storeId,
List<Category> categories){
// ...
}
}
after
public class StoreService {
@Nonnull
public Store fetchStore(final String storeId) {
Assert.notNull(storeId, "store-id must not be null.");
// ...
}
@Nullable
public List<Store> fetchSisterStores(final String storeId) {
Assert.notNull(storeId, "store-id must not be null.");
// ...
}
@Nonnull
public List<Coupon> fetchCoupons(final String storeId,
final List<Category> categories) {
Assert.notNull(storeId, "store-id must not be null.");
Assert.notNull(categories, "categories must not be null.");
// ...
}
}
Isn't it a more expressive code? Just by reading a few lines before and after the signature, you can instantly pick up most of the examples, and the code is user-friendly.
From the reviewer's point of view, the difference in the specifications of the List
type returned byfetchSisterStores (...)
andfetchCoupons (...)
is more apparent, and the quality of the review is likely to improve.
Choose the null
measures as a team and cut down the technical debt caused by null
to the utmost limit!
And let's realize the following merits with the whole team!
--Improved code readability --Improved review quality --Reduced nights when wetting pillows with Nullpo
Let's have a good null
life!
Recommended Posts