Dance with Tech

プログラミングとか学んだことの備忘録ブログです。

レガシーシステムをリプレイスして古の遺産を浄化した話

まえがき

タイトルの通り、少し前に 8 年近く(正確な歴史は不明)動いていたシステムをリプレイスしました。

かかった期間は約 2 年、発行した課題チケット数は 6000 超え、リリース直前に直属上司が退職など紆余曲折ありました。

良かった点や反省点が多くあったので、記憶が新しいうちにアウトプットしようと思います。

なぜリプレイスするのか

単純にエンジニアが「レガシーだからモダンな環境にリプレイスしたい」と言っても、事業責任者や経営層にメリットを理解してもらえないと実施できません。

今回は後述する問題によって、事業の足を引っ張っているという結論が出たためリプレイスに至ったと認識しています。

セキュリティの問題

システムの問題

  • フレームワークのコア部分を魔改造
  • 一度リプレイスしようとして失敗した昔の残骸(Python のコード)が残っている
  • テストコードがない
  • バージョン管理が Subversion
  • 密結合
  • 1 つのリポジトリを別部署の別サービスと共有している
  • サービスA のバリデーション定義を変更したら、サービスB のバリデーション定義も変更されてしまう
  • エラーに気づけない(ユーザーからの問い合わせで初めて気づくなど)
  • サイトが http

DBの問題

  • 1 テーブルのカラムが大量に存在する
  • 使用していないテーブルが混ざっている
  • 何でも DB で管理しようとしているためデータが複雑化している(〇〇カテゴリーのネスト構造をマスターとして管理など)
  • スロークエリ多数
  • 命名に一貫性がない
  • ***_table2 が存在する
  • m_***_table のようにマスターテーブルを想起させるプレフィックスが付いていたりするが、実際はマスターではなく頻繁に更新される普通のテーブルだったりする

事業的な問題

  • 上述の理由によりデリバリーのスピードが出せず、施策が実行できない(時代の変化についていけない)
  • テストが人力のみなのでシステムのクオリティが担保できない
  • 枯れた技術を使用しているため、エンジニア採用時の足かせになる(または退職される)

どうリプレイスしたか

ここは書こうと思えばいくらでも具体的にかけますが、キリがないのでざっくりポイントだけ書きます。

システム構成

  • オンプレからクラウドAWS)に移行
  • マイクロサービスアーキテクチャ導入
  • Frontend ⇔ API GatewayAPI
  • API 実装時はテストコード必須に
  • PHP は 7 系にアップデートし、フレームワークは Laravel に変更
  • MySQL は 5.7 互換の Aurora に変更
  • DB は全て再設計し、新テーブル用にデータをコンバート
  • 画像系と静的コンテンツは S3 で管理
  • インフラ周りは Terraform と Ansible で管理
  • フロントエンドは Vue や React で作成

開発方法

  • 2 週間ごとにスプリントを切って回していくスクラムを導入
  • 課題の管理や進捗の把握は JIRA で統一
  • 1 人でフロントエンドからバックエンドまでを担当
  • システムとしてどうあるべきかということを先に提案し、なるべく既存システムに近づけてひたすら機能を開発していく

体制

開始時

  • エンジニア: 2 名
  • プロダクトオーナー(直属上司) 1 名
  • 部長: 1 名

終了時

  • エンジニア: 5 名
  • 部長: 1 名

やらなかったこと

  • デザインのリプレイス(リニューアル)
    • 単純にデザイナーがいなかったというのと、システムに比べてスタイルガイドなどはかなり丁寧に作られていたのでデザインは踏襲することにしました
    • ただ、純粋なコーディング部分は Webpack で管理できるように書き換えました

リプレイスするにあたり追い風だったこと

  • リリース当日はサイト停止 OK
  • 廃止できる機能が多かった

大変だったこと

旧システムの有識者が 0 の状態からのリプレイス

プロジェクトにアサイン後、唯一の有識者だった派遣社員エンジニアが退職してしまい、手を動かすエンジニアがアサインされたばかりの自分と、入社したばかりの業務委託の方のみになってしまいました。

そのため、かなり手探りの状態からリプレイスプロジェクトが始まり、スタートダッシュができませんでした。

データの移行

データを移行するためにデータコンバーターを作成しました。

「旧DBからデータ取得→バリデーション→新DB用にデータを加工→新DBにインサート」という流れです。

移行するテーブル 1 つひとつに、このロジックとテストコードを作成しなくてはいけないため、かなり時間を費やしました。

また、データの移行を失敗すると取り返しがつかないことが多いので、かなり慎重に行う必要がありました。

パスワードの移行

可逆だったパスワードを不可逆の値にするために一旦復号化する必要がありました。

旧パスワードが pear の Crypt_Blowfish を使用していたため、composer に pear のライブラリを追加しました。。

そして、そのままでは PHP 7 系では動かないので、/pear-pear.php.net/Crypt_Blowfish/Crypt/Blowfish.php を改修することに。。

※ そのときの調査ログ

工夫したこと

フロントエンドはなるべくサーバーレスに

EC2 インスタンスは結構料金がかかるので、可能な限り SPA で構築することにしました。

SEO 対策が必要なサービスは SSR できる Next と Nuxt を導入して対応しました。

反省点

SEO の影響をなめていた

そこまで SEO に依存していないコンテンツでしたが、それでも目に見えて集客力が下がったため、もう少し真剣に考慮するべきだったと思います。

ちなみに SPA にした影響というよりは、旧 URL からのリダイレクトやエラーページのステータスコード、ページ構成などが主な理由です。

サービス間の連携テストの実施が遅かった

これはマイクロサービスならではですが、各サービス間をまたいだテストをするのが少し遅かったです。

連携テストをして初めてログイン周りの不具合などが見つかりました。

そして、結果的にリリース日を 2 週間ずらすことになってしまいました。。

サービスが属人化してしまった

スピードを重視していたため、1 人 1 サービス(場合によっては複数)を実装してもらうことにしたのですが、そのサービスについて詳しい人物が限定されてしまいリスクを生んでしまいました。

ある程度はスピードとのトレードオフなので仕方ないかもですが、もう少し横断的に開発していくべきだったなと思っています。

ただ、メンバー全員が責任を持って取り組んでくれたおかげで、誰もメンバーが欠けることなくリプレイスを終えることができました。

あとがき

0 → 1 というより、マイナス → 0 にするフェーズだったのでかなり貴重な経験をさせてもらいました。

エンジニアとしても成長できました。

事業責任者と関わることも多かったので、浮かび上がる課題に対してエンジニアリング以外で解決する方法を学べました。

また、エンジニアという役割上、課題をどう解決していくかという How に目が行きがちですが、そもそも課題や目的は何なのか、はたまたそれは本当に課題なのかという Why の視点を持てるようになったことが良かったです。

おまけ

新旧リプレイス表

環境
全体構成 モノリシック マイクロサービス
サーバー オンプレ クラウド(AWS)
インフラ構成管理 手動 Terraform, Ansible
バックエンド言語 PHP 5.1 PHP 7.1
バックエンドフレームワーク Ethna Laravel
フロントエンド jQurey Vue, React
DB MySQL 5.5 MySQL 5.7(Aurora)
バージョン管理 Subversion Github
メール オンプレ SendGrid API

ソフトバンクiPhoneからSIMフリーiPhoneに乗り換えた手順を公開する

はじめに

つい最近、ソフトバンクiPhone6 から SIMフリー版(LINEモバイル)iPhone7 に変えたので、その手順や実際にやったことなどを書いていこうと思います。

キャリアはソフトバンクですが、どのキャリアでも手順はほとんど変わらないはず。

僕の場合、乗り換えたことにより、月々の支払いが大体 5,000円弱安くなる算段です。

月々のデータ通信を把握する

まずは自分が大体月にどれくらいデータ通信しているのか確認します。

「キャリア名 通信量」とかでググれば出てきます。

ログインして確認しましょう。

僕は大体 4GB くらいでした。

どこのSIMカードにするか決める

自分の通信量やスマホの使い方を元に、どのSIMカード会社が自分にとって 1番得なのか徹底的に比較します。

僕に最適であろう、4GB というプランは中途半端なのか、どの会社にも存在しないことが多いです。

なので 3GB か 5GB になる訳ですが、どうにか 3GB に抑えたいところです。

Freetel(フリーテル)と LINEモバイルには「カウントフリー」という

「ある特定のアプリだけ通信量を無料にしますよ」という神制度があります。

「カウントフリー」になるアプリはどちらも大体同じですが、

Freetel には AppStore の通信費を無料にする制度があり、

LINEモバイル には LINE電話 の通信費が無料になる制度があります。

AppStore は家や会社の Wi-Fi を使ってダウンロードとアップデートをすれば良いと思うので、今回は LINEモバイル にしました。

また、LINEモバイル にすると地味に LINE ID で友達追加できたり(他はできない)、

Amazon経由 で申し込めば登録事務手数料の 3000円が無料になったりして良いです。

iPhoneを買う

iPhone を普通に買うだけです。

iPhone は大体どこで買っても価格は同じなので、僕は Apple ストア公式から購入しました。

2日くらいで届きました。

ついでに、iPhone ケースと液晶保護フィルムをこのタイミングで買っておきました。

MNP予約番号を取る

各携帯会社の MNP 転出専用ダイヤルに連絡をします。

「キャリア名 MNP 転出」とググれば出てきます。

土日は電話が混んでいて結構待たされるので注意。

ソフトバンクの場合、MNP の予約番号をすぐに SMS で送信してくれました。

SIMカード会社にMNPする

MNP予約番号を控えて、対象のSIMカード会社に「MNP したいんですけど」と連絡します。

最近は家電量販店に実店舗があったりするので、そちらでも良いと思います。

LINEモバイルの場合は実店舗がないので、MNP 予約番号をネット上から入力して SIM カードを配送してもらいます。

ここで注意なんですが、

MNPの開通受付窓口へお電話がない場合、SIMカードが配送された翌々日の午後に自動的に切り替えを順次実施します

公式がアナウンスしているので、

なるべく休日に SIM カードが届くように手配した方がいいです。

大体 2日くらいで届くので、土日休みの人は木曜くらいですかね。

仕事中にいきなり切り替わったりしたら大変ですからね。

LINEモバイルの場合、開通手続きの電話をして完了するまで 2時間弱かかりました。

また、完了後は一度 iPhone を再起動しないと回線を拾ってくれませんでした。

iPhoneを買取りに出す

以上で乗り換え完了です。

ついでなので、旧iPhone を買い取りに出しましょう。

色々調べた結果、じゃんぱら が 1番高く買い取ってくれる気がします。

ただ、土日だと人が多く、90分くらい待たされるので要注意。

おまけ

最近 Qiita をはじめました。

技術的な話はこちらで更新してますので、よかったら読んでください。

Django(Python)のDB操作まとめ

仕事でDjangoPython)に触る機会があり、0から学習しながら進めています。

今回は個人的に分かりづらかった、DB(SQL)周りの内容をまとめました。

ドキュメントを読んでも分かりますが、ちょっと読みづらいです

 

条件指定

SQLで条件を指定したい場合は「filter」を使えばできます。

誤解を恐れないで言うと、

filter = where

という認識で良いと思います。

 

サンプル

 

複雑な条件を使いたいときは Q object を使う

 

日付型のインサートとアップデート

ちょっとSQLとズレますが、Model で以下のように設定すると、良しなにやってくれます。

 

・auto_now_add=True にすると自動で今の時間がインサートされます

createdt = models.DateTimeField(auto_now_add=True)

 

・auto_now=True にすると自動でインサートされるしアップデートもされます

update_dt = models.DateTimeField(auto_now=True)

 

※参考先↓


 

Google Developers Summit:Progressive Web Appsに行ってきた

少し前に行われたGoogle Developers Summit : Progressive Web Appsに行ってきたので、PWAについて自分なりにまとめたいと思います。

f:id:kmatz90:20160508164153j:plain

 

Progressive Web Apps(PWA)とは?

無理やりシンプルに説明すると、今までのWebアプリ(サービス)に、

プッシュ通知やオフラインアクセスなどをできるようにした新しいWebアプリの概念です。

 

Webアプリでプッシュ通知やオフラインアクセスを使うにはどうするのか?

答え:Service Workerを使う!

 

Service Worker(SW)とは?

Webページとは別にバックグラウンドで実行されるJavascript環境(API)のことです。

プロキシ的な感覚が近い?と思います。

なので、技術的にはPWAを勉強するというより、

SWを勉強すると表現した方がいいかもしれません。

詳細はこちらを参照。 

 

Service Workerを使うには?

具体的な使い方はこちらを参照

なお、Service Workerを使うには、SSL化(HTTPS)が必須になります。

 

SUUMOのPWA導入事例

これは実際にカンファレンスで聞いてきた話です。

 

SSL化の課題

SUUMOでPWAを導入する際に1番ネックになったのがSSL化で、

かれこれ1年以上かかっているそう(大きな理由はlocalStorage)。。

しかも紙媒体のURL表記が「http」のものもあるので、

「HSTS」を導入する予定とのこと。

 

Add to Homescreen

ホーム画面にショートカットを追加させる施策です。

スーモに再来訪したら「ホーム画面に追加しませんか?」的なバナーを出して追加を促したそう。

ホーム画面から来た人はCVRが約1.2倍と言っていたので、導入効果はあるもよう。

 

Offline Cache

利用したことで表示速度が約4倍に。

 

プッシュ通知

ユーザーが新着案件(賃貸)情報を受け取る設定をしたら、

スマホにプッシュ通知できるような仕組みを検討中とのこと。

 

その他

ジオフェンシングもそのうちやりたいと話していた気が。

 

まとめ

スピーカーも話していましたが、ネイティブアプリは色々大変なんですよね。

リリースとアップデートに審査が必要だし、

GoogleAppleを挟む分、自由じゃないし時間がかかったり。

その点、PWAのようにWebにあるといつでも改修できるし、

各OSに依存しないのでネイティブアプリのデメリットを解消できます。

 

結構明るい技術だと思うのですが、

今のところブラウザのSafariMicrosoft Edgeに対応していないようです。

※対応状況はこちらで確認できます。

なので、iOS主流の日本ではすぐすぐ取り入れる技術ではないかもしれませんが、

今後のアプリのトレンドして抑えておく必要はありそうです。

パーフェクトJavaScript

パーフェクトJavaScript

 

プロダクトマネージャーになりたい人は「Inspired: 顧客の心を捉える製品の創り方」を読むといいかも

少し前からバズワードっぽくなっているプロダクトマネージャー。

結局どういう人なの?って思ったので、

Inspired: 顧客の心を捉える製品の創り方 を読んでみました。

 

※以下からPMと表記する箇所があります

 

プロダクトマネージャの役割(仕事)とは?

この書籍には「PMの役割とは?」みたいなものが散りばめられているのですが、

その中でもよりシンプルに表現されているのが以下。

 

プロダクトマネージャーの主な任務としては 2つある。

製品の市場性を評価すること(1)と、

開発すべき製品を定義すること(2)である。

 
(1)製品の市場性を評価すること

製品の仕様を決めることだけが仕事ではないのです。

そもそも作ろうとしているプロダクトが、

本当に価値のあるものなのか、

あるいはどうやって価値を高めていくのか

という検証をすることも仕事になります。

 

どうやって作るか(How)だけではなく、

何(what)を、なぜ(why)作るかのレイヤーまで手を出すイメージですかね。

 

また、製品の価値やユーザーの意向を測る指標として、

NPS(ネットプロモータースコア)というものがよく使われているようです。

 

(2)開発すべき製品を定義すること

プロダクトマネージャーの仕事は、

究極の製品を定義することではなく、

目的を達成するために必要最小限までそぎ落とされた製品を定義することである。

これ言うのは簡単なのですが、実際にはかなり難しいんですよね。

製品(機能)を削るというのは、偉い人や顧客の承認を得ないといけないので。

つまり「そぎ落とす理由をロジカルに説明できて」、

なおかつ「偉い人たちと臆せず戦えるキモを持ちあわせた人物」でないとPMは務まらないということですね。

 

プロダクトマネージャーはコードを書くのか?

書籍を読む限りほとんど書かないようです。

というのも、

エンジニアリング部門というのは、基本的に、

正しい製品を作ることではなく

製品を正しく作ることに専念することになっている。

と書いてあるように、 

実際にプレイヤーになると「製品を正しく作ること」に専念してしまい、

「何が正しい製品なのか」混乱すると思います。

 

ではコードを書けなくてもいいのか?

優秀なプロダクトマネージャーになるためには、

自分で新しい技術を発明したり、使いこなしたりする能力を身につける必要はないけれど、

その技術を理解し、活用の可能性を調べられるぐらいには使いこなさなければならない。

書けなくてもいいようですが、 フィジビリティを判断する能力は必要とのこと。

 

プロダクトマネージャになるには?

プロダクトマネージャーは、

エンジニアが質の高い製品を作るために必要だと思っていることを自由にやらせるようにしなければいけないし、

エンジニアは、

プロダクトマネージャーが使いやすくて、価値の高い製品を自由に思い描けるように配慮しなければいけない。

 

すばらしい製品の定義を思いついて、それをエンジニアリングチームに丸投げしてしまう、というのがある。

そのせいで、何をしたいかと何ができるのかをすり合わせるという非常に重要な作業に取りかかるのが遅れて、

いろいろな情報をしっかり検討する時間もないまま意思決定をしなければならない状況に陥ってから、慌ててすり合わせをする羽目になる。

 

やっぱり実際の現場でエンジニアとして経験を積んだ人の方が、上記のような気持ちが分かると思います。

気持ちが理解できるということは、エンジニアチームと上手くコミュニケーションが取れるということだと思うので、

PMになるにはエンジニアとして修行を積むというのが近道だと思います。

※SEじゃダメ

 

まとめ

PMは「製品(プロダクト)のCEO」とどこかで聞きましたが、

ほんとにそんなイメージだと思いました。

 

プロダクトマネージャという言葉が、

世間に認知される前(できる前)からこの役割はあったと思いますが、

なぜここ最近でいっきにフォーカスされるようになったんですかね。

いわゆるITが成熟してきて、単純なサービスの内容だけでは勝負できなくなって、

製品をより良いものにする人、ひいては製品に責任を持つ人を作ろうといった背景ですかね。

 

ちなみにクックパッドでは、PMのことをディレクターと読んでいるらしいです。

呼び名は様々ですが、いずれにしても、

ユーザーを幸せにするサービスを作るためには、

学んで検証をするPDCAを回し続ける人物が必要ですね。

Inspired: 顧客の心を捉える製品の創り方

Inspired: 顧客の心を捉える製品の創り方

 

Swiftでランダムな文字列を生成する方法

Xcodeのバージョン:7.1

Swiftのバージョン:2.1

 

方法

ランダムな数値を生成した後、

その数値の場所の文字列を取得すれば、

おのずとランダムな文字列が生成できます。

 

Swift 2以降は、

advancedBy(n)

を使って任意の場所の文字列を取得できます。

 

 

注意点

上述した通り、

letter[letter.startIndex.advancedBy(randNum)]

のように、

文字列の変数[]

で囲まないと正常に動作しませんでした。

具体的に言うと、advancedBy(n) の「n」に入った数値をそのまま出力してしまいました。

 

何か僕がミスってるのかもしれないですが、

同じような状況に陥った方は上記の方法を試してみてください。

 

詳解 Swift 改訂版

詳解 Swift 改訂版

 

Swiftでキャリア情報とかOS情報とかデバイス名とかIPアドレスとか取得する方法

Xcodeのバージョン:7.1

Swiftのバージョン:2.1

 

ユーザーが使用している端末のデータを取得したいときがあります。

キャリア名とかOSのバージョンとかデバイス名とか。。

ある程度の情報は、以下の方法で簡単に取得できます。

 

IPアドレスだけ特殊で、

Bridging Header(ブリッジングヘッダー)を使わなければ取得できないようです。

ブリッジングヘッダー作成の方法はこちらを参考にしました。

追加したブリッジングヘッダー(.hファイル)に

#include <ifaddrs.h> 

を追加後、

で取得できます。

 

ちなみに、フレームワークプロジェクト(Cocoa Touch framework)だと、

ブリッジングヘッダーは使えないそうです。。

 

詳解 Swift 改訂版

詳解 Swift 改訂版