Works by

Works by

プログラミング等IT技術関連でメモする

【App】社内イベント用モバイルアプリ開発をやっていった話

まえおき

この発言は個人の見解であり、所属する組織の公式見解ではありません。

TL;DR

社内イベント用のアプリ開発を、フロントエンドを中心にやっていきました。

f:id:rennnosukesann:20181112102759j:plain

経緯

私の所属する会社では年2回ほど著名人や社内で活躍する方々を招いた大規模なラーニングイベントを開催しており、そのイベント用のモバイルアプリ開発が昨年より行われていることを知ったので、開発メンバーにコンタクトを取ってジョインさせていただきました。

どんなアプリなのか

いわゆるGoogle I/OMicrosoftのTech Summitで配布されるようなイベント公式アプリの位置付けです。開催されるセッションやイベントのスケジュールやイベントの詳細・フロア情報などのほか、アプリユーザからの発信を行える機能(セッションへのコメントなど)をなど実装しました。

なぜ、フロントを

すでに業務内でWebアプリのフロント開発にある程度携わっていたのですが、まだフロント開発をやり始めて1年も経っておらずもっと開発機会が欲しいと感じていました。また使っていたフレームワークが(前任者の関係で)AngularJSだったことでもう少しモダンなフロントのフレームワークを使ってみたい気持ちがあったことや、最近はバックエンド開発ばかりでフロントから離れていた、かつ本プロジェクトのフロント開発の人員が不足している...など様々な理由があり、フロントチームに入ることにしました。

アーキテクチャ

アプリケーションの構成ですが、フレームワークにはバックエンドのAPIサーバでSpring Boot、フロントエンドではVue.jsを採用しました。採用した理由は(聞いたところ)本アプリ開発メンバーが所属する社内組織でこれらのフレームワークが使われており、ノウハウがある程度蓄積されているからとのこと。 フロントエンドのフレームワークとしては新しめなVue.jsがいじれたので楽しく開発できました。

またインフラレベルではIBM Cloud上にCloud FoundlyランタイムやObject Strage、Cloudant、CI/CD等配置し利用しました。この辺の話は今回バックエンド/インフラとPMを担当してくれた@Santea3173に譲ります。

社内イベントアプリを作成しました【第二弾】 | Project Respite

フレームワーク、ライブラリ、ツールなど

Vue.js

言わずとしれた今流行りの軽量フロントエンドフレームワーク。Angularとは異なりフルスタックではないためモジュールが予め全部入りというわけではなく、Reactのように欲しい機能があれば公式やサードパーティのモジュールを引っ張ってくる形になります。とはいえ、Router( vue-router )や後述するReduxのような状態管理モジュール( Vuex )は公式が用意してくれており、基本的な機能実装はこれらで事足りました。

機能としては双方向バインディング.vue ファイルを使ってUIコンポーネントごとにロジック・テンプレート・スタイルをまとめて定義できるなど、まるでAngularとReactのいいとこ取りみたいなフレームワークといった感じでした。 またAngularの angular-cli 、Reactの create-react-app よろしくCLIツール vue-cli があり(今回は3.0を使った)、プロジェクトの設定にもそれほど困りませんでした。Vueが初めてでも、他のフレームワークを使っていればとっつきやすいのがこのフレームワークの魅力だと思います。

Vuex

Fluxにインスパイアされた状態管理モジュール。ReactでいうRedux。 Vuexに関する感想は後述します。

Vue CLI (3.0)

フロントエンドフレームワーク環境の構築には無くてはならない、CLIツールのVue版です。コマンド一つで自動化ツール・トランスパイラ、テスティングフレームワーク・Lintツール...などを一気に設定できます。数多あるWebツールを一つずつプロジェクトに導入する時代はもう終わったのかもしれません。。。

Vue公式が用意したYOMANのようなもの。

vue-property-decorator

少し細部にフォーカスした話になりますが、今回VueのUIコンポーネントの作成には vue-property-decorator を利用しました。これはアノテーションを使ってVueコンポーネントをよりシンプルに書けるようになるライブラリです。

公式より引用)

Before

export default {
  props: {
    propA: {
      type: Number
    },
    propB: {
      default: 'default value'
    },
    propC: {
      type: [String, Boolean]
    },
  }
}

After

import { Vue, Component, Prop } from 'vue-property-decorator'

@Component
export default class YourComponent extends Vue {
  @Prop(Number) propA!: number
  @Prop({ default: 'default value' }) propB!: string
  @Prop([String, Boolean]) propC: string | boolean
}

これでUIコンポーネントの見通しが良くなるだけでなく、TypeScriptプロジェクトを作成した際に型の恩恵を受けることができます。 Vue CLIでTypeScriptプロジェクトを選択すると自動で導入されるようになっており、もしかしたら今後TypeScript + Vueによるフロント開発ではこちらの書き方が主流になっていくかもしれません。

Bulma

一部Drawerの実装等で使用したものの、結局ガッツリとは使わずに終わりました。本当はきちんと使えばUIコンポーネントデザイン開発工数を短縮できたのかもしれませんが、今回作成したアプリのコンポーネントは一般のデザインとは少し趣向が異なるものだったので、ほぼSCSS/Sassでの開発となりました。

やっていった後の気づき

技術関連

Vuexの使いどころ

Flux実装をまともに使うのは初めてだったので(AngularJSではscopeマネジメントに苦しんでいたので)、実験的にVuexを使ってみた側面が大きいかもしれません。使ってみて思ったのは、やっぱり状態をもつデータを一元管理できるのは便利だし、状態の変更結果をシームレスにViewに波及できるのも嬉しいです。データの状態と、アプリの表現に矛盾が起きないのは使っていてとても気持ちが良いです。

一方で過度にstoreに頼るのも禁物で、例えば一画面内で完結する状態変数をstoreで管理してしまうと、別のデータを使って同じ画面を使いたいときに前のstoreの状態がキャッシュされていて矛盾が起こる...といった寧ろ面倒なことも発生します。こういうシーンでは使い捨てのプロパティ変数で十分だな、と思いました。逆に画面間で同じデータ状態を共有したいときは積極的に使っていくべきだと思います。

CLIツールから一気にキャッチアップする

CLIがサポートするツール/ライブラリは現行のフロントエンド界隈でよく使われているモダンなものばかりです。CLIがデフォルトで用意してくれるプロジェクトから開発をスタートすることで、どのようなツールを使うべきなのか素早くキャッチアップすることができました。もちろんこれらの環境構築は自動でやってくれます。

  • Webpack
  • Babel
  • Gulp
  • Chai
  • Nightwatch(結局使ってない...)
  • TSLint
  • TypeScript(AltJS)

また(というかもちろん)Vue専用のライブラリも一通り揃えてくれます。

  • vue-class-component
  • vue-property-decorator
  • vue-router
  • vuex

セットアップの手間が省ける点も大きなメリットなのですが、こういったツールを利用することで現行の技術を把握できる点も非常に美味しいです。

CSS、Sass

Sassはあまり本格的に導入したことはなく、今回も少しだけ採用。 結果「Sass、CSSの完全上位互換では・・・?」という感想を抱く事になりました。

普通のCSS + プログラマブルなロジック。 CSSの中に変数や条件分岐、継承等を導入できるのは便利すぎます。 またそれを差し引いてもシンプルな記述ができるので今後も使っていこうと思いました。

運用関連

チーム開発の難しさ

普段所属しているプロジェクトのワークでは開発系の方はほぼおらず、ほぼ個人でプログラムを書いてばかりいました。チーム開発自体は何度か経験したことはあったのですがご無沙汰だったので、久々にPR出したりレビューしたりできました。

一方で通常ワークとのスケジュールの兼ね合いでレビューが遅延したり、変更箇所が局所化されていないためにデグレが発生したり、Conflictが発生したりすることもありました。こちらも予め開発方針をきちんと固めておけばよかったのですが、最低限のモジュールテンプレだけ用意して開発をスタートしてしまったのが仇になりました。

またレビューに関しても反省すべき点があり、とにかく時間がなかったため動作ベースでの検証のみが殆どとなってしまいました。ここでも、上記同様開発方針を硬め、それに沿ったコードレベルのレビューを心がけるべきでした。

終わりに

開発を終えて、やっぱりやってよかったなと言う気持ちです。

今回の開発はチーム統括始めバックエンド/インフラの面で@Santea3173に助けられました(フロントもやってくれました)。何から何までありがとう!

他の開発メンバーにもこの場を借りてお礼申し上げます。ありがとうございました!

【python】QRコードを生成する

メモ。

qrcode モジュールを使えば、pythonで簡単にQRコードの作成ができます。

Usage

import qrcode

# QRコードに埋め込みたいテキストを引数に渡す
# PIL.Imageオブジェクトが返戻される
img = qrcode.make('hoge')
# 保存
img.save('./qrcode.png')

Result

f:id:rennnosukesann:20180816175239p:plain

参考

pypi.org

【Java】log4j2

log4j2

log4j2はJavaのロギングユーティリティであるlog4jの後継です。
厳密にはv1のlog4jがv2担っただけのものですが、プロパティファイルの命名やプロパティの設定方法などが一部新しくなっています。

Log4j – Apache Log4j 2 - Apache Log4j 2

Usage

Mavendependencyを追加する場合は以下。

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.11.1</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.11.1</version>
</dependency>

Source

LogManagerでロガーを取得できます。
Loggerオブジェクトは名称によって異なるインスタンスを扱い、ログも別々に出力されます。 Loggerによって、ファイルやコンソールなどの出力先や、ログのアーカイブの設定なども、後述するプロパティファイルの設定で別々に行うことができます。

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

... 

// Loggerオブジェクトの取得
Logger logger = LogManager.getLogger(Hoge.class);
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

// 簡単なLoggerのラッパークラス
public class LoggerWrapper {

    private Logger logger;

    private LoggerWrapper(String name) {
        logger = LogManager.getLogger(name);
    }

    public static LoggerWrapper getLogger(String name) {
        return new LoggerWrapper(name);
    }

    public void trace(Object message) {
        logger.trace(message);
    }

    public void debug(Object message) {
        logger.debug(message);
    }

    public void info(Object message) {
        logger.info(message);
    }

    public void warn(Object message) {
        logger.warn(message);
    }

    public void error(Object message) {
        logger.error(message);
    }

    public void fatal(Object message) {
        logger.fatal(message);
    }

        public void begin(String message){
                this.info("BEGIN : " + message);
        }

        public void end(String message){
                this.info("END : " + message);
        }
}

log4j2のプロパティファイル

log4j2の設定は以下のファイルをクラスパス配下に置くことで可能になります。

  • log4j2.properties
  • log4j2.yml
  • log4j2.json
  • log4j2.xml

設定ファイルはproperties > yaml > json > xml の優先度で適用されます。
詳細な設定方法は以下。

Log4j – Configuring Log4j 2 - Apache Log4j 2

参考

Log4j – Apache Log4j 2 - Apache Log4j 2

【CloudFoundly】CloudFoundlyアプリケーションに対してssh接続を行う

メモ。

CloudFoundly上で立ち上がっているアプリケーションのホストにSSH通信したいとき、cf コマンドを利用できます。

cf

こちらのページからインストーラをダウンロードし、インストールして完了。

github.com

brew/yum/apt-getでもインストール可能です。

github.com

$ brew install cloudfoundry/tap/cf-cli

Usage

cf sshssh接続できます。

# アプリ一覧
$ cf apps
hoge@fuga.com として組織 Hoge / スペース dev 内のアプリを取得しています...
OK

名前                     要求された状態   インスタンス   メモリー   ディスク   URL
test1    started          1/1            2G         2G                         test1.mybluemix.net
test2    started          1/1            2G         2G                         test2.mybluemix.net

# ssh接続
$ cf ssh test1
hoge@XXXXXXXXXXXXXXXXXXXX:~

参考

Accessing Apps with SSH | Cloud Foundry Docs

【shell】任意拡張子を持つファイルの総行数をカウントする

メモ。

ある拡張子(複数可)を持つファイルすべての行数をカウントするコマンドは以下のようになります。

$ find . -type f | grep -E ".*\.java|.*\.css|.*\.html|.*\.js|.*\.php|.*\.py" | xargs cat | wc -l 

適当にフィルタを掛けたい場合はパイプしてgrep -vに渡します。

$ find . -type f | grep -E ".*\.java|.*\.css|.*\.html|.*\.js|.*\.php|.*\.py" | grep -v "filtered" | xargs cat | wc -l 

以上。

【Mac】rootlessとcsrutil

rootless

MacではOS X 10.11(El Capitan)より、/userや/binなどのディレクトリへの書き込みがroot権限でも不可能となりました。

$ sudo mkdir /usr/hoge
Password:
mkdir: /usr/hoge: Operation not permitted

この措置はrootlessと呼ばれるシステム整合性保護で、root権限をダッシュされたときのリスクを減らします。rootlessは下記のディレクトリを保護します。

  • /システム
  • /usr
  • /bin
  • /sbin

加えて、OS X にあらかじめインストールされているアプリも変更することができなくなります。

しかしながら、これらのディレクトリへの書き込みを実行する一部のアプリケーションインストールなどが正常に動作しなくなる可能性もあります。

csrutil

rootlessを無効にするには、csrutilを使います。

$ csrutil status
System Integrity Protection status: enabled.

csrutil statusでrootlessが有効かどうかをチェックすることができます。

csrtoolによるrootless設定の変更は、起動中のOSシェル上では利用できず、リカバリーモードでしか動作しません。 したがってリカバリーモードに移行する必要があります。リカバリーモードに移行するには、Mac起動中にCtrl+Rを長押しします。

f:id:rennnosukesann:20180801172405p:plain

すると上記のようなウィンドウが表示されるので、左上の「ユーティリティ」->「ターミナル」を選択します。

rootless無効化/有効化のコマンドは下記のとおりです。 (変更に関する責任は負いかねます)

# 無効化
$ csrutil disable

# 有効化
$ csrutil enable

rootlessは一旦無効化しても、直ぐに有効化することを推奨します。

参考

support.apple.com

【python】google-image-downloadでGoogle上の画像を一括取得する

google-image-download

コマンドライン上で動作する画像収集用ツールです。

github.com

Usage

pipでインストールします。

$ pip install google_images_download

これですぐ利用可能になります。
shell上で以下のコマンドを実行すると、実行ディレクトリ配下にdownloadsフォルダが作成され、指定した検索キーワードに関連する100枚の画像のダウンロードが開始されます。

$ googleimagesdownload --keywords "雷門 雷神"

Item no.: 1 --> Item name = 雷門 雷神
Evaluating...
Starting Download...
Completed Image ====> 1. c4657c3b20ead6bd7eda55b72056e0fc.png
...

f:id:rennnosukesann:20180728185259p:plain

機械学習用の画像を手短に収集するのに便利です。

参考

github.com