初日、行ってまいりました。

流行りの環境うんぬんは単なる手段であり、"経営陣を含めたマインドセットの更新が大事"ってのはありますが、そんな話みんな読みたくないでしょ?

僕が調べた現状と、こういう風に持って行きたいという理想の環境を書き出してみました。

現状

  • 本番環境
    • さくらのマネージドサーバー(FreeBSD)
  • ステージング環境
    • 共有開発サーバー(社内に古めのCentOS)
  • 開発環境
    • 共有開発サーバー(社内に古めのCentOS)
  • ソースコード管理
    • svn
    • 共有開発サーバーのコードを担当者一人が全員を代表してsvnにコミットする。バックアップ的な役割
  • タスク管理
    • 社内の独自タスク管理システム
  • デプロイ
    • 共有開発サーバーのソースをFTPでアップする
  • 開発マシン
    • Windows7
  • コーディング規約
    • PEAR標準コーディング規約をカスタマイズしたもの
  • コードレビュー
    • なし
  • チャット
  • ナレッジ共有
    • 社内の独自情報共有システム
    • 社内の独自日報システム
  • 自動テスト
    • なし
  • サーバー監視
    • なし
  • エラー管理
    • メールが飛ぶ
  • ライブラリ利用
    • なし
  • フレームワーク
    • なし(一部Codeigniter)

理想

  • 本番環境
    • AWS?
    • DigitalOcean?
  • ステージング環境
    • 上記サービス上に構築
  • 開発環境
    • 各自のローカルマシン
      • Vagrant?
      • Docker?
      • XAMMP?
      • 共通開発サーバーに全員分の環境を作る?
  • ソースコード管理
  • タスク管理
    • Github Issue?
    • Pivotal?
    • Trello?
    • これは現状維持でもいいかも
  • デプロイ
  • 開発マシン
    • Mac?
    • Linux?
    • Windows?
  • コーディング規約
    • PSR-4(via @tadsan さん)
    • PSR-2
  • コードレビュー
    • PRベースで行う
  • チャット
  • ナレッジ共有
    • Github Wiki?
    • これも現状維持でいいかも
  • 自動テスト
  • サーバー監視
  • エラー管理
  • ライブラリ利用
  • フレームワーク

感想

正直レガシーPHPの現場というと、"鳴り止まぬクレーム電話"、"デスマ続きで死んだ目をしたプログラマの群れ"などをイメージしてたんですが、現行のシステムでちゃんと商売が回って売上が上がっているし、現状を良くしていきたいというポジティブな雰囲気があったのでそれだけで行ける気がしました。

現行のツール類や開発フローに関しては、皆さんも思ったかもしれませんが、"懐かしい"の一語に付きます。昔は僕らだってみんなこうだったんだよ!

これはレガシーPHP(Legacy PHP)というより古き良きPHP(The good old PHP)と呼びたい感じ。

見えてきた開発環境の今昔

こうやってカテゴリ分けしてみると昔と今で同じ方向ですべてのツールが進んでるように感じます。

昔(って言い切るのはひどいですが)は社内で閉じていて外からは使えません。今のツール群はオープンでどこからでもスマホなどいろんなデバイスで使える傾向にあります。

また、昔のツールは1人または少人数で同期的に使うように出来ていますが、今のツールは多人数・非同期で作業することが前提となっています。

要は「場所・人数・時間」を選ばないように進化してきてるってことですかね。

困っていること

理想に近づけるのにまずやる必要があるのが、みんながひとつの開発環境を使っている現状から個別のローカルで開発してコミットするというフローに変更するところ。

たくさんのサイトが社内の共通開発環境で動いてるのですが、デザイナーも含めてWindowsでローカル開発に変えるには今だとどうするのが一番いいんでしょうか?

XAMPP?Vagrant?Docker?どっかのサーバーに全員分の環境を作る?

もしおすすめがあったら教えていただけるとありがたいです。

世の中のレガシーPHPを減らしたい

レガシーPHPを改善する一連のフローを毎回苦労して行うのは無駄ですよね。レガシーPHPを改善したいと思っている会社さんはたくさんあると思うし、それができる小さい会社やフリーランスのプログラマーもたくさんいると思いますし、求人・お仕事のマッチングもたくさん生まれるのではないかと思います。(前回ご一緒させていただいた @kaz_29さんや@kjirouなど僕が出会えてる人はその本当一部なので)

そこで、上手くいきそうだったらレガシーPHP改善のノウハウを共有するイベントや実際に改善していく集団・コミュニティーが出来たらいいなとおもいます。

関連:レガシーPHP改善日記シリーズ

レガシー坂は終わっていなかった。

3年前のレガシーPHP改善日記を見てレガシーPHPと開発フローの改善したいとのご依頼があったので再びレガシーPHPと格闘することになりました。

今回は皆さんWindowsをお使いとのこと。そこに若干の不安。どうなることやら・・・。

関連:レガシーPHP改善日記シリーズ

Mac版Office 2011は読み取り専用で使うなら無料なんですね。homebrewから入れられるのが嬉しい。

$ brew cask install microsoft-office

"Use Office to view your files for free"を選べばOK。

他社から複雑なレイアウトのExcelとか送られてきた時に。(←腹立つ)

brew doectorして知ったんですが、Mac OS Xデフォってcase-insensitiveだったんですね・・・。どうもAdobeとかSteamのゲームとかインストール時に文句言われるなあとかおもってたんですが・・・。

formatするときにcase-sensitiveにするかcase-insensitiveにするか聞かれたら前者選んじゃうのが人情ってもんじゃないですかあ。

% brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry and just ignore them. Thanks!

Warning: The filesystem on / appears to be case-sensitive.
The default OS X filesystem is case-insensitive. Please report any apparent problems.

じゃけん再クリーンインストールしましょうねぇ〜・・・

例えばコメント投稿のテスト。

# test/integration/post_comment_to_comic_test.rb:
require 'test_helper'

class PostCommentToComicTest < ActionDispatch::IntegrationTest
  test 'Post a comment' do
    visit comic_path comics(:comic)
    within('#new_comment') do
      fill_in 'comment[body]', with: 'コメントのテスト'
    end
    click_button '規約に同意してコメントする'
    assert has_selector? '.content-comment__body-text',
      text: 'コメントのテスト'
  end
end

よくあるこういうのを実行したら下記のエラーが。

% ruby -Itest test/integration/post_comment_to_comic_test.rb -n PostCommentToComicTest#test_Post_a_comment
Run options: -n PostCommentToComicTest#test_Post_a_comment --seed 29141

# Running:

E

Finished in 5.497046s, 0.1819 runs/s, 0.0000 assertions/s.

  1) Error:
PostCommentToComicTest#test_Post_a_comment:
Capybara::Webkit::ClickFailed: Failed to click element /html/body/div[@id='content']/div[@id='comments']/div/div[1]/form[@id='new_comment']/div[@id='comment_action']/input because of overlapping element /html/body/div[@id='content']/nav/div/ul/li[2]/a/span at position 831, 1025; 
A screenshot of the page at the time of the failure has been written to /var/folders/nb/5jp6psyd7h19my68chb0svvh0000gn/T/click_failed_W60479.png
    test/integration/post_comment_to_comic_test.rb:23:in `block in '

1 runs, 0 assertions, 0 failures, 1 errors, 0 skips

クリックできなかったElementのxpathを表示してくれる。そして何故クリックできなかったのか、overlapしているElementのpositionとxpathも表示してくれる。更にscreenshotここに撮っておいたからってどこまで至れり尽くせりだよ。

この場合、要はこんな感じになっててコメントボタンがクリックできない。

こんな方法でいいのかどうかわかりませんが、テスト前にexecute_scriptでoverlapしてるメニューをhideして対処。

# test/integration/post_comment_to_comic_test.rb:
require 'test_helper'

class PostCommentToComicTest < ActionDispatch::IntegrationTest
  test 'Post a comment' do
    visit comic_path comics(:comic)
    execute_script("$('nav.other-pages-nav').hide()") # It's workaround.
    within('#new_comment') do
      fill_in 'comment[body]', with: 'コメントのテスト'
    end
    click_button '規約に同意してコメントする'
    assert has_selector? '.content-comment__body-text',
      text: 'コメントのテスト'
  end
end

更に背景と同色の文字問題とかもサポートしてくれたら手動QA不要とはいわないけどもっと自動テスト化できますね。

ツバから採取したDNAから病気の発症リスクなどを教えてくれるMYCODEを(会社の経費で)使ってみました。

MYCODE(マイコード) | これから先の健康のために自宅でできる遺伝子検査を

日本人平均と比べてかかりやすい病気とその対策を教えてくれます。

僕が申し込んだのはオールインワン280+ってやつです。280項目と言われてもそんなに見きれませんが。

Webサイトから購入するとこういう昔のAdobeのパッケージみたいなので検査キットが届きます。

DNAを採取するのにツバってのは確かに便利かもなあという感じ。

「唾液を出しやすくするために、ご覧ください。」

と、こういうカードが入ってるのが面白い。

郵送で送り返してからWebサイトで結果が見れるようになるまで二週間ぐらいかかった気がします。

その間に体や生活習慣に関するアンケートが大量にあって、その回答も結果に影響してくるようです。

こういう非IT系のITサービス(?)のWebサイトはクッソ使い辛いのが常ですが、大量のアンケートもサクサク答えられるような使いやすいUIになってるのはさすがDeNAという感じ。

検査結果

検査結果が出たとのメールが来てアクセスしてみると個人情報についての注意書きが。

DNAは親兄弟・子供の情報も含むことになるので個人情報を超えた一族情報とでも言うべきものなのでクッソ注意しろとのこと。自己責任どころじゃ済まない情報の扱いにちとビビる。

日本人平均と比べて一番なりやすいのが円形脱毛症だってさ!

注視したいのは日本人平均に比べてかかりやすい病気と予防法。僕の場合は極端に倍率の高い深刻な病気はなかったので一安心ですが、他の人の見せてもらったら全然違ったので寿命に関わる場合もあるんじゃないでしょうか。

感想としては、僕の場合、アンケート結果が「うつ病」って感じなので、アドバイスが「時々ハイキングに行け」とかなのはDNAっぽくなくて残念。

また、現時点で予防法が無いものが多いので「って言われてもな・・・」となることが多い点。

あとは、日本人平均1倍だとしてももっと注意すべき危険な病気(いろんな癌とか)がたくさんあるので、そっちが知りたいなとかです。

サービスへの感想

郵送されてきたものにツバ入れて返すだけなので苦痛とかゼロですし人間ドックや健康診断と違って会社を半休したりしなくて済むのが働いてる人的には嬉しいです。

統計とったらちゃんと病気にかかる確率が減ってるんじゃないでしょうか。それで病気が減るなら検査にかかるサービス提供側の手間も少なそうだし、保険が効けば更にみんな使って国の医療費も減るんじゃないの?やっちゃいなよ!って感じでした。

医者の代わりにはならないですが、とにかく手間が無いのがありがたいです。こういう試みはどんどん進んでいって欲しいです。

sass-railsの5.0から、foo.css.sassfoo.sassに変えよというWARNINGが出るようになってました。(エラーが出たらとりあえずGoogle検索欄に放り込む人=俺用のエントリータイトル)
DEPRECATION WARNING: Extra .css in SASS file is unnecessary. Rename /Users/komagata/code/kowabana/app/assets/stylesheets/blocks/footer/_footer-pages-nav.css.sass to /Users/komagata/code/kowabana/app/assets/stylesheets/blocks/footer/_footer-pages-nav.sass
...
...
...

デザイナーの作業とコンフリクトする予感!

% ls app/assets/stylesheets/**/*.css.sass | wc -l
     107

すげーたくさんあってやんなりますよぉ~

% zmv app/assets/stylesheets/**/*.css.sass app/assets/stylesheets/**/*.sass
% zmv app/assets/stylesheets/*.css.sass app/assets/stylesheets/*.sass
% git add 'app/assets/stylesheets/**/*.sass'
% git add 'app/assets/stylesheets/*.sass'
% git rm 'app/assets/stylesheets/**/*.css.sass'
% git rm 'app/assets/stylesheets/*.css.sass'

zmv使うとちょっと楽。

参照:zsh の zmv を使って簡単に複数ファイルを一括リネームする - mollifier delta blog

こちらの記事の解決編です。

ActiveRecord::RecordNotFoundのエラーは放置すべきか? - komagata

@hiroshi3110さんからズバリな答えをいただきました。

怖話で実装

# lib/record_not_found_by_trustless_param.rb:
class RecordNotFoundByTrustlessParam < StandardError; end
# app/controllers/comics_controller.rb:
class ComicsController < ApplicationController
  before_action :set_comic, only: :show
  
  def show
  end

  private
  def set_comic
    unless @comic = Comic.find_by(id: params[:id])
      raise RecordNotFoundByTrustlessParam                                                                                                                                                                  
    end
  end
end
# app/controllers/application_controller.rb:
class ApplicationController < ActionController::Base
  rescue_from RecordNotFoundByTrustlessParam, with: :not_found
  
  private
  def not_found
    render file: "#{Rails.root}/public/404.html", layout: false, status: 404
  end
end

@hiroshi3110さんの言うとおり、信頼出来ない外部からのidを元にしたfindで見つからない場合はRecordNotFoundByTrustlessParamにし、rescue_fromで拾って404を出すようにしました。(404を動的テンプレートで出すのは良くないと思うのでpublic以下の静的ファイルを読む)

自分の中のベストプラクティスにしようと思いました。

Rollbarとかのエラー管理サービス使ってるとActiveRecord::RecordNotFound がWARNINGレベルのエラーでたくさん残るので気になる。

idに適当な数字入れれば必ず出るんだから。rollbarの無料プランは月のエラー数に上限があるのでもったいない。

しかし、特定の存在しないidが何度もアクセスされるのは問題の兆候だったりするから完全にmuteするのも気が引ける。皆さんどうしてるんでしょう?

追記:

ActiveRecord::RecordNotFoundエラーを防ぐ - komagata

wootheeを見習って他reposからgit submoduleしやすいように祝日データをrubyからyamlにしました。(organization化と言語非依存にrepos化はちょっとしたholiday_jpのようなライブラリではやり過ぎかなと思ってやってません。submodule使えば祝日データの一元管理という要は足りるしね。)

komagata/holiday_jp

僕がgemを作る時ってすごく画期的なアイデアが見つかったとかあんまりないので、ほとんどが仕事上で必要だけど既存のgemが存在しない=日本語やi18n関係ばっかりになっちゃうんですよね。

昔に使ったので我ながら設計が変ですが、テストが合ったのでテストに変更が無いように実装を変えただけです。あとはテストにshoulda-contextとか今日び使わないのでtest-unit3に変えたぐらい。

最近gem作る時ちょっと便利だなと思うのはgemspecとか自動生成系ファイルをコーディング規約に合わせるために手作業しなくても$ rubocop -aでほとんどいけちゃうところ。