渋谷の片隅で吠える

エンジニアをしています。主にscalaとjavaを書いています。

READMEとWikiをハックする

開発規模が大きくなるに連れてREADMEとWikiの重要度が増す

個人や単一のプロジェクトのみの頃はいいのですが、会社の規模に合わせて 人が増え、ドキュメントが増え、プロジェクトが増えます。 弊社ではgithubを使ってソースの管理をしています。

そうなってくると同じ言葉でもプロジェクトごとに違う意味合いをもったり、 営業や運用サイドの人がissueを立てる機会も増えるものです。 そんな時、ふとコミュニケーションコストが結構あるなと思いました。

wikiに書いてあるもののプレフィックスの付け方で情報にたどり着けなくて質問したり、 サービスの流れやバッチの詳細がわからずに要件を詰め直すミーティングをしたり。 ここはREADMEとwkikiを整備してどのプロジェクトでも これはREADME見れば書いてある、これはwikiのこういうプレフィックスの場所に格納されてるとわかるようにすればいい!と思い立つわけです。

README

READMEにはプロジェクト概要とスタック、スタート方法を担わせます。 とりあえずREADMEみときゃフレームワークやら言語のバージョンがみらるようにするのが狙いです。

最低限の情報を簡潔にまとめ、できるだけ日本語の平易な文章にします。 これは運用サイドの人でも読めるようにしておくためです。 彼らは英語のドキュメントは読んでくれません。ググレカスは通じません。

そこにわかりやすいものを載せるこれだけの労力でコミュニケーションコストの 圧搾ができるなら手間をかけましょう。

Wiki

ここではエンジニアのための詳細な情報やテストの手順、デプロイなど サービス運営に置いての情報を一気通貫で置いておきます。 肝心なのは命名です。 これはwikiでも一緒。リーダブルなプレフィックスをつけましょう。(統一してください) ここでもルールは簡単にしておきたくて、 基本ルールは - 情報のまとまりはコンパクトに - 意味を揃えた言葉の使い方をする くらいでしょう。

それぞれを統一フォーマットを下敷きにする

ここでいちばん重要なのは言葉の意味の統一すべき部分の切り出し。 プログラムを書く上での単語レベルまで揃える必要はないですが、 説明の時の文章には使い方を統一した単語選びが重要です。

時に運用がみるページには最大限のおもてなしの心でwikiを書きましょう。。。

まとめ

README編

  • 書き方のフォーマットを作り運用
    • 丁寧に作りすぎないことがポイント
    • READMEの内容に変更があったことをログとして残したい(PR出せばいいのだろうけど面倒)

ここでの重要ポイントは統一フォーマットを下敷きにしてREADMEのプロジェクトごとの違いをなくすこと。 wikihへの誘導などがあると新しく人員が増えた時に質問コストが下がるので便利。

wiki

  • 同じく基本フォーマットを作る
    • 項目の情報は最小単位の情報で!
    • プレフィックスの付け方一つで格段に運用コストが下がるのでめんどくさがらないこと

READMEの足りない部分やプロジェクト独自の動きや操作等をまとめる。 一つの項目での情報を欲張らないようにしてコンパクトに!

所感

プレフィックスの付け方一つでここまで運用や新規ジョイン時にかかるコストが下がるとは思わなかった。 運用サイドの人が見る場合には非エンジニア向けの項目も追加しておくと やりとりが格段によくなり、情報の属人化を緩やかに緩和できると思った。 コミュニケーションコストの増加を招く原因は情報の場所の乱雑さ、そして統一されない言葉の意味にある。 言葉の意味の統制をするのは現実できでないならwikiやREADMEはせめて統一された意味を持つものと個別に意味を持つものを明確に書き分けて行きたいと思う。 ここまで時間のレバレッジと質問コストが下がるならば一つ真剣に取り組む価値があると思う。 ぜひ皆さんもREADMEとwikiを整備してHappyな開発ライフを!

最高の開発環境を求めて

より良い、より生産性の高い環境はエンジニアにとって水に等しい重要さだ。 例えが悪いけどどのくらい重要かと言えばその存在を言うまでもなく重要って意味で水と言ってます。

今回は僕の開発環境を一部紹介して行こうと思う。 僕のメインで扱う言語はJavaだがフロントからサーバーサイドまで一気にみる機会の多い 弊社の環境では時にモノリスな環境とjava7、時にplay2.5×scala×Reactと言った加減で変化が激しい。 環境変化に耐えられストレスなくプロジェクトの横断を可能にしてくれる環境を求めている。 さてそんな中CTOが頑張って勝ち取ってくれた我が開発環境を自慢させてくれと言うのが主題。

みなさんのおすすめ環境もおしえてほしい。

ハード編

PC

MacBook Pro OSX 10.12.6

マウス

iMac付属のもの

外部ディスプレイ

32インチ(LG)

ツール編

intellij idea Ultiimate

弊社では有料版に会社で加入しているため intellijをはじめWebStome等JetBrains製品は全て使えます。 intellijマジで便利すぎて大好きです。 開発環境を聞かれたらintellijとgitあれば何とかなるとすら思っています。

atom

メモと軽量な開発やスニペットはほぼ全てこれで書いています。 マークダウンに対応してくれるのがいいですよね。 最近はIDE化にも取り組み始めていてより見た目が好みになってきました。

iterm2

fishで運用中(https://fishshell.com/) 軽量でみためが好みだったのでoh my zshから脱却すべく乗り換えました。 問題はbashコマンドが一部使えないところ。。。 テーマやプラグインも豊富なので別記事で魅力を語ります。

まとめ

弊社では開発環境が揃いやすくエンジニアにとって理想の環境作りにはぴったりです。 ただ営業サイドとのコミュニケーションが多いので苦手な方からすると 苦行寺のような場所かもしれませんが。。。

まだまだ未熟な僕らが技術を高めるのに必要な開発環境。 ぜひケチケチしないで環境をつくってほしい。

DBにおける論理削除について考えてみた

そもそも論理削除とはなんなのか

DBの基本操作は4つ CRUDと略される「create(新規作成)」「read(読み取り)」「update(更新)」「delete(削除)」

このうち実際に使っていくと問題になるものがある。 それがdelete。

とあるテーブルの一定の条件を持つデータが不必要になったのでdeleteしようとする。 しかしこのデータが他の箇所で参照されている場合このデータを安易に削除することはできない。

こんな時に使うのが論理削除である。 具体的には新たにカラムを追加しそのカラムの型をbooleanにする。 そしてクエリ側で追加したカラムがtrueの時には(またはfalseの時には)取得をしないという処理で該当箇所へのデータをクエリから流さないように制御することができる。

これが論理削除の基本である。

しばしば問題になる論理削除

これは非常に便利で強力な考えだ。 何かプロジェクトをたちあげた時にDB設計をすると必ず入れたがる人がいる。

しかし本来あるべき状態の時には不活性で活性するのは非表示にするのみのレコードをデータとして持たせるのはいかがなものかという議論がある。

ないくていい仕組みができるなら 削除できた方がトランザクションもDB容量も圧迫されずに済むからだ。

delフラグは思考停止といいうひともいるくらい。 DELETE_FLAG を付ける前に確認したいこと。

具体的な対処をかんがえないといけない。

とりあえずの回答

プロジェクトの歴史によってdelがつけられる背景は様々である。 中には思いもよらぬピボットのために泣く泣くdelを作ったのかもしれない。 この議論には一定のプラクティスはあるかもしれないけど、基本は設計の段階での想定をいかにするか。運用する人や営業の人と密にコミュニケーションをとってありそうな状況を想定するしかないのだと考える。

bootstrap4がリリースされたので変更をまとめてみた

New!

  • LESS -> Sassに より高速な読み込みとシンプルでデバイスの違いを問題としないCSSの作りを目指した結果のようです。

また実際には2パターンのSass(LibsassとRuby Sass)が内蔵されているのでコンパイル時に好きな方が選べるようになりました。

  • グリッドシステムの変更 ブレイクポイントが4箇所に増えました。 Bootstrap3の時には切り捨てられてしまっていた768px以下の設定をひろうことが可能になりました。

より小さい画面のデバイスへの対応の結果で モバイルを意識した設計に変更されています。

またグリッドの単位がpxからremに変わっているので注意が必要です。

  • FireFoxへの対応 これまで対応してこなかったFireFoxへの対応がされるようになりました。 Flexboxを使用すると、既存のコンポーネントがfloatレイアウトからflexレイアウトへと移行されるそうです。

ただしこの機能は通常だとOFFなので切り替えをする必要があります。

グリッドの中に画像を入れ込むような時にはcardsを利用すれば良さそうです。 - リセットCSS リセットCSSが変更されたらしいですが大幅な改善があったという感じではありません。

追加されたSassファイルがbootstrap3の時のscaffolding.lessとほぼ同じ機能を有しています。

  • カスタマイズオプションの充実
  • remを採用 フォントやコンポーネントの単位がpxからremに変更になりました。 これはIEのサポート終了が大きな要因と考えられます。

またデフォルトのフォントサイズが14px -> 16pxへ変更になったため少し文字が大きく感じます。

  • ES6への刷新 javascript記法がES6へ全面移行しbabelでトランスパイルするようになっています。

バージョンアップに際しての所感

今回のバージョンアップの肝は読み込みの速さにこだわった点とマルチデバイスへの対応にあるのではないでしょうか。

かねてよりバランスを撮るのが難しい存在だったIEのサポートを切ったことでより幅の広いサポートが可能になったのではないかと思います。

またES6の導入やbabelでのトランスパイルを前提とした作りでより一層UIの構築がリッチになる予感です。

おまけ

remとはどんな単位なのか

remはCSS3で導入された単位です。 root emの略でルート(html)のサイズの継承をするemということlistの中の文字だけサイズがずれるなんてことが起きにくいのがいいですね!

pvmがうまく動かないのでなんとかしたい

pvmとは

pvmはnvmの流れを踏襲したplay frameworkのバージョン管理を行うツールである。 使い方はいたってシンプルで pvmのリポジトリをhomeディレクトリでクローンしシェルスクリプトを実行するだけ。

その後pvm install <version>を叩くとzipファイルをとりにいって保存。 pvm use <version>を叩いて適宜使い分けをするといった加減で使えるものだ。

ここまではReadMeにかいてある通りでなんだけど、 ぼくの環境ではpvm installのあたりから思った挙動にならない。

以下、どうなったのかをまとめる。 まあ気にくわないならpull requestおくるのが一番なんだけど。。。

エラーまでの流れ

実現したい事

平時play2.5をつかって開発をしているのだが、play1.2.7が必要なので特定のディレクトリではplay1.2.7が動いて欲しい。 ちなみにjenvを使ってjavaのパッケージ管理はできている。

pvmインストールする

git clone git://github.com/kaiinkinen/pvm.git ~/utils/pvm

その後 . ~/utils/pvm/pvm.shを叩く

pvmでplayを落とす

pvm install 2.0 とするとダウンロードが始まり
~/utils/pvm/src配下に2.0.zipと2.0.https_headerが置かれる

ここからが問題なのだけど zipはダウンロードできたにもかかわらずdownload failと表示がでる。

ダメ元でpvm use 2.0を叩くと インストールされていないと出てくる。

fxxck!!

とりあえずの解決策

どうしてもplay1.2.7が必要だったのでdirenvを入れて管理する事にした。

お世話になった記事 https://qiita.com/kompiro/items/5fc46089247a56243a62 https://qiita.com/honyahonyagemomo/items/4504e209905777d8220b

今月中にpull request送るからまっとけpvm

direnvでエレガントな開発環境を

direnvとは

ディレクトリごとに環境変数を定義してカレントディレクトリになった時に環境変数を適用してくれるツール。

Githubはこちら
https://github.com/direnv/direnv

Goでできててなうい感じ。 ドキュメントも充実してます。

インストール

Mac上でHomeBrewをいれているときはbrew install direnv

そうじゃない人は

git clone https://github.com/direnv/direnv.git
cd direnv
sudo make install

これでインストールは完了

hookの追加

.zshrcや.bashrcにhookを追加する。

export EDITOR=vim(ここはお気に入りのエディタに読み替えてください)
eval "$(direnv hook zsh)"

bashの場合は

eval "$(direnv hook bash)"

pathを通して環境を作る

環境構築したいディレクトリに移動して

direnv edit .

とすると記載のためのエディタが立ち上がるので、そこに

export PATH=bin:$PATH

を追加する。

PATH_add bin

こっちでもできます。

保存が完了すると.envrcができているので追加があるときは編集してください。

エラーが発生する

.envrcが読まれると時たまエラーが出ます。そんなときは

direnv allow

として問題解決

direnvを使うメリット

pvmとかpyenvとか色々管理ツールはあるわけですが管理ツールの管理に追われるというジレンマに陥りがち。

あれ、何が原因で動かないんだ?ってなった時に.envrcを見に行ってごにょごにょするだけでいいなら楽チンです。 僕はplayFrameworkの管理がきっかけで使うようになりました。 play1.2.7を使う時にjava7使わないといけなかったり他ではscala使ったりjava8つかったりしてる関係でとても重宝しています。

これで余計な労力を使わずエレガントな環境構築と変更が可能です。

おまけ

alias

.direnvrcを開いて

export_function() {
local name=$1
local alias_dir=$PWD/.direnv/aliases
mkdir -p "$alias_dir"
PATH_add "$alias_dir"
local target="$alias_dir/$name"
if declare -f "$name" >/dev/null; then
echo "#!/usr/bin/env bash" > "$target"
declare -f "$name" >> "$target" 2>/dev/null
echo "$name" >> "$target"
chmod +x "$target"
fi
}

を書き込む。

hoge() {
 こまんど
}
export_function hoge

こちらで議論してます。参考にどうぞ https://github.com/direnv/direnv/issues/73

Macにfabricを入れてherokuへデプロイしたい時につまずいた。

やろうとした事

fablicを使ってherokuにある本番へデプロイをしたい

環境

OS: OS X El Capitan 10.11.6 python : 2.7.0

pipをインストール

まずこのPCにはpipが入っていなかったのでpipをダウンロード。

sudo easy_install pip

動作確認

pip -V
pip 9.0.1 from /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages (python 2.7)

fabricをインストール

pip install Fabric

インストールの確認

pip freeze

asn1crypto==0.24.0
bcrypt==3.1.4
cffi==1.11.2
cryptography==2.1.4
enum34==1.1.6
Fabric==1.14.0
idna==2.6
ipaddress==1.0.19
paramiko==2.4.0
pyasn1==0.4.2
pycparser==2.18
PyNaCl==1.2.1
six==1.11.0

無事にfabricが入ったのでfabfileをつくる

デプロイのためのfabfile.pyをつくる

# -*- coding: utf-8 -*-
from fabric.api import *
from fabric.decorators import runs_once
from datetime import datetime

env.hosts = ['00.000.000.0']
env.user = 'ec2-user'
env.key_filename = '~/.ssh/deploy_file.pem'
env.project_root = '../'
env.build_path = project_path
env.config_path = project_conf_path
env.branch = 'master'
env.archive = ''
env.server_api_dir = path

@task
@runs_once
def build_play():
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    env.archive = "api-%(timestamp)s.tar.gz" % {"timestamp":timestamp}
    with lcd(env.project_root):
         local("/usr/local/bin/activator clean stage")
         local("tar cvfz %(archive)s target" % {"archive":env.archive})
         put("%(archive)s" % {"archive":env.archive}, "%(dir)s/" % {"dir" : env.server_api_dir})
         local("rm %(archive)s" % {"archive":env.archive})
@task
@runs_once
def unck():
    run("sudo rm -Rf %(dir)s/target" % {"dir" : env.server_api_dir})
    run("tar zxvf %(dir)s/%(archive)s -C %(dir)s" % {"dir" : env.server_api_dir, "archive":env.archive})

@task
@runs_once
def deploy(branch=env.branch):
    execute(build_play)
    execute(unpack)

ここまでは順調

問題発生

fabricは問題なくお登勢てるにもかかわらずfabコマンドが動かない

deployディレクトリに移動してfab deployを叩くも失敗 どうしたもんか。。。 heroku側の設定も問題ないし、何より上のコマンドで先輩はdeployできている。

もうちょい調べる必要がありそうです。