Firebase Functions ローカルで関数を実行する時に失敗する件について

Firebase Functionsは firebase-tools を使って、ローカルで関数を実行してテストできる。

結論

firebase functions:shell を使おう!

使い方はこちら

firebase.google.com

例えば、 myFunc という関数を定義したら、

firebase > myFunc.get()

とかで呼べるし、express で myFunc配下に関数 ( /greet ) がある場合には、

firebase > myFunc.get('/greet')

で呼べる。

続きを読む

vueで開いたり閉じたりするコンポーネントを作る

最近vanillaのjavascriptで開いたり閉じたりするUIを作ってて、すっげぇ苦労したので、 「くっ…!!(vueなら簡単に書けるのに…!!)」という気持ちを発散するために、実際に作ってみた。

仕様

開くボタン

  • 「開く」ボタンをクリックするとフォームが開く。
    • 開いている間は開くボタンは消える。

閉じるボタン

  • フォームには「閉じる」ボタンがあり、押すとフォームが閉じる。
    • 閉じている間は閉じるボタンは消える。

作ったもの

See the Pen Vue expand form by clash_m45 (@clash_m45) on CodePen.

コード

styleをはしょってるので、全文はcodepenのほう見てください。

単純に v-if を使って、プロパティ expand がtrueのとき開く、としているだけ。 buttonのon-clickで openメソッド、closeメソッドを呼んで、 expandを書き換えると、vueの力でbindingされて、動的にUIが変化する!

素晴らしい!

<template>
  <div>
    <h3>開いたり閉じたりする入力フォーム</h3>
    <hr>

    <button v-if="!expand" @click="open">開く</button>
    <div v-if="expand">

      <label for="hamburger">Do you like hamburger?</label>
      <input type="checkbox" name="hamburger" id="hamburger">
      <span>checked</span>
      <br>

      <button @click="close">閉じる</button>
    </div>
  </div>
</template>

<script>
  export default {
    name: "count",
    data () {
      return {
        expand: false
      }
    },
    methods: {
      open: function() {
        this.expand = true
      },
      close: function() {
        this.expand = false
      }
    }
  }
</script>

Spring BootとVue.jsを使ったシステムを作ってみた

前にこの記事を読んで、vue.jsを入門してた。

GUIアプリケーションアーキテクチャ総合!みたいなやつ書いてる - 猫型の蓄音機は 1 分間に 45 回にゃあと鳴く

実際にギョームで採用したいなーと思ったけど サーバサイドとの結合がよく分からなかったので、簡単なシステムを作ってみた。

github.com

vue.jsで作ったページのボタンをクリックすると、 Spring Bootで作ったHello World WebAPIを呼び出して、 値を画面に表示するっていう簡単なシステム。

出来る限り簡素な作りにしようと思って作った。 READMEに実装の手順を書いてみたので、参考になれば嬉しい。


フロントエンドはvscodeで実装して、 バックエンド(Java)はeclipseで実装するのが一番ラクだった。

ビルド周り凝り始めるとわかりづらくなるので書いてない。

vue.jsはわかり始めるとかなり書きやすいし、 DDD-like Layered Architectureに沿った作りにすると見通しも良くなりそう。

ギョームで使うにはまだ足りない機能が多い

  • バリデーション
  • ユーザ認証
  • Flux的なやつ(vue.js storeでもよさそう)

今日やったリファクタリング - 2 : Enumの値と比較

今日じゃないけど、最近やったリファクタリング

言語はC#.

enumって列挙型で、定数とかを定義するのに使います。
簡単な例で言うと、曜日とかを列挙したり。

public enum Days {
    Sat=1,
    Sun,
    Mon,
    Tue,
    Wed,
    Thu,
    Fri
}

ただ、このままだと結構使いづらくて、こんなコードを書いてしまう場合もあります。

Before

// todayが火曜であることを確認する処理
string today = "4";//どこかから取得した値
bool b = ((int)Days.Tue).ToString().Equals(today);

// 日曜かどうかboolを取りたい場合
bool b = ((int)Days.Sun).ToString().Equals(today);

ひたすらintにcastしてToString().Equals()…!

ダサいので、やめましょう。

After

今回リファクタリングした結果はこんな感じ。

public class Days {
    
    private enum _Days {
        Sat=1,
        Sun,
        Mon,
        Tue,
        Wed,
        Thu,
        Fri
    }

    private _Days val;
    private Days(_Days d) {
        this.val = d;
    }

    public static readonly Days Saturday = new Days(_Days.Sat);
    public static readonly Days Sunday = new Days(_Days.Sun);
    public static readonly Days Monday = new Days(_Days.Mon);
    public static readonly Days Tuesday = new Days(_Days.Tue);
    public static readonly Days Wednesday = new Days(_Days.Wed);
    public static readonly Days Thursday = new Days(_Days.Thu);

    public bool Equals(string value) {
        return Val().Equals(value);
    }

    public string Val() {
        return ((int)this.val).ToString();
    }
}

こんな風にenumをwrapするクラスを作りました。
そんで、使うときには、

// todayが火曜であることを確認する処理
string today = "2";//どこかから取得した値
bool b = Days.Tuesday.Equals(today);

// 日曜かどうかboolを取りたい場合
bool b = Days.Sunday.Equals(today);

毎回castするよりかは可読性は上がりました。


今回は、C#の場合でしたが、Javaでも同じような書き方が出来ます。
Javaではenumに独自メソッド書けるけど、まぁどっちがいいやろかね。

この記事みた後だと、今回の修正後もダサく感じてきます。

C#enum に関連する小技。

qiita.com

C#ではこのやり方が一番良いかも!

以上。

今日やったリファクタリング - 1 : 連番付きフィールド

あまりの糞コードに遭遇し、怒りのリファクタリングを行った。

ついでに「こんなリファクタリングしたよ」と残しておくとなんか良さそうだなと思い付き、
久しぶりにブログを書き始めた。

今日したのは、言語はC#で、
フィールドに連番の付いたフィールドがあり、そのどれかに値が入っていることを調べる処理のリファクタリング

モデルクラスは以下、

public class Model {
    // モデルのフィールドの構造は諸事情により、変更不可とする。
    // メソッドなどは追加してOK。
    public string Value1 { get; set; }
    public string Value2 { get; set; }
    public string Value3 { get; set; }
    public string Value4 { get; set; }
    public string Value5 { get; set; }
    public string Value6 { get; set; }
    public string Value7 { get; set; }
    public string Value8 { get; set; }
    public string Value9 { get; set; }
    public string Value10 { get; set; }
}

このモデルに対し、別の処理でこのどれかに値が入ってくる。 どのValueNに値が入っているか、Nの数値を取得したい。

Before

public class BusinessLogic {
    
    public int GetValueIndex(Model model) {
        if(! string.IsNullOrEmpty(model.Value10)) {
            return 10;
        }
        else if(! string.IsNullOrEmpty(model.Value9)) {
            return 9;
        }
        else if(! string.IsNullOrEmpty(model.Value8)) {
            return 8;
        }
        else if(! string.IsNullOrEmpty(model.Value7)) {
            return 7;
        }
        else if(! string.IsNullOrEmpty(model.Value6)) {
            return 6;
        }
        else if(! string.IsNullOrEmpty(model.Value5)) {
            return 5;
        }
        else if(! string.IsNullOrEmpty(model.Value4)) {
            return 4;
        }
        else if(! string.IsNullOrEmpty(model.Value3)) {
            return 3;
        }
        else if(! string.IsNullOrEmpty(model.Value2)) {
            return 2;
        }
        else if(! string.IsNullOrEmpty(model.Value1)) {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}

あぁ!もう!!!

このIF文乱舞で嫌気が差さない場合は自分を疑ったほうが良い。

私が修正した結果がこちら

After

まず、ModelにValue達をDictionaryで返すメソッドを追加した。

public class Model {
    
    // モデルの構造は諸事情により、変更不可とする。
    public string Value1 { get; set; }
    public string Value2 { get; set; }
    public string Value3 { get; set; }
    public string Value4 { get; set; }
    public string Value5 { get; set; }
    public string Value6 { get; set; }
    public string Value7 { get; set; }
    public string Value8 { get; set; }
    public string Value9 { get; set; }
    public string Value10 { get; set; }

    public Dictionary<int, string> GetValues() {
        return new Dictionary<int, string>() {
            {1, Value1},
            {2, Value2},
            {3, Value3},
            {4, Value4},
            {5, Value5},
            {6, Value6},
            {7, Value7},
            {8, Value8},
            {9, Value9},
            {10, Value10},
        }
    }
}

このメソッドを利用して、BudinessLogicもこう修正した。

public class BusinessLogic {
    
    public int GetValueIndex(Model model) {
        return model.GetValues().Where(v => !string.IsNullOrEmpty(v)).Select(v => v.Key).Max();
    }
}

だいぶマシになった。

ついでにこの後、メソッド名もGetValueIndexでは意味が違っているので、GetMaxValueIndexに変更した。

リファクタリングはテストコードを書いて、現状のメソッド仕様を把握・テスト出来る状態にしてから取り掛かったほうが良いね。

以上。

Selenium WebDriverの画面キャプチャ 拡張子を変える

Selenium WebDriverでキャプチャを撮って、画像ファイルに保存するときに拡張子をjpeg、giff、pngなど変えるやり方。

普通にキャプチャをファイルに保存するには

public void takeScreenShot(Path outputPath) {
    System.out.println("= Screen Shot =");
    File img = ((TakesScreenshot)this.webDriverInstance).getScreenshotAs(OutputType.FILE);
    try {
        FileUtils.copyFile(img, outputPath.toFile());
        System.out.println("Name : " + outputPath.toFile().getAbsolutePath());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

selenium-javaの依存関係にcommons-ioが入っているので、特別追加しなくてもFileUtilsを使える。

画像の拡張子を指定して画像保存する

    /**
     * 起動済みのブラウザでスクリーンショットを撮る。
     */
    public void takeScreenShot(Path outputPath) {
        System.out.println("= Screen Shot =");
        File img = ((TakesScreenshot)this.webDriverInstance).getScreenshotAs(OutputType.FILE);
        try {
            FileUtils.forceMkdirParent(outputPath.toFile());
            ImageIO.write(ImageIO.read(img), "jpeg", outputPath.toFile());
            System.out.println("Name : " + outputPath.toFile().getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

javax.imageio.ImageIOクラスで以下の拡張子に対応してるらしい。

WriterFormatNames:
BMP
bmp
jpeg
wbmp
png
JPG
PNG
jpg
WBMP
JPEG

参考

stackoverflow.com

www.javadrive.jp

typesafe/Config ConfigBeanFactoryの良さそうな使い方

設定ファイルを扱いたくて、イマドキどんな形式が良いんだろうなと調べてみたら、 typesafe/ConfigというライブラリでHOCONというファイル形式があるらしい。

紹介記事や簡単な使い方については、以下を参照。

Java アプリケーションのための設定ファイル形式の比較

Play Frameworkでも使われているコンフィグライブラリが非常に便利


で、

結論から言うと、 ConfigBeanFactory使うなら、typesafe/Config + lombok が良さそう!


typesafe/Configで、version 1.3から追加されたらしいConfigBeanFactoryクラスを使ってみた。

https://github.com/typesafehub/config#configbeanfactory

自作のjava beanクラス AppConfigを生成させている。

    /**
     * application.confを読み込み、Beanで返す。
     * @return AppConfig
     */
    public static AppConfig getConfig() {
        return ConfigBeanFactory.create(load(), AppConfig.class);
    }

読み込ませたい設定ファイルは、こんな感じで、

webdriver {
    chrome=/usr/local/bin/chromedriver
    ie=/usr/local/bin/iedriver
    firefox=/usr/local/bin/firefoxdriver
}
output{
    dirpath=.
    caseid=case
    image{
        extension=jpg
    }
}
browser{
    width=300
    height=300
}

AppConfigクラスはこんな感じで、フィールド名と設定ファイルのkeyが一致している必要がある。
またフィールドに対応するgetter/setterを記述する必要があるが、
そこをlombokで生成(ここでは @Data)してあげることで、
簡易にConfigBeanを実装することが出来ている。

import lombok.Data;

@Data
public class AppConfig {
    private WebDriverConf webdriver;
    private OutputConf output;
    private BrowserConf browser;
}

フィールドの型はこんな風にネストしてBeanを使うことも可能。

import lombok.Data;

@Data
public class WebDriverConf {
    private String chrome;
    private String ie;
    private String firefox;
}

その他のクラスはgithubにおいてあります。

github.com


個人的にはConfigBeanを作ることで、設定のkeyを管理しなくて良くなったので嬉しかった。

でも欠点は、ConfigBeanの値を変更して設定ファイルに保存(シリアライズ)したい時に、typesafeのConfigやConfigObjectに再変換するのが大変なこと。 たぶん地道にMapにpushするみたく、withValueメソッドを呼びまくらないといけない。

少し調べてstackoverflowのどこかのページで、「typesafe/Configはimmutableな設定を扱うツールだよ :)」とあり、設定の変更はあんまりやらない思想なのかな?ということで諦めモード。

一応config.root().render()シリアライズされた文字列が返るので、それをファイルに保存してやれば良い。
ConfigObjectクラスのrenderメソッド