より良い環境を求めて このページをアンテナに追加 RSSフィード

2015-08-22

[] Composerの検索をローカルにする

いつも忘れるのでメモ。


あらかじめ外部ライブラリはローカルにgit cloneしておく。



composer.json

    "repositories": [
      {"type": "vcs", "url": "/home/user/repo/my-framework"},
      {"type": "vcs", "url": "/home/user/repo/my-lib"},
      {"type": "vcs", "url": "/home/user/repo/Aura.Session"},
      {"type": "vcs", "url": "/home/user/repo/zend-diactoros"},
      {"type": "vcs", "url": "/home/user/repo/http-message"},
      {"packagist": false}
    ],

packagist: false で指定。


そうすると、ちょっとしたライブラリを自分で作ってるときに、それを更新してもいちいちネットワークを検索せずにすむ。

また、普通に使うときにも、あらかじめローカルにcloneしておけば全パッケージを探さなくて良いので更新が早い。依存関係が増えた場合などは自力で一つずつcloneしていかないとダメだが、そっちの方が早い気がする。

2015-08-12

[] wheezy のvmwareWindows 10 を入れる

今使っているVMware Playerはバージョン5だったので、まず7に上げる。

Linuxだろうとダウンロードしてきたインストーラを実行して、特に問題なく終了。

勝手に上書きインストールされてメニューのアイコンも変わった。動きがWindowsっぽい。


念のためVMwareのゲストデータがあるディレクトリをコピーしてバックアップや確認などしていたらゲスト一覧がバグった。

どうもこの一覧は ~/.vmware などではなく、 ~/.local/share/recently-used.xbel で管理しているらしい。該当部分を削除して対応。


そんでWindows8.1を起動すると表示がバグった。ファミコンのアレみたいに。

ディスプレイ設定の Accelerate 3D graphics をオフにする。設定が書き換わったのか元々だったのかは覚えてない。

そしてVMware Toolsの再インストール




VMwareゲストの場合は自動更新でWindows 10にしようとすると「VMware SVGA 3D お使いのディスプレイは、ディスプレイの製造元によってWindows10との互換性が認められていません。」のようなエラーになるので、自分でisoを取ってくる必要がある。

CDをマウントして実行したら何やらspwizeng.dllのエラーが出る。ちょっとハマったけどよく見たらVMware側でもエラーが出てた。isoファイルサイズが小さいのでダウンロード失敗した模様。もう一度ダウンロードする。3.9GB。長い。


Windows8.1からWindows10のCDを起動してアップデート。これまた長い。

その後VMwareのゲスト設定でOSWindows 10にしたら「Windows 10 x64 is not a supported guest operating system for Workstation 9.0 virtual machines. 〜」と警告が出た。

http://d.hatena.ne.jp/n314/20121218/1355818144 この辺をやればいいのだろうけど、問題が起きるまで取りあえずそのままで。

それからVMware Toolsをインストールし直す。

特にアプリは入れてないのでこれで完了。

待ち時間が長いだけで変なミスをしなければ特に問題なかった。





Windows 8.1VMwareLinuxデスクトップのサブとして使うにはまったく向いてなかったけど、Windows 10 なら大丈夫そうだ。

Windows XP に入っている OfficeとかAdobeとかをやっと移せるか…?

プログラムの削除はせずにとりあえずライセンスだけ移動するのが良いかもわからんね。






ちょっとメモ。

http://blog.drikin.com/2015/01/windows-2.html

ブコメが参考になる。

2015-08-04

[] 今更PHPモナド的なものを書く

http://blog.dakatsuka.jp/2013/09/03/php-maybe-monad.html

この辺とか

http://d.hatena.ne.jp/kazu-yamamoto/20110413/1302683869

この辺とか見てたらちょっとやってみたくなったので。


○○言語でMonad実装って結構あるけど、MonadPlus使えないとあまり意味ないよね?的なところもある。


上記URLのTree探索するやつの

msearch :: MonadPlus m => (Int -> Bool) -> Tree -> m Int

これ、型推論テンプレートジェネリクス戻り値の型がないPHPでは無理目なので、コンテキスト(MonadPlus m)を引数として渡すことにする。

traitがあればreturnやmzeroを共通化できるので多少マシじゃないかな?と思いつつ。


<?php
    private function searchTree(Context $m, callable $f, Tree $tree)
    {
        if ($tree instanceof EmptyTree)
            return $m->mzero();
        if ($f($tree->value))
            return $this->searchTree($m, $f, $tree->left)
                        ->mplus($m->ret($tree->value))
                        ->mplus($this->searchTree($m, $f, $tree->right));
        else
            return $this->searchTree($m, $f, $tree->left)
                        ->mplus($this->searchTree($m, $f, $tree->right));
    }

    private function getTree()
    {
        $empty = new EmptyTree();
        return new Tree(3,
                        new Tree(2, $empty, $empty),
                        new Tree(1, $empty, $empty));
    }

    public function testTreeDataList()
    {
        $c = new DataListContext();
        $f = function($a){ return $a % 2 == 1; };
        $t = $this->getTree();
        $ret = $this->searchTree($c, $f, $t);
        $this->assertEquals(Cons::fromArray([3,1]), $ret);
    }
    public function testTreeMaybe()
    {
        $c = new MaybeContext();
        $f = function($a){ return $a % 2 == 1; };
        $t = $this->getTree();
        $ret = $this->searchTree($c, $f, $t);
        $this->assertEquals(new Just(3), $ret);
    }
https://github.com/nishimura/laiz-monad/blob/master/test/src/Laiz/Test/Monad/ContextTest.php

タイプ量が多い…。

traitってこういう使い方で良かったんだっけ?ファイルの置き場所とかセオリーが分からん。

composer.json置いてるけど未登録。

2015-07-28

[][] ぼんやり振り返り

顧客は本当に欲しいものは知らない、と言うけれど同じような症状だ。

かゆいところに手が届かない。



自作フレームワークがつぎはぎになってきたのでカッとなって作ったやつ。

PHPの小規模用テンプレートエンジンを作った - より良い環境を求めて


なんかアノテーションマイブームだったっぽい。

PHPのフレームワークを作った - より良い環境を求めて

ただ利用しているZendのアノテーション解析が、あるバージョンでとても遅くなったので、アノテーションを使うことに不安を覚える。

言語レベルでやることをPHPで頑張ってやるべきじゃないな、などと思い直す。

@varアノテーションによるリクエスト変数のcastは結構便利だったんだけど。



ふと、Haskellっぽく書きたいよなー、前にそういうこと書いたよなーと思い出す。

バリデーターあれこれ - より良い環境を求めて

やっぱり書いてた。

ロジックの中の方でDBを呼び出すのは良くないよね、という話。


バリデーター繋がりで、Scalaでも何か書いてたなーと思い出す。

LiftでWebアプリ(4): フォーム用共通処理を作る 1 - より良い環境を求めて

この投稿の最後の方のコード、今見てもこんな風に書きたいなーと思える。

演算子が定義できないとどうしようもない…かな?


例えば、こんなの。

<?php
class SomePage{
  public function somePost(Request $req, Db $db){
    $form = $req->fragment('form1');
    $form->key('mail')->name('メールアドレス')
      ->trim()->required('{name}を入力してください')
      ->email('{name}の形式{input}が正しくありません');
    $form->key('body')->required('本文を入力してください')
      ->maxLength(1000, '{param0}文字以上は送信できません');
    $form->key('zip1')->key('zip2')->name('郵便番号')
      ->toHalf()->required('{name}を入力してください')
      ->length([3, 4])->numeric('{name}の形式が正しくありません');

    try {
      $values = $form->get();
      $account = $db->from('Account')->eq(['mail' => $values->mail])->getOne();
      ....
    }catch (IoException $e){
      $errors = $e->getErrors();
      ....
    }
  }
}

万能RequestクラスをTraitの寄せ集めで作って、Eitherの変わりに例外にして…。うーん…。

やっぱり演算子や結合がないとタイプ量が多い。


で、PSR-7もあるのでどうしようとか。



アプリは、Input => App => Output っていうのは確定で、これは

Request => App => Response に置き換えるとちょっとまずい。Outputがそのまま次のInputになった方がシンプルになりそう。

正確には Context & Request => App => Request | Response かなあ。

アプリがRequestを返したらリダイレクトなどをして、Responseを返したら終了。

いや、でもテンプレートエンジンを使うだろうしやっぱりResponseを返すのは特殊な場合だけになるのか。





まとまらないけど眠いので一旦投稿。

2015-07-13

[] 頭の体操

CodeIQ ホリエモンからの挑戦状

https://codeiq.jp/magazine/2015/07/26213/



何故か体調を崩して頭ふらふらのときに解説編の記事を見てHaskellでコードを書いていたので記念メモ。

module Main where

import Control.Applicative
import Data.Set (fromList, member)

main::IO ()
main = prog <$> getInputs >>= print
-- main = print $ prog (10000, [1..5000])

prog :: (Int, [Int]) -> Int
prog (ln, xs) = length $
     [(a, b, ln - a - b) | a <- [x | x <- xs],
                           b <- [x | x <- xs,
                                     a < x,
                                     x < ln - a - x,
                                     member (ln - a - x) $ fromList xs]
     ]

getInputs :: IO (Int, [Int])
getInputs = (,) <$> readLn <*> (readLn >>= readContents)

readContents :: Int -> IO [Int]
readContents n = take n <$> map read <$> lines <$> getContents

ghcの環境が壊れててそれを戻すだけで1時間以上かかった記憶がある。あとリスト操作部分よりもIO操作とApplicativeの使い方調べるのに時間がかかって、問題にある「想定時間10分」は余裕で超えた。1時間以上はかかった気がする。

そして https://gist.github.com/yancya/3c5fa7c0f09ad85f5230 こちらのRubyより遅い。リストのindexを使ったりListじゃないものを使えば速くなりそうだけども放置で。


http://www.sampou.org/cgi-bin/haskell.cgi?%A5%B0%A5%ED%A1%BC%A5%D0%A5%EB%CA%D1%BF%F4%A4%AC%CD%DF%A4%B7%A4%A4%CD%FD%CD%B3%A1%A9

こちらを読み返しつつの練習。

2015-07-04

[] Web開発時のGitでのゆるいワークフロー

Gitで何か低レベルの高度な操作が必要だっていうときは、大抵の場合は作業は一つのブランチでしかしない症候群にかかっている。

Gitはブランチやマージが軽いので、作業中のブランチを次々作っても上手い具合にマージしてくれる。



masterが本番、developがテストサーバー

この辺はreleaseでもstagingでも何でも良い。

f:id:n314:20150704165512p:image

一人開発でも効果ある。


masterからissue-1ブランチを切る

issue-1でcommit => developにマージ => テストサーバーで確認 => ちょっとここ直して〜

issue-1でcommit => developにマージ => テストサーバーで確認 => ちょっとここ直して〜

issue-1でcommit => developにマージ => テストサーバーで確認 => 確認中...時間がかかりそう

暇なのでmasterからissue-2ブランチを切る

(※ issue-1 を残したまま masterからissue-2 を作る。issue-1 の中で、あるいはdevelopから派生して別の作業をしてしまうと後で面倒なことになる。)

issue-2でcommit => developにマージ => テストサーバーで確認 => ちょっとここ直して〜

issue-2でcommit => developにマージ => テストサーバーで確認 => OK、本番に反映して〜

masterにissue-2をマージ => 本番反映

issue-1 はあとここだけ直して〜

issue-1でcommit => developにマージ => テストサーバーで確認 => OK、本番に反映して〜

masterにissue-1をマージ => 本番反映

masterとdevelopの差異が無い場合は適度にmasterにdevelopをマージ、developにmasterをマージ(単に履歴のグラフ表示を見やすくするため)



ちなみにPHPなので、デザイナーサーバーに直接画像をアップしたりHTMLを書き換えたりすることもある。

その場合は適当なタイミングでテストサーバーあるいは本番サーバー上で直接commit => push する。

次回pullせずに気付かずにpushしても弾かれるので特に問題は起きない。

2015-06-26

[] Redmineの少機能設定

以前はあれもこれもプラグインでできるなどと色々入れた結果、やることがぼやけたりRedmineのバージョンを上げづらくなったりということになっていた。


今回はとにかくメニューやリンクを減らす方向で設定。

  • admin以外はシステム管理者にしない
  • ロールと権限で開発者・報告者にメンバー管理を追加して、普段は開発者で使って他のユーザーの確認に報告者になったりチケット整理時だけ管理者になったりする
  • トラッカーで使うのは「担当者」「対象バージョン」「進捗率」とカスタムフィールドのみ
  • 進捗率はステータスから自動計算(設定のチケットトラッキング)
  • ワークフローは初期設定のものから更に削る
  • チケットのステータスは「要求待ち」「要件確定」「テスト待ち」「リリース待ち」など表記を変える
  • フィールドに対する権限で、一定のステータス以降は「担当者」「対象バージョン」を必須
  • バージョンは「6月リリース分」「7月リリース分」「未定」「随時」など
    • ここで期限を区切るのでチケットでは日付や工数を管理しない
  • プロジェクトのモジュールで使うのは「チケットトラッキング」「リポジトリ」「デフォルトカスタムクエリ

カレンダーやガントチャートは、必要なときほど情報が入力されていないことが多いので保留。



  • Redmine Default Custom Query」プラグインで、チケット一覧の初期表示を変える
  • Redmine Startpage plugin」でトップをマイページまたはチケット一覧に変える
  • 「View Customize plugin」で

他にもマイページに固定リンクやお知らせを入れたりメニューの順番を入れ替えたりできるView Customize pluginは思った以上に何でもできる。すごい。

担当者のデフォルト設定が〜〜とか色々記事があるけど、issues/new$ に対する設定で全部jQueryでやってしまえ的な。

$(function(){
  var val = 0;

  // 担当者初期値(自分)
  $('#issue_assigned_to_id option').each(function(){
    var v = $(this);
    if (v.text() == '<< 自分 >>'){
      val = v.attr('value');
      return false;
    }
  });
  $('#issue_assigned_to_id').val(val);

  // バージョン初期値(一番上)
  val = 0;
  $('#issue_fixed_version_id option').each(function(){
    var v = $(this);
    if (v.attr('value')){
      val = v.attr('value');
      return false;
    }
  });
  $('#issue_fixed_version_id').val(val);
});

グローバルな設定にロジックを埋め込んでも気にならないなら、かなり入力の手間を省けそう。

リポジトリへのリンクも、初期画面をmasterではなくdevelopに変更するとか。


サイドメニューを隠すJavaScriptの前にこれを入れて

  // プロジェクトタブの移動
  if ($('#main-menu a.overview')[0]){
    $('#sidebar').append('<h3>プロジェクト</h3>');
    var ul = $('<ul>');
    $('#sidebar').append(ul);
    $.each(['overview', 'activity', 'repository', 'settings'], function(k, v){
      ul.append($('#main-menu a.' + v).parent());
    });
  }

たまにしか見ないプロジェクトの概要、活動、リポジトリ、設定タブをサイドメニューに移すとか。