カテゴリー : 2016年 12月

2016年を振り返る

2016年の振り返り。

仕事

2016年は開発以外の色んな仕事に携われた。

1-3月は自社倉庫の業務改善。4-6月はマーチャンダイジングチームの業務改善。いずれもエンジニアリングをベースにした業務改善で、業務ヒアリングして、開発要件を GitHub issue に作成していくという感じだった。業務ヒアリングしていくと今やらなくていい開発案件もあったりして、優先度調整や期待値コントロールの難しさを体験した。

7-8月はマーケティングチームの業務改善を少しだけやった。期間が短かったのは組織体制が変わるのと、業務改善よりも売上・粗利アップさせるための仕事に方向転換があったためだ。
この期間に、データ分析の真似事も取り組んだ。データ分析は未経験だったので、何冊か本を読んで参考にしながら取り組んだ。

データ分析のために読んだ本

SEOにも取り組んだ。開発以外で社内調整しないといけない部分が多くて、現状まだ上手くいってない。1-8月でエンジニアとしての開発業務から離れていたので、また開発をがっつりやりたいなと思い始めた。というわけで、CTOに相談して開発業務の割合を増やしてもらった。

9月以降は主にエンジニアとしてプロダクト開発に取り組んだ。半年以上、開発から離れていたので戻ってから最初の2週間ぐらいはリハビリ期間みたいな感じで、勘を取り戻すのに苦労した。

フロントエンド JavaScript に苦手意識があったので、Vue.js に苦戦した。

11月末から、熊本でリモートワークして年を越した。

メリットとしては、開発に集中できる時間が増える。

デメリットとしては、スタートアップならではの熱量が伝わりにくい。オフィスの空気感が分からないので、緊急性の高いタスクがあったときに Slack に @channel で叫ばないと (メッセージ) しないといけない。Google ハングアウトの設定やネットワークトラブル問題が尽きない。オフラインコミュニーケーションがグッと減るので、業務上関わりのない人とほとんど接点が無くなる。

自分からお願いしてリモートワークさせてもらってる訳だけど、デメリットの部分を理解して導入しないとストレス溜まるなと改めて感じた。

家庭

5月のGW中に家族が他界した。
必要なときに仕事を休めることの有り難みを感じた。

12月末に第一子が生まれた。立会い出産したかったので、それにあわせて11月から2月上旬まで熊本からリモートワークをしてる。
結婚式や出産などのライフイベントにあわせて、リモートワークをさせてもらえるのは有難い。「いつリモートワークしても大丈夫なように、週1〜2回ぐらいやって、体を慣らしておいた方がいいのでは?」というのがDevチームのトピックとして挙がっている。

勉強

英語学習は途中でやめてしまった。モチベーションが続かなかったので、時期をみて再開したい。

読書は月10冊を目標にしていたけど、実際は月2~3冊ぐらいしか読めなかった。以下の本はどれも、もう一年早く読みたかったと思える良書だった。この点は経験が先か、知識が先かの違いなんだろうけど。

リモートワークで、通勤時間が無くなるので浮いた時間を使って勉強に充てたい。

などを読み直してる。
インプットが多めなので読書感想文みたいなものを、このブログにでもアウトプットしていきたい。

プライベートコードを書く量が少なかった。

今年はまず、フロントエンド JavaScript のスキルアップをしていきたい。他の技術も幅を広げるか深めていくかしていきたい。

総括・来年

20代最後の一年だった。

来年は30歳なので、今まで以上に今後のキャリアやライフプランを具体的にイメージして日々を生きていきたい。

[JavaScript] 改行コード \r\n \r \n を半角スペースに置換する正規表現とスニペット

JavaScript で改行文字を半角スペースに置換する正規表現とスニペットをご紹介します。

JavaScript

続きを読む

psql したら Library not loaded: libreadline エラーが出たので brew upgrade postgresql した

ひさしぶりに PostgreSQL を使おうと思い psql コマンドを実行したら Library not loaded: libreadline エラーが出たので brew upgrade postgresql して解決したというお話です。

psql コマンド実行で Library not loaded: libreadline エラー

$ psql
dyld: Library not loaded: /usr/local/opt/readline/lib/libreadline.6.2.dylib
  Referenced from: /usr/local/bin/psql
  Reason: image not found
[1]    61053 trace trap  psql

brew upgrade postgresql で PostgreSQL のバージョンアップ

brew update
brew upgrade postgresql
launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
mv /usr/local/var/postgres /usr/local/var/postgres9.3.1
initdb /usr/local/var/postgres
pg_upgrade \
  -b /usr/local/Cellar/postgresql/9.3.1/bin \
  -B /usr/local/Cellar/postgresql/9.6.1/bin \
  -d /usr/local/var/postgres9.3.1 \
  -D /usr/local/var/postgres
cp /usr/local/Cellar/postgresql/9.6.1/homebrew.mxcl.postgresql.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist

たまに PostgreSQL を使うぞってときに version アップデートからハマりたくはないですよね。

参考情報

Promise 参考記事まとめ [JavaScript/ECMASCript6]

JavaScript 標準仕様の ECMASCript6 (ES2015) の Promise について理解が定着していないので、よく読み返す記事を自分用にまとめました。

JavaScript

続きを読む

WordPress ファイルとデータベースを自動バックアップして Google ドライブにアップロードする

やっと当ブログの WordPress のファイルとデータベースをバックアップして Google ドライブにアップロードするまでの処理を自動化しました。

前提

扱っている技術的なものは以下のとおりです。

バックアップ処理を書いたシェルスクリプト

WordPress データベースのバックアップ

ひとまず、書いたシェルスクリプトを書き残しておきます。

# backup_db.sh
DB_NAME=mydbname
DB_USER=mydbuser
DB_PASSWORD=mydbpassword
DB_HOST=localhost
 
DATE_STR=$(date +\%Y\%m\%d-\%H\%M\%S)
BACKUP_PATH=/tmp
BACKUP_FILE=$DB_NAME-$DATE_STR.sql
GDRIVE_DIR_ID=0B840dMOrdKT5am9aRDlNUUFic0k
KEEP_DAYS=3
 
## backup DB
cd $BACKUP_PATH
mysqldump $DB_NAME --default-character-set=binary \
-h $DB_HOST -u $DB_USER -p$DB_PASSWORD > $BACKUP_FILE
tar zcvf $BACKUP_FILE.tar.gz $BACKUP_FILE
gdrive upload --parent $GDRIVE_DIR_ID $BACKUP_FILE.tar.gz
rm -f $BACKUP_FILE.tar.gz $BACKUP_FILE
 
## Housekeeping
LIMIT_TIMESTAMP=$(date -d "$KEEP_DAYS days ago" +%s)
gdrive list --no-header --max 1000 --query "'$GDRIVE_DIR_ID' in parents" | while read ln
do
  ITR_ID=$(echo $ln | awk '{print $1}')
  ITR_DATE=$(echo $ln | awk '{print $(NF-1),$NF}')
 
  if [ $(date -d "$ITR_DATE" +%s) -lt $LIMIT_TIMESTAMP ]
  then
    gdrive delete $ITR_ID
  fi
done

WordPress ファイルのバックアップ

# backup_file.sh
DATE_STR=$(date +\%Y\%m\%d-\%H\%M\%S)
 
TARGET_PATH=/var/www/vhosts/
TARGET_FILE=codenote.net
BACKUP_FILE=$TARGET_FILE-$DATE_STR.tar.gz
GDRIVE_DIR_ID=0B840dMOrdKT5SFg5UkZ2c05aWkU
 
KEEP_DAYS=7
 
## backup files
cd $TARGET_PATH
tar cfz $BACKUP_FILE $TARGET_FILE/
gdrive upload --parent $GDRIVE_DIR_ID $BACKUP_FILE
rm -f $BACKUP_FILE
 
## Housekeeping
LIMIT_TIMESTAMP=$(date -d "$KEEP_DAYS days ago" +%s)
gdrive list --no-header --max 1000 --query "'$GDRIVE_DIR_ID' in parents" | while read ln
do
  ITR_ID=$(echo $ln | awk '{print $1}')
  ITR_DATE=$(echo $ln | awk '{print $(NF-1),$NF}')
 
  if [ $(date -d "$ITR_DATE" +%s) -lt $LIMIT_TIMESTAMP ]
  then
    gdrive delete $ITR_ID
  fi
done

gdrive コマンドの Tips

gdrive list でディレクトリの一覧を表示する。

$ gdrive list --query "mimeType='application/vnd.google-apps.folder'"
Id                             Name   Type   Size   Created
0B840dMOrdKT5am9aRDlNUUFic0k   db     dir           2016-12-13 00:17:46

随時、内容をアップデートしていきます。

参考情報

[Mongoose][timekeeper] TypeError: Undefined type `FakeDate` at `fieldName`

Node.js + Mongoose な構成のウェブサービスのテストコードで timekeeper という時間操作モジュールを利用していてハマったことをメモ。

timekeeper.freeze と new mongoose.Schema でエラーの事例

timekeeper.freeze と new mongoose.Schema でエラーが発生するテストコード

'use strict';
 
const mongoose = require("mongoose");
const timekeeper = require("timekeeper");
 
describe("FakeDate error", () => {
  timekeeper.freeze(new Date());
  let schema = new mongoose.Schema({
    createdAt: {
      type: Date
    }
  });
  timekeeper.reset();
});

エラーメッセージ TypeError: Undefined type `FakeDate`

$ mocha test.js
 
/Users/bakorer/works/myapp/node_modules/mongoose/lib/schema.js:483
    throw new TypeError('Undefined type `' + name + '` at `' + path +
    ^
 
TypeError: Undefined type `FakeDate` at `createdAt`
  Did you try nesting Schemas? You can only nest using refs or arrays.
    at Function.Schema.interpretAsType (/Users/bakorer/works/myapp/node_modules/mongoose/lib/schema.js:483:11)
    at Schema.path (/Users/bakorer/works/myapp/node_modules/mongoose/lib/schema.js:415:29)
    at Schema.add (/Users/bakorer/works/myapp/node_modules/mongoose/lib/schema.js:310:12)
    at new Schema (/Users/bakorer/works/myapp/node_modules/mongoose/lib/schema.js:88:10)
    at Suite.<anonymous> (/Users/bakorer/works/myapp/test.js:8:16)
    at context.describe.context.context (/Users/bakorer/works/myapp/node_modules/mocha/lib/interfaces/bdd.js:73:10)
    at Object.<anonymous> (/Users/bakorer/works/myapp/test.js:6:1)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (/Users/bakorer/works/myapp/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at /Users/bakorer/works/myapp/node_modules/mocha/lib/mocha.js:157:27
    at Array.forEach (native)
    at Mocha.loadFiles (/Users/bakorer/works/myapp/node_modules/mocha/lib/mocha.js:154:14)
    at Mocha.run (/Users/bakorer/works/myapp/node_modules/mocha/lib/mocha.js:326:31)
    at Object.<anonymous> (/Users/bakorer/works/myapp/node_modules/mocha/bin/_mocha:350:7)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)
    at startup (node.js:139:18)
    at node.js:974:3

FakeDate は timekeeper が用意した Date

timekeeper が以下のように JavaScript の Date オブジェクトと、timekeeper で独自定義した FakeDate オブジェクトを入れ替える処理をしています。

  /**
   * Replace the `Date` with `FakeDate`.
   */
  function useFakeDate() {
    Date = FakeDate
  }
 
  /**
   * Restore the `Date` to `NativeDate`.
   */
  function useNativeDate() {
    Date = NativeDate
  }

Date が Date でなく FakeDate に入れ替わってるタイミングで、new mongoose.Schema を呼び出すが FakeDate は MongooseTypes に定義されていない SchemaType なので例外が投げられてるっていう感じです。ザックリ説明すると。

new mongoose.Schema で SchemaType チェックしている Mongoose のコードはこの辺です lib/schema.js#L652-L671

テストコードの書き方次第でエラーは避けられる

timekeeper.freeze して timekeeper.reset するまでの間に、明示的に new mongoose.Schema したいテストコードを書くことはほぼないと思ってます。なので、new mongoose.Schema の処理を書いてる Model を定義してる module などは事前に require() しておくことでエラーを退避したいですね。

[MongoDB] ISODate の年月日の文字列を取得する

MongoDB の ISODate から年月日の部分だけ文字列を取得するには、toISOString() と substring() を使って以下のようなコードで取得できます。

MongoDB

続きを読む