健康診断(2015上半期)
健康診断の結果が返ってきた。
続きを読むgeard をビルドしたいんだけど
こける。
ビルドしたい対象は https://github.com/openshift/geard
環境は Fedora 21 (一応サポートされてないけど、動くといいなと思った)
必要なパッケージをインストールして、 Golang 1.4 ビルドして、ビルドしたけどエラー
リポジトリに Dockerfile が含まれていて、 ( https://github.com/openshift/geard/blob/master/Dockerfile ) yum install している箇所がある。
ここを参考に、
$ yum install golang git hg bzr libselinux-devel glibc-static btrfs-progs-devel device-mapper-devel sqlite-devel libnetfilter_queue-devel gcc gcc-c++
して、
$ go get github.com/openshift/geard $ cd $GOPATH/src/github.com/openshift/geard $ contrib/build -s -i -l -n
するとこける。 (selinux のオプション無効にするとビルドできるけど、ね)
エラーは以下の感じ。
(git:master)[@localhost geard]$ cd $GOPATH/src/github.com/openshift/geard (git:master)[@localhost geard]$ contrib/build -s -i -l -n Building with GOPATH: /path/to/gopath/src/github.com/openshift/geard/contrib/../vendor:/path/to/gopath Version: version alpha3, build 99f3a87 ------------------------------------------ Building cmd/gear (target: linux)... ------------------------------------------ # github.com/openshift/geard/selinux/library selinux/library/selinux_impl.go:40: cannot use &con (type *C.security_context_t) as type **C.char in argument to _C2func_matchpathcon selinux/library/selinux_impl.go:56: cannot use &scon (type *C.security_context_t) as type **C.char in argument to _C2func_lgetfilecon selinux/library/selinux_impl.go:80: cannot use &scon (type *C.security_context_t) as type **C.char in argument to _C2func_getfscreatecon selinux/library/selinux_impl.go:91: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _Cfunc_getcon selinux/library/selinux_impl.go:100: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _C2func_getpidcon selinux/library/selinux_impl.go:112: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _C2func_getpeercon ===> FAILED ------------------------------------------ Building cmd/switchns (target: linux)... ------------------------------------------ # github.com/openshift/geard/selinux/library selinux/library/selinux_impl.go:40: cannot use &con (type *C.security_context_t) as type **C.char in argument to _C2func_matchpathcon selinux/library/selinux_impl.go:56: cannot use &scon (type *C.security_context_t) as type **C.char in argument to _C2func_lgetfilecon selinux/library/selinux_impl.go:80: cannot use &scon (type *C.security_context_t) as type **C.char in argument to _C2func_getfscreatecon selinux/library/selinux_impl.go:91: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _Cfunc_getcon selinux/library/selinux_impl.go:100: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _C2func_getpidcon selinux/library/selinux_impl.go:112: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _C2func_getpeercon ===> FAILED ------------------------------------------ Building ssh/cmd/gear-auth-keys-command (target: linux)... ------------------------------------------ # github.com/openshift/geard/selinux/library selinux/library/selinux_impl.go:40: cannot use &con (type *C.security_context_t) as type **C.char in argument to _C2func_matchpathcon selinux/library/selinux_impl.go:56: cannot use &scon (type *C.security_context_t) as type **C.char in argument to _C2func_lgetfilecon selinux/library/selinux_impl.go:80: cannot use &scon (type *C.security_context_t) as type **C.char in argument to _C2func_getfscreatecon selinux/library/selinux_impl.go:91: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _Cfunc_getcon selinux/library/selinux_impl.go:100: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _C2func_getpidcon selinux/library/selinux_impl.go:112: cannot use &pcon (type *C.security_context_t) as type **C.char in argument to _C2func_getpeercon ===> FAILED ------------------------------------------ Building cmd/sti (target: linux)... ------------------------------------------ ===> Success Exiting due to build failures.
selinux/library/selinux_impl.go の型が違うと思って直したけど、エラー
先ほどのエラーを見て、以下の修正かなと思って修正したけど、エラー。
diff --git a/selinux/library/selinux_impl.go b/selinux/library/selinux_impl.go index 17f2e0b..33fa694 100644 --- a/selinux/library/selinux_impl.go +++ b/selinux/library/selinux_impl.go @@ -35,7 +35,8 @@ var ( ) func Matchpathcon(path string, mode os.FileMode) (string, error) { - var con C.security_context_t + //var con C.security_context_t + var con *C.char var scon string rc, err := C.matchpathcon(C.CString(path), C.mode_t(mode), &con) if rc == 0 { @@ -51,7 +52,8 @@ func Setfilecon(path, scon string) (int, error) { } func Getfilecon(path string) (string, error) { - var scon C.security_context_t + //var scon C.security_context_t + var scon *C.char var fcon string rc, err := C.lgetfilecon(C.CString(path), &scon) if rc >= 0 { @@ -75,7 +77,8 @@ func Setfscreatecon(scon string) (int, error) { } func Getfscreatecon() (string, error) { - var scon C.security_context_t + //var scon C.security_context_t + var scon *C.char var fcon string rc, err := C.getfscreatecon(&scon) if rc >= 0 { @@ -87,7 +90,8 @@ func Getfscreatecon() (string, error) { } func Getcon() string { - var pcon C.security_context_t + //var pcon C.security_context_t + var pcon *C.char C.getcon(&pcon) scon := C.GoString(pcon) C.freecon(pcon) @@ -95,7 +99,8 @@ func Getcon() string { } func Getpidcon(pid int) (string, error) { - var pcon C.security_context_t + //var pcon C.security_context_t + var pcon *C.char var scon string rc, err := C.getpidcon(C.pid_t(pid), &pcon) if rc >= 0 { @@ -107,7 +112,8 @@ func Getpidcon(pid int) (string, error) { } func Getpeercon(socket int) (string, error) { - var pcon C.security_context_t + //var pcon C.security_context_t + var pcon *C.char var scon string rc, err := C.getpeercon(C.int(socket), &pcon) if rc >= 0 {
エラーは以下の感じ。
(git:master)[@localhost geard]$ contrib/build -s -i -l -n Building with GOPATH: /path/to/gopath/src/github.com/openshift/geard/contrib/../vendor:/path/to/gopath Version: version alpha3, build 99f3a87 ------------------------------------------ Building cmd/gear (target: linux)... ------------------------------------------ # github.com/openshift/geard/containers/cmd containers/cmd/cmd.go:79: cannot use &ctx.portPairs (type *PortPairs) as type pflag.Value in argument to installImageCmd.Flags().VarP: *PortPairs does not implement pflag.Value (missing Type method) containers/cmd/cmd.go:80: cannot use &ctx.networkLinks (type *NetworkLinks) as type pflag.Value in argument to installImageCmd.Flags().VarP: *NetworkLinks does not implement pflag.Value (missing Type method) containers/cmd/cmd.go:81: cannot use &ctx.volumeConfig (type *VolumeConfig) as type pflag.Value in argument to installImageCmd.Flags().VarP: *VolumeConfig does not implement pflag.Value (missing Type method) containers/cmd/cmd.go:141: cannot use &ctx.networkLinks (type *NetworkLinks) as type pflag.Value in argument to linkCmd.Flags().VarP: *NetworkLinks does not implement pflag.Value (missing Type method) # github.com/openshift/geard/containers/systemd/init containers/systemd/init/cmd.go:19: inconsistent definition for type pflag.Value during import interface { Set(string) error; String() string } (in "github.com/spf13/cobra") interface { Set(string) error; String() string; Type() string } (in "github.com/openshift/geard/cmd") containers/systemd/init/cmd.go:19: inconsistent definition for type cobra.Command during import struct { name string; Use string; Short string; Long string; flags *pflag.FlagSet; pflags *pflag.FlagSet; Run func(*cobra.Command, []string); commands []*cobra.Command; par ent *cobra.Command; commandsMaxUseLen int; commandsMaxCommandPathLen int; flagErrorBuf *bytes.Buffer; args []string; output *io.Writer; usageFunc func(*cobra.Command) error; usageT emplate string; helpTemplate string; helpFunc func(*cobra.Command, []string); helpCommand *cobra.Command } (in "github.com/spf13/cobra") struct { name string; Use string; Aliases []string; Short string; Long string; flags *pflag.FlagSet; pflags *pflag.FlagSet; Run func(*cobra.Command, []string); commands []* cobra.Command; parent *cobra.Command; commandsMaxUseLen int; commandsMaxCommandPathLen int; flagErrorBuf *bytes.Buffer; cmdErrorBuf *bytes.Buffer; args []string; output *io.Writer; usageFunc func(*cobra.Command) error; usageTemplate string; helpTemplate string; helpFunc func(*cobra.Command, []string); helpCommand *cobra.Command; helpFlagVal bool } (in "githu b.com/openshift/geard/cmd") ===> FAILED ------------------------------------------ Building cmd/switchns (target: linux)... ------------------------------------------ # github.com/openshift/geard/cmd/switchns cmd/switchns/main.go:48: cannot use &envs (type *Environment) as type pflag.Value in argument to switchnsCmd.Flags().VarP: *Environment does not implement pflag.Value (missing Type method) ===> FAILED ------------------------------------------ Building ssh/cmd/gear-auth-keys-command (target: linux)... ------------------------------------------ ===> Success ------------------------------------------ Building cmd/sti (target: linux)... ------------------------------------------ ===> Success Exiting due to build failures.
よくわからないね。
レガシーコード改善勉強会 2014/09/27 #wewlc_jp
http://passmarket.yahoo.co.jp/event/show/detail/01pitgwzj67m.html
講演者の方々お疲れ様でした。
Yahoo様も会場をありがとうございました。
レガシーコード改善のすすめ 平澤 章
自己紹介 年齢が高くなって管理職 → いや、技術職 本書きたい 一番年上だから管理職やれ http://enterprisegeeks.hatenablog.com/ ここ 3年 - 5年保守開発で保守案件増えた ERP の発展、プラグインとして開発 メインフレーム → オープン化 お金がない 保守開発はひどい ソースコードひどい ユニットテストない 資料がない 担当者が離職した 潜在バグのリスク管理 ドキュメントどう構築していけばよいの? テストどうしよう 動いて当たり前とかないし 保守開発のデフレスパイラル 1. コードわらかん 2. 手探り 3. デグレ 4. 上からの怒り 5. やっつけ 6. 1 に戻る 時間外に呼び出される 人事評価が悪くなる スキルが身につかない 仕事がどんどんつまらなくなる 脱却方法 1 → リファクタリング 3 → テスト書く レガシーコードのジレンマ リファクタリングの前に単体テストないとね by まーちん レガシーコードの場合、先にリファクタリングする必要がある ということで、レガシーコード改善ガイド 10年前 翻訳 5年前 テストがないコードはレガシーコードだ! 本に書いてあること 1. レガシーコードをテストで保護する手法 (アンダーテスト テストの下ってことか 2. レガシーコードと闘うための技術大全 3. レガシーコードと闘いでえられる果実 本は TDDケンカ本だ 通常のTDDの本はわりとクリーンルームな本だ この本は、町のケンカだ、 not 綺麗ごと レガシーコードのジレンマへの対処方法 1 単体テストを強引に書くとかやり方としてある → スプラウトメソッド / スプラウトクラス テストのデータとしてNullをとりあえず渡して動いたら OK レガシーコードのジレンマへの対処方法 2 どちらかというとメイン 最初に最低限のリファクタリングをする テストしたいメソッドを static にしてしまう インスタンスメソッドをダミーに置き換える インターフェースの抽出 呼び出しの抽出とオーバーライド (面倒な処理をメソッドに切り出して、 テスト時にオーバーライドしてスキップする レガシーコードを解読するための様々な手法 1 仕様化テスト そのまま動かして期待した結果のようなテスト 試行リファクタリング 簡単にリファクタリングしてみて、理解する メソッド分類法 private/protected/public とかそういう切り口で分割 機能スケッチ 処理の流れを自由に書いてみる 白紙のCRC カードを利用して UML っぽく動かしてみる レガシーコードと戦うためのその他の技術 1 コンパイラ任せ versionアップとか? ペアプログラミング 間違い防止 超集中編集 集中して対応する コードが自然にきれいになる 単体テストを整備すると、クラスやメソッドの独立性が高くなる 凝縮度が上がり、結合度が下がる コードがどんどん綺麗になる 技術者のメリット 隣の新規開発の芝はそれほど青くない 新規だとね 実践的な設計スキルが身につく 設計のトレードオフ判断がしやすい レガシコードとの闘いは意外と楽しい 綺麗になる過程は楽しい 翻訳のこぼれ話 レガシーなのにCOBOLが出てこない 翻訳作業中に原初の読書会に参加 t_wada さん関係でやっていた 2章のタイトルの変更 本の名前の決定 まとめ 1. レガシーコード改善技術を身に着けると、デグレが起こりにくくなって、 デフレスパイラスが行らなくなり、良い円環になる。 2. デグレードが起こらない 3. 顧客や上司に褒められる 4. 余裕をもってリファクタリングできる 5. コードがどんどんキレになる 6. 確信をもって修正できる
テスト、リファクタリングに関する深い方法論 きょん
自己紹介 テストアーキテクト@なごや 興味 基礎勉強会 SCMBC Nagoya Testing Cafe Testing 伝えたいこと エンジニアであるという立場で話す レールに乗っていただけだってこと、道を切り開けと伝えたい 重要なこと リグレッションしてはいけない 変更にバグはない 保守し易いことが望ましい コード場所にバグがあるので注意しましょう 安全な方法 できること テスト 形式的手法 Brownfield Development Brownfield とは工業用地とか打ち捨てられた場所 システムと格闘する コード分析 タスク管理 プロセス管理 プロジェクトを冥確認する粒度を決める 粒に適した表現で理解 プロジェクトを変えていく 例えば 単位のまとめ方 TestLevel とか UserLevel とか、 単位の中で適した方法で明確にする テスト分析 要求、コード、分析 ユーザーから見てバグであるかどうかも含めて明確にすることが重要 テストを作る形式手法がある テストレベル テストレベルの分け方 Unit Component Integrate System ユーザーレベルでの分け方 Developer Operator PO Tester ActiveUser DisinterestUser Payer 保守期間 保守する期間 1日から半年 or 未定とか 頻繁に変更される場所でなければそこまで頑張らなくても TCO ViewPoint Perspective ViewPoint 着眼点 機能、情報など Perspective 横断的関心毎 セキュリティなど 品質モデル 手段 ISO25000 FQM 明確にする手段 状態遷移図 2 bleis 月 A3用紙 40枚 → テスト時に参照する マトリックス 表 組み合わせを表現する デシジョンテーブルとか 1 kyon_mm 月 → 20万行 → 適切な行を選択する これらを利用すると マトリックスで各状況における表現方法で分けるなど どういった単位で区切ってどういった表現でみせると理解できるか きまれば Do it テスト やることやるとテストの自動生成ツールを使える (自動生成ツールはある種の DSL だな) テストの実施方法 計画的 探索的 → ある方針に従ってテストの設計から実施まで行う タスク管理 WBS Mikado Method ? Mikado Graph Mikado Method という方法論で書くもの シンプルな図 タスクマネジメントの手法にもレイヤーがある high layer 顧客に近い low layer 開発者に近い Mikado Game があって名前がとられた Mikado Graph Todo の chaine をつくるもの あることやるにはこれもやらないとねってことをつなげる 全部やれば終わり 作成した木を整理する → 思考リファクタリング (scratch refactoring) のプロセス化 Mikado Method Naive Approach 知るために書いた不要なコードはいらないので捨てよう レガシーコード改善は知るために書くコードが多い Simple 簡単に書けて、開発を妨げない incremental に改善できる Safety 求めるコードしかシステムにはいらないので安全 Communication ぱっと見わかる Mikado Method と共に適用する レガシーコード改善ガイド リファクタリング レガシーコード改善に必要なのは コードを変更する技術 テスト設計の技術 タスクを管理する技術 → 幅広く手段を持ちましょう
レガシーコードとの付き合い方と、そのテストでの話 goyoki
自己紹介 元組み込み系のエンジニア、今はコンサルタント レガシーコードの付き合い レガシーコードが多い 組み込みだと処理を共通化したらバグが出るとか 今日の話 ドメイン非依存の話をしたい 目的 どのような課題があるか 対策があるか 観点 人 環境 開発のアプローチ 人 問題 正しいものは正しく、間違っているものは間違いと動議を通せる環境 本人に〜のせいだとすとると 保身、 協力的でない 言い訳、 適切なサポートを得られない レガシーコードではリスキー 動議を通すにも工夫が必要 目標 プロジェクトの成功のために必要な人的なサポートを確保する 役立つ人を敵にしない 状況を理解してもらい、適切なフィードバックを得る (工数とか) 方針 1. コミュニケーションの基盤を作る - 要因をよく把握する 要因は一般に複合的 テストベースの問題 プロセスの問題 タスクの管理 - 理解を得るための証拠で武装する 蓄積、共有し状況を理解してもらう → 以下の手法があって、共有していかないと駄目、変わらない 一般的なメトリクスの確保 レガシーコードだと異常な値が出るので便利、関数の行数など 有用な定性的意見の指標化 アンケートとか、キーマンからの意見収集 実証 類似プロジェクト - 属人性を排除して問題を共有する 制約のせいにする 環境が糞 自分を含めたみんなおnせいにする チームビルディングが糞だ 2. 協力を得ながらレガシーコードに立ち向かう 相談や単眼でなく改善の提案・担当を Give&Take テストがダメなら自分で変える (変えていかないと変わらないよね) チームとして改善 環境 問題 環境改善による作業効率化が強力に求められる 工数が新規より減る 試行錯誤と立て直しが必要 環境に致命的な問題を持つことが珍しくない 目標 生産性向上のサポートは必須 ツールやプラクティスを活用しよう 方針 改善ツール バージョン管理 自動テスト 自動化 テストでも上記ツールを使う テストの妥当性を評価できるものも出てきている 間違ったものが入ったらレッドになるツールを利用する 自動生成 レガシーコード対応では有効 テストオラクル問題 → テストオラクル (期待値生成手段) をどうするか 構造ベー: 制御パス、カバレッジベースとか 仕様ベース: 仕様モデルベース、DSLベース、データ・キーワード駆動とか 経験ベース: ファジング、キャプチャ&リプレイとか 開発のアプローチ 爆弾を以下に予防するか 問題 行き当たりばったりだとカオスに カオスの解消も難しい、工数獲得が困難 全部直すとか難しい 目標 備えてから進む ミスの流出の防止 Cover & Modify アプローチの妥当性を確保 XDDP: 変更を仕様書に書くアプローチ Web に適用は難しいでしょう ピンポイントの保守性の確保 方針 トップダウン 企画レベルの対応 リスクやロードマップの分析 OS を変える 言語を変える 適応する環境を変えるなど リスクを洗い出す 以下の分類が可能だろう 構造(コンポーネント, IF) 制約(スケジュール, メンバーの力量) 要求(顧客要求, ビジネス状況) リスクごとに対応を考える 保守性改善手段を用いる 要求、設計、実装 ゆもつよメソッド、 HAYST法など → いろいろ改善方法はあるので、視野狭窄にならないようにしましょう ボトムアップ 個々の開発者から始める ボーイスカウトルールの実施など
納品のない受託開発を支える、レガシーコードを作らない仕組み 西見公宏
自己紹介 ビジネスプログラマー @mah_lab 2008 ERP の SI の SE HP/Uzx PL/SQL Oracle Forms 2011 Sonic Garden 新規事業の立ち上げとかー Linux, OS, Ruby, Rails 本日はノウハウを話す 内容 レガシーコードとは 対応 レガシーコードとはなにか ジェンガのようなコード 少し触ると壊れる 誰かから引き継いだ ぐちゃぐちゃな 仕様のわからない コード レガシーコードとはテストのないコードです テストコードがなぜ必要か ソフトウェアを変更するため レガシーコードの問題 スフとウェアが変更しづらい 不具合に対応しづらい パッチをあてづらい レガシーコードの要因は、コードのみの問題なのか? インフラも含めてコード Infrastructure as a Code インフラも含めて変えていけるようにする必要がある アプリとインフラの対応 「「納品」をなくせばうまくいく」に沿って進めると良い 所有から利用へ Point of Sales (購入した時点が価値最大) Point of Use (利用につれ価値が上がる) 利用できるソフトウェアを開発していく 利用できるソフトウェアの為にはレガシーではいけない レガシー化を防ぐ方法 1. 継続して開発するビジネスモデル 2. 技術の共通化でアップデートを容易に 3. 同じ基盤を使う人間による相互レビュー 1. 継続して開発するビジネスモデル 変更し易いコードでなければコストがかかる 儲かるためにレガシーコード対策できる (共通の話題だな良い) 2. 技術の共通化でアップデートを容易に 共通化 Ruby on Rails Ruby Heroku / AWS バラバラなシステムで知見がなくなることを防ぐ LCC 飛行機とか 使用する飛行機の機種を統一することで整備費やパイロットの訓練費を削減 搭乗手続きのオンライン化などITを活用した自動化 乗務員が機内の清掃などを行い一人何役もこなすことによる人件費の削減 → 手法を受託開発の技術戦略に応用 Ruby / Rails の特性 バージョンアップが早く、バージョンのライフサイクルが短い バージョンアップを放置するとバージョンアップできなくなる OS / ミドルウェアもアップデートし続けなければならない 理由しているインフラ 以下を統一 Heroku PaaS AWS(OpsWorks) Chef 監視システム群 Nagios NewRelic Bugsnag munin とか 3. 同じ基盤を使う人間による相互レビュー 決済など特定の人しか保守できないコードは、将来的に保守できなくなるのであれば、レガシーだ 他の人が理解できないコードは、保守できないので、レガシーだ システムの知識がないと、レビューがなりたたない コードレビューでレガシーを防ぐ 本日話したこと 1. レガシーコードの何が問題か? - そもそもレガシーコードとは何か? - レガシーコードがもたらす問題とは何か? - コードだけの問題なのか? 2. 納品のない受胎区開発を支える、レガシーコードを作らない仕組み - 継続して開発するビジネスモデル - 技術の共有化でアップデートを容易に - 同じ基盤を使う人間による相互レビュー まとめ 仕組みでレガシーコードを防ぐ
レガシーコードを改善した先にあるもの、それは継続的インテグレーション 佐藤聖規
自己紹介 @lino_s Jenkins実践入門 コード修正 Edit -> Pray -> Work -> OMG レガシーコードがなくなると Cover & Modify → Happy 継続的インテグレーション CI 以下を防ぎたい 手作業でミスが多発 別の環境だとビルドできない 結合テストで修正地獄に リリース直前なのに動作しない 1日に何回もビルドして、テストして、フィードバックサイクルを短くする メリット 1. 手戻りの削減・品質の維持 ビッグバンテストとかー 対策として継続的インテグレーション 2. いつでも、だれでも、実行可能なソフトウェアが作成できる ユーザーには: 動くソフトウェアを常に提供して、信頼を 開発者には: 動かない不安を取り除き、自信を 3. 機械にできることは機械に 開発者は知的な作業に専念 4. 機械による作業の正確さ・綿密さ・あいまい性の排除 慣れた作業でもミスをする 5. 開発データを蓄積し、レポート、分析することで継続的カイゼンができる CI の歴史 2000年ごろ eXtream Programming のプラクティスとして確立 CI の仕組み 実行 → フィードバッグ CI を Jenkins で Jenkins のインストールとか 分散ビルドに対応しているので便利 プラグインあるよ いろいろな言語に対応している CIサービス Team Foundation Server Bamboo Travis CI Circle CI CI でなにをするか コンパイル ユニットテスト JUnit 互換の XML 書き出すと綺麗に表示できる ユニットテストない場合最初が難しい カバレッジ インスペクション (静的解析) デプロイ / インフラ構築 インテグレーションテスト Selenium とか 結果が HTML のものは HTML Publisher Plugin を使うとシームレスに見れて便利 CI はプラクティス ツールを入れて終わりではなく、日々コミットしてサイクルを回す習慣を アジャイルアカデミーってところで、Jenkins のワークショップが開催されている
PHP版レガシーコード改善に役立つ新パターン 佐藤祐司
自己紹介 PHP @kuidaoring 話すこと 業務とレガシーコード パターンの紹介 テストをまずかけるようにする手順 幸せになれるのか 業務とレガシーコード Yahoo! Japan の Topページ 5.83 BPV / M 0.14 BUB / M 2008年リニューアルした チーム 40人 PC 40人 開発は 20人 スマホ アプリ Join した当時 すくない自動テスト リニューアル時の開発メンバーはゼロ どんどん開発メンバーが増える なぜこうなったかの想定 ローンチ、リリース優先 ヒットするかわからない その後人を追加 → カオス 優先順位の話 そのままでよくない どうしたか 有志による改善活動 社内でもノウハウがたまってきた ユニットテスト拡充 CI整備 開発フローの整備 パターンの紹介 PHP Web に特化、置けば動く HTML に埋め込まれる、 template engine 標準関数が豊富 レガシーコードを呼びやすいやつ 環境に依存 構造を持たない スーパーグローバル変数 $_GET, $_POST, $_SESSION など 不用意な exit 方針 1. テストを書く 2. テストで保護 3. リファクタリング 4. テスト、リファクタリングをっ繰り返す 問題点 HTML で DB に接続 exit getパラメーター ビューとロジックの混在 とか どうにかしてテストを書くパターン 関数オーバーライド 名前空間を使って組み込み関数数などを上書き この場合名前空間が接合部 ラップ関数 変数の処理を getter/setter とかつくってアクセス どうするの ? 1. テストを書く 環境の分離 DB に接続する箇所で関数オーバーライドする スーパーグローバル変数の関節参照 ラップ関数を使う exit の検討 PHPUnit 自体落とすのでやめたい 2. テストで保護 ビューとロジックが混ざっているので HTML 含めたテストを書く 3. リファクタリング ファイルを分割、関数に分離、クラスに分離 global が邪魔をする 地道に消す 4. テスト、リファクタリングをっ繰り返す これで幸せになれるのか? とりあえず今できることはやった 最終的なゴールには近づけた (少し幸せになった)
レガシーコード改善の戦略と戦術 和田卓人
講演資料: レガシーコード改善の戦略と戦術
自己紹介 @t_wada コンサルティング的な話 戦略編 銀の弾丸は無い 個別の状況に応じて変わる 自動化は強力だが、手段の一つで必須ではない ストレスと (手動)テスト実行 ストレスが増えるとテストが減る テストが減るとストレスが増える 自動テストが増えるとストレスが減る ストレスが減ると自動テストが増える テスト書く時間がない? James Grenning 曰く「逆で、テストがないから時間がなくなる」 文化を変える 変えるのに長い時間がかかる 動くコードに触れなければ死があるのみ イマココから始める 最終的なグランドデザインを構築できないと文化は変えられない 人を知る 変えることのむずかしさ 「リファクタリングしたい」というとリファクタリングできない Grace Hopper 曰く「事前に許可を得るより、後で許してもらう方が楽」 全ては変化する 仕様が固まることは無い。 (流転する) 開発が終わることは無い。 技術的負債の四象限 テストは品質を上げない 品質が「わかる」ようになる 戦術編 どこからやるか 最も困っているところから お金、個人情報、 ... ... 塹壕からのテスト対象選び リスク 手動テストのコスト 自動化コスト だれとやるか 一度に多くの人ができるようになるとか無理 こだわるな ベストな手法にこだわらない。何が重要か TDD にもこだわらない こだわる 良いユニットテストの指標にも優先度がある 再現性、繰り返し可能 (Repeatable) 独立していること (Independent) 他はそれからで良い レガシーコード改善ガイド 読む 「仕様化テスト」のすすめ コンテクストが消えている状況があって、直さないといけなくて大変。 「絞り込み点」を探す 見える化 割れ窓理論 メトリクスをとる 静的解析を使いこなす 動的テスト 対象を動かしてテスト ユニットテストとか 静的テスト 対象を動かさずにテスト メトリクスなど 設計の可動域を確保する テストがないのは設計が悪い兆候 コードレビューの文化 インフラ WIP PR シンプルさ シンプルさは信頼性の前提である simple (構造が簡単) と easy (人によってかわる楽さ) は異なる モジュール化の原則 Unix思想 エレガンス 力と単純性、 Thin ボーイスカウトルール 背中を見せる Social Change starts with YOU あなたが書けるようにならなければ、誰も書けるようにならない
A Tour of Go の 1/72 - 41/72 進めた
OCaml とか触ってたけど、 GAE で Golang のアプリ試してみたいなと思って Golang に手を出した。
とりあえず A Tour of Go を途中の 41/72 まで進めてみた。
個人的には #10 Named results で戻り値パラメータとして戻り値に名前を付けてコード上で代入できてしまうのが面白かった。
map の要素の削除が delete(m, key) なのかとか。 m.Delete(key) とか m.Remove(key) とかはないんだなーと。
基本型だからないのかなと。
残りもゆるゆると進めたい。
OCaml 高階関数、多相性、匿名関数、カリー化とリスト
いつまで続くかわからないけど、 M.Hiroi's Home Page / お気楽 OCaml プログラミング入門 - 高階関数 リスト を読んで、 OCaml 書いた。
続きを読むVim のソースビルド、セットアップ手順
vim gtk2版gvim をビルドして、 /opt/vim/
1. 必要なソフトウェアの事前インストール
$ sudo apt-get build-dep vim $ sudo apt-get install \ libxmu-dev libgtk2.0-dev libxpm-dev \ libperl-dev python-dev python3-dev ruby-dev \ lua5.2 liblua5.2-dev luajit libluajit-5.1
2. ソースの取得、ビルド、インストール
$ hg clone https://vim.googlecode.com/hg/ vim $ cd vim $ hg tags | less # 現在有効なタグを出力する。 $ sudo mkdir -p /opt/vim/<tag> $ hg up -r <tag> # いずれかのタグにアップデートする。 $ ./configure \ --prefix="/opt/vim/<tag>" \ --with-features=huge --enable-gui=gtk2 \ --enable-perlinterp --enable-pythoninterp \ --enable-python3interp --enable-rubyinterp \ --enable-luainterp --with-luajit \ --enable-fail-if-missing $ make -j 3 # 2コアだったので。 $ sudo make install
3. 環境変数の整備
以下の環境変数を profile などで設定する。
_vim="/opt/vim/<tag>" export VIM="$_vim/bin" export VIMRUNTIME="$_vim/share/vim/vim74/" # vim のバージョンに合わせて読み替えること。 export PATH="$VIM:$PATH" unset _vim
4. neobundle.vim のインストール
$ mkdir -p ~/.vim/bundle $ git clone github.com:Shougo/neobundle.vim.git ~/.vim/bundle/neobundle.vim