多様性(ダイバーシティ)について

唐突ですが…

私は牛乳やチーズなど乳製品全般が苦手です。
口にすると、体が拒絶しているのか全て吐き出してしまいます。
今ではピザ程度なら食べる事ができますが、チーズだけのトッピングや匂いのきついチーズを使ったピザは今でも食べる事ができません。

続きを読む

2017年の振り返りと2018年の抱負

はじめに

新年明けましておめでとうございます。 2018年も宜しくお願い申し上げます。

2017年を振り返って

担当サービスの安定稼働

私がテックリードを担当する全サービスが、大きなトラブルもなく無事に新年を迎えられました。

大袈裟かもしれませんが、自分が作ったサービスは娘のような存在です。誕生から成長まで、正しい道へと導きつつ全力で守るのが親であるエンジニアの重要な役割だと考えています。
私はその信念に基づいて行動してきた事が、安定稼働に結び付いたのだと思います。

大規模マイグレーションの成功

昨秋、2つのサービスの大規模なマイグレーションプロジェクトが始動し、1つを昨年中に無事成功させました。

このマイグレーションを終えたサービス、実は約10年前に私が中心となって開発したものでした。
10年前の私はまだまだ未熟だった事もあり、遣り残していた事も多く、いつかは直したいとずっと心残りだったのですが、私自身の手でマイグレーションをする事が決まった時は運命というものを強く感じました。
マイグレーションプロジェクトの中で遣り残していた幾つかの課題を解消し、ようやく晴れて安心してバトンタッチする事ができます。

異動

派遣時代から数えて約14年間、アプリケーション・エンジニアとして最前線を走り続けてきましたが、今月末を以て別の職種に転向することとなりました。
少々未練はありますが、もし再びサービスを作りたくなってしまったら、その時は趣味で作ろうと思います。

2018年の抱負

ブログ更新の継続

前回の投稿から1年以上放置してしまいましたが、今年からは定期的に投稿する事にします。

職場での仕事は、基本的に表舞台で私の名前が出る事は殆ど無いと思います。 そう考えると、セルフブランディングの為には定期的なアウトプットが重要だと考えたためです。

私の技術的な知識は会社の資産ではなく私の資産です。私が経験してきたのと同じ事で苦労している人がいるのなら、その人達を助けるために使いたいと思います。

新しいステージでの挑戦と成長 

異動に伴い、業務内容も今までとは異なります。 新しい部署でどれだけ自分が役に立てるのか、期待と不安が入り混じっています。
自分の引き出しを増やす良い機会だと思いますので、前向きに挑戦し、成長に繋げたいと思います。

最後に

久し振りの投稿で書きたい事がなかなか整理できず、ギリギリ三ヶ日滑り込みセーフになってしまいました。

もう少し洗練した記事を書くように心掛けますので、今後とも宜しくお願いいたします。

エンジニアという仕事について

社会人デビューしてゲーム業界から始まった自分のエンジニアという生業。

18歳から45歳に至るまで、「会社の為に頑張ろう」と考えた事は正直言って殆どというか、全く無かったと思う。


自分の目指す道と会社が求めている事が一致する限りは共存していこうとは考えるけど、自分にとって何か大切なものをを犠牲にして磨り減っていくなら、それはもう相思相愛な関係では無いと考える。

 

確かに、年齢的には後輩の為に身を粉にする立場なのかもしれないけど、必死になって足掻く人には喜んで手を差し伸べても、その立ち位置で満足しているような人の為に身を粉にする筋合いは無いというのが自分のエンジニアとしての持論。

自分だけが磨り減って犠牲になるなんて、本当に真っ平御免だと思っている。

 

己を磨く為に日々研鑽するにストイックな“侍”と久しく出逢っていない。

過去に何人もの“侍”と出逢ってきたお陰で、本物のエンジニアというものを見てきたし、彼等と接してきたからこそ「今の自分では全然足りない」という考え方に辿り着く。

 また、あの時のヒリヒリした感覚を味わえる日が来るのだろうか。
それとも、今の時代にそんな事を望む自分の考え方が間違ってるのだろうか。

 

今の環境における自分の存在意義は、エンジニア同士の共鳴ではなくて、「もしかしたら自分が活躍できるチャンスがあるかもしれない」という可能性の方が強いと思う。

 幕末から明治維新を迎えた武士のように、自分のようなエンジニアは現代に生き残ってはいけない存在なのかもしれない。

HTMLテンプレート作成のツボ

はじめに

Webアプリケーション開発において、テンプレートの作成はプログラミングと同等にセンスを問われる作業です。

「たかがテンプレート」と侮っていると、何処からリファクタリングすれば良いのか頭を抱えるようなテンプレートを量産しかねません。 正しい知識を身に着ける事で、理想的なテンプレートを自然に書けるようになりましょう。

この記事ではサンプルコードとしてPerl + Sledge + Template Toolkitを用いていますが、 記事で言及している内容は、PHP + Smarty等ほぼ全ての言語・テンプレートエンジンにも共通しております。

それでは4種類のアンチパターンを例に挙げて、リファクタリング方法を解説していきます。

目次

  1. テンプレートエンジンへの変数の割り付け方
  2. 修飾子の使い方
  3. ループ処理
  4. 冗長なテンプレート

1. テンプレートエンジンへの変数の割り付け方

1-1. メソッド実行回数が無駄に多い

複数の変数をそれぞれバラバラにテンプレートエンジンへ割り付けるのは非効率的です。

一般的なテンプレートエンジンは、複数の変数を一括で割り付ける機能を持っています。 バラバラに割り付けるのはソースコードの可読性を悪くするだけで何一つメリットはありません。

リファクタリング

$self->tmpl->param( name => 'Terui' );
$self->tmpl->param( id   => 'teruism' );
$self->tmpl->param( pref => 'Kanagawa' );

リファクタリング

$self->tmpl->param(
    name => 'Terui',
    id   => 'teruism',
    pref => 'Kanagawa',
);

1-2. 無計画な変数名の割り当て方

nameやidなど、何の名前やIDなのか特定できないような変数名を割り当てるのは事故に繋がります。 テンプレートを作成した時点では問題が無いのかもしれませんが、似たような変数名が追加された場合、どちらが目的の変数なのか区別できなくなります。

下記例では、userという連想配列としてテンプレートエンジンに割り当てるようにリファクタリングしています。

リファクタリング

$self->tmpl->param(
    name => 'Terui',
    id   => 'teruism',
    pref => 'Kanagawa',
);

リファクタリング

$self->tmpl->param(
    user => {
        name => 'Terui',
        id   => 'teruism',
        pref => 'Kanagawa',
    },
)

1-3. 変数の値による文字列の出し分け

テンプレートを作成していると、ある値に対応する文字列を表示するケースが非常に多い事に気付くでしょう。 そういった場合、値によって条件分岐で表示内容を切り替えるのは非効率的です。

文字列を配列に格納し、割り当てた変数の値を添字として目的の文字列を表示するように実装しましょう。

リファクタリング

$self->tmpl->param(
    pref  => 0,
    pref_name0 => '北海道',
    pref_name1 => '青森県',
    pref_name2 => '岩手県',
);
[% IF pref == 0 %]
  [% pref_name0 %]
[% ELSIF pref == 1 %]
  [% pref_name1 %]
[% ELSE %]
  [% pref_name2 %]
[% END %]

リファクタリング

$self->tmpl->param(
    pref => 0,
    pref_names => [ '北海道', '青森県', '岩手県' ],
);
[% pref_name.$pref %]

2. 修飾子の使い方

2-1. ロジック側でフィルタ処理を実行

Webアプリケーションでは、クロスサイト・スクリプティングなどの攻撃から守るためにデータベースから取得した値をエスケープする事が求められる他、 改行コードを
タグに置換するなど、様々なフィルタ処理を行う必要があります。

但し、フィルタ処理を行うのはロジックではなくテンプレートエンジン側であるべきです。 ロジックで実装してしまうと、テンプレートエンジンに割り当てる変数の数が無尽蔵に増えてしまうだけでなく、 フィルタ処理を忘れた変数がそのままWebブラウザに表示されてしまう可能性があります。

次のサンプルでは、テンプレートエンジン側でHTMLエンティティをエスケープさせるようにリファクタリングしています。

リファクタリング

$self->tmpl->param(
    userid_espaced => encode_entities( $userid, q{ &<>'" } ),
);
<td>
  [% userid_escaped %]
</td>

リファクタリング

$self->tmpl->param(
    userid => $userid,
);
<td>
  [% userid | html %]
</td>

2-2. 「独自の修飾が必要」という理由で修飾処理をロジック側に実装

Webアプリケーションを開発していると「独自の修飾が必要なのでロジック側で実装する」と主張する人が少なからず存在しますが、 絶対にその主張に同意してはいけません。 テンプレートエンジンには自作の修飾子を使用するための仕組みが必ず用意されていますので、ロジック側で修飾する必要は一切無いのです。

次のサンプルでは、変数$useridをMD5ハッシュに変換していますが、 ロジック側では修飾せずにテンプレート側で修飾するようにリファクタリングしています。

リファクタリング

$self->tmpl->param(
    md5_userid => MD5->hexhash( $userid ),
);
<td>[% md5_userid %]

リファクタリング

$self->tmpl->param(
    userid => $userid,
);
[% USE md5 %]
<td>[% userid | md5 %]</td>

3. ループ処理

3-1. イテレータを使わないループ処理(1)

データベースから取得したリストを表示する際、添字となる変数を使ったループ処理をテンプレートに書く必要はありません。 ほぼ全てのテンプレートエンジンには「イテレータ」が実装されていますので、積極的にイテレータを活用しましょう。

次のサンプルでは、変数counterを用いて0から変数item_size-1までの値でループ処理していたものを、 FOREACHでシンプルにリファクタリングしています。

リファクタリング

[% counter = 0 %]
[% WHILE counter < item_size %]
  <td>
    [% items.$counter %]
  </td>
  [% counter = counter + 1 %]
[% END %]

リファクタリング

[% FOREACH item = items %]
  <td>
    [% item %]
  </td>
[% END %]

3-2. イテレータを使わないループ処理(2)

3-1でイテレータの使用を推奨しましたが、「任意の行で何か表示する場合は変数が必要なのでは?」と言う人がいるでしょう。 イテレータには、リストの要素数や現在のインデックスを取得できるメソッドが用意されているだけでなく、 現在のインデックスが最初の要素なのか、最後の要素なのかを知ることができるメソッドが用意されています。

次のサンプルでは、変数counterを使う代わりにイテレータのメソッドを使い、およびを適切な位置に出力するようリファクタリングしています。

リファクタリング

[% counter = 0 %]
[% WHILE counter < item_size %]
  [% IF counter == 0 %]
    <tr>
  [% END %]
  <td>
    [% items.$counter %]
  </td>
  [% IF counter = item_size - 1 %]
    </tr>
  [% END %]
  [% counter = counter + 1 %]
[% END %]
[% UNLESS item_size %]
  商品はありません
[% END %]

リファクタリング

[% FOREACH item = items %]
  [% IF loop.first %]
    <tr>
  [% END %]
  <td>
    [% item %]
  </td>
  [% IF loop.last %]
    </tr>
  [% END %]
[% END %]
[% UNLESS items.size %]
  商品はありません
[% END %]

4. 冗長なテンプレート

4-1. 同一内容を複数出力するために同一の記述を行う

下記は一覧表示ページによくある「前の10件」「次の10件」といったページネーションのサンプルです。 一覧表示の上下にページネーションを表示しているのですが、全く同じ事を2箇所に書くのは冗長であり、 将来的に「両方を修正したつもりが片方しか修正していなかった」といったミスを招いてしまいます。

リファクタリング後は、paginationという名前でページネーションのブロックを宣言し、 リストの上下でブロックの内容を展開しています。

リファクタリング

<div>
  <a href="?page=[% page - 1 %]">前の10件</a> <a href="?page=[% page + 1 %]">次の10件</a>
</div>
<ol>
  [% FOREACH item=items %]
    <li>[% item %]</li>
  [% END %]
</ol>
<div>
  <a href="?page=[% page - 1 %]">前の10件</a> <a href="?page=[% page + 1 %]">次の10件</a>
</div>

リファクタリング

[% BLOCK pagination %]
<div>
  <a href="?page=[% page - 1 %]">前の10件</a> <a href="?page=[% page + 1 %]">次の10件</a>
</div>
[% END %]
[% PROCESS pagination %]
<ol>
  [% FOREACH item=items %]
    <li>[% item %]</li>
  [% END %]
</ol>
[% PROCESS pagination %]

4-2. 複数のページで同一の情報を表示する

4-1で紹介した手法は、同一ページ内に限った事ではありません。 パーツとしてインクルードファイルを用意し、使用したいテンプレートからインクルードする事で自由に使用できます。

リファクタリング後は、テーブル内の文言を変数msgで指定する事で、任意の文字をテーブルの中に出力できるようにしてあります。

リファクタリング

html/top.html

<div>
  <table>
    <tr>
      <th>header</th>
    </tr>
    <tr>
      <td>トップ</td>
    </tr>
  </table>
</div>

html/search.html

<div>
  <table>
    <tr>
      <th>header</th>
    </tr>
    <tr>
      <td>検索</td>
    </tr>
  </table>
</div>

リファクタリング

html/inc/table.inc

[% BLOCK table %]
  <table>
    <tr>
      <th>header</th>
    </tr>
    <tr>
      <td>[% msg | html %]</td>
    </tr>
  </table>
[% END %]

html/top.html

[% INCLUDE table.inc %]
<h1>top</h1>
<div>
[% PROCESS table msg="トップ" %]
</div>

html/search.html

[% INCLUDE table.inc %]
<h1>search</h1>
<div>
[% PROCESS table msg="検索" %]
</div>

最後に

今回紹介したコードは、どれもリファクタリング前と後で全く同じ出力結果を得られますが、そこが非常に重要なポイントです。

プログラミングとは確実な正解の無い仕事です。 それ故に、己の心に嘘をつかず、常に一定以上の速度でクオリティの高いアウトプットをする事が求められています。

エンジニアとしてのプライドを賭けて真摯に取り組めば、嘘などつけないはずです。

この記事があなたの成長や気付きのきっかけになれば幸いです。

[2016/10/16 20:52] 3-2のリファクタリング前後のテンプレートを修正(0件の場合に「商品はありません」と表示)。