きり丸の技術日記

技術・エンジニアのイベント・資格等はこちらにまとめる予定です

200記事突破しました

2021/04/15(木)に投稿した記事で200記事を突破しました!

f:id:nainaistar:20210417180419p:plain

投稿数を確認してみると、100記事を突破したのが2020/09なので、8ヵ月で100記事を書きました。3日に1投稿、週に2-3記事を書いたことになりますね。12月がアドベントカレンダーということもあり、投稿数はそこで稼げています。

f:id:nainaistar:20210417180436p:plain

PV数

PV数は少しずつ伸びてますね。月単位で見ると有意に増えていると言って良さそうです。

f:id:nainaistar:20210417180447p:plain

100から200記事まで変化を見てみると、8割のアクセスは100から200記事までの間に来ていただいたようですね。ありがたいです。

f:id:nainaistar:20210417180502p:plain

具体的な記事のPV

全期間と比較しても、100記事以降のPV数とあまり変わらないようですね。300記事を書いたときに、また200記事以降の記事で満たせるようにしたいです。

f:id:nainaistar:20210417180516p:plain f:id:nainaistar:20210417180530p:plain

終わりに

2021年も100記事は書こうとは思っています。週2投稿のペースなら9月くらいに達成できそうですね。300記事は12月頃でしょうか。

もっといいエンジニアになって、自分用の記事を量産していき、ついでに文章力等を上げて本業にも活かせるようにしたいです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

JavaでNullPointerException回避する方法をまとめる

今日も小ネタ。

NullPointerExceptionを回避するのは簡単だけど、もうちょっとスマートに書けない?

ということを纏める記事。

余談ですが、NullPointerExceptionは「ぬるぽ」とか大文字取って「NPE」とか呼んでます。以後、「NPE」で統一します。

環境

データ構造

次のような親子孫関係を持つ。

リストでのNPE回避も表現したいので、リストも持たせています。

  • Parent
    • Child
      • GrandChild

f:id:nainaistar:20210410182258p:plain

一番シンプル

!= nullで回避するのが一番簡単です。

nullは基本型なのでIDEで色分けされて見やすいので、よく使用しています。

Parent parent = null;

if(parent != null) {
  // 以後の処理
}

ただし、入れ子が複雑になると、都度null回避をしなければならないので面倒です。

if (parent != null ||
  parent.getChild() != null ||
  parent.getChild().getGrandChild() != null) {

  BigDecimal zero = parent.getChild().getGrandChild().getRate();
}

Optional型を使用する

Optional型に設定する方法があります。

Parent parent = null;

Optional.ofNullable(parent)
  .orElse(null); // もしparentがnullならnullを返却する

入れ子構造が複雑になっても、中間でNPEが発生しないのでコードが書きやすいです。

Optional.ofNullable(parent)
    .map(Parent::getChild)
    .map(Child::getGrandChild)
    .map(GrandChild::getRate)
    .orElse(BigDecimal.ZERO)

型変換したい時にもOptional型を使うと、安全にNPE回避できて便利ですね。

BigDecimal a = null;
Optional.ofNullable(a).map(BigDecimal::toPlainString).orElse(null);

Objects型を使用する

Objects型にisNullnonNullメソッドがあります。

Parent parent = null;

if(Objects.nonNull(parent)) {
  // 以後の処理
}

私は単体で扱うことはあまりなく、Stream処理のfilterでNPE回避のためによく使用します。メソッド参照を使用すると、思考コストが減るので便利です。

// 親と子はいるが、孫がいないので、NPE回避を導入しないとエラーになる
ArrayList<Child> baseDetailList = new ArrayList<>();
baseDetailList.add(Child.builder().build());

Parent parent = Parent.builder()
  .children(baseDetailList)
  .build();

assertThat(
  Optional.ofNullable(parent.getChildren())
    .stream().flatMap(Collection::stream)
    .map(Child::getGrandChildren)
    .filter(Objects::nonNull) // NPE回避用ロジック
//  .filter(e -> e != null) 一瞬、何がNullではないものかがわからない。  
//  .filter(e -> e.tax != null) 実はtaxがNull以外かもしれない、という思考になる
    .flatMap(Collection::stream)
    .map(GrandChild::getRate)
    .collect(Collectors.toList())
).isEmpty();

どのNPE回避方法がオススメ?

NPE回避できればどれでもいいです。どれを使っていたらカッコイイ、とかも無いと思います。

次のコードは同じ処理をしていますが、はっきり言うとどれもイケてないな、と感じてしまいます。

BigDecimal a = null;

String hoge = a == null ? null : a.toPlainString();
String fuga = Optional.ofNullable(a).map(BigDecimal::toPlainString).orElse(null);

TypescriptにはOptional Chaining、KotlinにはSafe CallというNPE回避する方法があります。?.と書くだけです。これで書けたら一番カッコイイのですが、Javaにはありません。

String hoge = a?.toPlainString();

個人的には次の手癖でコーディングしています。参考程度に見てください。

  • 入れ子構造と型変換が少ない
    • == null
  • 入れ子構造と型変換が多い
    • Optional型を使う
  • Stream APIで処理する
    • Objects型を使う

ソースコード

https://github.com/hirotoKirimaru/cucumber-sample/blob/332777e969ef1836e0e3cd0653db6ee59bacc610/src/test/java/kirimaru/biz/domain/nest/OptionalTests.java

https://github.com/hirotoKirimaru/cucumber-sample/blob/ce9c23e0bcbd7385753c20e85288cbe658463b33/src/test/java/kirimaru/biz/domain/nest/NPETests.java

終わりに

Optional型は自分で生成するものではない、というイメージからなんとなく避けていましたが、複雑になったケースだと一考の余地ありますね。今回、Optional型で色々検証して安全にデータを取り出せることに気づけて良かったです。

まぁ、気を付けていても結構な頻度でNPEは起こしちゃうんですけどね…。

できれば、@Nullable@NonNullとか表現はしてほしいのですが、自分も付与し忘れることはたくさんあるので人のことは言えません。

NPEの回避って地味に面倒なのであんまりやりたくはないのですが、起こしてしまうと恥ずかしいので今後も地道に頑張りたいです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

類似記事

JavaでNullを意識せずにNullableな配列項目をStream APIで処理する nainaistar.hatenablog.com

f:id:nainaistar:20210410153137p:plain

【Tips】GoogleDriveでバックアップするなら元ファイルを最新とすべき

小ネタだけどよくやらかすのでメモ。


ファイルをコピペして、特定のバージョンを示すためにバックアップを残すことはよくあると思います。

GoogleDriveのスプレッドシートでは、履歴を持つことができ、更に復元できます。

しかし、バックアップのファイルの作成方法を間違えてしまうと、履歴を残すことができなくなります。

今回の記事では、GoogleDriveで履歴を残したままファイルをバックアップする方法を記述します。

スプレッドシートの履歴ごとコピペする方法の記事ではありません。

環境

ゴール

  • 履歴があるファイルを最新ファイルとして残す
    • ファイルを変えないので、URLが変わらない
  • 履歴がないファイルをバックアップファイルとして残す

概要

  • 既存のファイルを最新ファイルとして扱う
  • コピーしたファイルをバックアップファイルとして扱う

バージョンが無い場合

特に複雑なことはありません。

  1. バックアップ対象のファイルを右クリックしてコピーします

f:id:nainaistar:20210404231258p:plain

  1. コピー先の「XXXのコピー」をバックアップファイルとします

f:id:nainaistar:20210404231320p:plain f:id:nainaistar:20210404231336p:plain

「XXXのコピー」だけ修正すればいいので、わかりやすいですね。

バージョンがある場合

ちょっとだけ複雑になります。

バックアップ前の状態は、既にV1, V2のファイルがある状態とします。

f:id:nainaistar:20210404231354p:plain

  1. 最新のバージョンファイルを右クリックしてコピーします

f:id:nainaistar:20210404231408p:plain f:id:nainaistar:20210404231420p:plain

  1. 最新のバージョンファイルのバージョンアップします

今回の例では「V2」ファイルを「V3」のバージョンアップします。

※ 「V2のコピー」を「V3」にしないでください。コピーファイルには履歴は存在しません。

f:id:nainaistar:20210404231434p:plain

  1. バックアップしたファイルをバージョンアップ前のバージョンにします

今回の例では「V2のコピー」を「V2」にします。

f:id:nainaistar:20210404231450p:plain

備考(バックアップ後の履歴)

履歴を確認するには、リボンの右側にある「最終編集:」のリンクをクリックします。

f:id:nainaistar:20210404231506p:plain

今回のV3には履歴が残ります。

f:id:nainaistar:20210404231536p:plain

今回のV2には履歴が残りません。「コピペした日時」の履歴のみ残ります。

f:id:nainaistar:20210404231819p:plain

履歴以外のメリット

既存のファイルを最新とする = ファイルは変わりません。ですので、ファイルのURLが変わりません。

GoogleDriveのファイルを設計書として共有している場合、常に最新バージョンを参照できることになります。

GoogleDriveは頭がいいので、前回参照したファイルを提案してくれます。また、ディレクトリが変わっても、ファイルのリンクは変わりません。これが合わさると、ファイルのディレクトリがバックアップやOldフォルダに移っても気づきづらいです。

以前参画したプロジェクトでは、古いバージョンを参照してしまい、認識齟齬が頻発していました。

終わりに

GoogleDriveでのバックアップ方法なんて、地味な内容ではあります。

しかし、失敗した時のデメリットが想像以上に大きいです。

古い設計書を参照していた場合、最新の設計書との差分を見ないと取り込めませんからね。しかも、誰がどのバージョンの設計書を参照しているかを把握する方法はありません…。(同一ファイルを参照するとアイコンがつくので、わかりますが)

相手がリンク集を作ってたりすると、もっとファイルが古くなっていることに気付く手段が少なくて最悪ですね。

そもそもコピペでバックアップするな、という話もありますが。履歴自体の上限数があったり、意図しない履歴も残ってしまったりと、キッチリ履歴を運用していくのも厳しいものがあります。

もし、GoogleDriveを使用しているかたはこの記事を見て、GoogleDriveの運用方法を見直しするきっかけになれば幸いです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考

kdnakt blog:Googleスプレッドシートの履歴からファイルを復元する kdnakt.hatenablog.com

f:id:nainaistar:20210404232230p:plain