レガシーPHP診断を作りました。
回答結果はこちらで見られます。
基本的に選択肢の上の方がよりおすすめという感じです。まずは自社の環境がどのような状態か把握するチェックリストとして使っていただければいいかなと思いました。
改善に関してはPHP: The Right Wayが参考になると思います。
レガシーPHP診断を作りました。
回答結果はこちらで見られます。
基本的に選択肢の上の方がよりおすすめという感じです。まずは自社の環境がどのような状態か把握するチェックリストとして使っていただければいいかなと思いました。
改善に関してはPHP: The Right Wayが参考になると思います。
初日、行ってまいりました。
流行りの環境うんぬんは単なる手段であり、"経営陣を含めたマインドセットの更新が大事"ってのはありますが、そんな話みんな読みたくないでしょ?
僕が調べた現状と、こういう風に持って行きたいという理想の環境を書き出してみました。
@komagata 記事を読ませていただきました! コーディングスタイルの規約はPSR-4ではなく、PSR-2 http://t.co/yM2wqwmtji かと(4はオートローダーのための名前空間のための規約)
— tanasinnな∴(・)∴∴(・)∴ (@tadsan) 2015, 2月 12
正直レガシーPHPの現場というと、"鳴り止まぬクレーム電話"、"デスマ続きで死んだ目をしたプログラマの群れ"などをイメージしてたんですが、現行のシステムでちゃんと商売が回って売上が上がっているし、現状を良くしていきたいというポジティブな雰囲気があったのでそれだけで行ける気がしました。
現行のツール類や開発フローに関しては、皆さんも思ったかもしれませんが、"懐かしい"の一語に付きます。昔は僕らだってみんなこうだったんだよ!
これはレガシーPHP(Legacy PHP)というより古き良きPHP(The good old PHP)と呼びたい感じ。
こうやってカテゴリ分けしてみると昔と今で同じ方向ですべてのツールが進んでるように感じます。
昔(って言い切るのはひどいですが)は社内で閉じていて外からは使えません。今のツール群はオープンでどこからでもスマホなどいろんなデバイスで使える傾向にあります。
また、昔のツールは1人または少人数で同期的に使うように出来ていますが、今のツールは多人数・非同期で作業することが前提となっています。
要は「場所・人数・時間」を選ばないように進化してきてるってことですかね。
理想に近づけるのにまずやる必要があるのが、みんながひとつの開発環境を使っている現状から個別のローカルで開発してコミットするというフローに変更するところ。
たくさんのサイトが社内の共通開発環境で動いてるのですが、デザイナーも含めてWindowsでローカル開発に変えるには今だとどうするのが一番いいんでしょうか?
XAMPP?Vagrant?Docker?どっかのサーバーに全員分の環境を作る?
もしおすすめがあったら教えていただけるとありがたいです。
レガシーPHPを改善する一連のフローを毎回苦労して行うのは無駄ですよね。レガシーPHPを改善したいと思っている会社さんはたくさんあると思うし、それができる小さい会社やフリーランスのプログラマーもたくさんいると思いますし、求人・お仕事のマッチングもたくさん生まれるのではないかと思います。(前回ご一緒させていただいた @kaz_29さんや@kjirouなど僕が出会えてる人はその本当一部なので)
そこで、上手くいきそうだったらレガシーPHP改善のノウハウを共有するイベントや実際に改善していく集団・コミュニティーが出来たらいいなとおもいます。
レガシー坂は終わっていなかった。
3年前のレガシーPHP改善日記を見てレガシーPHPと開発フローの改善したいとのご依頼があったので再びレガシーPHPと格闘することになりました。
今回は皆さんWindowsをお使いとのこと。そこに若干の不安。どうなることやら・・・。
福岡で行われたPHPMatsuri2012に行って来ました。
PHPConference2012も行ってるし、訓練されたPHPerと言えそうです。
夜の闇PHPMatsuriのアン・リーダブルコード選手権にレガシーブラックが出てました。
レガシー戦隊。
「レガシーブラック、一体何者なんだ・・・。」
「全力でたけしの真似をして望んだがMr. レガシーになれなかった。プロジェクトの仲間である@hrysd, @kjirou, @kaz_29に申し訳が無い。気力も尽き、体力の限界っ!(via 千代の富士)」とはレガシーブラックの弁。
久しぶりに飛行機乗って旅行熱が高まりました。なにわともあれ、お話させて頂いた皆様、運営者の方々、お疲れ様です。ありがとうございました。
今は亡きWiseknot社の同僚であった「三度の飯より四度の飯、Javascriptはもっと好きです。」でお馴染みの@kjirouが一ヶ月来てくれる事になった。
また、アリウープ様にお願いしていた件もCakePHP2実践入門の著者の一人でもある@kaz_29さんが参戦してくださることになった。
「もうついたのか!」「はやい!」「きた!盾きた!」「これで勝つる!」と大歓迎状態だった。哀れにも@komagataは盾の役目を果たせず死んでいた近くで素早くフラッシュ(略
俺「あのポイント関連の処理ってどこでやってるの?」
@kjirou「あー、あれは共通化されてないからどっちかは処理されてないんだけど、片方は"軽く発生ポイント"でやっ(略」
俺「軽く?・・・何?」
@kjirou「だからカルクハッセイポイントクラスで」
俺「あー、Calculation?ちょwwwww CalcHasseiPointかよwwww。英語日本語英語のクラス名をさも一般名詞みたいに日常会話に混ぜないでよwwww」
@kjirou「いやそんなんこのコードの中じゃ普通でしょ、それより酷いのがこっちの処(略」
大量メール配信の部分もヤバイということで@kaz_29さんがSimpleTest(CakePHP1.3なのでPHPUnitじゃないところがまたダルいが)でテストを書き始めてくださった。
@kjirouも複雑怪奇な仕様と実装をGithub Wikiにまとめながらどんどんコードを書いてる。
@hrysdは先日仕込んだMailLoggerから容赦なくNotice, Warnningが飛んでくるのでそれを潰すのを担当。
盛り上がって来やがった。
app/tests/helper.php:
<?php require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; class CakePHPSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase { protected function assertNoError() { $html = $this->getHtmlSource(); $patterns = array( '/<b>Fatal Error<\/b> \(256\)/', '/<b>Warning<\/b> \(512\)/', '/<b>Notice<\/b> \(1024\)/' ); $result = 0; foreach ($patterns as $pattern) { $result += preg_match($pattern, $html); } $this->assertEquals($result, 0); } }
「とにかく普通に画面にエラーが出てる」
という問題を直すためにCakePHP1.3が出力するエラーを確かめるための強引なAssertionを作成。
app/tests/integrations/RegularOrdersTest.php:
<?php
require_once 'helper.php';
class RegularOrdersTest extends CakePHPSeleniumTestCase
{
protected function setUp()
{
$this->setBrowser('*firefox');
$this->setBrowserUrl('http://xxxxxxxxxx/');
}
public function testIndexTitle()
{
$this->open('/regular_orders');
$this->assertTitle('管理画面');
$this->assertNoError();
}
}
こんな感じで使う。
PHPUnitのソース追ってましたが、開発がかなり活発。APIとマイナーバージョンがどんどん変わってく。そんなに頑張るとハゲるぞセバスチャン。
まだJenkinsに怒られるけど来週には環境が整うはず。強引にCIに乗せようと思えば乗るもんだなあという感じ。
PHPMatsuri2012行きます。基本、Hackathonだそうなのでレガシーに役立つ何かが作れればなーと思います。
あるべき初期データの姿が不明。今動いてるDBが全て。という場合にmigrationをはじめるのが難しい。また、複合主キーを使ってる場合はそもそもmigration出来ない。なので無理矢理afterでdumpファイルを読み込んで対応。
<?php
class xxxxxxxxxxxxxxxxx extends CakeMigration
{
public $description = '';
public $migration = array(
'up' => array(),
'down' => array(),
);
public function before($direction)
{
return true;
}
public function after($direction)
{
if ($direction == 'up') {
$config = $this->db->config;
`mysql -u{$config['login']} -p{$config['password']} {$config['database']} < db/20121010154033_create_initialize.sql`;
}
return true;
}
}
レガシーコード改善ガイドが届いたので読みました。とても勇気づけられたし、レガシー改善のコーディングテクニックがいろいろと参考になりました。
個人的にはコーディング以外の開発環境やツール、スクリプト言語ならではな部分も知りたかったのでレガシーコード改善ガイド風に思いついたのを書いていこうと思います。
まずは深呼吸して、コードベースをeval, create_function, extractでgrepしましょう。意外と少ないでしょう?だったら大丈夫。findとgrepとviがあればいつかは何とかなります。
テスト環境みたいなのがあるはず(もしくは本番環境)なのでFTPとかSCPでそれを全部もってきてgithubに突っ込む。今後、開発はそこにコミットして、アップするときもそこからアップしてねと言う。
githubを借りる許可が出なかったらその辺のマシンにgitをreposを立てる。みんなでreposを使う合意が取れなかったら自分だけでもgitで管理する。githubの利点はpull requestとコードレビューがしやすい点。
ソフトウェア資産を失わないようにという話をすれば大抵聞き入れてくれるはず。
その辺のマシン、もしくはさくらVPS1Gを借りてreposにpushされたらそこにデプロイされるようにしよう。(capistranoとかで)
おそらく本番環境のDBの状態=仕様になっているのでしょう。3桁に迫るテーブルがある場合、まっさらなスキーマから手で初期データを作っていると日が暮れてしまいます。本番のDBをdumpしてきてそれをベースにテストを実行しましょう。ボトムアップではなく、トップダウンで初期データを少しずつあるべき状態にしてきましょう。
本業(デスマ)も「このくらいやってれば普通以上だろう」ぐらいやりつつ開いた時間でやろう。もしくは業務時間外でやりましょう。
ひどい状態なら怒られない範囲でブログに書けばネタになるし同僚や誰かが助けてくれるかもしれません。着実に改善していくところをRPGみたいに楽しもう。ナイトメアモードのゲームだと思えばやりがいがあります。
こんなこと書いてたけど普通にできた。(simpletestは必要)
% cake testsuite app all
知らんかった・・・。
ついでに、phpunitを使ったseleniumのテストも一緒にできるshell作った。
app/vendors/shells/tasks/integrations.php:
<?php
class IntegrationsTask extends Shell
{
public function startup() {}
public function execute()
{
$this->out(`phpunit app/tests/integrations`);
}
}
app/vendors/shells/test.php:
class TestShell extends Shell
{
public $tasks = array('Cases', 'Integrations');
public function startup() {}
public function main()
{
$arg = isset($this->args[0]) ? $this->args[0] : '';
switch ($arg) {
case 'cases':
$this->Cases->execute();
break;
case 'integrations':
$this->Integrations->execute();
break;
default:
$this->Cases->execute();
$this->Integrations->execute();
}
}
}
% cake test
とりあえず本番でエラーが起きてたら開発MLへメールしたい。レガシーPHP案件にとりかかる時はいつもやるphp.iniでメール飛ばす設定をしようとしたら、CakePHPがエラーを捕まえているので飛ばない。
大抵のフレームワークではググるとMailを飛ばすLoggerが見つかるもんだが、CakePHP1.3用のが見つからなかったので書いときました。
<?php
/**
* メールを送るロガー
*
* 使い方:
* // app/config/bootstrup.php:
* CakeLog::config('mailLog', array(
* 'engine' => 'MailLog',
* 'to' => 'to@example.com',
* 'from' => 'from@example.com'
* ));
*/
class MailLog
{
private $to;
private $from;
/**
* オプションを設定する
*
* @param array $options メールのto、fromの設定
* @return void
*/
public function __construct($options = array())
{
if (isset($options['to'])) {
$this->to = $options['to'];
}
if (isset($options['from'])) {
$this->from = $options['from'];
}
}
/**
* ログをメールで送る(ログを書く)
*
* @param string $type エラーの種類
* @param string $message エラーの内容
* @return void
*/
public function write($type, $message)
{
$subject = "[{$type}] ".mb_substr($message, 0, 32);
mb_send_mail($this->to, $subject, $message, "From: {$this->from}");
}
}