エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

2019/01/07週 気づきと振り返り

業務こなしての問題

Androidのprogaurd

年を跨いで対応していたが、いろいろひどい目にあった。

いじっていたが、何がダメなのか、袋小路に入って、ひたすら悩んでいた。
progaurdが無効のまま、progaurd.proに修正入れても反映されないでいろいろ悩んでいたりした。

もう、今となっては些細な問題だと思う。
仕組みをなんとなく覚えられたので、もう同じ轍を踏むことはないと信じたい。

package.jsonのdependenciyの削除

uninstallで消しましょう。
記述を削除すると、インストール済みのものが残ったままになり、間違って使ってしまって、他人がビルドしたとき、もしくは、CIかかったときに慌てるハメになる。

前にも書いた気がするな。。。

Androidのログ

タグは、パッケージ名を参考にしたほうがいいのではないかと思いました。
なぜなら、フィルタリングが楽になると思うから。

現場のタグ名が、クラス名になっているのだが、実装したクラスのログすべてをフィルタリングしたいってときに、どうすればいいのかかなり迷った。
結局、いい方法が思いつかなかったので、全出力で皿目で見るという作業になってしまった。

マジでタグ名をどうするかは、真剣に考えたほうがいい。

getter/setterの価値

俺は必要ないと思う派。

それなら、ただのpublicフィールドでいいじゃんって感じる。

カプセル化って言う人をたまに見るが、「ロジックが必要ない箇所に適用して、何か意味があるの?」って思う。
ロジックがないなら、普通にそのフィールドにアクセスしているのとなんら変わらないじゃんって思うんですよ。

JavaだとLombokが一時期話題になっていたが、そもそも単純getter/setterは必要ないと思っていたので、熱は早めに冷めた。

無力感

1ヶ月くらい、成果物を作ってない気がするのだが。。。
調査した結果、対応を見送る、難易度高すぎて諦めたタスクがいっぱいある。。。

存在意義とか、自分の能力を疑いたくなっちゃうよね。。。
他の人はタスクこなしているのに、俺だけ取れ高ゼロだもんな。。。

個人的に思いついた名言

  • 俺は組織の爆弾になる。潤滑油になどなるものか!
  • やればできる子なんだ。今はやらないだけなんだ。

【書評】読んだら忘れない読書術

読んだら忘れない読書術

読んだら忘れない読書術

まとメモ

基本原則

  • 記憶に残す
  • スキマ時間の利用
  • 速読より深読

読書術

ホームラン読書術

たくさん読むのではなく、読みたい本を選んで、自己成長に繋がるものを選ぶ。

守破離読書術

本を読む時、どのステージにいるのかを意識する。

守:基礎を学ぶ基本
破:他人の方法を学べる応用
離:自分のスタイルを学ぶブレイクスルー

自分のレベルにあってないものを読むのは、理解を困難にする。
自己満足を得るだけで、成長は得られない。

入門読書術

入門書で基礎知識と全体像を把握する。
深い学びを得るには必要なこと。

お勧め読書術

推薦されている本は、比較的ハズレを引きにくい。
誰が勧めているのかが重要。

自分軸読書術

売れているかどうかにかかわらず、自分が読みたい本か見極める。

専門書読書術

専門書は、大型書店で。

ネット書店読書術

  • 他者評価を知ることができる。
  • 他者評価は鵜呑みにしてはいけない。
  • レコメンドを使って本を紹介してもらう。

セレンディピティ読書術

自分の興味・関心を理解し、情報フィルターを準備しておく。
必要な本を発見できる確率を上げられる。

直感読書術

本を読むことで、本を見分けるデータが貯まる。
その結果、選球眼が養われる。

数珠つなぎ読書術

参考文献から次に読む本を選定する。
固め読みしたほうが、記憶に残りやすい

失敗しない基準

  • バランス良く読む
  • 長所を伸ばし、短所を克服させる
  • 情報と知識の偏りをなくす
  • ポートフォリオを作る

感想

ちょっと独善的すぎかなって気もする。

2018/12/17週24週 気づきと振り返り

業務こなしての問題

Oauth認証のImplictフロー

認証周りをImplictフロー利用してやるような実装に変えるタスクにチャレンジ中。
おそらく、refreshトークン使って再認証する処理を入れ込むと、ロジックが複雑になって、難読化するからだと思われる。

実装しているのだが、iframeを利用するのがうまくできない。。。
裏でアクセスさせるのが、途中でコケてしまうのよね。
年末で解決できなかったけど、たぶん、年始の俺が頑張って解決してくれるはず。

submoduleの移動

git mvで移動できる。
設定ファイルをイジって、git submodule sync したりするよりも、手間が少なく安全にできる。
設定ファイルをいじってやる場合、1日無駄に過ごす覚悟が必要。

gerritでhook忘れ

毎回忘れるのだが、新しくリポジトリをクローンしてきた際に、hookの設定をし忘れて、コミット&プッシュした時に、changeidが付与されず、あとあとコミットメッセージを入れ込む作業をしてしまう。
gerritのクローンコマンドに何か入れられないものなのだろうか?
クローンしてきたら、hookの設定を勝手にしてくれるのが一番嬉しいのだが。。。

logcatの切替

Androidで、logcatを環境ごとに出力するレベルを切り替えたいのだが、どうすればいいか?
build.gradleだったかをイジったが、その設定はダメっていうビルドエラーが出てきて萎えた。

個人的に思いついた名言

  • 明日の俺が頑張ってくれるはず。

intellij idea で micronaut + spring jdbc + sqliteのサンプル

きっかけ

年始が暇だから、何か作ろうと思い立った。
springbootでちゃっちゃと作ろうと思ったが、micronautで挫折したことを思い出し、再度チャレンジ。
とりあえず、動いたので、まとめる。

挫折したらそのままってのが、いつものパターンだったが、ゾンビランドサガを全話通して見て、再度チャレンジしたくなった。

まとめ

環境

OS

$sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.2
BuildVersion:   18C54

Java

$java -version
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)

Intellij IDEA

Intellij IDEA 2018.2.6 Community Edition

お金ないっす。。。
金がなくても、開発はできる。ちょっと手間が増えるだけ。

micronaut

$mn -V
| Micronaut Version: 1.0.2
| JVM Version: 11.0.1

インストールは、sdkmanを利用。
sdkmanは、Java関連の開発環境を用意するためのツール。
macのhomebrewみたいなもの。
前に調べたもののリンクを貼っておく。

suzaku-tec.hatenadiary.jp

インストールは、sdk install micronaut

sqlite

$sqlite3 -version
3.24.0 2018-06-04 14:10:15 95fbac39baaab1c3a84fdfc82ccb7f42398b2e92f18a2a57bce1d4a713cbaapl

sqlite関連

SqliteManager Version 4.8.1

まとめ

流れ

  1. micronaut初期化
  2. intellij にインポート
  3. とりあえずgoodmorning Saga!
  4. Sqliteにアクセスしてみる
    1. テストデータ用意
    2. spring jdbc + sqliteを追加
    3. ファクトリクラスの実装
    4. データアクセスサービスの実装
    5. コントローラクラスからDBアクセス
    6. 起動

micronaut初期化

まずは、micronautのプロジェクト作成から。

コマンドは、下記の通り

mn create-app {プロジェクト名}

このコマンドを打つと、カレントディレクトリにプロジェクト名のディレクトリが掘られて、gradle関連のソースが格納される。

今回は、mn create-app murakumoで作成

叢雲を選んだのは、個人のセンスです。

intellij にインポート

intellij を起動して、初期画面から import Project を選択してインポート。
インポートする際は、gradleのプロジェクトとしてインポートさせる。

じゃないと、いろいろエラーが出て挫折する。
たぶん、前回は、next連打してたから、気づかなかったのかも。。。
もしかしたら、import じゃなくて、openを選んで開いていたのかもしれない。

とりあえずgoodmorning Saga!

まずは、作ったら、goodmorning Saga!でしょ。
Hello Worldは、古い。

実装

package murakumo.controller;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

@Controller("/hello")
public class HelloController {

    @Get("/")
    public String index() {
        return "Goodmorning Saga!!";
    }
}

動作確認

下記コマンドで動かす。

$ ./gradlew run

そうすると、なんかビルドして動き出すはず。
自分の環境では、進捗が75%で止まるのだが、75%で localhost:8080/hello でアクセスすると、Goodmorning Saga!!が表示されるはず。
たぶんだが、75%のやつは、描画が更新されてないだけで、100%なんじゃなかろうか?

Sqliteにアクセスしてみる

今回は、いろいろORマッパーを探したけど、良さげなのがなかったので、Spring jdbcを使う。
本当は、脱springでやりたかったのだが、しょうがない。

テストデータ用意

まずは、DBの用意。
Sqliteは、DB作ると同時にtableも作らないとダメなので、ちょっとやっかい。

sqlite3 murakumo.db

カレントディレクトリは、murakumo直下

打つと、sqliteCLIに入るので、テーブルを作成する。 適当に、下create table sample(id, name)で、sampleテーブルを作る。
きちんとできているか確認するため、.tableを打つ。
そうすると、sampleって表示されるはず。

そしたら、一旦、sqliteCLIを抜けるため、.exitを打つ。
テーブルへのテストデータ投入は、sqlitemangerからやる。
sql文を打つのが早い人は、そっちでもいい。

spring jdbc + sqliteを追加

テストデータは用意できたので、今度はsqliteを利用するためのライブラリを追加する。

build.gradleのdependenciesに下記を追加。

    compile "io.micronaut.configuration:micronaut-jdbc-tomcat"
    compile 'org.springframework:org.springframework.jdbc:3.2.2.RELEASE'
    compile "io.micronaut:micronaut-spring"
    compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.25.2'

保存したら、勝手にライブラリのダウンロードが走るはず。

そしたら、今度は、jdbc接続用の設定を、application.ymlに追加する。
datasourcesが、今回追加した箇所。

micronaut:
    application:
        name: murakumo

datasources:
    default:
        url: jdbc:sqlite:murakumo.db
        driverClassName: org.sqlite.JDBC

ファクトリクラスの実装

今度は、jdbcアクセスようのDatasourceを生成するクラスを書く。
俺はよく知らないが、spring-jdbcは、こうやるものらしい。

package murakumo.factory;

import io.micronaut.context.annotation.Factory;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.sql.DataSource;

@Factory
public class JdbcTemplateFactory {

    @Inject
    DataSource dataSource;

    @Bean
    @Singleton
    JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource);
    }
}

JdbcTemplateを生成して返すだけ。

データアクセスサービスの実装

今度は、テーブルからデータを引っこ抜いてくるクラスを作る。

package murakumo.service;

import io.micronaut.context.annotation.Requires;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Singleton;

@Singleton
@Requires(beans = JdbcTemplate.class)
public class TestService {

    private final JdbcTemplate jdbcTemplate;

    public TestService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Transactional
    public void printSampleTable() {
        jdbcTemplate.query("select * from sample", (rs) -> {
            System.out.println(rs.getString("id"));
            System.out.println(rs.getString("name"));
        });
    }

}

printSampleTableが実際にDBアクセスしている箇所。
ResultSetをLambda使って処理できるのは、今っぽい。
昔だと、resultSet取ってきたら、ぐるぐる回して結果を見るのが多かった。

コントローラクラスからDBアクセス

当然、アクセスは、DIしたものを使ってやる。
アノテーションは、@Injection でできるらしい。
Springは、たしか、@Autowired だったかな?
@Controllerや@Getは、Springに近い動きをするので、なんとなくわかる。

package murakumo.controller;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import murakumo.service.TestService;

import javax.inject.Inject;

@Controller("/hello")
public class HelloController {

    @Inject
    private TestService testService;

    @Get("/")
    public String index() {
        testService.printSampleTable();
        return "Goodmorning Saga!!";
    }
}

TestServiceをDIして、indexで使ってるだけ。

起動

./gradlew run で起動して、localhost:8080/helloにアクセス。

すると、ターミナルに、登録したデータが表示されるはず。

感想

なんでだ。。。
何に苦戦してたんだ、俺は。
すんなりできすぎて、逆に怖いんですけど。

あとは、spring-jdbcの知識がつけば、いろいろできそう。

組み込み系のDBは、もうsqlite一択な気がしてきたな。
mysqlやpostgressも考えたけど、環境準備するのが面倒くさいんだよね。
手軽に永続化できるのが、魅力だと思う。
docker使えば、mysqlとかの準備も楽そうな気もするが、dockerの習熟度がまだ足りない。

参考サイト

javaからsqliteに素早く書き込みたい - Qiita

Using Spring's JDBCTemplate with Micronaut

Spring Boot - Spring Boot MavenでSQLite3に接続したい。|teratail

データベースの作成と接続 - SQLite入門

java.lang.reflect.Proxyクラスを試してみる

きっかけ

JavaのAdvent Callendar で、Proxyクラスについて触れている記事があった。
そういえば、試したことが無かったので、暇な年始に試してみた。

実験

環境

java

$java -version
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)

os

$sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.2
BuildVersion:   18C54

実装

今回、結構てこずった。。。。
何にてこずったかと言うと、必要となるクラスが思ったより多かったので、それの役割を理解するのが辛かった。。。
Javaのリフレクションの動きは分かっていたが、クラスが増えると、意外と混乱する。
あと、Javaから離れていたせいか、staticメソッドの制約を忘れていて、ドツボにハマった。。。

まずは、必要となるクラスの説明から

  • Main:実験用に呼び出すクラス
  • IFの定義(interface):今回のテスト対象のクラスのIF定義。なくてもいい気もするが、実装の隠蔽のためのプロキシなので、実際に使われる際の状況を意識するために用意
  • 呼び出すクラス:IF定義を実装したクラス。こいつを呼び出す。
  • Proxy:代理呼び出しの実装をするクラス。
  • Handler:呼び出すクラスとプロキシの間を中継するクラス。

では、実際に実装へ

IF定義

public interface Driveintori {
  public String getStoreName();
}

みんな大好き、ドラ鳥をテーマに実装していきます。
ドラ鳥ってなんだ?って思った人は、「ドライブイン鳥」、もしくは、「ゾンビランドサガ ドラ鳥」で検索してね。

呼び出すクラス

public class DriveintoriImpl implements Driveintori {
  @Override
  public String getStoreName() {
    return "ドライブイン鳥 伊万里店";
  }
}

伊万里店として実装。

Proxy & Handler

ここが一番重要。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DriveintoriProxy {
  private Driveintori store;
  private Object proxy;

  private DriveintoriProxy(Driveintori store) {
    this.store = store;
    this.proxy = Proxy.newProxyInstance(Driveintori.class.getClassLoader(), new Class[] { Driveintori.class },
        new DriveintoriHandler());
  }

  public static Driveintori createProxy(Driveintori store) {
    DriveintoriProxy dp = new DriveintoriProxy(store);
    return Driveintori.class.cast(dp.proxy);
  }

  /**
   * Proxyのメソッド呼び出しハンドラ.
   */
  private class DriveintoriHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println("Let's go Doratori!!");
      Object o = method.invoke(store, args);
      System.out.println("comming agein Doratori!");
      Class type = method.getReturnType();
      return type.cast(o);
    }
  }
}

DriveintoriProxyのコンストラクタで、Proxy.newProxyInstanceしているのが実際のプロキシの生成処理。
一番厄介なのは、Objectで返すところ。
本当は、引数で指定したclassの型を返して欲しいのだが、何か理由があってこういう実装になったのだろうか?
汎用性を意識しすぎて、使いにくい気がしないでもない。 使う側としては、DroiveintoriのIF定義で返して欲しいので、createProxy内でキャストして返してる。

Handlerクラスというのは、DriveintoriHandlerが該当する。
実際に、生成したProxyクラスでメソッド呼び出しをすると、DriveintoriHandlerのinvokeを経由して、Driveintoriの実装クラスであるDriveintoriImplが呼び出される。

Mainクラス

public class Main {
  public static void main(String[] args) {
    System.out.println("start");
    Driveintori proxy = DriveintoriProxy.createProxy(new DriveintoriImpl());
    var name = proxy.getStoreName();
    System.out.println("name:" + name);
    System.out.println("end");
  }
}

各クラスを繋ぎ合わせて実験。

実行結果

実際に実行してみる。

start
Let's go Doratori!!
comming agein Doratori!
name:ドライブイン鳥 伊万里店
end

ドラ鳥の伊万里店が表示されました。

所感

やっぱり、クラス多くなるのがネック。
クラス図描いていかないと、実際の業務で利用するってなった時に、結構迷いそう。

気になったのは、実際にリフレクションするのと、Proxy使うのとで、アクセス時間に差がでるのかが気になった。

使われそうな箇所としては、ログ周りかなと思う。
あとは、DB接続とかの前処理・後処理が必要となる箇所。
切替が必要そうな箇所は、だいたい適用できるのではないかと思う。
ただ、本当に適用が必要なのかは、よくよく考える必要があるとは思うが。

参考サイト

Proxy (Java Platform SE 8)

java.lang.reflect.Proxyの使い方(1) - Qiita

Macで日本語入力するときの変換でイラついた話

きっかけ

年始が暇だから、いろいろブログの記事を書こうと思ってタイピングした際に、ムカついたことがあったので、晒す。

顛末

macを使っているのだが、入力して変換する際に、変換したい文字にカーソル当ててエンターを押したら、文字が確定してなくて、続きの文字を入力して変換が変になった。

ライブ変換という機能らしい。

慣れれば使えるのかもしれないが、windowsと環境を行ったり来たりするので、とても不便だった。
ライブ変換を切れば、windows環境と同じタイピングができるようになる。
※参考サイトの中身を参照

メニューバーに入力切替のアイコンがない場合は、システム環境設定→キーボード→入力ソースにある、「メニューバーに入力メニューを表示」にチェックを入れれば、表示される。

思うこと

思うんだけど、ライブ変換って、タイピング量が増える気がするのだが、気のせいか??

もしかしたら、全角入力のための機能ではないのかも知れない。

参考サイト

Mac - 日本語入力のライブ変換を「オン/オフ」に設定 - PC設定のカルマ

Javaでカスタムランタイムを試す

きっかけ

JavaのAdvent Callenderでjigsawでカスタムランタイム作ってる記事を見て、そういえばまだやってないなって思ってやろうと決心した。

実験

実装

実験の流れ

  1. サンプルクラス作成&実行
  2. jarを作る
  3. 依存モジュールの調査
  4. 最小構成JRE作成
  5. 4で作成した環境で実行してみる。

環境

os

$sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.2
BuildVersion:   18C54

もう、mojaveです。
最初、 もじゃば と読んでしまった流派の人です。
モハベが正しいらしい。
海外では、ややこしい読み方をカッコいいと感じるのだろうか?
日本だと、無理矢理感のあるルビは、もうイタイの部類に入ってきたと思うが、世界は遅れているな。

ダークモードにしたくて、恐る恐る変えた。

java

$ java -version
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)

実験のたたき台クラス

簡単なサンプルクラスを作る

public class HelloSaga {
  public static void main(String[] args) {
    System.out.println("Hello Saga!");
  }
}

もう、佐賀が好きすぎて hello world じゃなくて hello Saga にしないと気が済まない。
worldより偉大なSagaであります。

コンパイル実行

$ javac HelloSaga.java
$ java HelloSaga
Hello Saga!

当然、動きますよね。

jarを作る

これから、いろいろやるための準備として、jarを作る。

jar --create --file hello.jar --main-class HelloSaga HelloSaga.class

当然、動きます。

$ java -jar hello.jar
Hello Saga!

依存関係を調べる

java9で入った、jdepsコマンドで、依存しているモジュール郡を調べる。

$jdeps --list-deps hello.jar
   java.base

System.out.println が標準クラスに属しているので、 java.base のみが出てくる。

--list-depsは、公式サイトの説明を見ると、モジュールの依存関係の他、JDKの内部API (参照される場合)のパッケージ名もリストします。 とある。
コマンドの説明が見たい場合は、jdeps -hで参照可能。

ちなみに、何もつけないで実行した場合、下記の表記になる。

$jdeps hello.jar
hello.jar -> java.base
   <unnamed>                                          -> java.io                                            java.base
   <unnamed>                                          -> java.lang                                          java.base

java.ioだけだと思ったら、Stringも使ってるから、java.langも入るのか。。。
ただ、どっちもjava.baseに入っているから、見たい情報が重複するので、依存モジュールを見たいときは、--list-deps をつけるのが良さそう。

小さなJREを作る

依存しているモジュールが、java.baseだけということがわかったので、java.baseのみのJREを作る。
JREを作るには、jlinkコマンドを使う。

jlink --compress=2 --module-path "{jdkのパス}/jmods" --add-modules java.base --output jre-min

自分は、なぜかjlinkの環境パスが通ってなかったので、フルパスを打って実行した。
jenvを使っているのだが、それがいろいろやっているんでしょ?的な感じがした。
本題とそれるので、スルー。
目的を見失うからな。

とりあえず、jlinkのコマンド説明。

jlink

参考サイトにもオプション説明はあるが、疑問符が浮かぶ箇所もあったので、改めて説明をまとめる。

引数 説明
--compress=2 圧縮オプション。2を指定するとzipで圧縮。0はなし、1は、定数の共有
--module-path jlinkツールで参照可能なモジュールを検出するパス。
--add-modules 追加するモジュール郡。複数指定可能。今回は、java.baseのみを使うので、ここに指定
–output 出力する場所

オプションを詳しく知りたい場合は、 jlinks -h で調べられる。

上記のJRE生成コマンドを実行した場合、jremin ディレクトリが作られる。

もとのJREのフォルダのサイズを調べたが、自分の環境では286Mあった。
生成したjreminは、26M。
java.baseしか使ってないからだが、かなり減った。

実行

何も入ってない環境にするのが億劫なので、手打ちで試す。

$jremin/bin/java -jar hello.jar
Hello Saga!

無事に動いた!
最悪、javaをインストールしてない環境でも、生成したJREとjarがあれば、動かせるってことですね。
これらをIoT端末に載せて動かそうってのが、意図だろう。
もしかすると、末端の部品は、更に省メモリだから、エッジ端末くらいかもしれないが。
ハードのことは、よくわからんとです。
Androidが可能性として高そうな気がする。

考察

jdeps/jlinkといったツールが、かなり使える印象。
ある程度、ソフトウェアが育ってしまうと、モジュール分割したい要望が出てくるので、それを調査するのにも使えそう。
とういうか、モジュール分割をする作業をjavascriptでかなり苦戦してやっていたので、このツールのありがたみは、よく分かる。

初めてカスタムランタイムを作ったが、思ったよりあっさりできた。
もっと苦戦すると思ったんだがな。
環境周りの知識がついてきているおかげかも知れない。

参考サイト

アプリケーション配布用に小さなJREを作る

jdeps

jdeps

jlink