聞こえないJavaエンジニアが適当に書き連ねていく

つらつらとメモしたり日頃の溜まっている想いを吐き出す場所です。

プログラミングと執筆

プログラミング言語とあるのだからJavaCOBOLC言語も日本語や英語と同じ言語と言える。文法が違うだけ。

言語なので、プログラミングイコール執筆、または作文と同一なのではないか。

文章にするときは起承転結や全体の構成が大事。それはプログラミングでも同様で、まず処理全体の構成を考えて、それから内容を詰めていく。

変数名イコール文章内での言葉の使い方であり、適切な言葉を使うことでその文書全体の読みやすさ、伝わりやすさが変わってくる。

プログラマーイコールインタビュー、または編集者と考えられる。プログラミングは相手が伝えたいことを形にするもの、インタビュー記事は相手が伝えたいことを文章にするもの、出来上がるものは違うけどやりたいことは同じなのでは。

パッケージング&クラス名イコール索引であり、目的のところにたどり着くための手がかりである。適当にパッケージングして、適切なクラス名をつけると、書いている時は覚えているかもしれないが、後から読む人にとっては手掛かりがないので読めない。

コメントイコール注釈であり、仕様説明用のコメントイコール図解である。注釈が多い文書は読みにくいし、図解がない文書は読みにくい。

フォーマットイコール段落であり、段落がガタガタな文書は読みにくい。

 

一人で書くプログラミングでも、今プログラムを書いている時に読めていたコードが数日後の自分も読めるかは非常に怪しいものがある。

チーム開発は赤の他人が集まって行うものなので、他人が読みやすいものになっているかを充分に意識して書かないといけない。

 

 

 

Effective Java 第3版を買いました

Effective Java 第3版を溜まってた楽天ポイントで買ったので実質無料でゲットなのです。

f:id:su_zu_ki_1010:20181030143926j:image

1ページめくるたびに、わかるような、わからないような、そんな気分を味わう。でも、それでいいのです。載っている90個全てがすぐに完全に理解できるわけがないので、実務と読書を繰り返してある日ストンと腑に落ちる日が来ればいいんだろうなー、と思いながら睡魔に耐えてまたページをめくる、そんな日々。

第2版も出版されてからかなり時間が経っているのに、今でも読み返すと新しい気づきがある。

第3版も一度、通して読み終えたら気になる部分を再度読み返して行くことで理解を深める、そんな本ですね。

Java初学者にはオススメ出来なくて、むしろ、Javaは完全にマスターしました!という人が読むべき本。

Spring Boot 2.0.6で日時を固定したテストを書きたいとき

断り書き

個人的な覚書です。 バージョンアップで動かなくなる可能性があるので検索でヒットして、真似る時は気を付けてください。

前提

以下に書かれている記述が動いた時のバージョンは以下の通り。

  • Java 1.8
  • Spring boot 2.0.6
  • JUnit Platform 1.3.1
  • JUnit Jupiter 5.1.1 (Spring boot のtesterデフォルト)
  • JUnit Vintage 5.1.1 (Spring boot のtesterデフォルト)
  • Jmockit 1.43

やりたいこと

プログラム内で行っている、システム日付取得の部分をJUnitでのテストの時は固定の日時にしたい。 ※時間に応じて挙動が変わる個所があるため。

試したこと

ダメだったもの

最初はここに書かれている内容を真似して書いたらうまくいった。

JMockit を使用して LocalDateTime.now() で指定した日時を取得する. · GitHub

しかし、実はJmockitのバージョンがかなり古いものを使っていた。(どこかの記述をコピペしたのが原因)
諸事情でIDEを変えた時に、JMockitのバージョンも上げたら java.lang.ExceptionInInitializerError を吐いてしまった…。
調べると、JMockitのバージョンアップで今まで書けていた内容がNGになった模様。

うまくいったもの

仕方ないので再度調べ直したら、以下のサイトがヒットした。

sebastiankoltun-blog.com

ここに書かれていることを参考に、書き直したら日時を固定できるようになった。

現在日時を返すだけのfactoryクラスを作る。

import java.time.LocalDateTime;

import org.springframework.stereotype.Component;

@Component
public class TimeFactory {

    public LocalDateTime now() {
        return LocalDateTime.now();
    }

}

呼び出す側は、TimeFactory.java をインジェクションする。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import org.springframework.stereotype.Component;

@Component
public class TimeFactoryCall {

    private TimeFactory clock;
    
    public TimeFactoryCall(TimeFactory factory) {
        this.clock = factory;
    }
    
    public String get() {
        
        LocalDateTime date = clock.now();
        return date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
        
    }
    
}

テストプログラムはこんな感じ。

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

import java.time.LocalDateTime;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@SpringBootTest
class TimeFactoryCallTest {

    @MockBean
    private TimeFactory clock;

    @Test
    void test() {

        LocalDateTime TEST = LocalDateTime.of(2018, 10, 16, 14, 23, 59);
        when(clock.now()).thenReturn(TEST);

        TimeFactoryCall call = new TimeFactoryCall(clock);

        assertEquals(call.get(), "2018/10/16 14:23:59");

    }
}

他に参考にしたサイト

qiita.com

“ゴミ記事” について考えてみた

最近、エンジニアはブログを書けとかゴミ記事は書くな、という話題をシステム開発界隈で見かけるので個人的に思うことを書いてみる。

 

まず、ブログを書けという論調、これには同意する。個人的なメモでも、1ヶ月後の自分、1年後の自分にとって役にたつことがある。

ただし、その場合は未来の自分が検索ワードに使いそうな言葉を必ず書いておくこと。今は自明な言葉でも、未来の自分は忘れている可能性が大だから。

それに、やってみたときのバージョン情報も必ず載せること。バージョンによって動いたり動かなかったりすることがあるので、このバージョンで動いたという事実を載せることは大事。

 

次に、ゴミ記事は書くなという論調。これも気持ちとしては分からなくも無い。自分も検索してヒットしたものが求めていなかった内容だった時は一瞬空を仰ぐし、ため息も出てしまうかもしれない。

でも、自分にとってゴミ記事でも、他の人にとってはお宝かもしれない。

やってみた記事であれば、自分は動かなかった内容がその人は動いているわけで、何が違うのか?を確認することが出来る。逆に、もしかしたら当時は動いたけどバージョンアップで動かなくなった、ということがわかるかもしれない。

やってみたけど動かなかった、という記事もゴミ扱いされるが、ちょっと待ってほしい。

まず、動かなかった、をそのまま信じてしまうのは勿体ない。バージョンアップで動くようになっているかもしれないから。

同じバージョンだとしたら、あなたがやろうとしていることは今のバージョンでは出来ない、という事実がわかるので諦めるきっかけになるのではないか?

 

あとは、その記事を書く場所は適切な場所なのか?を考えてみる必要があると思っている。

自分のブログなら何を書いてもいいと思うが、情報共有系のサイトに書く時はそのサイトの指針にあっているかをちゃんと考えないといけない。

 

まぁそんなことをポンコツエンジニアはいろいろ読みながら考えたよ、っていうね。

 

 

今更ながらJavaでプレミアムフライデーを求めるロジックを考えた

www.waenavi.com これを読んで、Javaだとどうやって書けばいいか考えてみた。

まず、Java8以降は日付は LocalDate を使うようなのでAPIを読む。

LocalDate (Java Platform SE 8)

月末日をまず求めて、その日が金曜日じゃなかったら1日ずつ遡って曜日をチェックしていけばいいかな、と思いながら last をキーワードにしてページ内を検索してみる。

result = localDate.with(JULY).with(lastDayOfMonth());

という一文が出てくる。 これはいったい?と思い、ちょっとページを上に動かすと with というメソッドの説明だった。

https://docs.oracle.com/javase/jp/8/docs/api/java/time/LocalDate.html#with-java.time.temporal.TemporalAdjuster-

説明文を読んでみると、

一般的な調整の選択は、TemporalAdjustersで指定します。

と書かれており、TemporalAdjusters へのリンクが貼られている。

TemporalAdjusters (Java Platform SE 8)

リンクをクリックして、どんなメソッドがあるのかなと眺めると

lastInMonth(DayOfWeek dayOfWeek) 一致する最後の曜日を持つ同じ月の新しい日付を返す、月の最終アジャスタを返します。

という今回の用途にバリバリ使えそうなメソッドの説明が載っている。

https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/TemporalAdjusters.html#lastInMonth-java.time.DayOfWeek-

どうやらこれを使えば欲しいものが求められそう。

念のため、DayOfWeek へのリンクもクリックしてどんな定義があるのか眺めてみる。

DayOfWeek (Java Platform SE 8)

FRIDAY 「曜日」金曜日のシングルトン・インスタンス

という記述が確認出来たので、金曜日を求めるには FRIDAYという列挙型定数を使えばいいことが分かった。

あとはこれらを組み合わせてプログラムを書くだけである。

というわけで書いたのがこのプログラム。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.DayOfWeek;
import java.time.LocalDate;

import static java.time.temporal.TemporalAdjusters.lastInMonth;

public class LastFriday {

    private static final Logger logger = LoggerFactory.getLogger(LastFriday.class);

    public static void main(String... args) {

        var lastFriday = LocalDate.of(2017,2,24);
        logger.info(lastFriday.toString() + " " + lastFriday.getDayOfWeek());
        for(int i = 0; i < 99; i++) {
            lastFriday = lastFriday.plusMonths(1).with(lastInMonth(DayOfWeek.FRIDAY));
            logger.info(lastFriday.toString() + " " + lastFriday.getDayOfWeek());
        }

    }

}

まぁQiitaだと1年半ほど前に既に既出なんですけどね。

qiita.com

答えをすぐに検索するのではなく、JavaDocの中をどのようなキーワードで検索して書いたかの備忘録としてネットの片隅にメモしておく。

オリジナルのmaven archetype を作った

これは何?

デフォルトでmavenコマンドからJavaプロジェクトを作成すると、Java5+JUnit3.8.1のプロジェクトが出来る。 流石に古いので最新バージョンのプロジェクトが出来るようにオリジナルのarchetypeを作成したときのメモ。

作成手順

Maven – Guide to Creating Archetypes を見ながら手を動かせばそれなりのものが出来る。

作ったもの

github.com

メモ

  • JUnit5の依存関係はJUnit 5 User Guideチュートリアルにあるmavenプロジェクトの記述をコピーした。
  • ただ、サンプルプロジェクトの記述をコピーしただけだとeclipseでJUnit5を動かそうとすると落ちるので記述の追加が必要。

qiita.com

感想

意外に簡単だった。

"git configをプロジェクトによって使い分ける" 導入メモ

"git configをプロジェクトによって使い分ける" 導入メモ

Gitアカウントを使い分ける必要が生じたので qiita.com

を見ながら作業しようとしたら上手くいかなかったのであれこれ試行錯誤したときの個人的なメモ。

うまくいかなかったところ

gitconfigを見ながら書かれている通りに書いたつもりなのに、使い分けが出来ていなかった

原因

"Git v2.13.0(2017/05/10リリース)でgit configにConditional includes(条件付きインクルード)という機能が実装され" とあるのに、ローカルのGitのバージョンが2.9だった。

やったこと

sbtをインストールする · Scala研修テキストchocolatey.org

というツールがあるのを知った。 コマンドで一括更新できるという部分に魅力を感じていたので、まずは chocolatey をインストールする。

chocolatey のインストール

Installation に書かれているコマンドを実行すればいいが、PowerShellを管理者モードで起動しないとエラーになる、というところで一度はまる。 管理者モードで立ち上げた後はハマリポイントは無かった。

Gitのインストール

  • chocolatey.exe list -v -e Git でGitがバージョン管理下にあることを確認する。2.19が存在することを確認出来た。
  • chocolatey.exe install Git でGitをインストールする。
  • git --version で2.19がインストールされていることを確認する。

改めて git config を編集

Windowsなので\\でエスケープしないといけないのかなと思い、パスを\でエスケープしてみたが設定が反映されない。 検索したら stackoverflow.com を発見したので読んでみる。 回答の記述がスラッシュでの記述だったので、スラッシュに書き直してみる。 確認コマンドも回答に書かれているように、

git config --show-origin --get user.email

で確認してみた。

[includeIf "gitdir:C:/Users/<users>/Documents/sampledir/"]
  path = .gitconfig_work

と定義したとき、

sampledir  ← .gitconfig の定義が使われる
   ├ aaa  ← .gitconfig_work の定義が使われる
   └ bbb  ← .gitconfig_work の定義が使われる

ということが分かった。