mike-neckのブログ

Java or Groovy or Swift or Golang

Spring Batch を Spring Boot で作った場合のプロセスの終了コード(exit code) の設定の仕方

f:id:mike_neck:20200309072715p:plain

Spring Batch で終了コードを設定する方法を調べると、おそらく次の資料に出くわす

docs.spring.io

terasoluna-batch.github.io

ただ、 Spring Boot で Spring Batch を作る場合はこの方法では多分うまくいかない。これらの資料では Spring Batch にある CommandLineJobRunner というクラスで実行することを前提にしている。しかし、 Spring Boot で作ったバッチの場合は spring-boot-autoconfigure にある JobLauncherCommandLineRunner によって起動されるため、これらの資料の方法で作る ExitCodeMapper は使われない。

続きを読む

ターミナルで画像ファイルをクリップボードにコピーするツール作った

表題にあるようなツールがないかと探してみたのですが、テキストをクリップボードにコピーするツール(pbcopy のラッパー)は見つかるものの、画像ファイルをコピーするツールが見当たらないので作ってみた。

github.com

README.md に書いてありますが、コマンドのパラメーターに画像ファイルを指定するだけです。

$ imgcopy <クリップボードにコピーしたい画像ファイル>

制限事項として PNG 形式のみサポートしていて、 GIF と JPEG は対応していません。 Cocoa フレームワークの制限です。

配布できるようにしたかったけど、 codesign のあたりで面倒になってきたのでやめました。そのうちやるかもしれない

インストール

上記のレポジトリーをクローンして、 make build するだけ。ビルドしたら .build/release というディレクトリーにバイナリーができてるので、あとは適当にパスの通っている場所に置くだけ。なお、 Cocoa と書いている通り、 Mac OSX でしか動きません。

使い所

画像ファイルだけを集めておくディレクトリーを作っておいて、 peco と一緒に使うのがよさそう

f:id:mike_neck:20200224124849p:plain

f:id:mike_neck:20200224124928p:plain

f:id:mike_neck:20200224125023p:plain

最近見た残念なコード

最近見た残念なコード。なお、プロダクションで使われているコードなので、意味内容を変えつつ誇張して書いているため、実際はここまでひどくはない。

class App {
  Map<String, String[]> map;

  public void add(String protocol, String base, String[] paths) {
    for (String path : paths) {
      String[] items = new String[3];
      if (!map.containsKey(path)) {
        items[Constants.APP_URL_PROTOCOL] = protocol;
        String sep = paths.startsWith("/")? "" : "/";
        items[Constants.APP_URL_URL] = protocol.concat("://").concat(base).concat(sep).concat(path);
        items[Constants.APP_URL_PATH] = path;
        map.put(path, items);
      }
    }
  }

  public boolean storeUrls() {
    for(String key : map.keySet()) {
      String[] infos = map.get(key);
      // infos[Constants.APP_URL_PROTOCOL] などを使った処理
      // infos[Constants.APP_URL_URL] などを保存する処理
      // infos[Constants.APP_URL_PATH] などを保存する処理
    }
  }
}

他のところで取り出した URL を保存する処理なのだが、 URL だけでなく、プロトコルとかパスなども保存しているらしい。それは特段問題ではないのだが、問題なのはこれを URL を使えば意味も明確に処理できるのに対して、 String と配列という抽象的な要素をやりくりしてアプリを構築しているところである。

class App {

  Set<URL> urls;

  public void add(String protocol, String base, String[] paths) {
    for (String path : paths) {
      String sep = paths.startsWith("/")? "" : "/";
      URL url = new (protocol, base, sep.concat(path));
      urls.add(url);
    }
  }

  public boolean storeUrls() {
    for(URL url : urls) {
      // url.getProtocol() などを使った処理
      // url などを保存する処理
      // url.getPath() などを保存する処理
    }
  }
}

URL を使うことによって、何を保持しているか明確になった。もちろん、一部実装が変わっているところがある。それは、パスで一意性を保証していたのに対して、 URL で一意性を保証するように変わってしまったとことであるが、問題であるようならその場合にはパスによって一意性を保証するような専用の型を作れば良い。


まとめると

  • String や配列のような抽象的な型をロジック中でやりくりしてデータを表現しない
  • 何でも自力でやらない。標準APIやライブラリーが提供しているものを使う。
  • API で提供していない、ライブラリーがないなら、専用の型を定義する。抽象的な型で頑張らない。