先月で31歳となりました。
先月分はこちら -> じぶん Release Notes ver 0.30.11 - ざきの学習帳(旧 zackey推し )
- 学んだこと
- 本
- 読書中
- 完了
- やめてみたシリーズから、まずやめてみる
- 本
- ブログ
- PV数
- Challenge Every Month
- 2020/10の結果
- 輪読会についていく
- 2020/11の目標
- 輪読会についていく
- チャリの冬支度を済ませる
- viteseeを参考にVue3 x viteの素振りをする
- 2020/10の結果
- おわりと所感
先月で31歳となりました。
先月分はこちら -> じぶん Release Notes ver 0.30.11 - ざきの学習帳(旧 zackey推し )
とある要件でInstagram Graph APIを使う事になったのですが、
使用するにはFacebookログインを行なっている動画撮影と
アプリ申請が必要となることがわかりました。
Facebookログインするやり方を素振りしましたので、
参考にしたものや調査・実装したなかでの注目点を
本記事にまとめておきたいと思います。
vue-facebook-login-component
という
Facebookログイン用のVueコンポーネントが公開されています。
vue-facebook-login-component/packages/vue-facebook-login-component/src/Sdk.jsに
Facebook JavaScript SDKをラッパーした実装が記述されていました。
vue-facebook-login-component
の実装を参考に、
Facebookログインまでを実装し直してみたのが以下になります。
window.FB
の定義Facebook JavaScript SDKをscript
タグ等でダウンロード・実行すると、
window.FB
に様々なメソッド等が定義されます。
これらをコード補完させたい(かつ型定義の練習のため)、
公式ドキュメントの仕様を元に一部API・レスポンス等を
以下tsファイルへ定義しました。
/* ~省略~ */ interface Facebook { // https://developers.facebook.com/docs/javascript/reference/FB.init/v8.0 init(param: FacebookInitParameter): void; // https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus getLoginStatus(callback: (response: FacebookCallbackResponse) => void): void; // https://developers.facebook.com/docs/reference/javascript/FB.login/v8.0 login(callback: (response: FacebookCallbackResponse) => void): void; // https://developers.facebook.com/docs/reference/javascript/FB.logout/v8.0 logout(callback: (response: FacebookCallbackResponse) => void): void; } interface Window { FB: Facebook; }
@types/facebook-js-sdk
があるので、
自分で型定義したくない方はこちらをどうぞ。
以下tsファイルのload
メソッドに実装しました。
// ~省略~ private load(): void { if (document.getElementById(this.FACEBOOK_SCRIPT_ID)) { // facebookのsdkが読み込まれていたら終了 return; } // sdkを読み込むためのscriptタグを生成 const scriptElement = document.createElement("script"); scriptElement.id = this.FACEBOOK_SCRIPT_ID; scriptElement.src = this.srcUrl; scriptElement.onerror = error => { console.error(`${this.srcUrl} load Fail.`); new Error(error.toString()); }; // headに仕込む&読み込みさせる document.querySelector("head")?.appendChild(scriptElement); } // ~省略~
コメント文通りですが、
head
タグにscript
タグを追加することで
SDKをダウンロードさせています。
あとは
appId
でFB.init
-> 初期化FB.login
でログインするだけです。
yarn install && yarn serve
すれば実行できます。
同じようなことをやりたい方の参考になれば幸いです。
window.FB
実装時に参考にした
レガシーコードからの脱却 ―ソフトウェアの寿命を延ばし価値を高める9つのプラクティス
5章が印象的だったので、
メモとして思ったことを書き残しておきたいと思います。
5章は、タイトルに記載してある「9つのプラクティス」のうち、
1つめ「やり方より先に目的、理由、誰のためか伝える」が紹介されています。
受託案件ではクライアント、プロダクト開発ではユーザーから「こうしたい、こうしてほしい」という要件をもとに開発すると思います。
要件を出す側は「こうしたい、こうしてほしい」のような具体的の方法ではなく、その目的を話すべき。具体的な方法を伝えると、それを正として開発しがちとなり、目的に沿ったものが出来上がらないことが多い。また、方法をそのまま実装すると、システムに最適な設計プロセスが損なわれ、レガシーになるのを止められない。
と、本書から解釈しました。
実際、ユーザー側に「こうしたい、こうしてほしいを伝えないで、何をしたいか目的を伝えて」と言える機会は少ないと思っています。(言える機会があるのは、社内システム開発のようなパターンと考えています)
本書で記載されている通り、目的を知らないまま開発すると、
目的や効果がでないものが出来上がる可能性を拭えません。
そのため、以下のような手法等を使い、
目的を割り出す必要があると感じています。
本当は、目的を直で聞けるのが一番だと思いますが、
話す方も「こうあるべき」という先入観にとらわれている可能性があるため、
整理するためにこういった方法や壁打ちして整理 -> 目的を明確にした方が良い。
と、思っています。
目的をもとにユーザーストーリーを作り、POが受け入れ基準(何をするのか、いつ動くのか)を定義する。そうすると、開発者はストーリーと受け入れ基準を満たすため、最適な設計・開発に集中できる。
と、解釈しました。
内容は納得しました。
記載されている通り、POはいた方が良いというのは当然なのですが、
どの部門・立ち位置の人がなるべきなのか...というのが疑問です。
もし、本書の通り代替パス・エッジケース等を含めた受け入れ基準を定義するには、
プログラミング的な観点がある開発側の人が最適かなと考えています。
(ただ、ユーザーの業務知識・システムを十分に知り尽くしているということが前提)
ビジネス側の人がPOになる際は、
開発側から受け入れ基準を明確にするためのヒヤリングを行い、
共通認識を得るプロセスが必要と感じました。
以上です。
本書の内容をそのまま適用するのは難しいですが、
目的と受け入れ基準を元に開発するということが重要であると認識しました。
普段、「目的は?」「受け入れ基準は?」を言語化せず、
自然とこなしているケースが多いため、再認識して開発に望もうと思います。
Effective PythonでsubTest
の存在を知ったため、
メモとして書き残しておこうと思います。
Effective Python 第2版 ―Pythonプログラムを改良する90項目
Pythonに組み込まれているunittest
において、
Python3.4からsubTest
という関数が実装されました。
subTest
内で実行した検証(assert_hogehoge
)は、失敗しても終了しないため、
1つのテストケース内で複数件のデータをまとめて検証するのに有効...と思いました。
python-remote-container/src/effective/09/76_test.pyのコードから抜粋します。
class Logic: @classmethod def to_str(cls, data): if isinstance(data, str): return data elif isinstance(data, bytes): return data.decode("utf-8") else: raise TypeError(f"Must supply str or bytes, found: {data!r}") from unittest import TestCase, main class DataDrivenTestCase(TestCase): def test_good(self): good_cases = [ (b"my bytes", "my bytes"), ("no error", b"no error"), # 失敗ケース ("aaa", "bbb"), # 失敗ケース ("other str", "other str"), ] for value, expected in good_cases: with self.subTest(value): self.assertEqual(expected, Logic.to_str(value)) if __name__ == "__main__": main()
# 実行結果 pwd /code python src/effective/09/76_test.py DataDrivenTestCase ====================================================================== FAIL: test_good (__main__.DataDrivenTestCase) [no error] ---------------------------------------------------------------------- Traceback (most recent call last): File "/code/src/effective/09/76_test.py", line 55, in test_good self.assertEqual(expected, Logic.to_str(value)) AssertionError: b'no error' != 'no error' ====================================================================== FAIL: test_good (__main__.DataDrivenTestCase) [aaa] ---------------------------------------------------------------------- Traceback (most recent call last): File "/code/src/effective/09/76_test.py", line 55, in test_good self.assertEqual(expected, Logic.to_str(value)) AssertionError: 'bbb' != 'aaa' - bbb + aaa ---------------------------------------------------------------------- Ran 1 test in 0.003s FAILED (failures=2)
通常では、
AssertionError: b'no error' != 'no error'
でテストが中断され、
すべてのテストケースを確認することができません。
subTest
を使うことで、
("no error", b"no error")
以降(("aaa", "bbb")
)のテストケースも実行可能です。
以上です。
Python3.4から使用可能なので、注意してください。
先月分はこちら -> じぶん Release Notes ver 0.30.10 - ざきの学習帳(旧 zackey推し )