途中からWebサービスを多言語対応した苦労話
はじめに
世の中の多言語対応してるWebサービスは
- パターン1:ここ最近のインバウンドのニーズを踏まえて最近立ち上げた
- なのでサービスローンチして1,2年程度
- パターン2:最初に日本語版を始めていた。サービス継続してく中で、多言語対応の親和性がありそうで横展開を狙い、結果、対応言語が増えた
という形なのかなと推測してます。
自分が関わっているお店の予約代行をするようなサービスで、上記の自分の分類でいうと、パターン2になります。
どういう形で対応したのか大まかに書くと
- 日本語版を開始
- その後、英語版を追加
- 英語版をベースに外部の機械翻訳のサービス(ググるととすぐに出てくる割と著名なやつ)を使って中国語版対応
- 機械翻訳の文章は違和感あり翻訳データーを環理できる管理機能を作った上で、多言語対応(日本語、英語、中国語の3言語)
という形でちょっとづつ多言語対応してきてます。
自分は、上記の3の頃から開発に関わってますが、当初から多言語対応をするという前提ではないため
- Webアプリケーション含めてサービス全体の設計として当初のターゲットユーザーの言語設定がベースにになってる
- ある意味後付で多言語対応なので、システム含めてトータルで色々考えないといけない
という形で、色々苦労しているので、そこでの学びとして以下の2つについて簡単にまとめようと思います。
- 多言語対応に伴い電話番号の仕様再検討
- 全ての機能について多言語対応を最初から全部行うとは限らない
多言語対応に伴い電話番号の仕様再検討
サービス利用する申請フォームでユーザーさんに電話番号を入力いただくようになってます。
※ 予約代行というようなサービスの特性上、こちらからユーザーさんに連絡を取りたい状況が発生するために、入力いただいてます。
当初は日本人だけだったので、仕様はシンプルだった
日本人を当初ターゲットにしていた時は、そんなに深く考えることなく
- 携帯電話
- 固定電話
のいづれかを入力してもらうだけでOKでした。
多言語対応すると考慮ポイントが増える
ここからが今回のテーマに関連する話題なのですが、多言語対応によって、電話番号についての仕様が途端に難しくなりました。
具体的には
- 日本人以外のユーザーさんの場合、申込時に入力いただく必要があるのは 日本に滞在中に連絡がとれる連絡先 である必要があります。
- 相手の電話番号がわかっても その人がどこの国の人 か判別できないと、こちらから連絡取れないため、国番号を入力いただく
というあたりです。
国番号が必要になる理由
Softbankのサイトから関連する情報をちょっと引用します
日本から海外事業者の携帯電話・一般電話へ電話をかけた場合は、「国際電話」の扱いになります。 Softbankのサポートページより
自国で所有してる携帯電話を滞在先の日本でも利用するケースがほとんどだと思うのですが、そういう人に対して、こちらから連絡を取る時には
国番号+携帯電話の番号
で発信しないと、電話がつながらないため、画面上では、セレクトボックスで出身国を選択していただき、実際の値は、出身国に紐づく国番号が登録されるようにすることでこの問題を解決しました。
全ての機能について多言語対応を最初から全部行うとは限らない
冒頭のパターン2のケースの場合についていうと、最初から全部を多言語対応するのは現実的に難しいと思います。
理由としては開発に関わるエンジニアのリソースが足りないのもあるのですが、全ての取引先が多言語対応の業務ができる体制になってない or その体制作るのに凄く時間かかるということも考慮しないといけないためそのあたりが大きな要因になります。
最初は限定して、その後に増やすというアプローチになるかと思い実際、自分のケースでも
- Webサービス側の翻訳が全部対応しきれない
- お店の予約代行という特性上、お店側の事情で対応出来ない
というようなことがあり、ちょっとすつ多言語対応していくという形になりました。
ちょっとづつ多言語対応は意外とやっかい
システム開発の観点で
- toC向け
- 管理機能
- 多言語対応のための管理機能はどこまで作り込まれてないといけないのか?
- 英語の情報をベースに中国語に翻訳していく業務フローだったので、中国語版で、部分的に英語の情報が混じっていても許容できる仕様にしてよいか
- 多言語対応のための管理機能はどこまで作り込まれてないといけないのか?
というような点について、どういう仕様なら現実的なのかを考慮しないといけませんでした。
実際の業務を考慮しつつ、プロトタイプとなる機能を作る→試してもらう→問題点ありそうなら改修→再度チェック・・・という繰り返しをしながら対応していきました。
事前には想像出来なかった追加仕様も出た
3言語の対応をできるように開発を進めていたのですが、取引先は3言語全て使うものだと思いこんでいたのですが、取引先によっては
「折角なのでこれを機会に、xx の言語だけにしたい」 「出来れば、xxと○○の2言語だけにしたい」
など地味に細かい要望が出てきました。
今となってはそのあたりの背景は理解できるのですが、作ってる当初は当然ながらそんなことは想像出来ず、当初作っていた処理を見直すことになりました。
その追加仕様に対応できる構造にしていおいたことで、柔軟な運用ができるようになったので、結果的に良かったのかなぁと思います。
どうしても非効率なことが出るのは仕方ない
上記アプローチだと翻訳する人はシステム開発が終わるまで何も出来なくなります。
そのため並行して翻訳対象データーをGoogleスプレッドシートに登録&翻訳データー作る作業をしていたのですが
- 翻訳データは、実際のDBの構造を反映した形になってなかった
- そのため、機能開発終わったら、1つづつデーターをコピペする形になった
という感じで、今思うともう少し効率的なやり方があったのかなと思います。
最後に
企画段階では他の要望(例:言語ごとにページのレイアウトを変更したい等)があったのですが、社内・社外の各種事情を考慮しながら、実現可能なものから多言語対応着手するのを考えるのは、今振り返っても難しい問題だなと改めて思います。
1on1コーチング体験をしてきました。
思考と現場の間でのid:tsuyokさんのファンで、いつか機会があれば、中の人にお会いしたいなぁーと思っていました。
少し前に「1on1コーチング体験」参加者募集という記事を書かれていたので、申込んで先月にお会いしたので、どんなことをしてきたのか振り返りつつまとめようと思います。
- 何故1on1コーチング体験を申込んだのか?
- 当日の流れ
- 実は凄くモヤモヤするきっかけがあった
- 1on1した時の違い
- 別の会社で日本人の方に1on1してもらった時のことも振り返ってみた
- 1on1コーチング体験を通じて得られた「 1on1 って何なのか?」という自分なりの気付き
- この気付きを自分なりにどう活かすか?
何故1on1コーチング体験を申込んだのか?
私自身は、1on1 を受ける立場なのですが「そもそも 1on1 って何なのか?」ということについて凄くモヤモヤしたものを感じていました。
専門的に対応されてる方がどのように考えてるのかヒントをもらえればと思い申し込んで見ました。
当日の流れ
- アイスブレイク的に雑談
- 雑談後に、今回申し込んだきっかけなどから入り、徐々に革新の話題について、問いかけをもらう
- 自分が話す→問いかけしてもらう→そこについて考えつつ話す・・・繰り返し
- クロージング
という感じで約1時間ほどでしたがかなり濃密な時間を過ごせました。
余談ですが前職のキャリアカウンセラー時代にこういう1対1の対応を毎日のようにしていたのですが、自分の経験上1時間が限界&体内時計でなんとなく時間がわかるので今回久しぶりにすごく集中したなぁと終わってから気づきました。
話を戻すと徐々に革新の話題について問いかけをもらう中で実は凄くモヤモヤするきっかけがあったことに気付かされたのでその辺りからちょっとづつ振り返ろうと思います
実は凄くモヤモヤするきっかけがあった
- Aさん:つい最近(2,3ヶ月前に)経験した1on1
- 責任者が外国の方(フランス系)で英語は話せるけど日本語は全く出来ない
- Bさん:凄く昔(10年以上前の派遣先の外資系の企業)に経験した1on1
- 当時のマネージャーがオーストラリア出身の方で日本語は全くできない。(ネイティブの方が半分冗談で、その人の英語がたまにわからないとイジっていた)
自分自身は、技術的な話だけに限定すれば、ある程度口頭で説明できる程度の英語スキルであるのに対して、対応してもらった人の属性が
- ともに外国籍の人で文化/習慣など自分とは全く異なる
- 日本語が話せない
という感じで基本的には同じような状況だったにもかかわらず、前者の人との1on1は、淡々と話が進み特に何も印象に残ることがありませんでした。
一方で、後者の方は、未だに彼の1on1はとても良かったという印象が強く残ってます。
後者については凄く昔のことなので、美化されてるというのは一定の割合であるとは思います。
ただそういうのを考慮しても1on1を受ける側にとって印象に残るケース/そうでないケースの要因としてどのようなものがあるのかなと話しながら気付かされました。
1on1した時の違い
ここから、更にいくつか問いかけしてもらったのですが振り返ってみると
- Aさん
- 淡々と話しが進んでいった
- 何となく面接(悪い言い方だと尋問っぽい)形で話が進む
- Bさん
- こちらの拙い英語でもしっかり聞こうとする姿勢が強く感じられる
- 困ってることがあれば、遠慮なく言ってくれれば助けてくれるというスタンスを常に出してくれていた
- 関係する人が多そうで、かつ、実際に会ったことがない人も含まれそうな社内的に込み入った面倒な出来事があったけどBさんに相談したら、その場で関係する人に電話して一発で解決してくれた
という感じで、対応する時の姿勢とか心構えが根本的に違うことに気付かされました。
別の会社で日本人の方に1on1してもらった時のことも振り返ってみた
別の会社でも日本人の方に1on1 をしてもらった経験が何度かあるのですが、あらかじめ決めておいた質問事項に沿って対応してくという雰囲気だったことも有り、その時も 1on1が終わってから特に何も自分で感じることはありませんでした。
1on1コーチング体験を通じて得られた「 1on1 って何なのか?」という自分なりの気付き
- 対応してもらう人が話す内容自体は大きく変わらない
- 前述のBさんの場合も正直どんなことを当時話していたのかは全く覚えてない
- ただ1on1をしてる時の姿勢とか心構え含めた 空気感 みたいなものが大きく異なる
- これが決定的に異なっていそう。
- 1on1終わって、印象に残ってるのは、自分なりの気付きだったり次に向かって頑張ろうというというモチベートされた状態で終わっていた気がする
というようなものが気がします。
この気付きを自分なりにどう活かすか?
フリーランスという自分の立場上、1on1を受けることはあっても、自分で1on1をする機会は基本的には作れません。
ただ、最近は、就活相談の対応ができるMatcherというサービスでキャリアカウンセリングのようなことを不定期に行ってるのでそういう対応をする時に今回の学びとか気づきを活用していこうと改めて思いました。
テストがほとんどなかった状況からチーム全体でテスト書く習慣が身につくまでの課程を振り返る
はじめに
先日小〜中規模のWebサービスを数年運用して学んだことをまとめていきます。と書いたので、まずはテストに関する話題を今回まとめようと思います。
この記事の全体像
最近はチーム全体でテスト書く習慣が完全に身についてるのですが、そこに至るまでの過程を振り返ると色々あったことに気づいたので以下まとめていきます。
なお、過去3年を振り返ってみて、以下の3つに分類できそうなので、この区分で以下整理して書いていきます。
- 初期
- 2016年5月〜
- 中期
- 2017年6月〜
- 最近
- 2018年10月頃から
初期
お仕事関わった当初、そのサービスのテストの充実度についていうと
- ちょっとだけrequestスペック書かれていた。
- 基本的にテストを書くという習慣がない
- CI環境も当然ながら無し
という感じでした。
また、この頃の初期の自分のテストに関するスキルについて言うと
- 別の案件でRails/RSpecという組み合わせで、request/controller/model specは一通り書いていた
- ただ、別の人が書いたものを見よう見まねで書いてるレベルだったので、ふんわりとした理解で書いていた。
という感じでした。
初期の問題踏まえて取り組んだこと
- 自分自身のテストに関するスキルが正直大したことがない状況だった
- ただその状態で、今後新しい機能の開発をしたり、不具合対応をするのが不安だった
- (きっかけは覚えてないのですが)この時期からPRのレビューをしっかりする習慣が出てきたことで、コードの改善について、当時の開発メンバー全員が割と意識を持つようになった
というようなことが重なり、現場の責任者の方に提案してちょっとづつ改善してきました。
具体的には
- GitHubにテスト改善的なラベルを作る
- そこで、当面の目的・目標を書く
- 既存仕様がよくわからない所が多いので、コードの現在の振る舞いを確認する 仕様化テスト を頑張って書く
ということをしていました。
初期の限界
仕様化テストでちょっとだけ安心を得たけど、それほど大きな改善につながってる感じがしてませんでした。
というのも
- その処理のControllerに色々な処理が入り混じってる
- テストを実行しづらい構造になってる
という状況だったので、この複雑な処理の全体像がざっくり見えてきても、根本的な所は何も解決しないので、その処理の見直しを考えるというIssueを作って、さらなる改善をしようと考えました。
ところが、そのタイミングで売上を伸ばすための企画よりの仕事をちょっと頼まれてそこからしばらくの間、改善系の作業に着手できなくなった 😥 ことで、そのままこの初期が終わったという感じです。
中期
企画よりの仕事が一区切りついた2017年の6月頃に新しい機能開発の話がでました。
この頃のGitHubのIssueを見てると
- 新規開発する処理はRailsEngineの仕組みを使って開発する前提だったので可能な限りcontroller/model specは書く
- なぜRailsEngineだったかは別に書きます
- CircleCI+NightwatchでUI自動化テストするプロトタイプ作る
- エンジニア経験が浅い人(しかも外国の方)がチームに加わったので、既存実装理解をしてもらいつつ、これまでカバーしてない処理のテストを書き溜める
という感じで作業を進めてました。
なぜCircleCI+NightwatchのUI自動化テスト?
初期(2016年5月〜)には、CIとかUI自動化テストという発想が全く持てない位に、各種リソース(人&時間)余裕がなかった気がします。
ただ中期の時は時間的な余裕が多少あったことに加え
- 個人的には、この仕事に関わる前に一時期クローラーを作る仕事をたくさんしていたので、Nightwatchみたいなものを使うのは得意だった
- 新しい機能開発で毎回手動テストは辛いのは明白だった
- UIを刷新する上に PC/スマホ x ユーザー属性 x 申込み方法 という組み合わで考えると20パターン以上あった。
ということを踏まえて、CircleCI+NightwatchのUI自動化テストを整備しました。
※ 完全な余談ですが、クローラーを作ることに比べると、自分たちでマークアップしたHTMLは当然ながらスクレイピングしやすい構造だったので作業しやすかった 👍
中期の限界
- 単純にテストコードの数は増えていったのですが、ビジネス的に重要な処理について、テストコードの充実度はまだまだ改善の余地がある
- CircleCI+NightwatchのUI自動化テストとかが出来たのは嬉しい反面、だんだん CircleCIの実行時間が長くなっていった
というような課題が出てきました。
最近
2018年10月頃から一定期間だったのですが、とても頼りになるエンジニアが2名チームに加わりました。
最近の成果その1
その人達が本来やるべき開発の合間に
- CircleCIの処理の見直し等
- FactoryGirl (Bot)のcreate/ build / build_stubbed を正しく使い分ける
- その他細々としたもの
という改善をやってくれたおかげで、現在は
- RSpecの方は600弱のテストケース(CircleCIの並列実行の仕組みを利用)
- UI自動化テストのほうは350個程度のテストケース
がCircleCIでそこまでストレスを感じない時間で実行されるようになりました 💪
最近の成果その2
こちらは、テストだけにとどまらない話なのですがapp配下のディレクトリ単位でREADME.mdを作って、それぞれの処理の大まかな設計方針を言語化しておくようにしました。
※ 外国の方がチームにちょっとづつ増えていく傾向にあるので、出来る限り英語化もしてる
設計方針を書いてる処理についてはすでにいくつかのパターンでテストも書かれてるため、
- Ruby/Railsにそこまで精通してない人に対して
- ある程度お手本となる実装サンプルがある
- 経験豊富な人
- 過去の経緯を説明しつつ、現状の設計方針でより良い方法があればそれを前提に設計考えなおして、実装&テストも改善しやすい
という効果が得られてます。
最後に
テストがほとんどなかった3年前の状況から今に至るまでを振り返ってみました。
振り返りついでに、もしも今の自分が3年前にアドバイスするとしたらおそらく以下のようなことを話すかなと思うので最後に触れておこうと思います。
- ほとんどテストコードが無い状況でCapybara使ってrequestスペック書くのは割と良かった。
- 当時、一番ヤバいなぁと思っていた所から着手していた。
- t-wadaさんの組織にテストを書く文化を根付かせる戦略と戦術(2019夏版)でちょうどそんなことが書いてある
- 当時は選択肢としてNightwatchで良かったけど、その後の情報はキャッチアップしたほうが良い
- ある程度、テストを書く&PRのレビューの習慣が身についてきたら、レビュー目的は言語化しておくのがベター
小〜中規模のWebサービスを数年運用して学んだことをまとめていきます。
ブログや勉強会などで大規模なWebサービス運用に関する話は比較的入手しやすい一方で、小〜中規模のWebサービスついての情報はあまりまとまってないなぁと何となく感じてました。
フリーランスになってから、掛け持ちで色々なプロジェクトに関わってきたのですが、3年以上に渡ってWebサービスの開発&運用を通じて、色々悩んだり学んだことが多くあります。
世の中に自分と同じような境遇の人が少なからずいるのかなと思い、そういう人に少しでも役に立てればと思って、これから数回に分けて学んだことをまとめていきます。
前提として
自分が関わってきたWebサービスの規模や開発体制とか簡単にまとめておきます。
- サービスの規模:小〜中規模位
- こういうやつの規模の定義がイマイチよくわからない
- サービスの内容
- BtoBtoCな感じ
- 予約とか決済とかが絡む
- 最初の1年位は日本人だけがターゲット。途中から多言語対応
- 技術構成:Ruby/Rails。
- rake statsすると以下のような感じ。
- Model:Classesが150ちょっと
- Controller:Classesが160ちょっと
- app配下に、Form/Query/Policyのようなクラスも作ってる
- 自分は詳細知らないけど、サービス当初はRails3系だったみたい。
- rake statsすると以下のような感じ。
- チーム規模:
- 最小:エンジニア3名+ディレクター1名
- 最大:エンジニア8名程度(うち1名はとても頼りになるプロダクトオーナーがいる)
これから書いていこうと思ってるテーマ
大きく分けると
という形に整理できそうです。
Webサービスの運用に関するテーマに関連することは、知識転用を上手く行えると思ってるので、なるべくこちらが手厚くなるように出来る限り情報を整理してまとめていく予定です。
※ ちなみに、1年ほど前から並行して行ってるお仕事がLaravel/PHPと全く異なる技術スタックなのですが、それまでに学んできたWebサービスの運用に関する色々なことがとても役に立ってます。
Railsに関連がありそうなテーマ
- テストがほとんどなかった状況で、チーム全体でテスト書く習慣が身につくまでの課程
- ドキュメンテーションどうしてきたか?
- 社内のドキュメント管理のツール見たら3年で159個書いた。
- これは今回のプロジェクトに限定しないけど、前任者がいたけど情報が更新されてない/うまく分類されなかったり、そもそも全く手付かずの状況で、何をどんな順番でまとめてきたのか
- 過去一度もbundle updateしてないプロジェクトでどこから手を付けるべきか
- RailsEngine採用したけどどうだったか?
- 以下2点考慮して採用
- 既存の処理を残しつつ新しい仕組みを取り入れたい要望(=途中から多言語対応)に応えるために採用
- 既存のView/JavaScript/CSSのメンテナンスが大変だったのでキレイにしたかった
- 以下2点考慮して採用
Webサービスの運用に関するテーマ
- 決済処理でこれをやっておかないと苦労すること
- とにかく大変なメール送信まわり
- 想定チーム規模だとSendGridのようなSaaSを使うと思うけど、その中で自分たちで考えないといけないこと
- DBの寿命はアプリより長いを実感したあれこれ
- DBのMigrationのコードレビューで意識するべきこと
- カジュアルに index作成すると、痛い目に合う、実際のSQLを想定して、実行計画とかを一応チェックするのが無難、などなど)
- 多言語対応固有の問題
- チート対策的なこと(qq.comを利用した会員登録してきた等)
- 途中から多言語対応を始めた場合の苦労とか
多言語対応色々書きたいけど、正直、こういうのをやってる人・チームって多くないので、あまり需要なさそうだからちょっと悩むなぁ・・
今年抑えたい技術領域の自己評価&どういう状態になりたいかまとめてみた
フリーランスで、Ruby/Rails&JavaScript+AWSの各種サービスみたいな構成でWebアプリケーション開発のしてますが
- 現在使ってるけど何となくふわっとした理解のもの
- 仕事をしてる中で「あー、こういう場面だときっとxxxの技術(サービス)使うことでもう少し良い構造になりそう」
みたいなことが最近増えてきてるなぁと感じてます。
特に、前者のふわっとした理解のものが最近すごく気になってててるので、そこを解消するために
- 2019年に抑えておきたい技術領域を書き出す
- 書き出した技術について自己評価&どういう状態になりたいか?
という感じで以下にまとめていこうと思います
2019年に抑えておきたい技術領域
Ruby/Rails&JavaScript+AWSの各種サービスみたいな構成でお仕事をして来てるので、今後抑えておきたい技術領域を個別にまとめていきます
フロントエンドのWebアプリケーション開発
最近半年位は
- TypeScript&Angular6/7
- Vue/Vuex
- Nuxt&TypeScriptを少し
という感じだったので、それを踏まえて優先順位が高い順に
- TypeScript
- Vuex
を抑えます。
バックエンド寄りのWebアプリケーション開発
というのを踏まえるとさらにRailsを掘り下げるのがオーソドックスな考えかと思います。
それなりの規模を経験出来たことで
- これから直面しそうな問題
- その問題解決にあたって、自分が出来る・すぐには出来ない領域がある程度見えてる
という感じで、それに加えて Nuxt.js (TypeScript) on Netlifyの良さを広めたいを読んでて、Nuxt.jsとNetlifyが気になっており、SSR なものを1つ抑えておきたいなぁとぼんやりと考えていた のでNuxt.jsとNetlifyにします。
次点というわけではないのですが、このスライド見てたら、AWS Amplify も気になってるので一応書き出しておきます。
ちなみに、バックエンド寄りというくくりで考えて、ここ数年色々悩まされてきた問題解決の手段として、データベースのリファクタリングを抑えたいんですよね ただ、そこは実際運用してるサービスを通じてでないと中々知見が得られない領域なので一旦保留😅
AWS 関連
基本AWSサービス(EC2/S3/RDS/VPC/ELB など)の構成でお仕事をしてますが
- 開発環境の一部
- CirceCI 1.0 →2.0 への移行など
を通じて徐々にDocker化進んできた自分のお仕事環境を踏まえると
あたりを抑えておきたいと思ってます。
なぜTerraformとかLambda with Rubyなのか?
自分がこれまでお手伝いしてきた位の規模だとAWSの構成についてしっかりと情報がまとまってなかったりするので
- せっかくなのでコード化しておく
- 既存構成をベースに、何か改善したくなった場合の検証などの作業やりやすさ
なんかを考えて、Terraform を抑えておきたいかなと思ってます。
ちょっと前にTerraform使って、ALB&VPC(public/privateなサブネットに分割)みたいなものを作れるようにしていたベースがあるのでそこをもう少し掘り下げたいなぁと思ってます
書き出した技術について自己評価&どういう状態になりたいか?
項目 | 自己評価 | どういう状態になりたいか? |
---|---|---|
TypeScript | そもそも静的型付けの言語経験がないので、型についての理解が甘い | 型定義ファイル( d.ts )とかが読み書きできる |
Vuex | mapGettersとmapActionsの理解が甘い | 最近のお仕事経験も踏まえるとドメインの複雑さをstoreにうまいこと集約できるような設計ができる |
Nuxt.js | ちょっと触った程度なので自信がない | アプリが書けるのはもちろん、本番環境での運用を踏まえてトータルで |
Netlify | そもそも触ってない状態 | ひとまず説明ができて、サンプルアプリならサクッと動かせる |
AWS Amplify | そもそも触ってない状態 | ひとまず説明ができて、サンプルアプリならサクッと動かせる |
Amazon ECS | そもそも触ってない状態 | EC2ベースのホストからの移行みたいなシナリオでどういう手順でECSに持っていけるか自分の考えを持てる |
Terraform | ALB/EC2/VPCとかは作れる | 既存のAWS構成をTerraform化するようなシナリオの時にどのような手順で作業できるか自分の考えを持てる |
API Gateway& AWS Lambda(Ruby) | ちょっと触った程度 | EC2/Railsみたいな構成でcron使ったバッチ処理を AWS Lambda(Ruby)で置き換える時の勘所がつかめてる |
まとめ
自分が抑えておきたい技術領域を書き出してみたら、
- フロントエンドのWebアプリケーション開発
- TypeScript
- Vuex
- バックエンド寄り
- Nuxt.js
- Netlify
- AWS Amplify
- AWS 関連
- Amazon ECS
- Terraform
- API Gateway& AWS Lambda(Ruby)
という感じでかなりのボリュームになって正直これを全部やるのはツラいかな😫
ただ、可視化というか言語化したことで、課題が見えて来たのはすごく良かったので、書き出して正解でした ✌
AngularでRxJSが使われる理由がわからず色々調べたら腹落ちした
はじめに
ここ半年ほど、とあるWebサービスの管理機能をAngular6/7系で書いてます。
AngularでサーバーサイドのWebAPIと連携する処理を書く時に以下のようなロジックになるかと思います。
import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; export class SomeService { find(id: number): Observable<any> { const url = `/xxxxx/${id}`; return this.http .get<any>(url) .pipe(map(response => response.data.product)); }
上記のSomeServiceクラスの中で行われてる処理は以下のようなことになるのですが、個人的に当初疑問に思ったことがあったので以下で詳しくまとめていきます
- findメソッドの戻り値は Observable objectを返す
- Observable objectに対する操作は色々ある
- 上記のコードの場合にはpipe()メソッドでmap()オペレータを適用している。
- 詳しいことは以下の引用文を参考
RxJS 6では、オペレータはpipe()メソッドの引数に渡さなければなりません。このメソッドそのものは、バージョン5.5で備わったものです(「Operator pipe syntax」)。けれどこのときは、Observableのメソッドとしてオペレータを呼び出すバージョン5の書き方もできました。それがpipe()メソッド一択になったということです。 RxJS 6: オペレータをつくってみる
そもそもRxJSとは何?
関数型プログラミングの文脈で出てきそうなmapなどの名前が出てきてるので、やってる処理は何となくイメージは付いていたのですが、そもそもRxJSって何だろうというベースがわかってませんでした。
そんな理解の中で
- serviceクラスの中で必ずと言って良いほど出てくるのでサーバーサイドとの通信処理など、非同期処理の結果を適切に処理するためにRxJSが利用されてるっぽいなぁ
- AngularJSの時代なら$http や$resourceなどを利用するコードだったけど、その時はRxJS相当のロジックはなかったけど何故こんなことをするんだろうか 🤔
- 単に非同期処理をスッキリ書くだけなら別のアプローチもありそう
という感じで、他の人が書いた実装を読んでいたのですが、ふと
「最後の非同期処理をスッキリ書くだけならPromise使った書き方でも良いのかな?」
と思ったのでそこを少し掘り下げてみました
非同期処理するだけなら、ES6のPromise使った処理でも良いのでは?
let getURL = (URL) => { return new Promise((resolve, reject) => { let req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = () => { if (req.status === 200) { let result = JSON.parse(req.responseText); resolve(result); } else { reject(new Error(req.statusText)); } }; req.send(); }); };
【ES6】Promiseクラスの基本的な使い方より上記コードは引用してますが、ざっくりとやってることを書くと
- Promiseをインスタンス化
- インスタンス化のときに成功時(resolve)、失敗時(reject)の2つの引数を渡す
- XMLHttpRequest通じて通信処理が実行されて、HTTPのステータスコードによって成功時、失敗時それぞれの処理を呼ばれる
という流れになるかと思います。
ES6/7の時代なので、こういうPromise使った処理でも良いのではと最初思ってました。
とあるQiitaの記事でObservableの位置づけがよくわかった
「Angular Promise Observable 」みたいなキーワードで適当にググってた中で、少し古いのですがAngular2のHttpモジュールを眺めてベストプラクティスを考えるのPromise v.s. Observableという記事に行き当たり、こちらの記事を読んでいて、何故Observableが登場してきたのか時代背景みたいなものを考えた時に、すごく腹落ちできました。
Promise ではなく、Observableを使うポイント
上記のQiitaの記事に書かれてるように、最近のWebアプリケーションで非同期処理が必要な場面はいくつかあると思います。
記事中では6つに大別してましたが、自分の最近の仕事では
- Ajax
- Promiseで対処できる
- ただし Promise使った場合にキャンセルできないためレスポンスを待っている間にページが切り替わっても中断は不可 という欠点がある
- DOM Event
- Animations
という3つがひとまず対象になるのでそこだけで考えたとしても、Promiseが対処できる箇所は少ない上に、Promiseの特徴として
- 連続した非同期処理の結果を扱えない
- 遅延実行できない
- 即実行され、resolveした直後にthenが実行される
という点があるためにAngularではRxJSを利用した処理になってる。
逆にRxJSを利用することで
- 上記のような非同期処理はすべて対処できる
- ストリームという概念を導入してるので、Ajax&DOM Eventなど異なる非同期処理を集約&連続して扱える
などのことが行えるため、色々な種類の非同期処理を同じように扱えるRxJSを使うのがベストという結論になるっていうので、点と点のような状態だった自分の理解がようやく1つにつながりました 😉
まとめ
単にAjaxな処理だけするならPromiseでも良いかもしれないけど、最近のWebアプリケーションではユーザーイベント(例:テキストボックスの入力内容や状態)を検知して、ある状況になったらサーバーサイドにリクエストを投げる・・・といった色々な種類の非同期処理が連携する必要が出てきます。
PromiseはそもそもAjaxな処理しかカバーしてない上に、連続した非同期処理の結果を扱えないことも考えるとAngular2でRxJSを利用する処理が採用されてそれが今に至ったんだなぁーというのがすごく納得できて腹落ちしました✌
アラフィフWebエンジニアの生存戦略について考える
あと数年で50歳という年齢が現実的になってるのでアラフィフWebエンジニアの生存戦略考えてみました。
noteの方にも書いたのですがこっちはちょっとだけ加筆してみました
本題に入る前に自分の経歴をざっくり
ざっくりといいつ、それなりに年齢重ねてるので、文字数多くなってすみません・・
20代:
一応就職活動したけど、何となくしっくり来ないので、2年ほどフリーターで、早朝にサーフィンしてから、仕事するみたいな生活をしていた。
フリーター時代にWindows/MS Access & VBAを独学で覚えたのをきっかけに、派遣社員として働くようになって、とある外資系企業で当時としてはかなり大規模なネットワーク環境の中で色々なことを経験させてもらったので
など色々学びました。
30代:
20代でアルバイト&派遣しか経験してない負い目があって、正社員を志すも挫折して、もとの派遣先に戻って色々経験させてもらう。
外資系企業で何故かプロジェクトマネージャーの役割をさせてもらえので、必然的に英語を嫌でも勉強しないといけない状況だったので、スキルアップになったし、そのままそこの正社員っていう道もあったけど、色々考えた末に、人材派遣会社に入社。 人生初の正社員になって、キャリアカウンセラーとして色々やった
40代前半:
キャリアカウンセラーとして、色々な人の人生を垣間見てきたことで、色々考えさせられることが増えてきて、1社に雇用されててその1社からの収入に全てを依存することに怖さを感じていたので8年ほど勤めた会社を退職してフリーランスになりました。(詳しいことは昔にブログに書いてるので興味ある方はこちらを)
退職後は
- 前職で趣味と多少実益を兼ねてバックエンドとiOS/Android向けアプリをつくったりしてずっとコードを書いていて、知り合いの会社でエンジニアがいなくいというので、そこでWebアプリケーション開発、運用、その他何でもという感じで仕事を開始
- それがフリーランス最初の仕事で、過去何人もの人が関わってきたRuby/Rails&AngularJSという構成で1人で色々見るのはそれなりに大変だった
- その後は、基本的に自分で営業したり知り合い経由でお仕事の相談を受けて、基本は2社かけもちする形でお仕事
という感じで気づいたら5年近くフリーランスでWeb系のエンジニア+αな仕事をしてます。
本題の生存戦略について考える
普通のWebエンジニアとして生きていくと思ってます。
普通っていう言葉の意味合いがどのようにでも解釈できてしまうと思いますがジャンルが違うけど
相手は普通の男がいい、というあなた。会話力・ルックス・身長・清潔感・ファッションセンス・学歴・年収がすべて普通の男なんて、たったの0.8%! 普通のダンナがなぜ見つからない?っていう本より
みたいな感じをイメージしてるのですが、流石にこの引用だけでは伝わらないんので、掘り下げてみます。
仕事をする時に期待されそうなことを3軸程度で自己評価してそれぞれが「普通」に出来ることをイメージ Web系のエンジニアとして仕事をしていく場合に複数名のチーム(私は2名〜8名位規模がほとんど)体制で仕事をするのが一般的かと思います。
付け加えると技術情報について調べるのに一定の英語スキルというのも問われてくるケースがあるかと思うのでそのため仕事をこなすスキルとして
- ベースのWeb関連の技術スキル
- チーム開発の中で目標達成に向けてのマネジメントスキル
- 読むスキルを中心とした英語
という3軸で表現できるかなと思ってます。
3軸を自己評価
Web系の技術:
Ruby/RaisベースのWebサービスでおそらく5年位運用してる会社のお手伝いをしてます。 そこはModel/Controllerとも100を超えてて、色々手を入れづらい状況だったのでコツコツとテスト書いたり、業務固有の概念をPORO(Pure Old Ruby Object)でFatModel/Controllerの状態をちょっとづつ解消していき、gem のアップデート(含むRails本体)なんかもこなせます
フロントエンドの方は管理画面系の処理を書くことがほとんどですが
- 4年位前に関わったとある案件で、かなり肥大化して&たまに謎の挙動するjQuery+αのやつをChromeDeveloperToolsを毎日眺めつつ既存実装読み解
- jQueryメインだったフロントエンドを徐々にVueを採用
- AngularJS(つまりは1系)の既存実装をちょっとづつAngular6/7&TypeScriptに書き換える みたいなことも対応
マネジメントスキル:
立場的に自分がチームの運営を主体的にすることはないのですが、基本的に複数案件をこなしてるので、セルフマネジメントの必須スキル「タスクばらし」そのポイントで触れられてるタスクばらしは常に行ってます。
「タスクばらし」とは、読んで字のごとく、仕事をタスクにバラすことである。仕事に取り掛かる前に、その仕事の要素を分解し、どのように進めるか道筋を立てることで、どれくらい時間がかかるか、リスクは何か、見通しを得ることができる。
基本的に2つ(一時期は3つ)仕事を掛け持ちしてるので
- それぞれの仕事の現状やらないといけない作業をバラす
- だいたい1時間単位になるようにする
- 開発のお仕事でだいたいSprint単位でやることが決まるので、その枠組みの中で、タスクばらしされた内容の中で、難しいそうなやつとか緊急度高そうなものを自分のピークタイムに実施する
- Sprint始まりにそういうのを集中させる
- 平日だいたい5時頃から仕事してるので、そういうのは朝一番に着手する
という感じで日頃自分のやることは処理してます。
あとは、長くお手伝いしてる所だと、なるべく情報・状況を自分だけに属人化しないように、ペアプロとかペアオペでこまめに情報共有してるので、そういう作業を差し込めるように他の人の進捗なんかも気にしながら作業は日々行ってるので、30代でプロジェクトマネージャーしてた経験が今になってだいぶ役に立ってますね
英語:
昨年からイギリスの人と一緒に仕事をするようになりました。その人は日本語は話せるけどエンジニア未経験だったので、GitHubのIssueとかPRレビューとかはなるべく英語で説明していました。 ※ちなみにここ最近3ヶ月間くらいは、毎朝zoomでその人と英語80%位の割合で話してます
3軸を可視化するときっとこんな感じ
それぞれの軸で、自分よりももっとデキる人を何人も知ってるのですが、3軸を満遍なく見た時には、そんなに悪くない所に自分はいるかなと思ってます
私は、フリーランスでお手伝いする立場なので、最終的な意思決定はする立場にはないけれど意思決定をしてもらう上での状況を整理して相手の知識や経験を踏まえて言語化・可視化して、みんながやりたがらない雑多なことを拾うのは、割と好きだったりします。
なので相手の人/会社にとって都合よく使ってもらえるような普通のWeb系エンジニアとして生きていくのが自分なりの戦略かなと思ってます