A Day In The Boy's Life -25ページ目

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

「好きなことで生きていく」ことの現実@狐の王国


好きなことを仕事にして生活できたら素敵だなと思う。

自分は元々ゲーム好きというところがあって、将来はゲーム会社に入りたかったりしたんですが、就職活動でことごとく蹴られ、今の会社に勤め似たような職種としてプログラマをやっていたりするわけですが、結果論から言えばこれはこれでよかったんじゃないかと思ってたりもするわけです。

自分としては、好きなものが社会人になってから見つかったって感じだからです。



好きのレベルがそんなもんだった


まぁ、ゲーム好きっていってもよくある子供のころにゲームのハードもってたからよく遊んでましたってレベルで、「俺ならこんなゲーム作るのに」とかって妄想を抱いていたようなもんだったわけですよ。

子供のころの付き合いのレベルで言えば、俺はあいつより高得点が出せるとか、隠れ技を知っているとかのもんで、その範囲で自分のやりこみレベルが高いと勘違いして好きなんだって思い込みをしていたわけですが、いざ就職活動して説明会とかに集まったライバルの多さや募集要項を見てみると自分にない高いスキルレベルを求められているわけで、そこで現実を知ったわけです。


プログラマとして応募したのに大学時代にろくにプログラミングをしてこなかったから当然そういった競争社会で勝ち抜く術もなく「他の人にはない観察眼を持ってます」とか「周りにないアイデアの出すことができます」とかスキルがない故の恥ずかしい言葉を並べて何とか背伸びしようとしていたんですけど当たり前に受け入れてくれるところもなく。

で、今の会社に応募したらあっさり採用されたんでプログラマとしての人生を始められたわけですが、最初は仕事に対してモチベーションとか全く無かったんですけど好きとか嫌いというレベルではなくただただ必死にやってました。

恵まれた環境だったこともあり、のびのびとプログラミングを学ぶことができたおかげで作る楽しさというのを知ることができ、そこで新しい好きなことができたわけです。


本当に好きを貫く人ならとことん突き詰めていくところが、自分では勘違いしていた好きというレベル感の現実を知って、一気にその気持ちが萎えてしまったところがあります。

ですから「好きなことやってるだけで仕事にできるなんていいね」って思っている人でも、当人にとってはその壁を突き抜けても好きを貫き通しているわけで、相当な覚悟がないとできないんじゃないかと思うわけです。


当人はそれが好きって思っているから覚悟なんてものは感じてないんでしょうけど、例えばゲームを一日8時間プレイするのを毎日かかさずするとか、ゲームの中の敵のステータスやダンジョンのマップを全てメモするとか、隠れ技が無いか延々とやりこむとか、全ストーリーを網羅するとか、仕事同様にそれにかける時間は膨大になるわけで、そういうことができるかって言われたら自分は多分無理なような気がします。


改めて考えると今のレベルで言えばそこそこプログラミングのスキルも身についてきて、頑張ればちょっとしたゲームを作るということも可能なような気もするのですが、その気持ちも今のところ沸いてこない。

就活の時に心が折れたというのもあるかもしれませんがつまるところ、好きって言ってもそんなもんだったんだと。



好きの定義


ゲームを作りたいというのも、ゲームを通して他の人を楽しませたいとかそういった観点があったわけで、こうしたことは今やっているビジネスツールやサービスの構築においても同様のことが当てはまるということに気がつきました。

業務で困っている人がいて、それを解決することで仕事が楽になったり、仕事をするのが楽しいと思えたり、そういった観点は自分が好きと思っていたゲームを作りたいという原点の奥底にあったものだと気がついたからこそ、今の仕事を続けてられるんだと思います。


YoutubeのCMに「好きなことで生きていく」というキャッチフレーズが出てきますが、決して「Youtubeで生きていく」ということをいっているわけではありません。

あくまでYoutubeはツールでしかなくて、好きを表現する手段でしかないわけですから、そもそも好きという定義をあまり狭く限定的に考える必要はないんじゃないかと思います。


これが好きだ、これを仕事にするんだ!って気持ちは大事ですし、とことん突き進むパワーがあれば問題ないでしょうけど、そうではない場合は何でそれが好きなのかという分析をしてみれば新たな好きなことというのも見つかるかもしれません。

その好きを実現する職業は一つとも限りませんし、それを表現するサービスも決して一つではないはずで、色んな役割や立場で好きなことを実現する方法ってあるんじゃないかと思います。


とまぁ、偉そうなことをいって見ても、いくら開発業務自体が好きになったからといっても社会人の仕組みや組織としてのごたごたに辟易することも多々あって、なんかすごいアイデアが舞い降りてそれをプライベートで作った仕組みが大当たりして、一日2,3時間適当に運用するぐらいで生活費を稼げるぐらいのサービス作れないかな俺、とか思ったりしている今日この頃です。




Apache Solrには同義語の定義ができます。

要するに検索する際のキーワードやインデックスのAとBは同じ言葉ということを定義できるわけですが、こういったことを人力で行うのは不可能に近いことです。

で、もっとも身近なデータから機械的に同義語データを定義できたらいいなということでWikipediaのデータを使って同義語ファイルを作成してみました。


結果からいうとこの同義語ファイルはまぁまぁ・・・な内容です。

Wikipediaでは厳密に同義語だという扱いをしているわけではなく、情報を正式名称のページに寄せているだけですからそれは同義語じゃないよねってデータも含まれるのですが、その辺の情報を精査するものは別途作る必要があるかと思います。



Wikipediaのデータから同義語となるデータを抽出する


使うのはWikipediaの記事データで、下記のURLに誰でもダウンロードできるように公開されています。


http://dumps.wikimedia.org/jawiki/latest/


で、この中で使えるデータがjawiki-latest-stub-articles.xml.gz(このファイルはあまりに巨大なので、今回使うのは分割しているjawiki-latest-stub-articlesN.xml.gz(Nは数字で2015.01時点では4分割)というファイルを使ってます)というファイルで、この中身はXML形式で記事のタイトルなどが含まれています。


<page>
    <title>ヨーロッパ</title>
    <ns>0</ns>
    <id>32</id>
    <revision>
      <id>52739692</id>
      <parentid>52357980</parentid>
      <timestamp>2014-08-31T09:03:15Z</timestamp>
      <contributor>
        <username>Dexbot</username>
        <id>620423</id>
      </contributor>
      <minor/>
      <comment>Bot: Removing Link FA template</comment>
      <text id="52784825" bytes="54708" />
      <sha1>giuwvpewi1w7k2luxgwmyk2u7pyu08a</sha1>
      <model>wikitext</model>
      <format>text/x-wiki</format>
    </revision>
  </page>
  <page>
    <title>生物</title>
    <ns>0</ns>
    <id>42</id>
    <revision>
      <id>52108199</id>
      <parentid>51054233</parentid>
      <timestamp>2014-06-27T14:18:57Z</timestamp>
      <contributor>
        <ip>118.153.79.10</ip>
      </contributor>
      <comment>説明の具体化</comment>
      <text id="52146183" bytes="13225" />
      <sha1>gjcin6me04awp6g9z5rgwu563x30an8</sha1>
      <model>wikitext</model>
      <format>text/x-wiki</format>
    </revision>
  </page>
  <page>
    <title>コケ植物</title>
    <ns>0</ns>
    <id>43</id>
    <revision>
      <id>49410361</id>
      <parentid>48129936</parentid>
      <timestamp>2013-10-14T02:13:55Z</timestamp>
      <contributor>
        <username>Zqmykbvoh</username>
        <id>140470</id>
      </contributor>
      <minor/>
      <comment>「単相」 lk 修正</comment>
      <text id="49421841" bytes="20742" />
      <sha1>jp71dgglkk20tqoj11arwm02am8p856</sha1>
      <model>wikitext</model>
      <format>text/x-wiki</format>
    </revision>
  </page>

この中で、Wikipediaでよく見かけるリダイレクトをかけている項目を抽出します。

例えば、こういうページ


http://ja.wikipedia.org/w/index.php?title=%E3%83%AA%E3%83%8A%E3%83%83%E3%82%AF%E3%82%B9&amp;redirect=no


これが、元のWikipediaのデータだと下記のようになっています。


  <page>
    <title>リナックス</title>
    <ns>0</ns>
    <id>1016</id>
    <redirect title="Linux" />
    <revision>
      <id>2169766</id>
      <parentid>8081</parentid>
      <timestamp>2003-03-02T19:47:50Z</timestamp>
      <contributor>
        <username>Okome</username>
        <id>98</id>
      </contributor>
      <text id="2169766" bytes="19" />
      <sha1>ow6122zxo9so312b35n5wtu21s92l0c</sha1>
      <model>wikitext</model>
      <format>text/x-wiki</format>
    </revision>
  </page>

redirectという要素があって、そこのtitle属性に転送先が書かれているわけですね。

ってことで、このデータを抽出して同義語ファイルを作るということです。



Solr用同義語ファイルを作成するPHPスクリプト


PHPで作った抽出スクリプトは下記のものです。


<?php

class CreateSynonymFile {

    // Solrの辞書データのパス
    public $dicPathIndex = "/path/to/solr/conf/synonyms.txt";
    // Wikiの元ファイルがおかれたディレクトリ
    public $wikiFileDir = "/tmp/articles/";

    function execute() {

        // Wikipediaの元ファイルのパスを取得
        $wikiFiles = $this->getWikiFiles();
        $fileCnt = count($wikiFiles);

        for ($i = 0; $i < $fileCnt; $i++) {
            $xml = simplexml_load_file($wikiFiles[$i]);
            $xmlCnt = count($xml->page);

            $fp = fopen($this->dicPathIndex, "w");

            for ($j = 0; $j < $xmlCnt; $j++) {
                $title    = (string) $xml->page[$j]->title;
                $redirect = (string) $xml->page[$j]->redirect[0]["title"];
                if ($this->checkSynonym($title, $redirect)) {
                    $line = $title . " => " . $redirect . PHP_EOL;
                    fwrite($fp, $line);
                }
            }
            fclose($fp);
        }
    }

    /**
     * 同義語として登録するかどうかチェックする
     * @param string $title    : 元の言葉
     * @param string $redirect : リダイレクト先
     * @return bool : 同義語登録対象の場合はTRUE、それ以外はFALSE
     */
    protected function checkSynonym($title, $redirect) {
        // 空白は全て除去
        $title    = str_replace(array(" ", " "), "", $title);
        $redirect = str_replace(array(" ", " "), "", $redirect);

        // データが空の場合は対象外
        if (empty($title) || empty($redirect)) {
            return FALSE;
        }
        // 対象の文字列が3文字未満なら対象外
        if ((mb_strlen($title) < 3) || (mb_strlen($redirect) < 3)) {
            return FALSE;
        }
        // Wikipedia関連記事のリダイレクトは対象外
        if ((strstr($title, "Wikipedia") !== FALSE) || (strstr($redirect, "Wikipedia") !== FALSE)) {
            return FALSE;
        }
        // 大文字・小文字の違いだけの場合は対象外
        if (strtolower($title) == strtolower($redirect)) {
            return FALSE;
        }
        // 「一覧」という言葉が含まれるものは抽象的な用語であるため対象外
        if ((strstr($title, "一覧") !== FALSE) || (strstr($redirect, "一覧") !== FALSE)) {
            return FALSE;
        }
        // 「曖昧さ回避」という言葉が含まれるものは抽象的な用語であるため対象外
        if ((strstr($title, "曖昧さ回避") !== FALSE) || (strstr($redirect, "曖昧さ回避") !== FALSE)) {
            return FALSE;
        }
        // ひらがな・カタカナの違いだけのものは対象外
        if (mb_convert_kana($title, "h") == mb_convert_kana($redirect, "h")) {
            return FALSE;
        }
        return TRUE;
    }

    /*
     * Wikipediaの元ファイルを取得する
     */
    protected function getWikiFiles() {
        $dir = array();
        if (is_dir($this->wikiFileDir) && $dh = opendir($this->wikiFileDir)) {
            while (($file = readdir($dh)) !== false) {
                if (preg_match("/jawiki-latest-stub-articles[0-9]+.xml/", $file)) {
                    $dir[] = $this->wikiFileDir . $file;
                    break;
                }
            }
        }
        closedir($dh);
        sort($dir);
        return $dir;
    }
}

やってることはそんなに複雑じゃないんですけど、simplexml_load_file()をつかってXMLを解析し、redirectの項目の有無とその転送先(title属性)を抽出しています。

checkSynonym()では、同義語として登録するかどうかの関数ですが、この辺が最初に書いたようにまぁまぁな内容をどこまで精査できるかってところで、Wikipediaのデータには下記のような曖昧さ回避をする言葉もありますから、その辺は同義語として登録すべきかどうか判断が必要です(今回の場合は無視)。


http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB_(%E6%9B%96%E6%98%A7%E3%81%95%E5%9B%9E%E9%81%BF)


出来上がったSolrの同義語ファイルは下記のような感じのもの。


森田一義 => タモリ
.NET => .NET Framework
OSI基本参照モデル => OSI参照モデル
クーロン相互作用 => 電磁相互作用
場の理論 => 場の量子論

こういった例は全然いいんですけど、


エロス物 => エロス作品

これは、人の解釈によるんじゃないかとか、


錯乱坊 => うる星やつらの登場人物

そんな同義語必要ないんじゃないかとか、


将棋棋士 => 棋士 (将棋)

元の語のほうがわかりやすいと思うとか、まぁリダイレクトの処理からの抽出ですし、あくまでWikipedia上でのデータになりますから情報の精査は追加対応が必要そうです。





起業家が開発者の管理で犯しやすい11の失敗 @ readwrite.jp


起業家ではないにしろ、システム開発においてはエンジニアとの付き合いというのはうまくしていくに越したことはありません。

例えエンジニア同士であったとしてもその管理というのは結構難しくて気を使うものだったりします。



エンジニアとしての立場を尊重すること


仕事をしていく上では役割というものがあるわけですので、担当しているエンジニアの領域というものをきちんと尊重してあげる必要があります。


よくありがちなのが非エンジニアが技術的なことに口出しをしてしまい、過去に自分が使ったことがあるツールであったり、他のサービスで利用している仕組みをそのまま当てはめようとするようなケースがあったりして、こういったことはエンジニア自身によって、そのシステムの組み上げ方やアーキテクチャとの相性やインフラにおいての特性などを考慮して決めるべきだったりします。

そういったことを考えて決めようとするときにこういった横槍を入れられるとエンジニア自身のモチベーションが下がるだけでなく、システム構成がめちゃくちゃになって保守性が落ち、サービスの寿命を縮める結果になるかもしれません。


エンジニア同士であれば、それが先輩後輩としての教育の一環ということであれば大きく介入せざるを得ない場合がありますが、異なる役割のエンジニアとしてならその立場をある程度尊重してあげないと同じ結果になるかもしれません。

一言でエンジニアといっても専門分野が大きく異なりますし、インフラならインフラ担当としての意見もありますが、それによってアプリケーションの構成に大きな偏りが出てしまったりもするのでそれぞれの立場としての意見をきちんと言い合えるのが重要ではないかと思います。



技術的な苦労を理解する


技術が如何に進歩したからといって、システムを組み上げていく苦労が単純に減っていくわけではありません。

前回の「フルスタックエンジニアなんて目指さない方がいい 」の中で書きましたが、エンジニアが会得しなくてはならないスキルというのは多様化しているので求められるスキルレベルはどんどん上がってきているかと思います。

ですから、システム構築の際に技術的な課題にぶち当たり悩むこと自体が減っているわけでもなく、また技術的な進歩によって悩むレベルが低くなっているわけでもありません。


まぁ、エンジニアを管理する立場の人がエンジニアとしての業務を経験した人ばかりというわけではなかったりするわけですが、技術的な問題で悩むエンジニアは結構孤独で戦っていたりもするので、その状況を把握してあげて、技術的なこと以外での解決方法(例えば運用的な回避やそもそもその課題を先延ばしにすることでスケジュール的な負担を軽減できないかとか)がないかを一緒に模索してあげることも必要です。


ここでわかっていないことをジャストアイデアで言ったりするとさっき書いたようなケースに陥ったりもしますし、エンジニアの立場からすればわかっていない人に言われたくないって思いもあったりして(非エンジニアからすればその技術的な課題が何で解決できないのかがわからないので)、こういったナーバスな状況においては双方の言い分の応酬になるので注意が必要です。

もちろんエンジニアとしても、それ以外の役割で動いている人の立場を理解してあげる必要はあるかと思いますが。



作ったものを否定しない


例え他人のアイデアだったとしても作ったプログラマは作ったシステムに誇りや愛着をもっていたりもしますので、その仕様を考えた本人がそれを否定したくなったとしても言葉を選ぶ必要があります。


サービスの要件はそれを作ったときから流行りなどによって常に変化していきます。

ですので、リリース後に全く異なるものを作りたくなる気持ちもわからなくはないのですが、作ったものを否定するのは(例えそれがそのサービスの仕様や特徴という意味であったとしても)、エンジニアから見れば自分たちが作ったものが否定されるものと同じ意味に捉えられかねません。


大事なのはきちんとサービスのロードマップを作り、各フェーズを終えて次のステップに移っていることを共有しておくことです。

行き当たりばったりで作っては壊しというステップを踏むのはエンジニアの疲弊を招き次のモノづくりをしようとする意欲を削いだりします。



集中できる環境を作る


エンジニアとしての役割に注力して欲しいならその業務に集中できる環境を提供してあげる必要があります。

しかしこれは組織や会社の多くのルールによって阻まれます。

出なくてもよい会議であったり、作っても読まれないドキュメントであったり、教育という名の下に使わない知識を埋め込まれたりするわけです


そういったものをなるべく取り除き、集中すべき仕事に割く時間を確保してもらうことが必要にはなりますが、これには多くのサポートが必要です。

エンジニアがそれをやらなくて済むように周りが多少の犠牲を払う必要もあるからで、それは本来やら無くてもいい仕事を自分や周りがかぶることにもなったりします。

もちろんエンジニアとしてはそういった環境を作ってもらえることに感謝を示すべきでしょうけど。



何を作るかをはっきり決める


特に経験の浅いエンジニアはタスクの優先順位を見誤ったりします。

技術的な興味が先行するあまり重要ではない機能を深掘りしたり、気まぐれで言ったことがエンジニアの心に火をつけて突っ走っていくことはよくあることで、後々それが大して重要なものではないとわかったりお蔵入りするような結果になったらエンジニアのその熱意が台無しとなります。


ですから何が重要で何が重要ではないかははっきりと決めておく必要があります。

この際に、サービスとしての優先順位と技術的な組み立ての意味での順序の折り合いをきちんと付けておくことです。

サービスとしては、この機能ができたら次にこれを作りたいという願望を持っていても、技術的な側面から見ればその順番の前にこの機能実装が必要だという順序がエンジニアの頭の中にあるので、それを互いに合意しながら進めていく必要があります。

これはサービスのリリーススケジュールに大きく影響がでることなので双方できちんと確認しておかないとプロジェクト管理上でもまずいことになりかねません。