時計を壊せ

駆け出してからそこそこ経ったWebプログラマーの雑記

Gotanda.pm #1 告知までにやったこと

忘備録です。

ざっくりやったこと

  1. Gotanda.pmを立ち上げる
  2. 大まかなスケジュールを立てる
  3. 会場を探す
  4. 日程と詳細なコマ割りを仮組みする
  5. イベント参加登録サービスに登録する
  6. 開催を告知する

Gotanda.pmを立ち上げる

Yokohama.pmは遠いし、Shibuya.pmは最近開催していないし、もっと近くで頻繁に開催するPerl Mongerな技術コミュニティを作りたい!みたいな事を考えて立ち上げました。
自分も発表などで参加したいので、開催コストを徹底的に効率化して開催サイドでも参加出来るカンファレンスにして、カジュアルに誰でも開催できるような感じにできれば良いなと思っているので、楽をするために思いつくことはどんどんやっていこうと思っていて、立ち上げのタイミングでもそれは実践しています。


まずは、WebサイトとGoogleカレンダーを用意しました。WebサイトはGotanda.pmについて調べたときにざっくりとした概要と最近の状況が分かると良いということで用意しました。
また、Googleカレンダーは自分のカレンダーにインポートしておけば勝手に自分のカレンダーにGotanda.pmの開催予定が入って、予定が空いたときにさくっと登録して行けたりするし、登録してたけど忘れてた!みたいなことを減らせるのでよさそうということで入れました。
また、Rijiを利用することでRSSも配信して、Gotanda.pmについての情報が自分のフィードリーダーに流れて来なかった!みたいなケースも防ぎやすくしました。


余談ですが、最近ノンデザイナーズ・デザインブックを読み始めたので、
その内容を実践する場としても使ってみました。とはいってもmargin整えて離すべき要素と近づけるべき要素を考慮してラインを作ったくらいで、
配色とかもセンスがないかんじで、デザインできる人が見たら笑ってしまうような代物ですが、レイアウトはそこそこ見やすくできたかなということで、
実践できて良かったなぁと思いました。こんなかんじです。
ただ、これをこのまま運用するのは恥ずかしいのでデザインテロとかお待ちしております!!!

ノンデザイナーズ・デザインブック [フルカラー新装増補版]

ノンデザイナーズ・デザインブック [フルカラー新装増補版]

テーマを決める

発表したい内容がある人は何を話しても構わないと思うのですが、なかなか決められない人も多いと思います。(自分自身そういう経験がありました)
そのため、テーマは一応決めておくとハードルが下がるのではないかということで僕の独断と偏見でテーマを決めました。
第一回のテーマは「Webサービスを支える技術」ということで普段の業務でWebサービスを作ってるひとにはとっかかりやすいお題になったのではないかなと思います。

大まかなスケジュールを立てる

Gotanda.pmはアクティブに活動を続けるために、3月/6月/9月/12月にカンファレンスの開催を予め決めています。
今回は6月ということで、じゃあどのように開催するかというのがあるわけですが、
まず土日の開催はやめました。貴重な休日ですので先の日程でも既に予定が埋まっていたというケースも大いに想定出来ますし、
会場によっては土日の開催が厳しい場所もあるので選択肢が狭まります。
また、感覚的なはなしですが、仕事終わってさくっと参加してさくっと呑んでさくっと帰るみたいな感じのが充実感あって濃くなっていい気がしてます。
そういうわけで僕の独断と偏見でこちらも平日の19:00~21:00くらいと決めました。*1
これで、『6月の平日の19:00~21:00くらいに借りれる』という条件が作れたので会場を探す条件が少しはっきりしました。

会場を探す

いよいよ会場を探します。今回は以下の項目について予め決めました。

希望時間帯
17:30~(準備時間含む)
希望の曜日
平日(可能であれば水曜日):
喫煙の可否
喫煙所があるとベター
プロジェクター利用の可否
必須
途中入退場の可否
出来るとうれしい
収容人数
最低20人(30人くらい余裕持って入れるとうれしい)

また、どれくらいの時間、会場を借りなければならないか。いつまでに現状復旧出来るか。を考えるために、
スケジュールも超ざっくり仮組みしました。
準備時間は初回なので苦労しそうだなということで多めに確保しています。
トークは2時間くらいできるといいかなぁという感じでこのように組みました。
最初は以下の様な感じでした。

時間 内容
17:30~18:30 準備時間
18:30~19:00 受付
19:00~21:00 内容
21:00~22:00 会場復旧

この条件で自分の勤務先のオフィスの会議室が使えそうだったので今回はそこを借りる事にしました。

日程と詳細なコマ割りを仮組みする

30人くらいなので、なんとなくですが、
20minくらいのtalkを3つくらいとLT6つくらいで、
ちょうどいいかな〜と思って切りました。

時間 内容
18:30〜19:00 参加者受付
19:00〜19:20 Talk(1)
19:20〜19:40 Talk(2)
19:40〜20:00 Talk(3)
20:00〜20:10 休憩
20:10〜20:15 LT(1)
20:15〜20:20 LT(2)
20:20〜20:25 LT(3)
20:25〜20:30 LT(4)
20:30〜20:35 LT(5)
20:35〜20:40 LT(6)
20:40〜 懇親会

ここは会場を借りる時間さえ決まっていれば、
その中でてきとうに調整してしまえばいいはずなので、
さくっと決められました。

イベント参加登録サービスに登録する

イベントの参加者とかを手で管理するのはつらいので、
イベント参加登録とかを管理してくれるサービスをつかいます。

いろいろありますが、今回はZussarを使わせて頂きました。
理由としてはAPIが認証を要求せず、JSからでもわりかし使いやすそうだったので、
Gotanda.pmのweb-siteに組み込みやすそうだなぁと思ったのが一番大きいです。


ここでやることはシンプルで上で決めた内容を書くだけです。
日時と場所を明示してスケジュールの表を貼ればそれでわりかし十分そうでした。


実際に使ってみたところ、意外と困ったのがイベント内容編集でした。
見た感じのままに編集出来るのはそれはそれで良いのですが、
Webサイトから文言だけコピペしてこようと思ってもスタイルごとコピペされてしまったり、
表をコピペしてきてもスタイルごとコピペされてしまい、
Zussarのイベントページのデザインを崩してしまったり、
表を作ろうにも下書きとして温めておいた表をそのまま使えず、
結局1セル毎に手作業でコピペしなければならず、苦労しました。
MarkdownやTextile等が使えれば良かったのですが、そうではなかったので、
次回以降はZussarで文言や表を先に作るか、あるいは他のサービスを使おうかと考えています。

開催を告知する

ZussarのイベントページができたのでそのURLを張りつつRijiで記事を書きます。
Googleカレンダーにも忘れずに登録します。
これであとで見返しても、ああ。Gotanda.pm#1開催したんだなぁと分かって便利になりました。

感想

いろいろあって大変だったのでいろいろ自動化したりして効率化していきたいなぁと思いました。
気持よく開催出来るよう引き続き準備がんばります!

*1:実際、これは短いかもしれないので次回からは長くするかもしれません

about.meをやめてオレオレabout.meを作った

もう去年の11月頃の事になるが、仕事の一環であるイベントに参加した。
イベントの参加者のエンジニア志向の学生と名刺やtwitter idなどを交換した。


当時の僕のtwitterのプロフィールなどに載せているURLはabout.meだった。
about.meは良いサービスだ。お手軽に自己紹介ページを公開出来る。似たようなWebページをわざわざ書かなくていいし、車輪の再発明を防ぐ。
しかし、当時のabout.meはスマートフォン向けにUIが最適化されなかった。スマートフォンでWebを閲覧する人が多い時代にこれは致命的だった。(現在はスマートフォン向けにもUIが最適化されてるようだ)*1
また、僕はWebエンジニアの端くれだ。仕事ではPerlでバックエンドサーバーのコードを書き、必要があらば新しいミドルウェアの導入からサーバーの構築、HTML/JS/CSSのコーディングから、AndroidアプリのためにJavaでゴリゴリロジックを組んだり、JNIを使ってCライブラリのバインディングを書く事もある、なんでも屋なWebエンジニアだ。
Webエンジニアのくせに自分のWebページすら自分でコーディングしてないのはどうなのだろうか。自己紹介ページ程度すら自分で組めないのか?今日会った学生にはあのひとは自身の自己紹介のWebページすら組めないようなエンジニアだと思われたりしないか?口だけのクソエンジニアだと思われたりはしないか?もしかしたら自分は死んだほうがいいのでは?などいろいろなもやもやした思考が駆け巡った。


そんなもやもや家に帰ってから1時間くらいでデザイン組んで2時間くらいでごりっとコーディングした。現在の様子がこれである。
http://karupas.org/


デザインは zurui-design // Speaker Deck を参考にしつつ、背景画像は適当なフリー素材をググって見付けて利用した。
CSSはそんなに得意では無いのであまり自信が無いがとりあえずゴリッと書いたきがする。あんまり覚えてないけど、たぶんCSS得意な人からしたらだいぶクソなCSSなんだろうとおもう。
CSSフレームワーク使ってたらなめられそうだからnormalize.cssだけ使ってごりーっと書いた。
コンテンツもてきとーにGithubとかから取ってきて埋め込むことにした。
モバイル向けのWebアプリを仕事で作ってるのにスマートフォン対応しないのもどうなんだろうと思って、昔ながらのリキッドレイアウトに加えてフレキシブルボックスを使ってなんちゃってレスポンシブな感じのを実装した。
でも、iPhoneとかで横幅が揃わなかったり、うまいこといかなくて次の週くらいにCSSをなにか修正した気がする。どう修正したかはあんまり覚えてない。
Angular.jsを初めて使ったがドキュメントが充実してて、サンプルコードも多く、あまり苦労せずに組めた。


当時のコードはこんな感じだった。(是非HEADのコードもみてもらいたい)
https://github.com/karupanerura/Profile/tree/e9e1b49b0a1bfe94f2918f17ca40587de0ea3b3b


もやもやした思いをコードを書くことによって晴らすことができて、エンジニア感あったし、いいかんじだった。
コード書き始めたのが24時頃で、次の日は仕事で、なるべく短時間でつくりたくてタイムアタック感あって楽しかった記憶がある。
あと、興味あったけどネタがなかったanguler,jsを試すにはちょうどいい題材だった。
こういうの楽しいしみんなやると面白いんじゃないかと思った。

*1:もしかしたら当時も既にこの施策は実施されていたかもしれないが長らく自分のabout.meを見ていなかった僕のabout.meに対する印象は昔のままだった。

Time::Strptime進捗

頭を悩ませながらのんびり作ってます。
https://github.com/karupanerura/Time-Strptime

Time::Strptimeとは

strptimeのpure perlによる実装です。
epochとoffsetだけを返すシンプルな機能を持っています。
pure perlですが最小構成のperl codeを文字列として構築してevalする事により条件分岐の回数などを極限まで減らし高速な動作を実現しています。

最近の変更

timezoneサポートを実装しました

具体的には%Z/%zを環境依存*1でparse出来るようになりました。
また、この変更に伴い、offsetを返すようになりました。parseした文字列のtimezone/offset、あるいは現在のtimezoneからoffsetを計算し、返します。
offsetの計算にはTime::TZOffsetが利用出きるケースではTime::TZOffsetを利用し、そうでないケースではTime::Localを利用しています。

localeサポートを実装しました

具体的には%b/%aがparse出来るようになりました。
Encode::LocaleとPOSIX::strftimeを使って動的に組み立てるというカッコイイことをしています。*2

ベンチマークスクリプトを更新しました

https://github.com/karupanerura/Time-Strptime/blob/master/author/benchmark.pl
Time::Pieceのインスタンスをキャッシュしてstrptimeするケースと、キャッシュしないケースを分けました。
テストも同時に実行しており、同じ結果を返すケースでのベンチマークである事がちゃんと分かるようになっています。
GMT/UTCにおいて、Time::Pieceのインスタンスをキャッシュしないケースより45%程度高速というベンチマーク結果となっております。


tpがTime::Piece、dtがDateTime、tsがTime::Strptime(本モジュール)です。

    # Subtest: GMT(+0000)
    ok 1
    ok 2
    1..2
ok 1 - GMT(+0000)
Benchmark: timing 100000 iterations of dt, dt(cached), tp, tp(cached), ts, ts(cached)...
        dt: 47 wallclock secs (46.43 usr +  0.09 sys = 46.52 CPU) @ 2149.61/s (n=100000)
dt(cached): 27 wallclock secs (27.22 usr +  0.05 sys = 27.27 CPU) @ 3667.03/s (n=100000)
        tp:  2 wallclock secs ( 1.62 usr +  0.00 sys =  1.62 CPU) @ 61728.40/s (n=100000)
tp(cached):  1 wallclock secs ( 0.96 usr +  0.01 sys =  0.97 CPU) @ 103092.78/s (n=100000)
        ts: 34 wallclock secs (34.09 usr +  0.11 sys = 34.20 CPU) @ 2923.98/s (n=100000)
ts(cached):  1 wallclock secs ( 1.12 usr +  0.00 sys =  1.12 CPU) @ 89285.71/s (n=100000)
               Rate       dt       ts dt(cached)        tp ts(cached) tp(cached)
dt           2150/s       --     -26%       -41%      -97%       -98%       -98%
ts           2924/s      36%       --       -20%      -95%       -97%       -97%
dt(cached)   3667/s      71%      25%         --      -94%       -96%       -96%
tp          61728/s    2772%    2011%      1583%        --       -31%       -40%
ts(cached)  89286/s    4054%    2954%      2335%       45%         --       -13%
tp(cached) 103093/s    4696%    3426%      2711%       67%        15%         --
    # Subtest: UTC(+0000)
    ok 1
    ok 2
    1..2
ok 2 - UTC(+0000)
Benchmark: timing 100000 iterations of dt, dt(cached), tp, tp(cached), ts, ts(cached)...
        dt: 47 wallclock secs (46.49 usr +  0.08 sys = 46.57 CPU) @ 2147.31/s (n=100000)
dt(cached): 27 wallclock secs (26.62 usr +  0.05 sys = 26.67 CPU) @ 3749.53/s (n=100000)
        tp:  1 wallclock secs ( 1.64 usr +  0.00 sys =  1.64 CPU) @ 60975.61/s (n=100000)
tp(cached):  1 wallclock secs ( 0.81 usr +  0.00 sys =  0.81 CPU) @ 123456.79/s (n=100000)
        ts: 34 wallclock secs (33.53 usr +  0.11 sys = 33.64 CPU) @ 2972.65/s (n=100000)
ts(cached):  1 wallclock secs ( 1.13 usr +  0.00 sys =  1.13 CPU) @ 88495.58/s (n=100000)
               Rate       dt       ts dt(cached)        tp ts(cached) tp(cached)
dt           2147/s       --     -28%       -43%      -96%       -98%       -98%
ts           2973/s      38%       --       -21%      -95%       -97%       -98%
dt(cached)   3750/s      75%      26%         --      -94%       -96%       -97%
tp          60976/s    2740%    1951%      1526%        --       -31%       -51%
ts(cached)  88496/s    4021%    2877%      2260%       45%         --       -28%
tp(cached) 123457/s    5649%    4053%      3193%      102%        40%         --
    # Subtest: Asia/Tokyo(+0900)
    ok 1
    ok 2
    1..2
ok 3 - Asia/Tokyo(+0900)
Benchmark: timing 100000 iterations of dt, dt(cached), tp, tp(cached), ts, ts(cached)...
        dt: 55 wallclock secs (54.70 usr +  0.11 sys = 54.81 CPU) @ 1824.48/s (n=100000)
dt(cached): 34 wallclock secs (33.92 usr +  0.06 sys = 33.98 CPU) @ 2942.91/s (n=100000)
        tp:  2 wallclock secs ( 1.61 usr +  0.01 sys =  1.62 CPU) @ 61728.40/s (n=100000)
tp(cached):  1 wallclock secs ( 0.79 usr +  0.00 sys =  0.79 CPU) @ 126582.28/s (n=100000)
        ts: 39 wallclock secs (39.50 usr +  0.13 sys = 39.63 CPU) @ 2523.34/s (n=100000)
ts(cached):  2 wallclock secs ( 1.79 usr +  0.01 sys =  1.80 CPU) @ 55555.56/s (n=100000)
               Rate       dt       ts dt(cached) ts(cached)        tp tp(cached)
dt           1824/s       --     -28%       -38%       -97%      -97%       -99%
ts           2523/s      38%       --       -14%       -95%      -96%       -98%
dt(cached)   2943/s      61%      17%         --       -95%      -95%       -98%
ts(cached)  55556/s    2945%    2102%      1788%         --      -10%       -56%
tp          61728/s    3283%    2346%      1998%        11%        --       -51%
tp(cached) 126582/s    6838%    4916%      4201%       128%      105%         --
    # Subtest: America/Whitehorse(-0700)
    ok 1
    ok 2
    1..2
ok 4 - America/Whitehorse(-0700)
Benchmark: timing 100000 iterations of dt, dt(cached), tp, tp(cached), ts, ts(cached)...
        dt: 57 wallclock secs (56.63 usr +  0.11 sys = 56.74 CPU) @ 1762.43/s (n=100000)
dt(cached): 36 wallclock secs (35.81 usr +  0.06 sys = 35.87 CPU) @ 2787.84/s (n=100000)
        tp:  2 wallclock secs ( 1.67 usr +  0.01 sys =  1.68 CPU) @ 59523.81/s (n=100000)
tp(cached):  1 wallclock secs ( 0.80 usr +  0.00 sys =  0.80 CPU) @ 125000.00/s (n=100000)
        ts: 40 wallclock secs (40.52 usr +  0.14 sys = 40.66 CPU) @ 2459.42/s (n=100000)
ts(cached):  3 wallclock secs ( 2.06 usr +  0.01 sys =  2.07 CPU) @ 48309.18/s (n=100000)
               Rate       dt       ts dt(cached) ts(cached)        tp tp(cached)
dt           1762/s       --     -28%       -37%       -96%      -97%       -99%
ts           2459/s      40%       --       -12%       -95%      -96%       -98%
dt(cached)   2788/s      58%      13%         --       -94%      -95%       -98%
ts(cached)  48309/s    2641%    1864%      1633%         --      -19%       -61%
tp          59524/s    3277%    2320%      2035%        23%        --       -52%
tp(cached) 125000/s    6992%    4982%      4384%       159%      110%         --
1..4

TODO

リファクタリング

スキマ時間でえいやと実装を進めてしまいがちで、カオスになってきたので整理する。

テストケースの追加

なんか微妙なバグを拾いきれてないきがするのでテストを整える。

サポートするべきフォーマットの選定/実装

他の実装のstrptimeを見てみて必要があらば実装する。

ドキュメンテーション

サポートしているformatの説明と形式、localeの変更のしかたなどを説明する。

リリース

https://github.com/chansen/p5-time-moment/issues/4#issuecomment-36947533
有益っぽいのではやくリリースしたい。

XSによる高速化

Time::Localの実行が遅いので互換制のあるインターフェースでXS版を書いてみる。

XS実装の作成

libcのstrptimeだと%z/%Zがparse出来ないので、結構頑張る必要がある。(たぶん作らない)

[追記] timezone処理の環境依存を切る

http://www.iana.org/time-zones のあたりからいい感じにモジュール化して別のpackageで出してそれに依存させる。

*1:/usr/share/localeなどに依存

*2:やめたい

ORDER BY狙いのキーが何故速いか

どの最適化が効くんや…とググった。
以前も調べた気がしたが思いだせず、ひたすらググる羽目になったので、
反省してブログに残す。ふつーにmysqlのdocumentに書いてあった。


http://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html

If you use LIMIT row_count with ORDER BY, MySQL ends the sorting as soon as it has found the first row_count rows of the sorted result, rather than sorting the entire result. If ordering is done by using an index, this is very fast.

バージョン古いけど日本語のほうも同じ内容書いてある。http://dev.mysql.com/doc/refman/5.1/ja/limit-optimization.html


というわけで、LIMITを付けていてかつORDER BYにINDEXが使われる場合は、
row_countぶん発見したらソートfetchを中断して結果を返すので、
rowsが結構デカくなってもLIMITがバカでかいとかでない限りだいたい速いということっぽい。
this is very fast. と言い切るあたり、かっこいいとおもう。


元ネタ: http://togetter.com/li/564015http://www.slideshare.net/yoku0825/devsdba


追記: MySQL Performance blogに詳しく書いてある記事があった
http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/


追記2: covering indexにならなくとも最適化は効くと思ってたので、検証してみます。分かったら追記します。
b+tree indexはsort済みなのでsortしなおす訳がなくて、たしかに「ソートを中断」より「fetchを中断」のほうが正しかったです。

#yokohamapm #10 に参加しました

ビールおいしかったです。スポンサーのKAYACさん、準備・運営して頂いた皆さんありがとうございました。


こんな感じの内容を話させて頂きました。


要約すると、既存のライブラリ、罠が多くて理解と慣れを要求されるけど、
Time::Momentがだいぶ良い感じな雰囲気なので、使っていこうよ。という感じの内容です。
strptime相当の機能が無いので、strptimeだけの機能を提供するモジュールを別モジュールとして用意すると良いんじゃないかなと考えています。
epochだけ返せば良いかなと思いつつ、offsetの情報がformatから失われるといろんなoffsetを含むformatをparseするケースでつらそうなので、
offsetの情報も返したほうがいいかなー。と思いつつ、どうなのだろうか。


karupanerura/Time-Strptime · GitHub
karupanerura/Time-Strptime-libc · GitHub


Time::StrptimeはApache::LogFormat::Compilerの個人的にeval compile hackと呼んでる実装を参考にしたんだけど、
そのへんでpure perl codeの高速化に関する知見が得られたのでこれは別途どっかに記事を書いたりはなしたりしたい。


あと、JSON Schemaおもしろいなーと思ったり、IRKitすごいっておもったり、DBD::mysql奥がふかいっておもった。
JSON Schema活用すると、client sideとserver sideでvalidatorのロジック/ルールを共通化できたり、
仕様書にもそのまんま使えて、実装と仕様書の差異を気にしなくてよくなるなと思ってり夢がひろがった。
最近、いにしえの技術について学び直したりもっと基礎的な部分の知識を補強したりしていて、最新の技術にすこし疎くなりがちなので、ちゃんと追っていきたいなーとおもった。

クソコード、あるいは技術的負債

クソコードについてここ数日で考えたことを書いてみる。

技術的負債まわりのえらいひとたちの議論を眺めてて、技術的負債って言うとなんかプロっぽいけど、クソコードって言ったほうが示したいモノを素直に表してるし分かりやすいきがしてきた。

 

 

クソコードを書くなとは思わないけど、クソコードをいつまでも放置するのはやめようって思う。

クソコードは次なるクソコードを生み出すし、バグを隠蔽するし、メンテナンスコスト増大の悪循環のキッカケになるし、新人の教育上良くないので無くて済むならもちろんないほうがいい。

 

 

ただ、ギークな人たちを除いて、さらっと60点*1のコードなんて書けない。僕を含め大多数のエンジニアは自分自身が書いたクソコードをリファクタリングして60点以上のコードを目指すための時間が必要になる。

そのうえ、そういうコードを書いてもだいたい時間経過に伴って事情が変わって、60点のコードの挙動を壊さないように慎重に書き換えてビジネス上の目的を達成していったら、どんどんコードはクソになってくとか、ザラだと思う。

そういうわけで、クソコード書くなって言っちゃうと、生産性*2は落ちると思う。

それに、だいたいビジネス上の目的を達成するためにはアホみたいに短い締め切りを守る必要があって、さもなくばチャンスを逃してしまい予算が達成できない。あるいはプロジェクトの継続が困難になってしまう。あるいは経理上ヤバイ数字になってしまってどうなってんだと株主から怒られる。あるいはユーザーに呆れられて製品から人が離れていく。いろんな最悪のシナリオが考えられて辛い気持ちになる。

そんなときはどんなにクソなコードを量産しようとも、ビジネス上の目的を達成しないといけない。いま自分の給料を稼いでくれているシステムはクソコードも厭わないビジネス上の目的を達成するための努力の結果出来上がったものかもしれない。

もちろん、最初からクソコードなしでそういうビジネス上の目的が達成出来れば最高だと思う。そこを目指すこと自体に異議は無い。

ただ、クソコード書くなって言っちゃうとビジネス上の目的を達成する事が(ただでさえ困難なのに)、より難しくなってしまう。

だから、クソコード書くなって言うのはやめた方がいいと思う。間に受けてひたすらコードを綺麗にするために命を懸けるみたいな事をする人が生まれかねない。*3

ただし、新人の場合は「こういうコードを目指せば良いのか」と思ってクソコードを量産するように育っても、自分達も本人も困る事になるのでちゃんとレビューしてクソコードは理由を説明しつつ突っぱねて良いコードが書けるように教育していくべきだと思う。

要するに、僕が思ったのは、やむなくクソコードを書いても、それで目的が達成出来るならいいじゃないか。ということだ。

 

 

ただし、クソコードはクソコードのままメンテナンスし続ける事は出来ない。

なぜなら、メンテナンスコストが増大し、ビジネス上の目的を達成するための変更を加えるのにかかる時間が増えていってしまうからだ。*4

クソコードの度合いにもよるが、時間経過に対して正比例的にメンテナンスコストは増大すると思う。(このへんは技術的負債が云々でホッテントリしてた人の記事が詳しく書いてたので読むといいと思う。僕はその記事にすごく共感した。)

だから、クソコードは直していかないとそのシステムでお給料を貰うのはどんどん困難になっていくと思う。

クソコードをメンテナンスし続けても給与3倍から遠ざかって行くし夢がない。

なので、クソコードは少しづつ改善しながらメンテナンスし続けていくのがいいと思う。これは最初からクソコードを書かないって事より遥かに難しいけど、給与3倍になると思えば出来ると思う。疲れてきた。

 

 

そして、時間的制約の中でどれだけ良いコードが書けるかというのは非常に大事だと思う。

クソコードは止むを得ず書くもので、クソコード自体は良いものではないので、書かなくて済めば書かないほど良い。

だから、スケジュールに影響が出ない程度に良いコードを目指すのはとても良い事だと思う。クソコードをちょっと直して60点以上になればビジネス上の目的を達成した上でコードは綺麗に保てるし最高だ。誰もが幸せになれる。

ただ、ぼくたちはだいたい未熟だしいつだってどんな仕様だって60点以上に出来る実力はないから、良いコードを書けるようになるために常日頃から努力を重ねる必要があると思う。だけど、ビジネス上の目的を達成出来ないと給与3倍から遠ざかっていくし、バランスが大事だと思う。その上で良いバランスを目指すために良いコードをさらっと書けるよう努力していくとみんな幸せになれそうだ。

 

 

iPhoneでベットでぬくぬくしながらてきとーに書いてたらつかれた。今日は有給だ。

*1:人によって基準は違うし、だいたいクソコードの基準を決めるのはギークな人たちなので、ここでは便宜上60点が合格点であると定義する

*2:時間あたりでどれだけの成果物を生み出せるかという意味合いでの

*3:もちろん、それはそれで良い事なんだけどビジネス上のメリットは殆んど無いケースが多いと思う

*4:そんな変更を加える必要も無いくらい完璧にシステムが作られているなら別だが、そうそうないでしょう