購読中です 読者をやめる 読者になる 読者になる

のらねこの気まま暮らし

Perlについてとか、創作についてとか、発展途上の自分と向き合う記録。

AngularJS x Webpack を使った構成の紹介

AngularJSとWebpackを上手いこと連携させてメンテナンスしやそうな構成を試行錯誤したので、 現状の記録と整理を兼ねて記事にしてみる。

結構いいかんじなアプローチなのではないかと思いつつ、まだ詰め切れていないところも多いので今後ブラッシュアップを重ねていきたい。

関連技術

要点

  • 役割でディレクトリを分ける
  • 汎用化出来そうな仕組みはアプリケーションの外に置く
  • DDDを意識してビジネスロジックを構築する
  • Webpackのローダーを活用する
  • Webpackのrequireをそこそこに活用する
  • $injectorを活用する
  • Angular UI-Routerの設定をもとにViewのディレクトリを作る

役割でディレクトリを分ける

AngularJSだと controller, service, config, directive のように機能でディレクトリを分けるのがスタンダードのようだけど、メンテナンスをしているとあっちいったりこっちいったりで結構面倒臭かったり、考えをごっちゃにしがちであまり使い勝手がよくなかった。

そんなわけでJSの役割を幾つかに別けて、それごとにディレクトリを切るようにしてみた。

  • app/config
    • アプリケーションの設定
  • app/domains
    • ビジネスロジックかつ見た目にかかわらない情報
    • DDDに影響を受けていたのでドメインと呼称している
    • 名前はともかく、controllerの肥大化を避けられる
  • app/views
    • 見た目に関する部分、 controllertemplate を内包する
    • view-modelとdomainを controller で連携させる
  • 汎用モジュール

汎用化出来そうな仕組みはアプリケーションの外に置く

モーダルやローディングなど汎用的に使え、アプリケーションに依存するものを設定に切り出せるようなモジュールは基本的に app (アプリケーションの本体)とは別のディレクトリにおく。

外出ししやすくなるし、管理を別けれるので一度FIXすれば後は気にしなくていい。

ディレクティブやView周りのproviderはだいたい汎用化出来そうなので、適当なプリフィクスを振って、 xx-modal みたいな感じでディレクトリを切ってそこに置くようにしている。

DDDを意識してビジネスロジックを組む

DDDというか、意識していることは以下。

  • 単一責務の原則
    • 一つのクラスが持つ役割はひとつ
    • 複数持つようなら分ける
  • Aggregateパターン
    • 複数のユーザストーリーを一つのクラスに集約することでViewから参照するクラスを制限する
    • しかし責務は分かれてるようにしているので相互影響は最小。最悪クラスの差し替えも想定してる
  • Repositoryパターン
    • APIやStorageへのアクセスを抽象化するようにしている
    • $resourceを使うことが多いけど、時には$localStorageなども使いたい
    • ビジネスロジック的にはどっちも同じように扱いたいので、localStorageを一段wrapして$resourceと同じような振る舞いをするようにしていたりする
    • 中途半端感あるのでこれはブラッシュアップしていきたいところ

いままであまりJavaScriptOOPを意識してこなかったのだけど、単一責務の原則をしっかりまもって、I/Fをある程度制約かければ結構取り回しが効いて良さそうな感じはする。 ただ、どのくらいの規模までハンドルできるかはちょっと見えてないので、今後の発展を見たい。

Webpackのローダーを活用する

CoffeeScriptコンパイルはもちろんだが、何より嬉しいのはHTMLをJavaScriptの文字列として展開できること。 これによって、 grunt-ng-template のようなライブラリは不要になったし、遷移のたびにXHRを投げる必要もなくなった。

UI-Routerと連携しつつ、templateファイルを require することで文字列をそのままわたせる。 ついでに、viewsのディレクトリの中で controllertemplateを並べせることができて、「controllertemplateはセットで編集したいのにディレクトリの移動面倒!」「ディレクトリ構造違くてわけわかんない」みたいな問題から開放された。

HTMLだけでなく、JSONYAMLのローダーを使うことで設定などの読み込みも容易になるのでなにかと便利になる。

Webpackのrequireをそこそこに活用する

webpackの拡張requireはあんまり使っていない。 index化したり拡張子の省略が主だけど、これが思いの外使い勝手が良かった。

Webpackのextensionsオプションに拡張子を登録しておけば、以下の様に拡張子を省略してかいた場合、 app.(js|coffee) あるいは app/index.(js|coffee) を探しにいってくれる。

var app = require("app");

設定的には、extensions: ["", "coffee"] とか登録しとくとCoffeeScriptも読んでくれるので便利。

indexファイルはファイルの機能によって何を書くかをわけている。

View系

exportするのはController。ユーザストーリーの入り口的な意味合いを持たせている。 DDDのAggregate的な扱いをしている雰囲気。雰囲気なのであまり厳密にやってない。

例としては、以下の様な感じ。

  • ユーザのサマリを出すページは user/index.js
  • ユーザの所持品を出すページは user/friend.js
  • ヘルプのページは help/index.js

モジュール系

angularの拡張としてproviderやfactoryを提供する場合。 ドメイン系はだいたいproviderとして提供しているし、汎用的なクラスだったりするとfactoryを提供する。

indexファイルでproviderやfactoryを定義し、別のファイルにクラスの定義をしている。

例として、ユーザクラスと、ユーザが持ってる友達のクラスを書くとしたら以下の様な構成にする。

+- domains/
  +- user/
    +- index.js
    +- user.js
    +- friend.js

$injectorを活用する

domainsなんかはクラスをたくさん作って、providerでインスタンス化している。

愚直にかくと以下のような書き方になる。

angular.module(module.exports = "user-domain", []).provider ()->
  User = require "./user"
  return {
    '$get': -> new User()
  }
  

requireで呼び出すことはできるけど、例えば $resource$q を使いたいときが結構ある。 呼び出すにしても $injector 呼ばなければならない。

$getでDIして、コンストラクタに渡す?でも無駄なプロパティは抱えたくない。

そこで、$injector.invoke を採用した。

こいつを使うと、以下のようにかける。

index.js:

angular.module(module.exports = "user-domain", []).provider () ->
  return {
    '$get': ($injector) ->
      new ($injector.invoke(require "./user"))
  }

user.js:

module.exports = ($resource) ->
  class User
    # Userクラスの定義

DIもクラス側に書けてメンテナンスがしやすくなった。

さらに、$injector.instantiateを使って、パラメータのバリデーションをしつつインスタンスを生成するようにする。

index.js:

angular.module(module.exports = "user-domain", []).provider () ->
  return {
    '$get': ($injector) ->
      $injector.instantiate($injector.invoke(require "./user"), {})
  }

$injector.instantiate を使うとコンストラクタに渡る値が存在しないときにErrorを投げてくれるので、「うっかり引数変え忘れた!」とかに気付ける。

若干鬱陶しいという気はしつつ、たくさんコードを書いているとどうしても漏れがでてくるのでエラーを投げてくれるのはありがたい。

Angular UI-Routerの設定をもとにViewのディレクトリを作る

state の構造と views のディレクトリ構造が合致するのが望ましい。

こうするとファイルをソースを見なくても探しにいけるし、なによりファイル名を決めるときに考えることが少ない。

templateとcontrollerを同じディレクトリにおいているので考える手間が一つになる。

$stateProvider
  .state "app",
    abstruct: true
    controller: require "app/views/app/index.coffee"
    template:   require "app/views/app/index.html"
  .state "app.user",
    url: "^/user/"
    controller: require "app/views/app/user/index.coffee"
    template:   require "app/views/app/user/index.html"
  .state "app.user.friend",
    url: "^/user/friend"
    controller: require "app/views/app/user/friend.coffee"
    template:   require "app/views/app/user/friend.html"

ディレクトリ構成

というわけで、大体以下の様な感じにディレクトリが出来上がる。

+- scripts
  +- xx-modal/
  +- xx-loading/
  +- xx-preload/
  +- app/
    +- config
    | +- router.coffee
    | +- resource.coffee
    | +- xx-modal.coffee
    +- domains/
    | +- user/
    | | +- user.coffee
    | | +- index.coffee
    | +- friend/
    +- views/
    +- app/        
    |  +- contents/
    |  |  +- header/
    |  |  +- index.coffee
    |  |  +- index.html
    |  |+- index.coffee
    |  +- index.html
    +- index.coffee

まとめ

AngularJS と Webpackを連携させる事例を紹介しました。 組み合わせて色々便利で管理も楽になっていいよ!

NodeJSでSystemJSを使ってES6を試す

SystemJSとは、ES6やAMD等の汎用的なモジュールシステム。 SystemJSを使うとどんなふうにロードされるのかを試した。

インストール

npm install --save systemjs

基本的な使い方

良い感じローディングするためには初期設定が必要。 require で呼び出すんだけど、うーん・・・ coffee-script.register()だと思えばまぁ・・・

importの返り値はpromiseなので、exportしている場合は、 .then で受け取れる。

index.js:

var System = require("systemjs");

System.import("./lib/example"); // ./lib/example.js を読んでくれる

ベースのパスを指定して ./lib の指定をなくす

baseURLにURLを指定することでそこを基点にファイルを探査してくれるらしい。 windowsではパスの先頭に file: の指定が必要とのこと。

index.js:

var path   = require("path");
var System = require("systemjs");
System.config({
  baseURL: path.resolve("./lib");
});
System.import("example");

node_modulesの読み込み

これまじかよって思った。

index.js

var path   = require("path");
var System = require("systemjs");
System.config({
  baseURL: path.resolve("./lib");
});
System.map['lodash'] = "../node_modules/lodash/index"; // `./lib` からの相対パス
System.import("example");

lib/example.js

import _ from "lodash"; // 相対パスを指定するか、mapに登録する必要がある様子
// any script

まとめ

SystemJSを使ったES6の簡単なサンプルの紹介でした。 npmライブラリはおとなしく require 使いつつ自作ライブラリに関してはimport使うとかするのがいいのかな。

issuesとか眺めながら様子みたい。

EC6のimport及びexportを使いたい

jspm関連でEC6を使おうとしたけど、moduleの管理の仕方いろいろあってどうすればいいのかわからなかったので調べた。 SystemJSを使ってブラウザでもEC6のコードを利用できます。

SystemJSのI/Fで利用

ファイルをimportする

<script src="system.js"></script>
<script>
System.import("runtime-hoge");
</script>

ファイルをimportして処理を行う

<scirpt src="system.js"></script>
<script>
System.import("promise-hoge").then((hoge) => {
  // exportした`hoge`が引数に渡される
  console.log(hoge);
});
</script>

pollyfillを使う

<scirpt src="system.js"></script>
<script type="module">
import {hoge} from 'hoge';
console.log(hoge);
</script>

Polyfillを使ったmoduleシステムの利用

名前付きでエクスポート

fuga.js:

export var fuga = 'hoge';

index.js:

import {fuga} from 'fuga';
console.log(fuga); // hoge

名前付きでエクスポート

fuga.js:

var fuga = 'hoge';
export {fuga};

index.js:

import {fuga} from 'fuga';
console.log(fuga); // hoge

名前を指定しないでエクスポート

fuga.js:

export default var fuga = 'hoge';

index.js:

import fuga from 'fuga';
console.log(fuga); // hoge

エクスポートしないでcodeだけ実行する

fuga.js:

console.log('fuga');

index.js:

import 'fuga'; // fuga

grunt-contrib-connectのmiddlewareの順序による挙動について

grunt-contrib-connectgrunt-connect-proxystubcellを設定したが POSTDELETE のリクエストが method not allowed で弾かれてしまって嵌ったのでメモ。

middlewareの設定順序が不適切

最初に正しい方法。middlewaresの先頭にproxyを挟む必要がある。

connect: {
  server: {
    options: {
      base: ["htdocs"],
      middleware: (connect, options, middlewares) ->
        middlewares.unshift(require("grunt-connect-proxy/lib/utils").proxyRequest);
        return middlewares;
      }
    },
    proxies: [
       // ... proxyの設定 ...
    ]
  }
}

middlewares.unshiftする必要性

引数で middlewares を受け取った時、connect.staticconnect.directoryIndex のmiddlewareがデフォルトで設定され、それらは GET , HEAD, OPTIONS のMethodしか許可していないため。

今回の僕のような POSTDELETE のようなRESTな感じのリクエストを投げたい場合にこれらよりあとにmiddlewareを設定してしまうとプロキシに到達する前に method not allowed となる。

middlewares.unshift のように先頭に middlewareを追加するか、 引数で middlewares を取らず、空の配列から新しくmiddlewaresを生成してしまうかするのが良いと思う。

背景

grunt-contrib-connect で静的ファイル(htmlとかjsとか)を配信し、RESTFulなAPIサーバーのモックとして stubcell を立てて、 grunt-connect-proxy でプロキシしてアプリ開発を行っていた。

が、proxyしているRESTFulなサーバに DELETEPOST を投げても 405 のレスポンスが返ってくる。

その時のGruntfileはこんな感じで、middlewaresにproxyRequestをpushしていた。 この時、middlewaresの配列が空の配列であるという錯覚が僕の3時間を無駄にした。

connect: {
  server: {
    options: {
      base: ["htdocs"],
      middleware: (connect, options, middlewares) ->
        middlewares.push(require("grunt-connect-proxy/lib/utils").proxyRequest);
        return middlewares;
      }
    },
    proxies: [
       // ... proxyの設定 ...
    ]
  }
}

調べた過程

ChromeのdevToolsを見ると、allowのヘッダが某かで付与されていた。 とりあえずmiddlewaresにallowを突っ込むヘッダを付与してみる。

moddleware.push(function (req, res, next) {
  res.setHeader('allow', 'GET, DELETE');
  next();
});

しかし通らない。

stubcellやproxiesのソースを読み、console.logを直で仕込みどこまでリクエストが伝播しているのかを調べているうちに、そもそも grunt-connect-proxy にリクエストが届いていないことが判明。

grunt-contrib-connect の某かで405を投げてるっぽい。 grunt-contrib-connect の中の node-connect のコードを読むが、 405 を投げている箇所が見当たらない。

検討がまったくつかないけれど、とりあえず障碍の範囲は絞れたので、grunt-contrib-connect の nextの実装に console.log をかまして様子を見る。

その過程で、どうやら、middlewareがproxyの前に幾つか処理されているらしいことがわかる。

gruntfile上で console.log(middleware) するとすでに配列にstaticとdirectoryIndexのmiddlewareが入っているではないか!

push辞めてunshiftして解決。

Dartを使ってみる

Dart

Dart: Structured web apps

  • ECMAの標準規格になったらしい
  • jsにcompile可能な汎用言語らしい
  • javajavascriptのいいとこ取りらしい

ってことで試してみる

イメージ

  • DartEditorなるものがあるけど、とりあえずvim使ってみる
  • Botでも書いてみるかー?
  • for web appsな雰囲気あるけど、現状はWEB向きってだけで別にCLIツールでも良さそう
  • とりあえず感触を知るところを目的に、いきあたりばったりで。

installation

core

homebrewでdartの1.6.0がインストールできるらしいのでいれてみる。

$ brew update
$ brew upgrade
$ brew install dart

versionを見てみる。

Dart VM version: 1.6.0 (Tue Aug 26 22:30:33 2014) on "macos_x64"

これで、以下のbinが入るよう。dart-sdkの梱包物。

  • dart
  • dart2js
  • dartanalyzer
  • dartfmt

今回はdart-editorいれなかったけど、brew install dart-editorでいけるっぽい。

vim-plugin

dart-vim-pluginがある。

NeoBundleの設定に追加してインストール。

NeoBundle 'dart-lang/dart-vim-plugin'

...とおもったら、デフォルトだとfiletype認識してくれないので以下を追加。

au BufNewFile,BufRead *.dart    set filetype=dart

hello world

hello-world.dart

void main() {
  print("hello world!");
}
$ dart hello-world.dart
hello world

できた。簡単。 ・・・ついでにdart2jsも試してみる。

$ dart2js hello-world.dart
Dart file (hello-world.dart) compiled to JavaScript: out.js

out.jsに吐出されたらしいのでひらいてみ・・・・・・・・・

・・・・

・・・・

・・・・そっ閉じ。

next()

とりあえずインストールはしたのでこれからコツコツ勉強してこう。

実際、今まで培ったnpmライブラリの知見を活かせない(dartdart専用のライブラリを使う)のは大分未練がある。 でもシンタックス的には結構良さそうにも見えるので、今後に期待を込めて続けられたらいいのかなって雰囲気。

npmライブラリを利用できるか、node上でdartをエミュレートできると移行と実験しやすいんだけど・・・。

まあ、ともあれ勉強っすな

CasperJSを拡張したライブラリをローカルに置こうとして苦戦した記録

CasperJSを使っていて大変苦労したのでその記録。

やりたかったコト

CasperJSを継承した独自拡張のライブラリを複数のファイルでrequireして個別にプログラムを実行したかった。

grunt-casperのようなライブラリをから使う場合と、単体のファイルをcasperjsコマンドで実行する二通りの用途を想定していた。

継承

継承自体は簡単に可能。 coffee-scriptを使っているならなおのこと。

Casper = require("casper").Casepr

class MyCasper extends Casper
  start: ->
    console.log "start my casper!"
    super

外部ファイルとしてrequireする

辛かったのはここから。 上記のクラスをmodule.exportsで吐き出し、他のファイルからrequireで参照しようとした。

"use strict"

Casper = require("casper").Casper

class MyCasper extends Casper
  start: ->
    console.log "start my casper!!"
    super

module.exports = MyCasper
"use strict"

MyCasper = require("my-casper.coffee")

casper = new Casper()
casper.start "https://www.google.com/", ->
  @echo "open #{ @getTitle() }"
casper.run()

上記のようなサンプルコードを用意して、コマンドを叩く。

vimshell% casperjs runner.coffee
Error: Cannot find module 'casper'

  phantomjs://bootstrap.js:289
  phantomjs://bootstrap.js:254 in require
  /home/mizuki/project/casper-sample/my-casper.coffee:8
  /home/mizuki/project/casper-sample/my-casper.coffee:29
  /home/mizuki/project/casper-sample/my-casper.coffee:30
ReferenceError: Can't find variable: Casper

  runner.coffee:8
  runner.coffee:16

Cannot find module 'casper'

requireしようととしているcasperが見つからない。 bootstrap.js:289このファイルをまず見に行く。

情報がほとんど無いので、エスパーで回答すると、

どう見てもずれている・・・

ここからPrintDebugタイムに突入し以下の情報を仕入れた。

  • PhantomJSのrequireにpatchを当てている
  • casperなる(CasperJSに関連した)node_modulesはなく、patchedRequireの中でCasperJSのmodulesのディレクトリを見に行くようにになっている

patchedRequireのコード casperjs/bootstrap.js at 4f105a91a0e1d48826d124b2be3627276986fcb9 · n1k0/casperjs · GitHub

その中で呼ばれているcasperBuiltinPathメソッドがcasperの内部のmodulesさんからcasperを探してきている。

        function casperBuiltinPath(path) {
            return resolveFile(path, fs.pathJoin(phantom.casperPath, 'modules'));
        }

さて、ここらへんにprintデバッグのコードを埋め込むわけだが端的に結論を行ってしまうと、 呼 ば れ て い な いのだ。

require先のライブラリの中ではcasperjsのpatchが当たらないらしい。 どういう仕組でそうなっているのかは、PhantomJSも含めて周辺コードを追跡しないといけないので、ひとまずはこの仕組を諦めることにした。

いずれリベンジしたいところである。

余談

ローカルパスの検索

phantom.casperScriptBaseDirもしくはfs.workingDirectoryを基準にrequireに指定したパスを走査する。

        function localModulePath(path) {
            return resolveFile(path, phantom.casperScriptBaseDir || fs.workingDirectory);
        }

casperScriptBaseDirはどこで設定されるのかというと、

コマンドラインtestサブコマンドを除く第一パラメーターである。 すなわち、下記のrunner.coffeeのディレクトリである。

vimshell% casperjs runner.coffee

今回示した例ならさほど問題はないが、src/runner.coffeeの様なケースだと、若干面倒になる。 これはnodeJSも同様だが、相対パスと実行ディレクトリを意識しなくてはならない。

casperScriptBaseDirを書き換えることでこの問題を回避することもできるがオススメしない。 Nodeであれば、NODE_PATHを追加することで、そのディレクトリをnode_modulesの走査対象とするが、CasperJSについてはそこまで確認していない。

この辺りのソースを追っていけばヒントは得られそう。 casperjs/bootstrap.js at 4f105a91a0e1d48826d124b2be3627276986fcb9 · n1k0/casperjs · GitHub

ともあれ、非常に苦戦したので、とりあえずその調査の記録だった。

YAPC::Asia 2014に参加してきました #yapcasia

YAPC::Asiaとは

8/29, 8/30に開催された、世界最大規模のプログラミングカンファレンスです。 Perl界隈のエンジニアからPerlは関係ないけど、プログラミングが好きな人が集まる年に一度のエンジニアの祭典!

YAPC::Asia 2014

この記事は

わたしく@mizuki_rの個人的な見解をだらだら述べる記事でございます。 なお、藤沢にある某メイドバーで執筆しているなう。何してんだ、ほんとなにしてるんだ僕。

全体の振り返り

最後のkeynoteのtypesterさんのトークは正直胸に刺さった。 なんだろう、まだうまい言葉に落とせていないような感動具合。 本当にいいトークだった。

通して、自分の立ち回りや今後のキャリアプランとかを改めて考えさせられるスピリチュアルなトークが多かった印象。 同期が二人発表しているのを見て、やっぱりトークしたかったなぁと思う反面 参加してよかったYAPC! 大好きYAPC! スタッフの皆さんお疲れ様でした!

@yusukebe さん大変だとおっしゃっていたけどぜひとも来年も開催を、そして次こそスピーカーとして参加したいw

あ、あと落選したトーク、どこかで話せる機会を作りたいな。

8/29日の振り返り

僕が参加したトークは以下。 真面目なまとめや評価に関しては、技評さんや他のすばらしいエンジニアのブログを参考にしてくれといいな。

あと、量が多いので個人的に興味のある記事だけピックアップしちゃう。

インフラエンジニア(狭義)は死んだ

WEBのインフラ系は、物理面を意識することも減ったし、便利なツールも増えてきている。 アプリが動いているのもソフトウェアだし、便利なツールもプログラミングできないと使いこなせない場合も増えている。 この先、プログラミングできないインフラエンジニアは死にそう。

そんな状況で、プログラミングから逃げていた(逃げていたとはもう今は思えない)studio3104氏がどうプログラミングと向き合ってきたのかっていうお話。

「インフラエンジニア」っていう言葉は「プログラミングできない」「プログラミングができなくてもいい」みたいな認識があって、 「インフラエンジニア」ってなのることでそのことを許容しているのではないか? 自称は自意識に影響を与えるというメッセージはすごく僕に刺さった。

僕自身フロントエンドエンジニアという自称の中で、いくつかの責務から目をそらしていた節がある。

与えられた役割、動ける範囲を改めて見直して自称ではなく、自分として何ができるかを改めて考えてみようと思った。

すごい意識の高いトークで一発目からしびれました。

お待たせしました。PerlでBDDを簡単に以下略

tokuhiromさんが書いてきたTest系Moduleの振り返りと、perl6並に夢の詰まったTest::Builder2の開発停止に伴う、じゃあぼくらはどうすればいいんだに対する回答。

それがTest::Kantan 最近のテストライブラリから、言うまでもなく後方互換を保ちつつテストの集計を刷新したunicode文字使ったり色つければウケがいいというフレームワーク

subtestはテストのコンテキストがわかりにくく、JavaScriptでBDDを主体としたSpecによるテストを行っていた最近の僕としては、 より可用性のあるライブラリっぽい気配がしてもう胸がたかなる。

なお、後輩が試した話によるとサンプルそのままだと動かなくて、describeバグってるぽい? 余裕見て検証したいところである。

Perl::Lint

バグとなりそうな危ういコードを指摘してメンテナビリティの高いコードを推奨しつつレビューの手間を省くツール、それがソースコードリンター。 PBPのポリシーを実装したperlcriticは遅いので、もっと早いのを作りました、というトーク。

Perlの静的解析の手法と、Perl::Lintの使い方の説明をしつつ、いやぁモダンな名前空間だなぁと思っていた。 perlcriticnのカスタマイズはなかなか職人芸な気がしていて手が出しにくい。しかも時間かかるから常にテストと一緒に走らせるには重い。

そんな状況の打開策を提案してくれるモジュールのよう。

独自ポリシーの定義をサポートしつつ、perlcriticのまんまのポリシーを定義している。

独自ポリシーの定義をサポートしつつ、perlcriticのまんまのポリシーを定義している。 もちろん、簡単なポリシーなら簡単にかけるが、難しいポリシーをかくのは難しいというまあそうだよねってところだけど、今後に期待。

なお現在ラスボスのようなポリシーを実装してくれるコントリビューターを募集しているそう。 われこそわという方はぜひ。

僕はjshintを読んで挫折しました。

8/30の振り返り

オープンソースの開発現場

perl 5.20で入ったsignaturesにまつわる議論についてのお話。 個人的にはベストトークショーになってほしいくらいいい話だった。

signaturesの実装を提案し議論を醸したMartini氏の奮戦とその立ち回り、p5pという民主主義のメリット・デメリットはとても興味深いものだった。 perl5は多様な人が居て、多様な意見がある。

そのなかで自分の目指すべきところを正確に見据え、その優先順位を守って、時には受け止め、時には受け流しうまいこと立ちまわることがOSSにおいて大事なのだと感じた。 いろんな人達の日々の努力よって僕らは支えられ、いまこうしてコードを書いているのだと改めて感謝したトークだった。

ちなみにはやくsingaturesを使うの楽しみにしてるぜ!!!

半端なPHPDisで以下略

皆まで言うな、今回のベストトークショーである。 perlのカンファレンスでPHPのトークがベストトークショーともう伝説だよねこれwwww

語るまでもない、PHPのもつ闇としかしその闇と戦うPHPerの強いメンタルを垣間見た。 元PHPerとしては、PHPの変化にちょっと興味をそそられ、たまには弄りたいなと思った。

でもやっぱりPHPはいいかなwwww

Perlあるある

豪華メンツを集めた対談みたいな、Perl初学者向けのトーク。 名を轟かすPerlMongersの赤裸々な素顔に迫るトークだった。

いろいろ名言いただきましたけど、ちょっと個々では割愛。 多くて・・・。

ただ、 「コードを書くのに許可はいらない」 「コードも作文も同じ。読まれて意味の分からないコードは書かない」 「基礎が大事」 「Done is better than perfect」 心に刻みたい。

追記

  • APC::AsiaになってたのでYAPC::Asiaに直した。
  • Papixはフリー素材
  • インフラエンジニア(狭義)は死んだを