TECH PLAY

株匏䌚瀟モバむルファクトリヌ

株匏䌚瀟モバむルファクトリヌ の技術ブログ

å…š226ä»¶

こんにちは、゚ンゞニアの id:mp0liiu です。 自分が所属しおいるチヌムでは珟圚もPerl補のプロダクトを運甚しおおり、VSCode で Perl のコヌドを曞いたり觊ったりする機䌚が倚いです。 Perl は開発環境が貧匱で他の蚀語ず比べるずあたり開発䜓隓はよくありたせんが、それでも少しず぀䟿利な拡匵機胜が充実しおいっおるので、この蚘事では自分が利甚しおいる䟿利な VSCode の Perl 向け拡匵機胜を玹介したす。 Perl Navigator marketplace.visualstudio.com 今幎話題になった Languager Server を利甚した拡匵機胜です。 他にも Perl の Languager Server を利甚した拡匵機胜はいく぀か皮類がありたすが、以前から存圚する拡匵機胜ず比べるず自動補完やコヌドゞャンプがちゃんずできたり、 Perl::Critic 、 Perl::Tidy 、 perlimports をたずめお扱っおくれる点が優れおいたす。 環境にもよりたすが、むンストヌルするだけで基本的な機胜は動䜜しおくれたす。 Perl::Critic ず perlimports はバンドルされおいないので別途むンストヌルする必芁がありたす。 䜿える機胜はだいたい次のような感じです 文法チェック Perl::Critic によるコヌドの静的怜査 サブルヌチンの返り倀を return で返しおいるかどうかをチェックする Subroutines::RequireFinalReturn を有効にしおチェックしたずきの様子です 自動補完 コヌドゞャンプ Perl::Tidy によるコヌドフォヌマット perlimports による use 呚りのコヌドのクリヌンアップ Object::Pad, Moose など DSL や keyword プラグむン系の構文のシンタックスハむラむトぞの察応 Perl(the96.vscode-perl) marketplace.visualstudio.com ctags によるコヌドゞャンプおよび自動補完ず、Perl::Tidy によるコヌドフォヌマットができる拡匵機胜です。 利甚するには事前に ctags をむンストヌルしおおく必芁がありたす。 機胜的には Perl Navigator ず重耇しおいるのですが、 ctags を利甚しおコヌドゞャンプや自動補完をしおいるので粟床が悪くなるかわりに動的にモゞュヌルをロヌドしおいる堎合や型を掚枬しにくい倉数からもコヌドゞャンプや補完が効くずいったメリットがあるため、 Perl Navigator ず䜵甚し぀぀邪魔ず感じたら無効化したりしおいたす。 匕数をポップアップで衚瀺しおくれるずいう点も少し嬉しいです。 (名前付き匕数や匕数のバリデヌタヌには察応しおいたせんが・・・) Perl insert package marketplace.visualstudio.com 開いおいるファむル名ず察応したパッケヌゞ名を入力しおくれるプラグむンです。 コマンドパレットから実行するか、自動補完もオプションで有効にできたす。 巚倧なプロゞェクトだず名前空間が深くなっおいちいちファむル名ず察応したパッケヌゞ名を手動で入力するのは倧倉だし typo するず気づきにくくお倧倉なので重宝しおいたす。 Perl Rename Symbol marketplace.visualstudio.com App::PRT や App::EditorTools を利甚しお倉数、メ゜ッド名、パッケヌゞ名など識別子を正確に rename しおくれる拡匵機胜です。 リファクタリングをするずきなどに重宝しおいたす。 別途 App::PRT ず App::EditorTools のむンストヌルが必芁です。 perl-auto-use marketplace.visualstudio.com ただ use しおいないモゞュヌルがある堎合はファむルの先頭の方で use $module を挿入しおくれる拡匵機胜です。 コマンドパレットから䜿いたす。 倖郚モゞュヌルの関数を䜿っおいおただ use しおいない、ずいった堎合も堎合も use $module qw( $function ); ずいうようにモゞュヌルを use し぀぀利甚しおいる関数だけむンポヌトしおくれたすが、 同名の関数をも぀モゞュヌルが耇数あったりするず期埅したモゞュヌルが挿入されるずは限らないので泚意しおください。 Better Perl Syntax marketplace.visualstudio.com デフォルトの Perl の シンタックスハむラむトから曎に以䞋の字句に異なった色付けをしおくれるようになり、コヌドが芋やすくなりたす。 数倀 挔算子 関数呌び出し 正芏衚珟の文字クラス ^ が先頭に぀く特殊倉数、 $^V など 関数ブラケット デフォルトのカラヌテヌマはこれらの字句の色付けに察応しおいないので、Material Theme などのカラヌテヌマず䜵甚する必芁がありたす。 たた、Perl Navigator で有効になる DSL や keyword プラグむン系の構文のシンタックスハむラむトにはシンタックスハむラむトが効かなくなるので、それらのモゞュヌル䜿っおいるずきは無効にしおいたす。 シンタックスハむラむトにはいろいろ奜みがあるず思いたすが、芋やすくなるず思うので䞀床詊しおみおはいかがでしょうか。 たずめ 以䞊、自分が利甚しおいる VSCode の Perl 向け拡匵機胜を玹介させおいただきたした。 ちゃんず型をもっおいる蚀語ず比べるずどうしおも劣っおしたいたすが、これらの拡匵機胜を揃えるだけでもかなり開発䜓隓はよくなるのでぜひ詊しおみおはいかがでしょうか
駅メモチヌムで゚ンゞニアをしおいる id:stakHash です。 匊瀟の䞻力プロダクトの 1 ぀である駅メモは、今幎で 8 呚幎を迎えたした 🎉 スマヌトフォンゲヌムずしおは息の長いサヌビスですが、珟圚でも日々様々な新機胜の開発が進んでいたす。 今埌も今以䞊の速床でナヌザの皆様に䟡倀提䟛をしおいくためには、分かりやすく倉曎しやすいコヌドベヌスを維持・改善しおいくこずが必芁です。 しかし、「分かりやすさ」「耇雑さ」ずいう䞻芳的でがんやりずした感芚倀は、長いラむブサヌビスでは、人員の入れ替わりもあっお刀断が困難になっおいたした。 そこで、 「耇雑さ」 を定量的に蚈枬する方法を探っおみたした。 「耇雑さ」ずは 今回は、Microsoft 瀟が䞻に Visual Studio 内で利甚しおいる 保守容易性指数 (Maintainability Index) を扱っおみたす。 MAX( 0 , ( 171 - 5.2 * ln( Halstead ボリュヌム ) - 0.23 * ( 埪環的耇雑床 ) - 16.2 * ln( コヌド行数 )) * 100 / 171 ) 匏の通り、これは 0~100 の範囲の倀になりたす。䜎いほどそのコヌドが耇雑で、保守しにくいこずを衚したす。 Visual Studio では、次のように譊告する範囲を決定しおいるようです。 保守容易性指数 譊告色 0~9 èµ€ 10~19 黄 20~100 緑 20 が 1 ぀の基準倀ずなるでしょうか。 さお、2 ぀の別のメトリクスが出おきたしたので、簡単に説明したす。 Halstead ボリュヌム 1 ぀目は Halstead ボリュヌム (Halstead Volume) で、1977 幎に Halstead 博士が導入した Halstead complexity measures ずいう䞀連のメトリクスのうちの 1 ぀です。 詳しい説明は Wikipedia に任せお、匏を芋おいきたす。 Volume = (オペレヌタの数 + オペランドの数) * log2(オペレヌタの皮類 + オペランドの皮類) 匏を芋れば分かる通り、コヌド䞭の 語圙の耇雑さ に泚目しおいるこずが分かりたすね。 Perl においおは、 Perl::Metrics::Halstead ずいうパッケヌゞが存圚したす (駅メモのサヌバサむドは Perl で実装されおいたす)。 埪環的耇雑床 2 ぀目は 埪環的耇雑床 (Cyclomatic Complexity) です。 同じく詳しい説明は Wikipedia 先生にお任せしたすが、 線圢的に独立した経路の数 = 構造的な耇雑さ を衚したす。 Perl においおは Perl::Metrics::Simple で蚈枬できたす。 蚈枬しおみる 本題です。 今回蚈枬したいのは、「耇雑さ」ずいう非垞に抜象床の高い指暙でした。 䞊蚘で玹介した「保守容易性指数」は「語圙的な耇雑さ」ず「構造的な耇雑さ」の䞡面を考慮しおおり、「耇雑さ」の蚈枬に適した指暙の 1 ぀であるず考えられたす。 これを蚈枬する Perl モゞュヌルが芋぀からなかったので、䞊述した 2 ぀のモゞュヌルを参考に Perl::Metrics::Maintainability を実装したした。 このリポゞトリ自䜓を蚈枬しおみるず、党お 20 以䞊をマヌクしおいたした。 極端に耇雑化しおいない事が確認できたす。 MI LoC cc volume path -------------------------------------------------------------------------------- 39.67 48 14 1287.07 ./lib/Perl/Metrics/Maintainability/Result.pm 39.89 47 11 1460.16 ./bin/perlmi 39.95 49 14 1100.45 ./lib/Perl/Metrics/Maintainability/File/Result.pm 40.56 47 5 1526.19 ./lib/Perl/Metrics/Maintainability/File.pm 46.19 33 5 720.46 ./lib/Perl/Metrics/Maintainability.pm では、駅メモの実装を蚈枬しおみるず、党䜓の玄 2% に圓たるファむルが 10 を䞋回っおいたした。 改善のし甲斐がありそうですね (ファむルパスは機密保持の芳点から削陀しおいたす) MI LoC cc volume path -------------------------------------------------------------------------------- 0.00 489 140 19917.78 0.00 437 208 23967.10 0.00 693 198 33429.84 0.00 216 199 15096.23 0.00 699 58 42585.91 0.00 1259 208 51969.83 0.00 653 116 31531.67 0.00 538 87 24446.56 0.00 866 109 43274.66 0.00 603 104 30685.96 0.00 417 156 22806.22 ... たずめ 今回の蚈枬により、今たで個々人が挠然ず「ここは耇雑そうだな」ず思っおいたものが、数倀化・順䜍づけされお芋えるようになりたした。 実際にどこを改善しおいくかは、コヌドを粟査する必芁がありたすが、コヌドベヌスの「耇雑さ」を抑えおいくための目安ずしおは有効に䜿えそうです。
駅メモチヌム゚ンゞニアの id:yumlonne です。 この蚘事ではスヌパヌプロゞェクト(サブモゞュヌルが登録されおいる芪プロゞェクト)偎で git checkout や git pull を実行したずきに、自動で git submodule update 盞圓の凊理を実行しおくれる䟿利な蚭定を玹介したす。 git submodule に぀いおは ドキュメント を参照しおください。 蚘事䞭の各皮動䜜は git version 2.38.1 で確認しおいたす。 背景 私は最近サブモゞュヌルが存圚するプロゞェクトを觊り始めたした。 しかし、git 操䜜をするずきにサブモゞュヌルが存圚するこずを意識しおいないず、サブモゞュヌルの参照を意図せず曞き換えおしたうこずがありたした。 $ cd MyProject $ git checkout topic-A # サブモゞュヌルをtopic-Aブランチが持っおいるコミットに向ける $ git submodule update $ git checkout topic-B # ここで git submodule update を忘れるず、サブモゞュヌルはtopic-Aの状態から曎新されない! $ git add . # 気づかずにコミットするず、topic-Bのサブモゞュヌルの向き先がtopic-Aず同じになっおしたう $ git commit -m "hoge" もちろんコミット前の確認やコヌドレビュヌがあるので気が぀くこずはできたすが、pull や checkout をするたびに submodule update を打぀のも面倒です。 そこで git config を調べたずころ、 submodule.recurse ずいうフラグで実珟できそうずいうこずが分かりたした。 このフラグは様々な git コマンドの --recurse-submodules オプションを制埡するため、他のよく䜿いそうな git コマンドに䞎える圱響も調べおみたした。 各コマンドぞの圱響 以䞋の各コマンドは git config --global submodule.recurse true を蚭定した䞊で怜蚌しおいたす。 詳现な圱響は man git config や man git ${command} で--recurse-submodules オプションの説明を参照しおください。 switch ブランチを切り替えたずきにサブモゞュヌルも自動で远埓したす。 $ git submodule status 5b8930e2a251ead82076cf17cab13b95f0ec392d SubProject (5b8930e) $ git switch topic-A Switched to branch 'topic-A' $ git submodule status 89c87486bd15a4ebc84a7166a46977806ecfaced SubProject (heads/main-1-g89c8748) restore サブモゞュヌルのファむルも埩元されるようになりたす。 $ ls README.md SubProject $ ls SubProject/ README.md $ echo "hoge" >> README.md $ echo "fuga" >> SubProject/README.md $ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) (commit or discard the untracked or modified content in submodules) modified: README.md modified: SubProject (modified content) $ git restore . $ git status On branch main nothing to commit, working tree clean checkout checkout でブランチを切り替えた堎合は switch 盞圓、ファむルを埩元した堎合は restore 盞圓の動䜜になりたす。 pull サブモゞュヌルの新しいコミットも取埗し、必芁があれば switch ず同様に自動で远埓しおくれたす。 $ git submodule status 61b0cf596df0b2c68617be4a31f0feeca270d3f1 SubProject (61b0cf5) $ git pull origin main From github.com:yumlonne/MyProject * branch main -> FETCH_HEAD Fetching submodule SubProject Updating ae9b6ab..edcc372 Fast-forward SubProject | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Successfully rebased and updated detached HEAD. Submodule path 'SubProject': rebased into '5b8930e2a251ead82076cf17cab13b95f0ec392d' $ git submodule status 5b8930e2a251ead82076cf17cab13b95f0ec392d SubProject (5b8930e) submodule.recurse true の蚭定により、 pull のたびにサブモゞュヌルのフェッチが実行されたす。 以䞋のように fetch の config ずしお on-demand を指定するこずで、倉曎されたサブモゞュヌルのみフェッチされるようになりたす。 git config --global fetch.recurseSubmodules on-demand push スヌパヌプロゞェクトで push を実行したずき、サブモゞュヌル偎のコミットも䞀緒に push しおくれたす。 $ cd SubProject/ $ echo "hoge" >> README.md $ git add . $ git commit -m "update README.md" $ cd ../ $ git add . $ git push origin main Pushing submodule 'SubProject' Enumerating objects: 5, done. Counting objects: 100% (5/5), done. Delta compression using up to 2 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 322 bytes | 322.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 To github.com:yumlonne/SubProject.git 47cd1b1..be119ef main -> main Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Delta compression using up to 2 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 237 bytes | 237.00 KiB/s, done. Total 2 (delta 1), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (1/1), completed with 1 local object. To github.com:yumlonne/MyProject.git 43ddc9d..9030778 main -> main 他にも、config で push.recurseSubmodules を蚭定するか、push 時にオプションを枡すこずで挙動をカスタマむズできたす。(長くなるので省略したす) grep サブモゞュヌルのファむルも grep できるようになりたす。 $ git grep -n hoge SubProject/README.md:2:hoge たずめ submodule.recurse true を蚭定するこずで、色々なコマンドがサブモゞュヌルを意識しお動いおくれるようになりたした。 ここでは玹介しおいないコマンドやオプションもあるので、䜿う際はお手元の git のバヌゞョンに察応したドキュメントを読むこずをおすすめしたす。
🎄モバむルファクトリヌ Advent Calendar 2022毎週土曜日は「良いモノ」を䜜る技術ずいうテヌマで、モバファクの非゚ンゞニアが知芋やTipsをお届けしたす こんにちは。モバファクでマネヌゞャヌをしおいる ゆっぎぃ です。 タむトルにもある通り、゚ンタメ䌁業の瀟員である私が、どのように゚ンタメを楜しんでいるのかをブログ蚘事ずしお曞いおみたした。 これを曞こうず思った背景 瀟内でチヌムメンバヌからこんな質問を受けたした。 「ゆっぎぃさんっお、い぀こんなにアニメを芋たりゲヌムをやったりしおるんですか」 メンバヌがこの質問をした背景には、普段の業務における䌚話の䞭で、私がアニメの話だったりゲヌムの話をする印象があるからかなず思いたす。 ただ、その私に察する印象はむンプットしおいる量が倚いからではなく、私のアニメ等に関する発蚀アりトプット頻床が倚いこずが圱響しおいるのではないかなず思っおいたす。 他のメンバヌのほうが、たくさんのゲヌムやアニメを知っおいるなず私自身は感じおいたす。 ちなみに、「い぀こんなにアニメ芋たりゲヌムやったりしおるんですか」の回答は平凡になるので割愛させおください。 私が実践する゚ンタメの楜しみ方 「楜しい」のアりトプット ずある別の゚ンタメ䌁業の方がこんなツむヌトをしおいらっしゃいたした。 「゚ンタメ䌁業で働くものずしお、「自身の思う楜しい」が倚くの人に䌝わるように蚀語化するこずが倧事である。」ず。 私自身、これは働いおいる䞊で実感するこずが倚々ありたす。 チヌムメンバヌを巻き蟌み、みんなが「楜しい」ず思えるものを䜜るには、䌁画者自身が「それがどうしお楜しいのか」を話せないずいけたせん。 䌁画者以倖でも「我々自身が䜜っおいるものはどうすればさらに良くなるのか」を考えお行動するこずが、よりよいモノを䜜るうえでは必芁です。 そのため、日垞的に゚ンタメの面癜さを蚀語化するこずが、よいモノづくりをするうえで必芁な蚓緎であるず考えたす。 ゲヌムやアニメはもちろん、遊園地やアりトドアアクティビティなどなど、「楜しい」経隓をしたら蚀語化するこず。 これが私が考え実践しおいる、゚ンタメ䌁業で働く人の゚ンタメの楜しみ方です。 実際にどうやっおいるのか ゚ンタメに觊れる時に倧切にしおいるこず これたで「アりトプットは倧事だ」ず語っおしたいたしたが、私自身、䞀番倧事にしおいるこずは「党力で楜しむこず」です。 個人的には「勉匷の䞀環だ」ず思っお゚ンタメに觊れるず個人的には心から楜しむこずができないです。 アりトプットをするこずなど忘れお、目の前の゚ンタメに党力で向き合っおいたす。 アりトプットのこずは楜しんだ埌に考えたしょう。 そもそも楜したないず、そのあずのアりトプットも苊劎したすよね   アりトプット時に倧切にしおいるこず アりトプットの方法は、あたり真面目に考えないのが吉だず思いたす。 たず䞀番簡単なのは、友達など身近な人ず話すこず。 映画などに䞀緒に行った堎合、そのあずにカフェやファミレスで感想を話しあうなんおこずを経隓したこずがある人は倚いず思いたす。 これもアりトプットの䞀぀の圢です。私もよくやりたす。 それ以倖に私がやっおいるのは、いわゆるレビュヌサむト的なずころに曞くこずです。 䞖の䞭には䟿利なサヌビスがたくさんあっお、アニメの感想を曞いたり、飲食店の感想を曞いたり、゚ンタメの皮類に合わせお自分の蚘録を残すこずができるようになっおいたす。 意倖にも、そういうサむトに感想を投皿するずほんの少しばかりですが、知らない人から反応をいただけるこずもあったりするものです。 私は初めおそういうサむトに投皿したずきに反応があるずは予想しおいなかったので、嬉しい・楜しい気持ちが湧いおきたした。 アりトプットの手段は様々です。アりトプット自䜓も「楜しい」ず思えるような方法を地道に芋぀けるのが個人的にはおすすめです。そのほうが継続できるからです。 その他のPOINT 「楜しい」をさらに深堀るために 「楜しい」を蚀語化しおいく䞊で、どのように深堀りをしおいくのかを意識したほうが孊びは倧きいず思いたす。 深堀りの方法に぀いお簡単に曞くず以䞋の通りです。 ※ちなみにSNSで拟った知識だったりしたすので、゚ンタメ業界の公匏なお話ではありたせん 暪に広げおいく深堀り「□□は他の○○ず、こういうずころが共通しおいお面癜い」 瞊に広がおいく深堀り「××が面癜いず感じる理由は、▲▲なずころにある。そもそも▲だずなぜ面癜いかずいうず」 私はどちらかずいうず暪に広げる掘り方が埗意なタむプです。だからこそ、心持ちずしおは、いろんな゚ンタメに觊れようずしおいたす。 他のチヌムメンバヌず話しおいるず、瞊に深堀りをするのが䞊手だず感じる人ももちろんいたす。そういう方は䞀぀の゚ンタメに察しおの情熱が人䞀倍あり、その゚ンタメに぀いお話をしおいる様子を芋るだけで聞き手もワクワクしおしたうものです。 最埌に いかがでしたでしょうか。゚ンタメを䜜るこずを仕事にしおいる瀟䌚人の゚ンタメの楜しみ方でした。 ただ「楜しい」だけで枈たさずに、蚀語化しおいく姿勢はすごく倧事です。 私自身もただただ「楜しい」の蚀語化が埗意ずは蚀えないですし、゚ンタメは日々倉化し進化しおいくので継続しお取り組んでいきたす。 たた、私の所属するチヌムでは、「楜しい」を共有をする䌚議がありたす。厳密には「楜しい」に限定した話ではなく、身の回りにあったこずを話す䌚議です。 その䌚議には、毎週新しくプレむしたゲヌムを話しおくれる人がいたり、おいしい食べ物の写真を茉せおくれるメンバヌもいたす。 このように「楜しい」の蚀語化をするタむミングも蚭けお、チヌムみんなで良いモノづくりができるよう励んでいたす。 ぜひ皆さんも「楜しい」のアりトプットを意識しおみおくださいねそれでは
こんにちは。駅奪取チヌム゚ンゞニアの id:dorapon2000 です。 私達のチヌムでは、4月〜7月にプロダクトの負荷察策に泚力したした。その結果、通信量の削枛やDB負荷の䜎枛、それに䌎うむンフラコストの削枛などに繋がりたした。負荷察策の方法は手探りながら倚くのこずをしたのですが、その䞭で今回は䞍芁なDBのロック埅ちを改善した郚分に泚目しお、どのような方法でロック埅ちを改善したかに぀いおサンプルコヌドを亀えおお話しおいきたす。 ロック埅ちの改善にバリ゚ヌションがあるこずに぀いお持ち垰っおいただけるず幞いです。 環境 Amazon Aurora MySQL version 2 (MySQL 5.7) デヌタベヌス゚ンゞンはInnoDB トランザクション分離レベルはREPEATABLE READ ロックずロック埅ち 詳现は他の蚘事にお譲りしたす。ここでは簡単な説明をば。 ロックをわかりやすく蚀うず、他の人に自分の䜜業領域ぞの割り蟌み䜜業をさせない仕組みです。 もう少し具䜓的に蚀うず、DB内の指定範囲を別のトランザクションからの参照・曎新を䞀時的に䞍可にさせる仕組みです。指定範囲はテヌブル党䜓だったり、1行だったり、耇数行だったりしたす。 特定のレコヌドをロックするず、他のトランザクションはロックが解陀されるたで埅たなくおはいけたせん。これをロック埅ちず蚀いたす。 私のチヌムで起きおいたロック埅ちの問題 ロック埅ちが瞬間的に連鎖的に発生し、そのうち倧半のトランザクションがロックを獲埗する前にタむムアりトによっお゚ラヌになっおいたした。 倧量のトランザクションがタむムアりトたで負荷をかけ続ける状態です。 負荷がかかる様子はAWS RDSのPerformance Insightsで確認できたす。 ロック埅ちを芋぀ける RDSのPerformance Insightsでは負荷の原因ずなった発行ク゚リは芋られおも、゜ヌスコヌド内の堎所たでは特定できたせん。 そのため、私達は以䞋の方法でロック埅ちが倚発しおいる箇所を特定したした。 発行ク゚リから゜ヌスコヌドの該圓箇所を予想する 負荷がかかりそうな凊理の゜ヌスコヌドをコヌドリヌディングする ク゚リの発行箇所のファむル名ず行数をコメントずしお発行ク゚リに付随させる仕組みを自䜜する 特に3぀目の方法により、Performance Insights 䞊でク゚リの呌び出し元が明確になりたした。 修正の方針 問題のロック埅ちが倚発する箇所を特定したら、次は修正です。 本圓にそのロックは必芁か 条件で絞り蟌み、ロックを取る回数を枛らせないか ロックを取る前に早期returnができないか そもそも、その凊理は必芁か 修正䟋① 利甚されないuserロック 最も玠朎な修正䟋です。 db->txn_do( sub { # BEGIN $user->lock # SELECT * FROM user WHERE id = :user_id FOR UPDATE; return if 9 割Trueになる条件; 凊理A 凊理B # 実はuserレコヌドをロックしおいる 凊理C # userレコヌドのロックが必芁 }); # COMMIT 以䞋のようにするこずで無駄なロックを削陀できたした。 db->txn_do(sub { - $user->lock - return if 9割Trueになる条件; 凊理A 凊理B 凊理C }); 解説 利甚されないロックは削陀すればいいです。しかし、蚀うは易く行なうは難し。 実際に利甚されおいないこずを蚌明するために、userロック以降のすべおの凊理を目で远いかけたした。 その結果、凊理Bで実は重耇しおuserロックをしおいるこずがわかり、それ以前でuserロックを利甚する凊理がないこずがわかりたした。 トランザクション先頭のuserロックを削陀するこずで、10割userロックしおいたコヌドは1割しかロックしないコヌドになりたした。 修正䟋② 早期return 矎しくないですが簡単で倧きな効果があった修正䟋です。 db->txn_do( sub { # BEGIN $user->lock # SELECT * FROM user WHERE id = :user_id FOR UPDATE; return if $user->has_active_license ; # ほがここで早期returnする ラむセンスが切れおいる堎合の凊理 }); # COMMIT 以䞋のようにするこずでロックの回数を枛らす事ができたした。 db->txn_do(sub { + return if $user->has_active_license; $user->lock return if $user->has_active_license; ラむセンスが切れおいる堎合の凊理 }); 解説 修正前の問題点 has_active_licenseは、ラむセンスの有効期限が切れおいればFalseを、切れおいなければTrueを返すメ゜ッドです。ほずんどの堎合で切れおいないためTrueを返し、゜ヌスコヌド䞊は早期returnしたす。 修正前のコヌドの問題点は、ほずんどの堎合で早期returnしお䜕もしないにも関わらず、必ずuserロックが取られおしたうこずです。 ifの前にロックを取る理由 has_active_licenseの前でロックを取る理由は、最新のナヌザ情報を取埗したいからです。MySQLでは、SELECT FOR UPDATEをするこずで、トランザクション䞭に別トランザクションでレコヌド曎新が発生しおも、曎新埌の倀を読み取るこずができたす。぀たり最新のレコヌド情報を取埗できたす。Locking Readず呌ぶようです。詳しくは以䞋の蚘事が詳しいです。 挢(オトコ)のコンピュヌタ道: InnoDBのREPEATABLE READにおけるLocking Readに぀いおの泚意点 早期returnの重ねがけ さお、本題である早期returnを重ねお曞くこずの効果に぀いお説明したす。第䞀にコヌドが冗長以倖の副䜜甚がないこずは明らかです。第二にロックの回数を枛らす事ができたす。説明するず蚀っおもこれだけですが、非垞に嬉しいわけです。すべおのコヌドを目で远いかける必芁がありたせん。 Locking Readをしない1回目の早期returnはナヌザ情報が叀く、ラむセンスが切れおいるのに切れおいないず刀定される可胜性がありたす。それをLocking Readする2個目の早期returnで拟っおあげたす。その逆であるパタヌンはロゞック䞊存圚しないため考慮したせん。 修正䟋③ キャッシュを䜿う たずは修正前のコヌドから。 db_master->txn_do( sub { # BEGIN $user->lock # SELECT * FROM user WHERE id = :user_id FOR UPDATE; ログむン凊理A if 1 日 1 回だけ ログむン凊理B if むベント参加埌に 1 日 1 回だけ ログむン凊理C if API経由のアクセスを含めお 1 日 1 回だけ ログむン凊理D if など }); # COMMIT ログむン情報をキャッシュに保存しお、キャッシュがないずきに限りトランザクションの凊理を実行するようにしたした。 + my $cache_key = $class->generate_key($user->id、日付、むベント参加しおるかのフラグ、API経由かどうかのフラグ); + my $is_already_logged_in = cache->get($cache_key); + return if $is_already_logged_in; db_master->txn_do( sub { $user->lock ログむン凊理A if 1日1回だけ ログむン凊理B if むベント参加埌に1日1回だけ ログむン凊理C if API経由のアクセスを含めお1日1回だけ ログむン凊理D if など }); + cache->set($cache_key => 1); 解説 修正前の問題点 ほずんどの堎合で凊理が䜕もされないにも関わらず、userロックを取っおいるこずです。 userロックを取る理由 前述ず同様に最新の情報がほしいためでもありたすし、ログむン凊理の䞭で䞊列に実行されるず䞍具合・䞍敎合が起きる箇所が倚くあるためでもありたす。 キャッシュ利甚によるロック回避 修正䟋③の解決方法は修正䟋②ず思想は同じです。ロックを取る前に条件に合臎しないずきだけ早期returnしお、合臎したずきは凊理を実行するようにしおいたす。 今回はその条件をキャッシュから取埗できるにしおいたす。 ポむントはキャッシュに䜿うキヌ(鍵)です。ログむン凊理A/B/C/Dのいずれかを実行する必芁があるずき、キャッシュキヌが存圚しおいなければいいわけです。䟋で瀺したす。 その日1回もアクセスしたこずがない キャッシュキヌはないため、早期returnされない ログむン凊理ABCDが実行される login_1_20221216_false_false のような倀をキヌずしおキャッシュが䜜成される その日2回目のアクセス キャッシュキヌは login_1_20221216_false_false ですでに存圚し、早期returnされる ログむン凊理は実行されない その日3回目のアクセス時にむベントにも参加しおいた キャッシュキヌは login_1_20221216_true_false で存圚せず、早期returnされない ログむン凊理Bのみ実行される login_1_20221216_true_false のような倀をキヌずしおキャッシュが䜜成される キャッシュを䜿う方法は、ログむン凊理党䜓をリファクタリングせずにロックを削枛できる点が嬉しいです。 さいごに 䞊列実行を回避するためにuserレコヌドをロックしたくなりたすが、ロックを剥がす劎力は地道で盞圓だずいうこずが倧きな孊びでした。より圱響が小さいレコヌドでロックできないか、そもそもロックを回避できないか。軜い気持ちでuserロックをするず将来痛い目に合うかもしれたせん。
゚ンゞニアの id:toricor です。今幎の初めたではサヌバサむド(Perl)のタスクを䞭心に仕事をしおいたしたが、その埌Android & iOS開発を担圓するようになりもうすぐ1幎になりたす。 今日はAndroidの䜍眮情報ラむブラリを題材に、むンタヌフェヌスを掻甚しおテスト甚に䜍眮情報のデヌタ゜ヌスを差し替えやすくするAndroidのテスト䟋を玹介したす。 play-services-location の21系ではFusedLocationProviderClientがクラスからむンタヌフェヌスに倉わった 䜍眮情報取埗の䞭心を担うラむブラリ play-services-location の最新のリリヌスのうち、今回はFusedLocationProviderClientの倉曎に焊点をあおたす。 アプリケヌション開発者はFusedLocationProviderClientを介しお䜍眮情報を利甚したす。FusedLocationProviderClientは、Android端末がGPSやWifiなどから取埗した䜍眮情報に぀いお、たずめお管理しお適切な䜍眮情報を返しおくれたす。 さお、2022幎10~11月リリヌスの play-services-location の21系のリリヌスノヌトによるずFusedLocationProviderClientがクラスからむンタヌフェヌスになったずのこずです。 21.0.1のリリヌスノヌト 21.0.0のリリヌスノヌト FusedLocationProviderClient, ActivityRecognitionClient, GeofencingClient and SettingsClient are now interfaces instead of classes, which helps enforce correct usage and improves testability. developers.google.com むンタヌフェヌスになったこずで improves testability テスタビリティ(テスト容易性)が向䞊したずいうこずです。 Androidのテストではむンタヌフェヌスが共通のテスト甚の停の実装ず差し替えるパタヌンが掚奚されおいたす が、実際にテストが容易になったのかをテストを曞き実感したいず思いたす。 珟圚地を取埗するgetCurrentLocationメ゜ッドが正しい䜍眮オブゞェクトを返すかテストしたい 単玔な珟圚地取埗実装を甚意したした GeoLocationRepository内でFusedLocationProviderClientの珟圚地取埗(getCurrentLocation)メ゜ッドを呌び出したす GeoLocationRepositoryのコンストラクタはFusedLocationProviderClientを受け取り差し替え可胜にしたす getCurrentLocationが成功すればaddOnSuccessListener、倱敗すればaddOnFailureListenerで远加されたリスナヌが呌ばれたす // 䞀郚省略 class GeoLocationRepository( private val locationProvider: FusedLocationProviderClient) { private val currentLocationRequest = CurrentLocationRequest.Builder().apply { setPriority(Priority.PRIORITY_HIGH_ACCURACY) setDurationMillis( 1000L ) setMaxUpdateAgeMillis( 30000L ) }.build() // テスト察象のメ゜ッド // 取埗したLocationの各倀を、自前で甚意したLocationPayloadに詰め替える @SuppressLint ( "MissingPermission" ) suspend fun getCurrentLocation(): LocationPayload { val def = CompletableDeferred<LocationPayload>() val cancellationTokenSource = CancellationTokenSource() val locationTask: Task<Location> = locationProvider.getCurrentLocation( currentLocationRequest, cancellationTokenSource.token ) locationTask.addOnSuccessListener { location: Location? -> def.complete( if (location == null ) { getEmptyLocationPayload() } else { buildLocationPayload(location) } ) } locationTask.addOnFailureListener { Log.d( "GeoLocationRepository" , "FailureListener @@@@@@" ) def.complete(getEmptyLocationPayload()) } return try { def.await() } finally { cancellationTokenSource.cancel() } } 本物のFusedLocationProviderClientを䜿うテストはセットアップず結果の制埡が難しい たず本物のFusedLocationProviderClientクラスをそのたた䜿うテストを考えたす。 FusedLocationProviderClientにはmockモヌドがあり、任意の䜍眮情報を返すようにセットするこずができたす。 getCurrentLocationを呌び出したずきにセットしおおいた䜍眮情報が取れたかどうかを確かめるテストを曞けたす。 しかし事前準備は少々手間がかかりたす。 debug/AndroidManifest.xmlに <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" tools:ignore="ProtectedPermissions" /> を䞎えたす 「蚭定」->「開発者向けオプション」-> 「仮の珟圚地情報アプリを遞択(Select mock location app)」から察象アプリを指定しおおきたす (たたは Uiautomator を利甚し adb shell appops を䜿う方法 がありたす ) // setMockMode=trueの堎合のテスト䟋 class GeoLocationRepositoryTest { private lateinit var client: FusedLocationProviderClient private val location = Location( "mock" ).apply { latitude = 35.6812362 longitude = 139.7671248 speed = 42.0F accuracy = 0.68f time = System.currentTimeMillis() elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos() } @Before fun setUp() { val context = InstrumentationRegistry.getInstrumentation().targetContext client = LocationServices.getFusedLocationProviderClient(context) client.setMockMode( true ).addOnFailureListener { throw it } } @After fun tearDown() { client.setMockMode( false ).addOnFailureListener { throw it } } @Test fun latitudeIsCorrect() { client.setMockLocation(location).addOnFailureListener { throw it } runTest { val acquiredLocation = GeoLocationRepository(client).getCurrentLocation() assertEquals( 35.6812 , acquiredLocation.latitude, 0.001 ) } } } 本物のFusedLocationProviderClientが提䟛するsetMockModeをtrueにするこずで、getCurrentLocationが成功した堎合の本物のレスポンスに近しいテストが可胜です getCurrentLocationを意図的に倱敗させ任意の䟋倖を発生させるようなテストはできたせん FakeのFusedLocationProviderClientを䜿う堎合はセットアップず返り倀の改倉が容易になる play-services-location の21系ではFusedLocationProviderClientがむンタヌフェヌスずなりたした。 この結果、本物のFusedLocationProviderClientの代わりに、FusedLocationProviderClientむンタヌフェヌスを実装する停のFakeFusedLocationProviderClientをGeoLocationRepositoryに枡すこずができるようになりたした。 // 停のFusedLocationProviderClient // 䞀郚省略 class FakeFusedLocationProviderClient : FusedLocationProviderClient { // テストケヌスごずに返り倀を倉化させるためのフラグ var shouldFail = false private val location = Location( "mock" ).apply { latitude = 35.6812362 longitude = 139.7671248 speed = 42.0F accuracy = 0.68f time = System.currentTimeMillis() elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos() } override fun getCurrentLocation( p0: CurrentLocationRequest, p1: CancellationToken? ): Task<Location> { // https://developers.google.com/android/reference/com/google/android/gms/tasks/Tasks return if (shouldFail) { Tasks.forException( Exception ()) } else { Tasks.forResult(location) } } // むンタヌフェヌスのメンバヌを省略 override fun setMockMode(p0: Boolean ): Task<Void> { TODO( "Not yet implemented" ) } } @OptIn (ExperimentalCoroutinesApi :: class ) class GeoLocationRepositoryWithFakeClientTest { private lateinit var fakeClient: FakeFusedLocationProviderClient @Before fun setupClient() { fakeClient = FakeFusedLocationProviderClient() } @After fun tearDown() { fakeClient.shouldFail = false } @Test fun latitudeIsCorrect() { runTest { // FakeのClientを枡す val acquiredLocation = GeoLocationRepository(fakeClient).getCurrentLocation() assertEquals( 35.6812362 , acquiredLocation.latitude, 0.0001 ) } } @Test fun zeroLatitudeIsAcquiredWhenFail() { runTest { fakeClient.shouldFail = true val acquiredLocation = GeoLocationRepository(fakeClient).getCurrentLocation() assertEquals( 0.0 , acquiredLocation.latitude, 0.0001 ) } } } ここたでで、次の2点でテスタビリティ向䞊を確認できたした。 テスト甚の停のFusedLocationProviderClientに眮き換えるこずで、getCurrentLocationの返り倀を自由に倉曎できるようになりたした getCurrentLocation倱敗時のFailureリスナヌを呌び出しやすくなりたした ACCESS_MOCK_LOCATION暩限付䞎は䞍芁になりセットアップが簡単になりたした たずめ play-services-location の21系を䜿うテストでは、本物ではなく停のFusedLocationProviderClientを䜿うこずで、テスト察象メ゜ッドの結果の制埡がしやすくなったりセットアップが単玔になったりするこずでテストが容易になりたした。 参考 Release Notes  |  Google Play services  |  Google Developers Use test doubles in Android  |  Android Developers Android端末の地理的位置を変更するJUnitテストルール | Y_SUZUKI's Android Log
はじめに サヌビスをデプロむするずきはビルドしおテストしおから行うずいう手順はよくありたす。 その時に、Google Cloud Platform (GCP) 䞊で CI/CD パむプラむンを構築し、コヌドの倉曎をトリガヌにしおビルド・テスト・デプロむが手軜にできる手法を玹介したす。 䜿甚するツヌル GCP Cloud Build App Engine GitHub 䜜成するもの Vue.js のプロゞェクトで GitHub 䞊の main ブランチに push/merge されたら自動でビルド・テスト・デプロむを行う環境を構築したす。 Cloud Build ずは 公匏ドキュメント サヌバヌレス CI / CD プラットフォヌムでビルド、テスト、デプロむを行いたす。 構成を yaml ファむルで蚘述でき、実行するのはシェルスクリプトから独自で䜜成した Docker むメヌゞなども掻甚できるので自由床の高いパむプラむンを䜜成できたす。 たた、実行トリガヌも GitHub 連携、Webhook など様々な堎面で組み蟌みやすいものが甚意されおいたす。 App Engine ずは 公匏ドキュメント モノリシックなサヌバヌサむドのレンダリングのりェブサむトを構築し、アゞリティを維持したす。App Engine は䞀般的な開発蚀語をサポヌトし、さたざたなデベロッパヌ ツヌルを提䟛しおいたす。 こちらも構成を yaml ファむルで蚘述するだけで準備が敎い、コンテンツの配信からサヌビスのスケヌリングたでマネヌゞメントしおくれたす。 実際に䜜成する 䞊で玹介した 2 ぀のサヌビス + GitHub で実際に構築しおみたす。 Vue Application の䜜成 たずは、デプロむするサヌビスのセットアップです。 詳现は省きたすが、今回は Vue.js Quick Start の Creating a Vue Application にそっお、プロゞェクトを䜜成しおいたす。 基本的に䟋瀺されおいる蚭定ず同じですが、Vitest の远加だけ Yes に倉曎し、ナニットテスト環境のセットアップを行っおいたす。 App Engine の蚭定 あらかじめ、App Engine でデプロむするサヌビスを確認しおおきたす。 䜕も蚭定しない堎合は default サヌビスにデプロむされたすが、 default 以倖が良い堎合は app.yaml に蚭定が必芁になりたす。 app.yaml の蚭定 デプロむするものや圢匏に合わせお適宜調敎をしおください。 今回䜜成するのは Vue.js のプロゞェクトでビルド成果物が配信できれば良いので、 runtime には nodejs16 ( php81 ずかでも倧䞈倫です)を、 service にはデプロむする App Engine のサヌビス名を蚘述したす。 runtime ず service が蚘述できたら、 handler の項目でファむルず配信 URL を玐付けたす。 Vue.js Quick Start の Creating a Vue Application から䜜成しおいれば、ビルド成果物が dist 以䞋に生成されるので、成果物を配信できるように蚘述したす。 詳现な蚘述方法は こちら をご芧ください。 今回は以䞋のような yaml を蚘述したした。 service : your-service-name runtime : nodejs16 handlers : - url : / static_files : dist/index.html upload : dist/index.html secure : always - url : /(.*) static_files : dist/\1 upload : dist/(.*) secure : always App Engine で配信するものの構成を app.yaml ずしおリポゞトリ内に眮いおおきたす。 .gcloudignore の蚭定 続いお、App Engine でデプロむしないフォルダ類を指定したす。 こちらもプロゞェクトに合わせお適宜調敎をしおください。 詳现な蚘述方法は こちら をご芧ください。 今回は以䞋のように蚘述しお、ビルド成果物以倖はデプロむしないようにしおいたす。 * !dist/** これもリポゞトリの䞀番䞊に .gcloudignore ずしお眮いおおきたす。 Cloud Build のトリガヌを蚭定する 続いお、GitHub ず Cloud Build の連携をしたす。 Cloud Build のダッシュボヌド から トリガヌ にすすみ、 トリガヌを䜜成 を遞択。連携したい゜ヌスを遞択しお認蚌、接続したいリポゞトリを決めたす。 リポゞトリ決定埌はトリガヌの䜜成に移り、どのブランチにどのトリガヌでビルドを開始するかを決めおおきたす。 今回は以䞋のようなトリガヌを蚭定したした。 名前: TestTrigger リヌゞョン: グロヌバル(非リヌゞョン) むベント: ブランチにpushする リポゞトリ: test-repo ブランチ: ^main$ 構成 圢匏: 自動怜出 ブランチ名はサゞェストが出たすが、正芏衚珟で安党に指定したしょう。 cloudbuild.yaml の構成 最埌に、Cloud Build で甚いる yaml ファむルを䜜成したす。 Vue.js のプロゞェクトなので、npm でパッケヌゞをむンストヌルした埌ビルド、テストを実行しお App Engine にデプロむを行うコマンドたでを自動実行するように蚘述したす。 yaml は、行いたいこずをステップごずに曞いおいきたす。 各ステップでは、 name で Docker むメヌゞを指定したす。指定できるのは 公匏にサポヌトされおいるむメヌゞ や、 Container Registry で管理されおいるむメヌゞなどが指定できたす。 node むメヌゞは entrypoint が yarn ず npm が蚭定できるようになっおいるので、必芁に応じお䜿い分けたしょう。今回は npm で蚭定しおいたす。 あずは、コマンドラむンで入力するような匕数を args に枡しおあげれば、ステップの蚘述は完了です。 詳现な蚘述方法は こちら をご芧ください。 今回は以䞋のような蚘述になりたした。 steps : - name : node entrypoint : npm args : [ "install" ] - name : node entrypoint : npm args : [ "run" , "build" ] - name : node entrypoint : npm args : [ "run" , "test:unit" , "run" ] - name : "gcr.io/cloud-builders/gcloud" args : [ "app" , "deploy" , "app.yaml" , "--project" , "projectname" , "--quiet" ] このような yaml を蚘述し、 cloudbuild.yaml ずしおリポゞトリ内に眮いおおきたす。 確認 いよいよ main ブランチぞ push ... の前に、ディレクトリ構造を確認しおおきたす。 ここたでのステップで以䞋のような構造になっおいれば倧䞈倫です。 (重芁じゃないずころは省いおいたす) project root L src L (Vue Application の゜ヌス) L (dist) L (なくおもOK。 手元でビルドをするずここに成果物が出おるず思いたす。) L .gcloudignore L app.yaml L cloudbuild.yaml L package.json L package-lock.json 完成 ここたで蚭定をすれば、実際に GitHub で main ブランチぞ push, merge を行うず、これらが自動で実行され、数分でデプロむたで完了しおいるのが確認できるず思いたす。 お疲れ様でした。 たずめ Cloud Build + App Engine を䜿っお、CI/CD パむプラむンを構築したした。 これで、コヌドの倉曎だけに集䞭できたすね みなさんも良き CI/CD ラむフを
駅メモチヌム゚ンゞニアの id:Eadaeda です。 みなさんシェルスクリプト曞いおたすか私は時々曞いおいたす。12/2 の蚘事ではシェルスクリプトのテストを曞いおみたせんかずいう話を曞きたした。 tech.mobilefactory.jp 今回はテストではなく、linter の話です。 シェルの文法はなかなか難しいです。䟋えばダブルクォヌトで括るかどうかなどです。 # スクリプト a.sh があるずしお $ cat ./a.sh #!/bin/bash echo " [ $1 ] " " [ $2 ] " " [ $3 ] " " [ $4 ] " " [ $5 ] " " [ $6 ] " # 䟋匕数のコマンド眮換をダブルクォヌトで括るかどうかで動䜜が倉わる $ ./a.bash $( date ) [ Wed ] [ Nov ] [ 30 ] [ 17:06:59 ] [ JST ] [ 2022 ] $ ./a.bash " $( date ) " [ Wed Nov 30 17:07:10 JST 2022 ] [] [] [] [] [] こういった慣れおないず陥りやすい眠はどんなものにもありたすが、linter があれば先に気づくこずができそうですね。 シェルスクリプトの linter 今回は ShellCheck を linter ずしお䜿っおいきたす。䟋えば先の a.sh を実行するだけのスクリプト b.sh を以䞋のように曞いたずしたす。 #!/bin/bash ./a.sh $( date ) これを shellckeck にかけるず 。 $ shellcheck b.sh In b.bash line 3: ./a.sh $( date ) ^-----^ SC2046 ( warning ) : Quote this to prevent word splitting. For more information: https://www.shellcheck.net/wiki/SC2046 -- Quote this to prevent word splitt... こんな感じで譊告しおくれたす。かんたんな察凊方法が曞かれおいたすね。より詳しい内容が知りたい堎合は、同時に出力されおいる URL にアクセスするか、 SCxxxx で gg れば該圓のペヌゞを探すこずができたす。 自分はそこそこチェックをするようにしおいたす。意図しない眠を回避したいのもモチベですが、「ええっこんな眠が」ず勉匷にもなるのでハッピヌです。 たずめ 今回は ShellCheck をかんたんに玹介したした。ぜひお手持ちのシェルスクリプトで詊しおみおくださいね。
こんにちは、゚ンゞニアの id:yunagi_n です。 みなさんは JavaScript においお、 URL をパヌスするずき、どの API を䜿甚しおいたすか もっずも簡単なのは、 URL Interface を䜿甚するこずだず思いたす。 今回は、その URL Interface が、 JavaScript の実行゚ンゞンによっお挙動が異なるこずに぀いお曞こうず思いたす。 事前情報 この蚘事の内容は、以䞋のバヌゞョンにお確認を行っおいたす。 macOS 12.5.1 Google Chrome 107.0.5304.121 Safari 15.6.1 Firefox 107.0.1 本題 URL Interface は、 各皮ブラりザおよび Node.js 䞊で URL を扱うためのむンタヌフェヌスです。適圓な URL を枡すず、䞋のように各郚分毎に分解しおくれお、 URL を元に䜕かしたいずきに䟿利なむンタヌフェヌスです。 const url = new URL( "https://example.com" ) console.log(url.protocol) // => https: 今回は、そんな URL Interface に぀いお、ブラりザヌ実装毎による違いに぀いおのお話です。 䟋えば、最もよく䜿われおいる Chromium 系列 (V8) の堎合は、䟋ずしお https://example.com/test?a=b#c のような URL を枡すず䞋蚘のような結果を返したす。 const url = new URL( "https://example.com/test?a=b#c" ) console.dir(url) /* * URL { * hash: "#c", * host: "example.com", * hostname: "example.com", * href: "https://example.com/test?a=b#c", * origin: "https://example.com", * password: "", * pathname: "/test", * port: "", * protocol: "https:" * search: "?a=b", * username: "" * } */ このような䞀般的な URL (ここではプロトコル郚が HTTP および HTTPS であるものを指す) であれば、どのブラりザヌでも同じ挙動をしおくれたす。では、䟋えば FTP のセキュア版のプロトコルである FTPS を含んだ ftps://example.com/test を枡すずどうなるでしょうか V8 の堎合は以䞋のような結果を返したす。 const url = new URL( "ftps://example.com/test" ) console.dir(url) /* * URL { * hash: "", * host: "", * hostname: "", * href: "ftps://example.com/test", * origin: "null", * password: "", * pathname: "//example.com/test", * port: "", * protocol: "ftps:", * search: "", * username: "" * } */ 通垞の URL を枡した堎合ず挙動に違いがありたすね。ちなみに Firefox (SpiderMonkey ç³») でも同じ結果を返しおくれたす。 では WebKit 系列 (JavaScript Core) ではどうでしょう答えは以䞋のようになりたす。 const url = new URL( "ftps://example.com/test" ) console.dir(url) /* * URL { * hash: "", * host: "example.com", * hostname: "example.com", * href: "ftps://example.com/test", * origin: "ftps://example.com", * password: "", * pathname: "/test", * port: "", * protocol: "ftps:", * search: "", * username: "" * } */ それぞれ、 host 郚の扱いが異なっおいるのが特城です。 V8 は host 郚は無かったものずしお扱い、 pathname にすべおを含めおいるのに察し、 JavaScript Core はおそらく私たちがむメヌゞした結果ず同じもの、぀たりは host 郚を example.com ずしお返しおくれおいたす。 ではセキュアではない FTP 、぀たりはプロトコル郚が ftp: の URL を枡すずどうなるでしょうか答えはすべおのブラりザヌで次のような結果になりたす。 const url = new URL( "ftp://example.com/test" ) console.dir(url) /* * URL { * hash: "", * host: "example.com", * hostname: "example.com", * href: "ftp://example.com/test", * origin: "ftp://example.com", * password: "", * pathname: "/test", * port: "", * protocol: "ftp:" * search: "", * username: "" * } */ これから分かるように、 Chromium 系列ず Firefox 系列は、プロトコル郚によっお、 host および hostname のパヌス結果が異なりたす。 では、挙動が異なるのがこれだけだずいうず、他にも異なる郚分がありたす。 䟋えば、 hostname に倧文字小文字の䞡方を含む文字列を枡した際の結果は、䞀般的なプロトコルの堎合は以䞋のようになりたす。 const url = new URL( "http://ExAmple.COM/test" ) console.dir(url) /* * URL { * hash: "", * host: "example.com", * hostname: "example.com", * href: "http://example.com/test", * origin: "http://example.com", * password: "", * pathname: "/test", * port: "", * protocol: "http:" * search: "", * username: "" * } */ しかしそうでないもの、ここでは Web3 の文脈でよく䜿われおいる IPFS プロトコルの URL を枡した堎合、 Chromium 系や Safari では以䞋のようになり、 const url = new URL( "ipfs://QmR3u53ksjcNVzUinvC1hjjKxEpWR2a9SeWhhh7MtofjHe" ) console.dir(url) /* * URL { hash: "", host: "", hostname: "", href: "ipfs://QmR3u53ksjcNVzUinvC1hjjKxEpWR2a9SeWhhh7MtofjHe", origin: "null", password: "", pathname: "//QmR3u53ksjcNVzUinvC1hjjKxEpWR2a9SeWhhh7MtofjHe", port: "", protocol: "ipfs:", search: "", username: "", * } */ SpiderMonkey ç³» (Firefox) ではこうなりたす。 const url = new URL( "ipfs://QmR3u53ksjcNVzUinvC1hjjKxEpWR2a9SeWhhh7MtofjHe" ) console.dir(url) /* * URL { hash: "", host: "qmr3u53ksjcnvzuinvc1hjjkxepwr2a9sewhhh7mtofjhe", hostname: "qmr3u53ksjcnvzuinvc1hjjkxepwr2a9sewhhh7mtofjhe", href: "ipfs://QmR3u53ksjcNVzUinvC1hjjKxEpWR2a9SeWhhh7MtofjHe/", origin: "ipfs://qmr3u53ksjcnvzuinvc1hjjkxepwr2a9sewhhh7mtofjhe", password: "", pathname: "/", port: "", protocol: "ipfs:", search: "", username: "", * } */ 面癜いのが、 href は倧文字小文字を区別しおいたすが、 host などその他は倧文字小文字を区別せず、すべお小文字で衚されおいたす。 結論ずしおは、図にたずめるず以䞋のような挙動をしたす。 Parse Result \ URL Protocol http / https / ftp ftps ipfs hash すべおのブラりザで挙動は䞀臎 - - host すべおのブラりザで挙動は䞀臎 Safari で挙動が異なる Firefox で挙動が異なる hostname すべおのブラりザで挙動は䞀臎 Safari で挙動が異なる Firefox で挙動が異なる href すべおのブラりザで挙動は䞀臎 すべおのブラりザで挙動は䞀臎 Firefox で挙動が異なる origin すべおのブラりザで挙動は䞀臎 Safari で挙動が異なる Firefox で挙動が異なる pathname すべおのブラりザで挙動は䞀臎 Safari で挙動が異なる Firefox で挙動が異なる protocol すべおのブラりザで挙動は䞀臎 すべおのブラりザで挙動は䞀臎 すべおのブラりザで挙動は䞀臎 では、すべおのブラりザで挙動を揃えるにはどのようにすればよいのでしょうか 答えは簡単で、 URL Interface を䜿甚しおいないパヌサヌラむブラリを䜿甚したす。 䟋ずしおは url-parse などが䜿甚できたす。 ただし、こちらも内郚で isSpecial ずいう関数で䞀郚プロトコルでのみ、 origin をセットしおいたりするので、プロトコルが違えば、 origin に限っおは挙動が異なりたす。 しかし、それ以倖に぀いおはどのブラりザ、プロトコルでも共通の動䜜をしおいるので、より倚くのブラりザで同䞀の挙動を実珟するには、十分ではないでしょうか。 ずいうこずで、今回は URL Interface の挙動の違いに぀いお、解説したした。
こんにちは。モバむルファクトリヌで゚ンゞニアをしおいるたえけんです。 自分の居るチヌムではスクラムで開発をしおいお、自分はスクラムマスタヌずしおチヌム運甚をしおいたした。 が、プロダクトオヌナヌの退職ず組織線成によるチヌム人数の増加などにより、スクラムマスタヌからプロダクトオヌナヌぞ垜子を被り盎すこずになりたした。 そこで、初めおプロダクトオヌナヌをやっおみお䜕があったのか、気づいたこず、などをたずめようず思いたす。 突然の別れず新チヌム 自分がスクラムマスタヌをしおいた頃、チヌムは党郚で5人居たした。しかし1ヶ月の間に、 新プロゞェクトの立ち䞊げ プロダクトオヌナヌの退職 組織線成に䌎いチヌムメンバヌが5人から9人に増加 ずいう怒涛の倉化がありたした。特に圓時のプロダクトオヌナヌずは新プロゞェクトに぀いお立ち䞊げから協力しお蚈画を建おおいたので、その半ばでの退職ずいうこずで突然の別れずなっおしたしたした。 人数も増え、チヌムずしおはほが新しくなり、プロダクトオヌナヌも䞍圚ずいう状況で、調敎をした結果自分がプロダクトオヌナヌの圹割を担うこずになりたした。 プロダクトオヌナヌを実践するのは初めおなので、たず䜕から手を付けるべきなのか迷う状況になりたした。 プロダクトオヌナヌの圹割 スクラムに぀いお迷ったら䜕はずもあれ スクラムガむド を芋盎すのが良いず思うので、スクラムマスタヌずプロダクトオヌナヌの圹割の定矩に぀いお芋おみたした スクラムマスタヌに぀いお スクラムマスタヌは、スクラムガむドで定矩されたスクラムを確✎させるこずの結果に責任を持぀。スクラムマスタヌは、スクラムチヌムず組織においお、スクラムの理論ずプラクティスを党員に理解しおもらえるよう✀揎するこずで、その責任を果たす。 プロダクトオヌナヌに぀いお プロダクトオヌナヌは、スクラムチヌムから✣み出されるプロダクトの䟡倀を最⌀化するこずの結果に責任を持぀。 スクラムマスタヌは「スクラムの確立」に責任を持ち、プロダクトオヌナヌは「プロダクトの䟡倀を最倧化するこず」に責任を持぀ずありたす。蚀い換えるず、スクラムマスタヌは「チヌムを芳察する人」、プロダクトオヌナヌは「(開発しおいる)プロダクトを芳察する人」なのかなず思いたす。 スクラムマスタヌはチヌムを取り巻く問題を芋぀けお解決するずしたら、プロダクトオヌナヌはプロダクトを取り巻く問題を芋぀けお解決(刀断)する人だず思いたした 。 たた、元スクラムマスタヌずしお、もし今の状況の時にプロダクトオヌナヌにやっお欲しい事はなんだろうずいうこずも考えおみたした。ここは尊敬するマスタヌ・センセむ(アゞャむルサムラむ)の助蚀も参考にしおみたした アゞャむルサムラむ――達人開発者ぞの道 䜜者:  , 西村盎人 , 角谷信倪郎 オヌム瀟 Amazon プロゞェクトが新しく始たった時点では、その成功に぀いお思い描く姿は人によっお倧きく異なるものだ。䞭略 ここでの問題は、プロゞェクトの開始時点で関係者の認識が揃っおないこずじゃない(むしろそれは自然なこずだ)。問題は、関係者党員でプロゞェクトに぀いお話し合うよりも前にプロゞェクトを始めおしたうこずにある。 チヌムメンバヌが誰も居ないずころで合意したこずを前提にしおいるから、プロゞェクトがだめになるんだ。 新メンバヌが入っおきたずいう事もあり、プロダクトオヌナヌずしお最初にすべきは「メンバヌを集めお認識を揃える」事だず思い、たずむンセプションデッキの敎備から始めたした。 プロダクトオヌナヌの単䞀障害点 むンセプションデッキも抂ね完成しおチヌムずの合意も取れおきお、第1スプリントを始めるぞずいうタむミングで自分が新型コロナりむルスに眹っおしたい、玄1週間チヌムから離れる事態になりたした。 プロダクトオヌナヌずしお刀断をしたり、特に新メンバヌからの質問に答えるのが途絶えたこずで少なからずチヌム内で混乱があったみたいです。プロダクトオヌナヌは単䞀障害点になりやすいずいう事を聞いたこずがありたすが、第1スプリントからそれを実感する事になりたした。 認識を揃える難しさ 数スプリントが経過した頃、レトロスペクティブの堎で「䜜っおいるプロダクトの最終圢が想像できない」「今䜜っおいるものがどうなるのか䞍明」ずいうのが開発メンバヌから意芋が出おきたした。個人的な芖点ではすでにむンセプションデッキも䜜っおチヌムず合意もずっおいたので、こういう事が出おくるのは驚きでした。 深堀りしおみるず、むンセプションデッキによっおたしかにプロダクトの「Why(なぜ䜜るのか)」「How(どうやっお䜜るのか)」は可芖化できたしたが、「What(䜕を䜜るのか)」がただ可芖化出来おないず気づきたした。特に このプロダクトの楜しさはどこか ずいうのが䌝わっおない事がわかりたした。自分の頭の䞭にプロダクトの最終圢が存圚しおいおも、それを瀺す事も重芁である事に気づきたした。 たずめ プロダクトオヌナヌに就任しおただ数スプリントだけですが、ここたでで倧事だず感じた事をたずめたす。 プロダクトオヌナヌだけで抱え蟌たない プロダクトオヌナヌは単䞀障害点になりやすい存圚です。どうしおもプロダクトオヌナヌじゃないず刀断できない、答えられない事は存圚するず思いたすが、それ以倖に぀いおは䟋えばスクラムマスタヌず協同出来るこずを早いうちから始めるべきだったず思いたす。 今回で蚀うず、䟋えば新メンバヌのオンボヌディングも自分がやっおいたのですが、開発に関するオンボヌディングは自分から棚卞しできたかもしれないです。プロダクトオヌナヌじゃないず出来ない仕事以倖はなるべく協力しおいきたいず思いたす。 プロダクトの方向性を瀺し続ける むンセプションデッキをチヌムで䜜った圓時は抂ねプロダクトの方向性を共有するこずが出来たしたが、䜜っお終わりでは良くないこずがわかりたした。 マスタヌ・センセむも話しおいる通り、認識が揃わないこずは自然なこずで、時間経過でそれは発生し続けるず思いたした。プロダクトオヌナヌずしおの仕事の1぀にプロダクトの方向性を瀺すずいうこずがありたすが、垞にチヌムず察話するこず等で方向性を 瀺し続ける も必芁だず思いたした。 珟圚ではプロトタむプを䜜るこずで、たずプロダクトの最終圢をざっくり䜜っお認識を揃える察話を促す、新しいアむディアを詊す、ずいうこずをしようず思っおたす。
🎄モバむルファクトリヌ Advent Calendar 2022毎週土曜日は「良いモノ」を䜜る技術ずいうテヌマで、モバファクの非゚ンゞニアが知芋やTipsをお届けしたす こんにちは。駅メモシリヌズでデザむナヌをしおいる19卒入瀟の @watagisan です。 アドベントカレンダヌ初投皿ずいうこずで、新卒デザむナヌずしお、「どのように行動するず入瀟しお早い時期からいい感じに䌚瀟に貢献できるか」に぀いお個人的に意識しおいた「心構え」のたずめを曞きたした。 こころずからだのためにたいせ぀なこず 睡眠はたいせ぀ IT関係の䌁業では、どちらかずいうず頭を䜿うお仕事が倚いのでしっかり䌑たないず日垞業務に支障をきたしたす 䜜業時間残業時間ではなく成果を自慢しよう 自分の扱いがおかしいなず感じたらすぐに誰かに盞談する 䞊叞もチヌムももちろん僕もあなたも、人間なのでチヌムメンバヌずの盞性が悪かったりする堎合がどうしおもありたす 䞊叞やチヌムからの扱いが䜕かおかしいなず感じたら、身近な人にすぐに盞談 わからなければすぐ質問 「Aさんに聞きたいけど忙しいかも 」→忙しければそう蚀っおくれるず思うので、聞いたほうがいいです 「たず自分で考えるべきかも 」→自分で考えるべき疑問であればそう促すず思うので、聞いたほうがいいです 知識がただ乏しい段階で「自分で考えるべき問題か」「質問すべき問題か」を刀断するのは難しいです 䞊叞に質問されるこずに怯えなくおもよい 䞊叞や先茩からの質問は詰問や叱責の意図を䌎っおいない なんずなく「怒られおいるのかな」ず勘違いしないこず 䟋えば「ここのストラむプのデザむンはどういう意図をもっおストラむプにしたの」ず蚀われた時 × ストラむプじゃ倉だからマシなデザむンにしろ ○ 数倚あるパタヌンからストラむプを遞んだ理由はなんだろうストラむプは適切だろうか アりトプットをしよう ここでいうアりトプットずは、自分が知り埗た知芋や技術などを他の人が利甚できるように瀟内向けのドキュメントずしおたずめおおくこずです 「自分の持っおいる知識なんおみんな知っおるだろうしアりトプットしおも意味ないかも 」ずいうのは間違いです 「自分が思い぀くようなこずはほずんど誰かが先に思い぀いおいる」のは正しいです ですが「思い぀いたこずを文字や図にアりトプットしおいる」かどうかは別 たずえ被っおいるずころがあったずしおも、䞀字䞀句同じになるこずはないのでアりトプットする意味はありたす 「自分が新卒で経隓したこずなんおみんな知っおるしドキュメントにしおたずめおおく必芁なんかないか 」 →あなたの経隓ずみんなの経隓は圓然異なるので、あなたの経隓や感想を曞き留めおおくこずは今埌の新卒の糧になりたす おしごずをする䞊での行動の心構え 組織の人間であるこずを意識しお責任を持぀ デザむンに限らずですが、瀟䌚人ずしお・組織の人間ずしお恥ずかしくない立ち振る舞いが求められたす なにか䞍祥事があるず䌚瀟の名前に傷が぀き、それは瀟員党員の瀟䌚掻動に圱響したす あなたがデザむンしたものは、「䌚瀟の制䜜物」ずしお䞖の䞭に認識されたす 制䜜を進める時に、それはリリヌスしお問題ない衚珟かを考えおおくずよいです あなたの行動によっお起きた䞍利益は䌚瀟が被りたす 䞻䜓性を持぀ お仕事を任せる時、党然やる気がなさそうな人よりも実瞟のある人ややる気がありそうな人に任せたくなりたす なので自分から手を挙げお仕事を取りに行くような姿勢だず、お仕事も成長のチャンスも倚くなりたす 瀟颚にもよりたすが、実瞟がなくおも新人ならお仕事を任せおもらえる颚土があれば䞻䜓的になりやすいです 垞に積極的に手を挙げる姿勢が早いうちに身に぀くず、どんどんお仕事を任せおもらえお実瞟も増え、スキルもどんどん向䞊したす 圓事者意識を持぀ 䜕か問題が起きた時に、問題解決のために自分から動こうずする姿勢を芋せるず、呚囲からの信頌は厚くなりたす 「自分には関係ない事だから 」ずか、「新卒の自分が出る幕じゃないな 」ず思う人には䌚瀟ずしおは問題解決を任せたくないです 䜕か自分にできるこずはないかずりあえず考えるようにしおおくず、自分にもできるこずがあった時にすぐ動けるようになりたす スピヌド感を持っお動く 䟋えば䜕か䜜業を頌たれた時、他に特別優先すべき事項がなければ、先にその頌たれた仕事を終わらせお報告した方が呚囲からの評䟡は䞊がりたす 他の重芁なタスクや業務時間を犠牲にしおたで先にやれずいうわけではないですが、もし順番を前埌しおも倧䞈倫なら先に終わらせおしたった方が評䟡されるし信頌もされやすくなるのでのちのち自分にずっお埗になるず思いたす もちろん仕事のスピヌドずクオリティの䞡方を満たすのがベストなんですが、クオリティ面で未熟な新卒のうちにチヌムに貢献するにはスピヌド重芖に振り切っおしたっおもよいず思いたす すばやく䜜業しおいろんな人に芋おもらっお、より倚くのフィヌドバックをもらっお修正しおいく方が時短になりたす なるべく 早めに呌びかけに応じる できれば オフィスにいるずきはデスクで仕事をしおいるこずが芋えたすが、リモヌトワヌクだずそれが芋えないのでチヌムメンバヌがそれぞれ䜕をしおいるのか忙しいのか暇そうなのかすらわかりたせん なので返事が遅いず「ちゃんず仕事しおるのかな 」ずか「無芖されちゃったのかな 」ずか心配になりたす これは信甚しおいないわけではなく、関係が浅い新卒のうちはどうしおも䞍安に感じおしたうずいう話です なので呌びかけがあった時などはなるべく早く応答するようにするず、呚囲は「この人には安心しお仕事を任せられるな」ず感じたす ミヌティング䞭だったりずっおも忙しいずきは「あずで確認しおお返事させおいただきたす」ずか「ミヌティングの埌にお返事したす」ずかずりあえず芋たよずいうこずを䌝えおあげるず声をかけた人は安心できたす 業務をする䞊での心構え 「䌚瀟、チヌム、䞊叞が自分に期埅しおいるこず」が䜕かを考える 新卒に限らずですが 自分が今呚囲から䜕を期埅されおいるのか考えおみる機䌚を蚭けるずよさそうです 䜕を期埅されお採甚されたのかを考え、その期埅になるべく応えられるように動くず評䟡は䞊がりやすいず思いたす 逆に䜕を期埅されおいるのかの認識を間違えお、期埅されおないこずを頑匵っおしたうずせっかく頑匵ったのに評䟡されなかったり、仕事ができない人だず思われおしたったりしおかなしいです 考えおもわかんないよ〜ずいうずきは盎接䞊叞やメンタヌの人に聞いおしたっおよいず思いたす ミスしたらすぐに正盎に報告する ミスが埌から発芚しお倧ごずになるより、ミスをすぐに共有しおみんなでリカバリできた方が䌚瀟ずしおの損害は少なくなりたす なので、やらかしたら気付き次第すぐに誰かに報告したしょう 䟋えば  「すみたせん、Googleドラむブ䞊の○○のデヌタを誀っお削陀しおしたったのですが、どうすればよいでしょうか削陀しおしたったデヌタは○○、削陀しおしたったデヌタがあったドラむブのURLは○○です」などなど わからないこずはすぐに聞く 仕様、玍期、芁件、デザむンの方向性などなど 入りたおの頃はわからないこずが倚いのは䌚瀟の人たちもみんな知っおいるので、忙しいかもしれないし ずか思わず遠慮せずに聞くずよさそうです 誰に聞けばいいかわからない ずいうずきは、「わかる方お願いしたす」ずかで聞いたら誰かが適切な人に繋いでくれるず思いたす わからないたた1人で考えお業務時間を浪費するよりも、頻繁に質問しお仕事を少しでも進められる方が䌚瀟ずしおは助かりたす 質問するずきは回答しやすいように質問する 初めのうちは䜕もわからないので難しいかもですが、聞かれた偎がすぐに返事しやすい質問だずお返事が早く返っおきやすいず思いたす 䟋えば 「質問するずきに自分なりの答えを添えお質問する」 「お疲れ様です、 自分の手持ちの䜜業に぀いおです。 指瀺されおいた画像制䜜の䜜業が終わったのですが、次に䜜業した方が良い䜜業などありたすか 自分ずしおはこの䜜業タスク情報のURLなど添え぀぀が玍期近そうか぀自分でも察応できそうなので、次はこれを䜜業しようかなず思いたすがどうでしょうか 」 ずいう感じで ①なにに぀いおの質問かわかるように前眮きをする盞手が忙しかった堎合に緊急で返事した方がいいか埌でもいいかの指暙になりたす ②質問したい内容を具䜓的に曞く必芁に応じおURLなどあるずなおよいです ③質問に察する自分の意芋を添える意芋が合っおいれば「それでいいよ」で返事が枈みたすし、間違っおいれば盞手も䜕が勘違いの原因になっおいるのか把握しやすいです 䟋えば 「関連情報を提瀺しお適切な回答を匕き出す」 「お疲れ様です、 こちらの画像制䜜に関しお、制䜜で䜿甚する キャラクタヌの玠材画像を探しおいるのですが、どこにあるか教えおいただけたせんでしょうか Googleドラむブ䞊で怜玢したのですが芋圓たりたせんでした。 こちらの画像制䜜芁件は以䞋のURLです。 」 ずいう感じで ①なにに぀いおの質問かわかるように前眮きをする ②質問したい内容を具䜓的に曞く ③質問前にどう行動したかを添えるなぜ質問をするに至ったのかがわかるので、回答する偎もどんな情報を提䟛すればいいか把握しやすいです ④関連する情報を瀺すもしそもそもの質問が間違っおいた時に指摘できるので、自分が知り埗る関連情報は党お提瀺しおおくず認識の霟霬が少なくなりたす さいごに 個人的な心構えなので誰しも参考になる内容ではないず思いたすが、入瀟しお困った時に圹に立ったらうれしいです。
こんにちは。駅奪取゚ンゞニアの id:dorapon2000 です。 コヌド差分の倧きなプルリク゚スト以䞋、プルリクをコヌドレビュヌした経隓は倚くの方があるず思いたす。 プルリクは小さく・単䜍ごずに、ずは頭でわかっおいおも、実装しおいる内に想定よりも倧きくなっおしたったり、1぀のプルリクにたずめなければコンテキストが䌝わらなかったり、どうしおもずいうこずはありたす。本圓に申し蚳ないず思い぀぀レビュヌ䟝頌を出したり、出されたり。 今回は、巚倧なプルリクを前にしお、自分がどうモチベヌションを保぀か、どう読み解いおいくか、同じ状況を避けるためにレビュヌむず協力できるこずはなにか、に぀いお自分の堎合を䟋に玹介しおいきたす。 プルリクは小さく ここでは巚倧なプルリクは避けるべきだずいう前提で蚘事を進めおいきたす。 ぀たり、プルリクは可胜な範囲で小さい方がよいずいう前提です。 その理由は、コヌドレビュヌに関する優良な蚘事が倚くあるため、そちらに譲りたす。 たた、どれほどで巚倧かは䞻芳で倧䞈倫です。レビュアヌの心の゜りルゞェムが濁り始めたら、この蚘事が圹に立぀かもしれたせん。 リスペクトを忘れない 自分はレビュヌむに察するリスペクトがコヌドレビュヌで䞀番倧切だず考えおいたす。それは巚倧なプルリクでも同様です。 悪意があっおプルリクを倧きくしたわけではありたせんし、実装も倧倉だったはずです。 よりよいコヌドぞするために協力するずいう気持ちずねぎらいを忘れないようにしおいたす。 読み解く3぀の遞択肢 巚倧なプルリクには様々なコンテキストが埋め蟌たれおおり、レビュアヌはApproveする前にそれらを理解する必芁がありたす。 理解にかかる時間ず䜓力が、頭を重くする理由です。 モチベヌションを保぀ためにも、理解しやすくするためにも、自分は3぀の遞択肢を考えたす。 プルリクを分割しおもらう 䌚話をしながらレビュヌむに説明しおもらう 簡単なもの⇒メむン凊理の順に読む 1. プルリクを分割しおもらう プルリクが倧きいならば、分割するこずで1぀あたりの負担も小さくなりたす。 たず䞀番最初に考える遞択肢ですが、同じこずはレビュヌむも考えおおり、たいおい分割できたせん。 珟状から分割するには䜙蚈に実装コストがかかったり、そもそも分割するほうがレビュヌが倧倉になる堎合です。 2. 䌚話をしながらレビュヌむに説明しおもらう 匊瀟は完党リモヌトなため、通話をし぀぀画面共有しおもらいながら、プルリクの各差分の意味を説明しおもらいたす。 䌚話のメリットは、なにより心理的な負担が䜎いこずです。自分でコヌドを远わずずも、䜕をする箇所に、どういう倉曎を、どういった意図で入ったのかを理解できたす。 プルリクが巚倧なため、疑問点も倚く出おくるでしょう。それも通話であれば即座に解決したす。このスピヌド感は非同期でするレビュヌにはない魅力です。 もちろん、通話しおいる分だけレビュヌむの時間も必芁です。しかし、通話のあるなしで䞡者がレビュヌに掛ける合蚈時間の差はないように感じたす。 䌚話ぞ入る前に、レビュヌむは事前解説コメントをプルリク゚ストに残したり、レビュアヌはプルリク党䜓を眺めおおくこずで、よりスムヌズな䌚話になりたす。 たた䌚話埌も、䌚話の内容をプルリク゚スト内に蚘茉しおおくこずで、実装意図を芋返す際や他のチヌムメンバヌぞ共有する際に圹立ちたす。 3. 簡単なもの⇒メむン凊理の順に読む 3぀目の遞択肢は、プルリクを地道に読みたす。 レビュヌむず郜合が぀かないなどの、䌚話の遞択肢が取れない苊肉の策だず思っおいたす。 自分の堎合、小さいプルリクでは衚瀺されおいるファむルの䞊から順に芋たす。プルリクが小さいため、それでも内容を把握できたす。倧きなプルリクではそうはいきたせん。たず、独立した簡単なものから芋おいきたす。これは、メむンの凊理にある最も耇雑なコンテキストを理解する際のノむズを最初に陀去するむメヌゞです。 CSSの簡単な倉曎だったり、単玔な倉数名の倉曎だったりです。 ノむズの陀去埌は、メむン凊理をプログラムの実行順に䞊から読んでいきたす。 過去に、実装するずきは䞊から順に、レビュヌするずきはバラバラ、ずいう時期がありたした。しかし、レビュヌするずきも䞊から順に読むほうが理解しやすいです。 将来の巚倧なプルリク゚ストを避ける ここたででレビュヌは終わりです。 最埌に、巚倧なプルリク゚ストを分割する方法があったかを、レビュヌを通しお埗られたプルリクの理解をもずに考えたす。 䜕床も蚀いたすが、倧きなプルリク゚ストのレビュヌは倧倉です。その䜓隓を通しお、どうすれば分割できるのかノりハりが溜たっおいくはずです。 ノりハりをレビュヌむにも共有しお、適切な粒床のプルリク゚ストをチヌムの文化にしおいきたす。
こんにちは、駅奪取チヌム゚ンゞニアの id:kebhr です。 駅奪取チヌムでは Pull-Request を本番環境に反映する前に Jenkins を甚いおフルテストを実行しおいたす。 手順ずしおは Jenkins をキックするシェルスクリプトを䜿い、開発環境で次のようなコマンドを実行したす。 cd $PROJECT_ROOT # カレントブランチのテストを実行する ./jenkins # or # 特定のブランチのテストを実行する ./jenkins ${branch_name} しかし、このスクリプトは push 忘れのチェックを行っおおらず、 ブランチ・コミットを push し忘れた状態でフルテストを走らせおしたう ずいう問題点がありたした。 push 忘れに気付いたずきに push し、フルテストを走らせれば問題ありたせんが、フルテストを二床走らせるこずになるためリヌドタむムが長くなりたす。 そこで、ロヌカルに push しおいないコミットが存圚する堎合は、フルテストを実行せずに゚ラヌを衚瀺するようにスクリプトを倉曎したした。 党䜓像 #!/bin/zsh set -ue # äž­ç•¥ # 匕数たたはカレントブランチを取埗し $BRANCH にブランチ名を栌玍 if ! git show-branch remotes/origin/ $BRANCH > /dev/null 2 >& 1 ; then echo " このブランチは push されおいたせん " exit 1 fi if ! git diff remotes/origin/ $BRANCH .. $BRANCH --quiet --exit-code ; then echo " push されおいないコミットがありたす " exit 1 fi # Jenkins API をキック ブランチの push 忘れを刀定する if ! git show-branch remotes/origin/ $BRANCH > /dev/null 2 >& 1 ; then echo " このブランチは push されおいたせん " exit 1 fi git show-branch <branch> は、匕数に䞎えたブランチが存圚すれば終了コヌド 0、存圚しなければ 128 を返したす。 ブランチの push 忘れを刀定するためには、origin にそのブランチが存圚するこずを確認すればよいので、匕数に remotes/origin/$BRANCH を䞎えたす。 なお、この実装では、fetch しおいないブランチのテストを実行しようずした際に「このブランチは push されおいたせん」ず衚瀺され゚ラヌ終了したすが、チヌム内でこのような状況には盎面しないため蚱容しおいたす。 コミットの push 忘れを刀定する if ! git diff remotes/origin/ $BRANCH .. $BRANCH --quiet --exit-code ; then echo " push されおいないコミットがありたす " exit 1 fi git diff A..B --quiet --exit-code は A ず B の間に差分が存圚すれば終了コヌド 1、存圚しなければ 0 を返したす。 コミットの push 忘れを刀定するためには、リモヌトずロヌカルの差分を確認すればよいので、匕数に remotes/origin/$BRANCH..$BRANCH を䞎えたす。 git diff は > /dev/null 2>&1 ずいったコマンドを甚いずずも、 --quiet オプションによっお出力を抑制できたす。 --exit-code オプションは結果を終了コヌドでも返すオプションです。しかし --quiet オプションを指定するず暗黙的に --exit-code オプションが有効になりたす。よっお --exit-code オプションは省略できたすが、コヌドの理解を容易にするために蚘述しおいたす。
id:nesh です。 今回の蚘事では駅メモ゚ンゞニアで定期的に開催しおいる瀟内勉匷䌚「Denco Tech Night」に぀いお玹介したいです。 Denco Tech Night に぀いお この勉匷䌚は 2017 幎から始めたした。 瀟内勉匷䌚が促進されおいる環境であるため、その瀟内勉匷䌚の 1 ぀ずしお駅メモ゚ンゞニアチヌムによる勉匷䌚です。 開催抂芁 参加者は駅メモ゚ンゞニアが参加必須です。 たた、他チヌムの゚ンゞニアも任意で参加できたす。珟状は駅奪取チヌムの゚ンゞニアも定期的に参加しおいたす。 発衚する内容の絞りは特になく、業務で埗た孊びや個人的に勉匷したこず、チヌムでの取り蟌みの共有などがありたす。 駅メモチヌムの人数は倚いため、この勉匷䌚のタむミングで他の人が開発したツヌルや、業務䞊の Tips などが共有されたりしたす。 今たであった発衚のタむトル䟋です。 Web Component 觊っおみた AstroNvim で Neovim をはじめたした アクセシビリティず WAI-ARIA に぀いお Android プロゞェクトのビルドを理解しお速くする Perl5.36 の倉曎点 開催頻床は隔週で行っおいたす。 開催を始めた時に参加するメンバヌを決めお、䞀通り党員が発衚し終わったタむミングを䞀区切りにしお、次の開催頻床や時間垯を怜蚎したりしたす。 開催目的 Denco Tech Night を開催する目的は次のずおりです。 「人前で説明する」緎習 ニヌズの理解ず解決の蚓緎 技術的知芋の理解・共有 ブランディング それぞれの目的に぀いお補足したす。 「人前で説明する」緎習 瀟倖勉匷䌚に参加しお発衚するハヌドルを䞋げるために、瀟内でも発衚できる機䌚を蚭けお、人前で説明するこずを慣れおもらう目的です。 ニヌズの理解ず解決の蚓緎 開催抂芁にも曞いたように発衚する内容の決たりはありたせん。 各々が発衚する内容を怜蚎するずき、今のチヌムにずっおどういった発衚の需芁があるかを元に発衚のネタを決めるこずもありたす。 Denco Tech Night でそういった蚓緎をしたす。 技術的知芋の理解・共有 蚀葉通りでチヌム内の他の人ずの技術的知芋の共有をしたり、発衚を通しおチヌム内の理解床を同レベルに持っおいくための堎ずしお䜿えたす。 ブランディング 発衚した内容によっお、その人は䜕が埗意かずかがわかりたす。 䌁業や䌚瀟のブランディングの意味に近いですが、勉匷䌚を通じお、瀟内環境で自分自身のブランディングができたす。 勉匷䌚を継続するための工倫 2017 幎から継続しお Denco Tech Night が開催できたこずに察しお、どういった工倫があったかを蚀語化しおみたした。 発衚準備の手間を枛らす Denco Tech Night の発衚圢匏は自由です。ほずんどの人は Docbase *1 に蚘事を曞いお、発衚時はその蚘事を画面共有しながら発衚したした。 業務時間内に勉匷䌚の発衚資料を䜜成できるように 発衚資料䜜成には時間が必芁です。発衚資料を䜜成するハヌドルを䞋げるために、業務時間内で Denco Tech Night 資料を䜜っおも良いこずにしたした。 本来の開発業務に状況次第ではリスケ可胜 業務䞊で忙しいタむミング時に発衚順が来たり、緊急のトラブル発生がしたりのように、さたざたな原因で発衚が難しくなるこずもあるので、リスケはできたす。 他の人ず発衚順を亀換しおみお、ダメなら発衚をスキップする圢でリスケされたす。 たずめ 以䞊が駅メモ゚ンゞニアによる瀟内勉匷䌚「Denco Tech Night」 の玹介でした。 たた、勉匷䌚を継続できるための工倫をたずめおみたした。 *1 : 瀟内で暙準利甚しおいる情報共有ツヌルです。
こんにちは。駅奪取チヌム゚ンゞニアの id:dorapon2000 です。 よくシェルスクリプトのIF文に >/dev/null 2>&1 を曞いお条件文ずするこずはありたせんか。実行結果の成吊をIF条件ずしお利甚したいのであっお実際に出力したいわけではないケヌスです。 実は身近なコマンドでもオプションで出力を抑制できたす。3぀玹介したす。 怜蚌環境 grep --quiet git diff --quiet apt list -qq aptの譊告に぀いお 怜蚌環境 Ubuntu 16.04 bash 4.3.48 grep --quiet 特定の文字列を含むずきにだけif文を実行したす。 たず、 >/dev/null 2>&1 を䜿う曞き方。grepに匕っかかるず0を返し(True)、grepに匕っかからないず1を返したす(False)。 if cat /var/log/syslog | grep " Error " > /dev/null 2 >& 1 ; then echo ' Found ' fi --quiet オプションを䜿うこずで、出力を抑制しおくれたす。 if cat /var/log/syslog | grep --quiet " Error "; then echo ' Found ' fi # -q でも可 if cat /var/log/syslog | grep -q " Error "; then echo ' Found ' fi 以䞋のサむトでは、 --quiet を䜿うこずで高速化もするずいう嬉しい情報もありたす。 シェルスクリプトでファむルに特定の文字が含たれおいるかどうかを高速に刀定する方法 | ゲンゟり甚ポストむット git diff --quiet git差分があるずきにだけif文を実行したす。 たず、 >/dev/null 2>&1 を䜿う曞き方。 git diff は差分のありなしに関わらず正垞終了の0を返すため、ifで䜿うには --exit-code オプションが必芁です。差分があるずきに1を(False)、差分がないずきに0を返すようになりたす(True) # ① --exit-code を䜿う堎合 if ! git diff --exit-code > /dev/null 2 >& 1 ; then echo ' Diff ' fi あるいは --exit-code を䜿わず以䞋のように曞く人もいるでしょう。 # ② [を䜿う if [ `git diff | wc -l` -gt 0 ]; then echo ' Diff ' fi # ③ bash構文を䜿う if [[ `git diff | wc -l` > 0 ]] ; then echo ' Diff ' fi さお、git diffにも --quiet オプションがありたす。さらに --quiet オプションは暗黙的に --exit-code オプションを利甚しおおり、䞀石二鳥です。 if ! git diff --quiet ; then echo ' Diff '; fi 非垞にスッキリしたしたね apt list -qq aptで特定のパッケヌゞをむンストヌルしおいなかったらむンストヌルしたいこずは倚いです。 たずは、前述した grep --quiet を䜿うやり方から。 if apt list --installed sl | grep -q sl ; then sudo apt install sl -y fi これでいいじゃんですが、aptの -qq オプションでも同じこずができるため玹介したす。 aptの -qq オプションは --quiet オプションをより匷力にしたもので、進捗情報を消しおくれたす。ログ出力のためにあるオプションのようです。完党に出力を消すものではありたせん。 $ apt list --installed sl 䞀芧衚瀺... 完了 # <-- これが消える sl/xenial,now 3 .03-17build1 amd64 [ むンストヌル枈み ] $ apt list -qq --installed sl sl/xenial,now 3 .03-17build1 amd64 [ むンストヌル枈み ] したがっお、最初のif文は以䞋のように曞き換える事ができたす。 grep ^ でパむプで枡される出力が空かどうかを刀定したす。 if ! apt list -qq --installed sl | grep -q ^ ; then sudo apt install sl -y fi aptの譊告に぀いお 䞊蚘䟋を実行するず譊告が衚瀺されたす。 WARNING: apt does not have a stable CLI interface. Use with caution in scripts. 曞かれおいるずおりで、aptは出力フォヌマットが安定しおいるわけではないため、出力結果を加工するスクリプトはあたりよろしくないようです。 可胜なら別のコマンドを利甚したほうがよく、 apt list --installed に関しおは dpkg -l で代替できたす。 if ! dpkg -l | grep -q sl ; then sudo apt install sl -y fi
こんにちは、ブロックチェヌンチヌムの゚ンゞニア id:charines です。 この蚘事ではJavaScriptにおける unhandledrejection がどのような条件で発生するのかをクむズ圢匏でたずめおいたす。 unhandledrejection ずは unhandledrejection ぱラヌハンドリングされおいない Promise が拒吊されたずきにグロヌバルスコヌプに送られるむベントです。 developer.mozilla.org unhandledrejection が発生したずきの挙動は環境によっお異なりたすが、䟋えばNodeJSではプロセスが匷制終了するため、気づかぬうちに発生させないよう泚意が必芁です。 では具䜓的にどのような状況で unhandledrejection が発生するのかをクむズ圢匏で芋おいきたす。 クむズ 次のコヌドを実行したずき unhandledrejection は発生するでしょうか。 各問題のコヌドはNode v18.12.1にお怜蚌しおいたす 問1 Promise.reject(); 解答・解説 発生する Promise.reject は拒吊された Promise を返す関数です。゚ラヌハンドラがないため unhandledrejection が発生したす。 問2 Promise.reject() . catch (() => {} ); 解答・解説 発生しない Promise.prototype.catch ぱラヌハンドラを蚭定する䞀般的な方法です。今回は空の関数を枡しおいるため、匏党䜓は undefined に解決したす。 問3 Promise.reject() .then(v => v) .then(v => v, () => {} ); 解答・解説 発生しない Promise.prototype.then の第二匕数は Promise.prototype.catch で゚ラヌハンドラを蚭定するのず同じ働きをしたす。 たた、ハンドラはPromiseチェヌンを蟿っお呌び出されたす。 問4 const f = async () => { const p = Promise.reject(); await sleep(); p. catch (() => {} ); } ; f(); ※ sleep は䞀定時間埌に解決する Promise を返す関数で実装は以䞋です。 import { setTimeout } from "timers/promises" ; const sleep = () => setTimeout(50); 解答・解説 発生する 4行目で゚ラヌハンドラを蚭定しおいたすが、2行目の時点で凊理が開始されるため、 p ぱラヌハンドラの蚭定より先に拒吊されおしたいたす。 ハンドラは Promise の䜜成盎埌に蚭定するべきです。 問5 const f = async () => { await Promise.reject(); } ; f(). catch (() => {} ); 解答・解説 発生しない await で埅った Promise が拒吊された堎合、 await 匏はその倀で䟋倖を発生させ、 f() が返す Promise は拒吊されるこずになりたす。4行目で f() に察しおハンドラを蚭定しおるため、この堎合 unhandledrejection は発生したせん。 2行目の await がない堎合は問1ず同じ状況なので unhandledrejection が発生したす。 問6 const f = async () => { const p = Promise.reject(). catch (e => { throw e } ); await sleep(); await p; } ; f(). catch (() => {} ); 解答・解説 発生する ゚ラヌハンドラの䞭で䟋倖を投げた堎合、 catch はさらに拒吊される Promise を返したす。 たた、4行目で await をしおいたすが、それより前に p は拒吊されおしたうので unhandledrejection が発生したす。 問7 const f = async () => { const p = Promise.reject(). catch (e => e); await sleep(); throw await p; } ; f(). catch (() => {} ); 解答・解説 発生しない ゚ラヌハンドラによっお p は拒吊されず゚ラヌの倀に解決したす。 非同期関数内で䟋倖を投げる堎合は、問5の await で埅った Promise が拒吊されるパタヌンず同じで、 f() の返す Promise が拒吊されたす。これは6行目で゚ラヌハンドラが蚭定されおいるので unhandledrejection は発生したせん。 最埌に 7問の Promise を䜿った簡単な実装を甚いお unhandledrejection が発生する条件をたずめおみたした。 特に問6のように拒吊され埗る Promise を䜜成しお埌から await するずいうパタヌンで unhandlerejection が発生しおしたうようなケヌスは泚意すべきだず思いたす。 参考文献 PromiseのUnhandled Rejectionを完全に理解する 日本語の蚘事でECMAScriptの仕様を読み解いおいたす
こんにちは、゚ンゞニアの id:kaoru-k_0106 です。 CloudFront で gzip 圧瞮を有効にしたずころ転送量が枛ったのはもちろんですが、予想倖にリク゚スト数も枛ったため、理由が気になっお調査しお蚘事にしおみたした。 背景 駅奪取シリヌズは、2022 幎珟圚もフィヌチャヌフォンガラケヌをサポヌトしおおり、非垞に機胜が限られたブラりザぞの察応が必芁ずなりたす。 そのため、gzip 圧瞮や Accept-Encoding ヘッダに察応しおいない端末があったずきのため、圓初 CloudFront の gzip 圧瞮を有効にしおいたせんでした。 埌に怜蚌しお、問題ないこずがわかったため有効にしたのですが、その際、転送量が枛ったのはもちろんですが、リク゚スト数もなぜか枛少したした。 リク゚スト数も課金の察象ですのでありがたいのですが、理由を考えたずころ、gzip 圧瞮されたたたキャッシュするこずで、ディスクキャッシュに保存できるファむル数が増えたのではないかず考えたため、怜蚌しおみたした。 Chrome のディスクキャッシュはどこにある 手元の Mac の堎合以䞋のディレクトリにありたした。 ~/Library/Caches/Google/Chrome/Default/Cache/Cache_Data なお、プロファむル= Chrome のナヌザごずに分かれおおり、 Default の郚分を Profile 1 などに倉曎するこずで各プロファむルごずのキャッシュを芋られたす。 ファむル名はハッシュのようで䞭身はわからないですが、このように倧量のファむルが入っおいたす。念の為ファむル名にはモザむクをかけおいたす キャッシュされおるデヌタを芋おみる この画像がディスクキャッシュされおるようなので、キャッシュから掘り起こしおみたしょう。 探し方が分からなかったので、詊しに URL で grep しおみるこずにしたす。 $ find . -type f -print | xargs grep 'https://static.ekidash.com/v16378249952/img/portal/pc/description.png' Binary file ./xxxxxxxxxxxxxxxx_x matches Binary file ./xxxxxxxxxxxxxxxx_x matches それらしきファむルが 2 ぀ヒットしたしたが、2 ぀ずもバむナリファむルのようなので、バむナリ゚ディタを䜿っお開いおみたす。 今回は VS Code のバむナリ゚ディタ拡匵機胜である Hex Editor で開いおみたした。 PNG のファむルヘッダが芋えるこずから、レスポンスをそのたたキャッシュしおいる可胜性が高そうです。 参考: https://ja.wikipedia.org/wiki/Portable_Network_Graphics gzip 圧瞮されたファむルのキャッシュを探す 続いお gzip 圧瞮されたレスポンスを探しおみるこずにしたしょう。 js ファむルは CloudFront で gzip 圧瞮されるので、portal.min.js をキャッシュから探しおみたしょう。 $ find . -type f -print | xargs grep 'https://static.ekidash.com/v16536443652/js/dist/production/portal.min.js' Binary file ./xxxxxxxxxxxxxxxx_x matches Binary file ./xxxxxxxxxxxxxxxx_x matches 芋぀かったファむルを開いたずころ、ファむルヘッダが gzip になっおいたす よっお、Chrome ではキャッシュが gzip のたた保存されるこずがわかりたした。 参考: http://openlab.ring.gr.jp/tsuneo/soft/tar32_2/tar32_2/sdk/TAR_FMT.TXT Chrome のキャッシュの最倧サむズは 続いお、ディスクキャッシュの最倧サむズを調べたずころ、こちらの Q&A サむトに䌌たような質問がありたした。 https://superuser.com/questions/378991/what-is-chrome-default-cache-size-limit ChromiumChrome のベヌスだず䞀般的に 10% of the available disk space 䜿甚可胜なディスク容量の 10%ずのこずです。 このこずから、機皮䟝存でありたすが 1 ファむルあたりのサむズが小さくなるず、より倚くのファむルがディスクキャッシュされるようになりそうです。 しっかり怜蚌するのであれば比范実隓をしたほうが良いのですが、今回の調査はいったんここたでずしたす。 Safari のキャッシュに぀いお少し調べた ブラりザ゚ンゞンが異なる Safari だずキャッシュ呚りの仕様が違いそうなので、こちらも少し調べおみたした。 開発者ツヌルで確認したずころ、リロヌドしたずきはメモリキャッシュが䜿われたしたが、再起動した堎合はディスクキャッシュが䜿われたした。 キャッシュの有効期限はどうなっおる 今回 Cache-Control ヘッダの蚭定をしおいなかったのですが、キャッシュされたのはなぜだったのでしょうか 調べたずころ、以䞋のブログ蚘事でこう觊れられおいたした。 䞀般的には Last-Modified ヘッダの日時ず Date ヘッダの日時の差の 10%の倀を有効期間ずしお定めるこずが倚いず RFC7234 に蚘茉されおいたす。 匕甚元: Cache-Control ヘッダがないずきもブラりザがキャッシュする そのため、ずくに蚭定しなくおもキャッシュしおくれるようですが、Cache-Control でキャッシュする日数を明瀺したほうが良さそうですね。 なおキャッシュする堎合は、キャッシュバスティングする仕組みを入れおおきたしょう。 たずめ 断蚀はできたせんが、リク゚ストが枛った理由ずしお、gzip 圧瞮によっおファむルサむズが小さくなるこずでキャッシュされるファむル数が増えたからだず考えられたす。 そしお、バむナリ゚ディタはこんなずきにも圹立ちたすね。
こんにちは モバファクで採甚担圓ずしお働く @overallfactory です。 毎週土曜日は「良いモノ」を䜜る技術ずいうテヌマで、モバファクの非゚ンゞニアが知芋やTipsをお届けしたす。今回の蚘事では、「良いモノ」=「良い組織」ず捉えお゚ンゞニア採甚に぀いお玹介したす。 具䜓的に玹介しおいくのはカゞュアル面談に぀いお。 私が面談時にどのような準備を行い、どのような時間の䜿い方をしおいるのかに぀いお蚘事にたずめたした。 近幎では、珟堎で働く゚ンゞニアもカゞュアル面談に関わるこずが増えおきおいるかず思いたす。個人の考えではありたすが、少しでも参考になれば、嬉しいです。 カゞュアル面談ずは カゞュアル面談ずは、遞考の前に求職者ず䌁業の担圓者が情報を亀換し合う堎のこずです。 䌁業偎ずしおは、求人の詳现や䌁業情報に぀いおの説明を行い、求職者に興味を持っおもらうこずを目的ずしおいたす。 泚意しないずいけないのは、遞考ではないずいうこず。決しお合吊を刀定する堎にしおはいけたせん。 モバファクの採甚では、基本的に面接前にカゞュアル面談を実斜しおおり、䌚瀟に぀いお理解しおいただいた䞊で遞考に進んでいただいおおりたす。 カゞュアル面談の心構え カゞュアル面談を行うに圓たっお、特に倧切にしおいる心構えに぀いお3぀玹介したす。 䞀芋、非効率的ず感じるかもしれたせんが、5幎以䞊の採甚経隓をする䞭で、効率的な採甚においお非垞に重芁な考え方だず思っおいたす。 ①カゞュアル面談では興味を獲埗すべし カゞュアル面談では「候補者に魅力を䌝え、遞考に進んでいただく」こずを第䞀に考えおいたす。 モバファクは䞊堎䌁業ずはいえども、名前を聞いたこずがないずいう人はずおも倚いです。 だからこそ、最初の面談は超重芁。1時間皋床の面談で「面談/面接に䜕床でも足を運びたい」ず思っおもらわないずいけたせん。 面談をする限りは色々ず聞いおみたいこずがあるず思いたすが、たずは党力で宣䌝を行い、「ずりあえず受けおみよう」ず求職者に思っおもらいたしょう。話はそこからです ②嘘や適圓な発蚀はしない わからないこずは「わからない」ず回答をするこずも倧切です。 私ぱンゞニアではないので、蟌み入った技術の話には答えられたせん。 回答が難しい質問があれば、「わからない」ず正盎に答えた䞊で、「メヌルで返答する」「別途゚ンゞニアず面談の機䌚を䜜る」など真摯に察応をするこずを心がけおいたす。 その堎を誀魔化そうず、知ったかぶりをしおも、信頌を倱うだけです。 ③䌚瀟の魅力を理解すべし 自瀟のどんなカルチャヌ/事業が他瀟に比べお秀でおいるかを垞に考えたしょう。 䟋え優れた制床やカルチャヌが自瀟にあったずしおも、求職者が芋おいる䌁業でも同様に存圚するものであれば、䌝えおもあたり効果はありたせん。 せっかく魅力を䌝えるのであれば、求職者の人に「おっ今たでになかった魅力的な䌁業だな」ず、思っおもらいたいものです。 短い時間で効率的に自瀟の魅力を䌝えるためにも、垞に他瀟の状況に目を向け、自瀟がどういう匷みを持っおいるのかを客芳的に知るこずがずおも倧切です。 カゞュアル面談前に準備するこず 「面談/面接の質は事前準備で決たる」ずいう考えを、モバファク採甚チヌムでは倧切にしおいたす。 面談の質を高めるために、私の堎合は倧きく2぀のこずを事前に行っおいたす。 ①求職者の情報を知る 事前に求職者の情報をもらっおいる堎合は、必ず䞁寧に目を通すようにしおいたす。 面談に慣れおいるずいっおも、準備がないず面談がスムヌズにいかないこずが倚いです。 面談をスムヌズに回すためにも、事前にどんな質問をするかを10個以䞊は曞き出すようにしおいたす。 たた、求職者にずっおも䌁業が事前に情報を読み蟌んできおくれるこずに、悪い気はしないはずです ②カゞュアル面談のストヌリヌを考える どのような流れで、どんな話を䌝えるのかを现かくたずめたす。 事前に履歎曞を芋おいる堎合は、「技術的に成長ができる環境を求めおいるから、勉匷䌚制床や孊習支揎制床の話をしおみよう」など、どうやっお魅力を蚎求するかも詳现に決めおおきたす。 倧事なのは䞀本槍にならないこず。仮に勉匷䌚制床の話に共感しおもらえなかった堎合、瀟員のキャリアモデルの話をするなど、䞀歩先のこずも考えおおくず面談が円滑に進みたす。 求職者の情報が事前に芋れないずきは、どういった話の流れで就掻の軞や将来像を聞き、回答によっおどんな話をするか、堎合分けをしおおきたす。 カゞュアル面談の流れ では、実際にカゞュアル面談でどのような話をどのような流れで行っおいるのかを玹介したす 䟋倖もありたすが、私の堎合以䞋のような流れで進めるこずが倚いです。 カゞュアル面談は基本的には60分で実斜しおいたす。 ①アむスブレむク カゞュアル面談の目的には、ミスマッチを防ぐこずも含たれたす。 だからこそ、お互いに本音で話し合うこずが理想的。 初察面ずいうこずもあるので限界はありたすが、砕けた䌚話を冒頭でするこずで、カゞュアルな雰囲気づくりを意識しおいたす。 事前に求職者から情報をいただいおいる堎合は、出身地の話や趣味の話などに觊れるこずが倚いです。 ②目的/流れの説明 個人的には、目的の説明が最も倧事だず思っおいたす。 目的がふわっずした面談を防ぐためには、カゞュアル面談が面接の堎ではなく、求職者偎が䌁業を遞ぶ堎であるずいうこずを明確にするこずが䜕よりも倧切です。 具䜓的には、「カゞュアル面談の目的は䜕なのか」「この面談で䜕を刀断しおいただきたいのか」に぀いお䞁寧に説明をするようにしおいたす。 目的ず流れの説明を怠るず、認識の霟霬から「䌚瀟説明だず思ったら、質問攻めにされおしたった」など、䞍信感を求職者に抱かせおしたう堎合があるのでご泚意を ③求職者ぞのヒアリング 䌚瀟の説明に移る前に、必ず簡単なヒアリングを行うようにしおいたす。 求職者が就掻においお求めおいるこずがわからないず、蚎求すべき点も芋えおきたせん。 だからこそ、䜕に興味を持っおいお、どんな軞で就職掻動をしおいるのか、そしお将来的にはどんなスキルを身に぀けおいきたいのかは、かなり具䜓的に聞くようにしおいたす。 たた、これたでの経歎、開発物に぀いおもヒアリングを行っおいたす。 モバファクが求める人材は「プログラミングが倧奜きな人」。瀟員やカルチャヌずのマッチングを知るために、どのようなモチベヌションで開発を行っおきたかなどを䌺いたす。志向性等で気になるポむントがあれば、具䜓的にその旚をお䌝えし、認識の霟霬がないようにしおいたす。 ④䌚瀟の説明 ヒアリングで䌺った就掻の軞や将来像に察しお、䌚瀟の魅力を蚎求しおいきたす。 求職者によっお流れはたちたちで、勉匷䌚などの文化を求めおる人には、䌚瀟のカルチャヌに぀いお。裁量を求める人には、䌚瀟の方針や1、2幎目のキャリアモデルをメむンに。 サヌビス面に興味が匷い方には、サヌビスの詳现や各サヌビスのやりがいに぀いお説明をしおいきたす。 合わせお、求職者の垌望に応えられそうにない点に぀いおも䞁寧に説明を行いたす。 䞍信感を抱かせないためにも、できないこずは「できない」ず正盎に䌝えるようにしおいたす。 ⑀遞考の案内 面談の終わりに「䌚瀟説明を受けお、遞考ぞ進みたいず思っおくれたか」ず聞き、「進みたい」ず蚀っおくれた方には、遞考のご案内を行いたす。 泚意点ずしおは、冒頭の目的の説明時に、「遞考に進むか吊かを最埌に刀断しお欲しい」ずいう旚を䌝えおおくこず。 事前に䌝えおおかないず、求職者偎に匷制的な印象を䞎えおしたうかもしれたせん。 ミスマッチを防ぐためにも「No」ず蚀えるような雰囲気を䜜っおおきたしょう。 最埌に カゞュアル面談に぀いお蚘茉をさせおいただきたした。 個人的に意識しおいるこずなので、正解ではないず思いたす。 ですが、これからカゞュアル面談に関わるみなさたにずっお、䜕かしらのヒントになっおいれば、嬉しいです。 最埌に宣䌝です 珟圚モバファクでは、䞭途゚ンゞニア、新卒゚ンゞニアを募集䞭です。 ご興味ある方は以䞋をご芧ください https://recruit.mobilefactory.jp/recruit/
駅メモチヌムで゚ンゞニアをしおいる id:Eadaeda です。シバンは #!/usr/bin/env を䜿う掟です。 皆さんはシェルスクリプト曞いおたすか 環境構築、開発、テスト、ビルド、デプロむなどなど、䞀連の䜜業を自動化するための手段ずしお時々出番があるんじゃないでしょうか。 ずころでそのシェルスクリプト、テスト曞いおたすか シェルスクリプトのテスト 「シェルスクリプトのテスト〜」っお感じですよね。殆どの堎合、䞀床曞いおしたえばあんたり壊れるこずはないし別に っお感じですよね。わかりたす。実際開発環境のために docker compose up するだけのスクリプトなら雑でもいいですよね。 でも、重芁な圹割をも぀スクリプトならどうでしょう。䟋えばアプリケヌションの゚ントリヌポむントや、リリヌスビルド・デプロむのためのスクリプトなどが思い぀きたす。 こういうのはテストである皋床保蚌されおいれば安心じゃないですかどうですか曞きたくなっおきたしたかずりあえず䞀回曞いおみたせんか Bats/ShellSpecでシェルスクリプトのテストを曞いおみよう シェルスクリプトにもテストフレヌムワヌクがありたす。たずえば Bats や ShellSpec などです。 今回は䞊蚘2぀に぀いお少しだけ玹介しようず思いたす。テスト察象のスクリプトは以䞋のものずしたす。 #!/usr/bin/env zsh if [[ " ${1} " == " en " ]] ; then echo " Hello World " elif [[ " ${1} " == "" ]] ; then echo " こんにちは 侖界 " fi 第䞀匕数に en を枡せば Hello World を、䜕も枡さなければ こんにちは 侖界 ず出力するだけのスクリプトです。これを bin/hello-world.sh ずしお保存しおおきたす。 Bats Bats は10幎ぐらい前からあるそこそこ定番のテストフレヌムワヌクです。簡玠に曞けるのがいいずころかなず思っおいたす。 test/hello-world.bats ずしお以䞋の内容を保存したす。 #!/usr/bin/env bats # 出力を怜査するシンプルなテスト。シェルの構文っぜく曞く @ test " 匕数がないずき、こんにちは 䞖界が返されるべき " { result = " $( ./bin/hello-world.sh ) " [ " $result " = "こんにちは 侖界" ] } @ test " 匕数がないずき、こんにちは 䞖界が返されるべき - 2 " { # run を䜿うず $output に出力が栌玍される run ./bin/hello-world.sh [ " $output " = "こんにちは 侖界" ] } # bats-core/bats-supportずbats-core/bats-assertを ./test/helpers 以䞋にcloneしお読み蟌めば # 様々なヘルパヌが䜿えるようになっお䟿利 load ' helpers/bats-support/load ' load ' helpers/bats-assert/load ' @ test " 匕数がenのずき、Hello Worldが返されるべき " { run ./bin/hello-world.sh en # runの出力が䞀臎しおいるかを芋るヘルパヌ assert_output ' Hello World ' } 実行は bats コマンドに枡しおやればよいです $ bats ./ test /hello-world.bats hello-world.bats ✓ 匕数がないずき、こんにちは 䞖界が返されるべき ✓ 匕数がないずき、こんにちは 䞖界が返されるべき - 2 ✓ 匕数がenのずき、Hello Worldが返されるべき 3 tests, 0 failures setup/teardownも曞くこずができたす #!/usr/bin/env bats setup() { # ヘルパヌのロヌドをsetupでやっちゃう load ' helpers/bats-support/load ' load ' helpers/bats-assert/load ' } @ test " 匕数がenのずき、Hello Worldが返されるべき " { run ./bin/hello-world.sh en # setupでロヌドしおるのでヘルパヌが䜿えちゃう assert_output ' Hello World ' } ShellSpec ShellSpec はBDDな単䜓テストフレヌムワヌクです。RSpecずかJestみたいな曞き味でテストを曞いおいくこずができ、機胜も豊富です。 たずはプロゞェクトのセットアップです。最䜎限 .shellspec ファむルが必芁ずなりたすが、 shellspec --init で䜜成できるので、これを䜿うのが楜です。 $ shellspec --init create /path/to/ pwd /.shellspec create /path/to/ pwd /spec/spec_helper.sh あずは spec/ 以䞋にテストを曞いおいきたす。今回、READMEの Typical directory structure にならっおファむル名は spec/bin/hello-world_spec.sh ずしたした。内容は以䞋の通りです。なんだかプログラムっおいうか普通の文章みたいになりたすね。 Describe " bin/hello-world.shに぀いお " Context " 匕数がないずき " It " こんにちは 䞖界が出力されるべき " When call ./bin/hello-world.sh The output should eq ' こんにちは 侖界 ' End End Context " 匕数がenのずき " It " Hello Worldが出力されるべき " When call ./bin/hello-world.sh en The output should eq ' Hello World ' End End End テストの実行は shellspec --init したディレクトリで shellspec を実行するだけです # --shell指定なしだず /bin/sh になる $ shellspec --shell zsh Running: /bin/zsh [ zsh 5 . 8 . 1 ] .. Finished in 0 . 27 seconds ( user 0 . 04 seconds, sys 0 . 04 seconds ) 2 examples, 0 failures たずめ 今回はシェルスクリプトのテストフレヌムワヌクであるBatsずShellSpecの觊りだけご玹介したした。どちらを䜿うかはREADMEを読んでみお決めおみおくださいね。 以䞊です。
BC チヌムで゚ンゞニアをしおいる id:d-kimuson です 11月にリリヌスされた TypeScript 4.9 から satisfies operator が远加されたした。satisfies operator が远加されたこずで 「React Router でのナビゲヌションを型安党にする」がやりやすくなったのでやっおみたした この蚘事で玹介するコヌドは TS Playground で詊すこずができたす React Router v6.4 からオブゞェクト圢匏でルヌティングをかけるようになり、ルヌティング宣蚀から型を拟いやすくなった React Router v6.4 から createXXXRouter のAPIが远加され、コンポヌネントではなく、プレヌンオブゞェクトでルヌティングを曞けるようになりたした import { createBrowserRouter } from "react-router-dom" const router = createBrowserRouter ( [ { path: "/" , element: < HomePage / >, } , ] ) な圢匏でルヌティングを宣蚀できたす 以前からある <BrowserRouter> <Routes> <Route path="/" component={HomePage} /> </Routes> </BrowserRouter> なコンポヌネント圢匏のルヌティングでは難しかった、「宣蚀から型情報を読み取る」こずができるようになりたした ルヌティングの宣蚀に型の制玄を課したいが、具䜓な型に解決させたい ルヌティングの宣蚀から型情報を拟えるようになったので、良い感じに拟っお型安党なナビゲヌションを実珟したいなず考えたす しかし 宣蚀に型の制玄を課し぀぀ 型自䜓は宣蚀から具䜓な型に解決させる はちょっず実珟が面倒です ルヌティングオブゞェクトの宣蚀に RouteObject[] 型の制玄を課すために圢泚釈を぀けるず import type { RouteObject } from "react-router-dom" const routes: RouteObject [] = [ { path: "/" , element: < HomePage / >, } , ] 制玄は課すこずができたすが、routes は RouteObject[] 型に解決されおしたうので、具䜓的なルヌティング( / ) を型情報から拟うこずができたせん 宣蚀に合わせた型を拟いたいなら泚釈を぀けずに as const を䜿うのが有効です const routes = [ { path: "/" , element: < HomePage / >, } , ] as const ただし、今床は routes に RouteObject[] な制玄をかけられおいたせん 結果、補完が効かなくなったり宣蚀ではなく䜿甚箇所での型゚ラヌになっおしたったりで望たしくありたせん satisfies operator この問題が satisfies operator で解決しお、「制玄を曞けるが具䜓な型に解決させる」ができるようになりたした satisfies operator は型の制玄をかしたすが、解決される型には圱響を䞎えたせん したがっお import type { ReadonlyDeep } from "type-fest" // as const するず readonly 化しおしたうので type RoutesDef = ReadonlyArray < ReadonlyDeep < RouteObject >> const routes = [ { path: "/" , element: < HomePage / >, } , ] as const satisfies RoutesDef で宣蚀するこずで、 RouteObject[] な制玄でルヌティングを宣蚀し぀぀、routes には宣蚀通りの型に解決させるこずができるようになりたした 䞊の routes 倉数は実際に const routes2: readonly [{ readonly path: "/" ; readonly element: JSX. Element ; }] 型に解決され、制玄に違反するず型゚ラヌが出たす ※ satisfies がないず実珟できないずいうわけではなく、Vue 関連の゚コシステムでよく䜿われおいる defineXXX のパタヌンでも䞀応同じこずは達成できたしたが、satiesfies operator で実珟しやすくなりたした 遷移に制玄を぀ける routes を具䜓な型に解決させられるようになったので、型挔算を通じお型安党なナビゲヌションを実珟できたす サンプルずしお、以䞋のルヌティングの宣蚀を甚意したす const routes = [ { path: "/" , element: < HomePage / >, } , { path: "/nests" , element: ( < div > < h2 > Nests route < /h2 > < Nav / > < /div > ), children: [ { path: ":nestId" , element: ( < div > < h2 > nests 20 < /h2 > < Nav / > < /div > ), } , ] , } , ] as const satisfies RoutesDef typeof routes を扱いやすい型に敎圢する ルヌティングのネストは children で曞かれおいお䜿いにくいので、たずは䜿いやすい型に倉換しおいきたす type RouteConfig < T extends RoutesDef , U = ToRouteUnion < T >> = AsObjectShape < U extends { path: string } ? U : { path: string } > /** * @desc children のネストを解決しお Union にする * { * readonly path: "/"; * readonly element: JSX.Element; * } | { * readonly path: "/example"; * readonly element: JSX.Element; * } | { * readonly path: "/nests"; * readonly element: JSX.Element; * readonly children: readonly [...]; * } | { * path: "/nests/:nestId"; * } */ type ToRouteUnion < T extends RoutesDef > = T extends ReadonlyArray < infer I > ? MergeChild < I > : never /** * @desc 䜿いやすい Object 圢匏に敎圢 * { * "/example": { * path: "/example"; * }; * "/nests": { * path: "/nests"; * }; * "/": { * path: "/"; * }; * "/nests/:nestId": { * path: "/nests/:nestId"; * } & { * params: { * nestId: string; * }; * }; * } */ type AsObjectShape < T extends { path: string } > = { [ K in T [ "path" ]] : { path: K } & ( ParsePathParams < K > extends infer Params ? keyof Params extends never ? {} : { params: Params } : never ) } type MergeChild < T > = T extends { path: string children: ReadonlyArray < infer Children extends { path: string } > } ? | ( T extends { element: JSX. Element } ? T : never ) | MergeChild < { path: ` ${ T[ "path" ] } / ${ Children[ "path" ] } ` } & ( Children extends { children: any } ? { children: Children [ "children" ] } : {} ) > : T /** * @desc リテラルなルヌティング文字列からパスパラメタを抜出する * @example ParsePathParams<'/nests/:nestId'> = { nestId: string } */ type ParsePathParams < T extends string > = [ T ] extends [ ` ${ string } : ${ infer I1 } ` ] ? I1 extends ` ${ infer Param } / ${ infer I2 } ` ? Required < { [ K in Param ] : string } & ParsePathParams < I2 >> : { [ K in I1 ] : string } : {} こういうパズルを組みたす ここでは詳现な説明はしたせんが children にネストしおいたルヌティングをマヌゞしお それぞれのパスからパスパラメタを抜出しお 䜿いやすい型に敎圢 をしおいたす typeof routes を枡しおあげるず export type RouteConf = RouteConfig <typeof routes > これは以䞋に解決されたす type RouteConf = { "/" : { path: "/" ; } ; "/nests" : { path: "/nests" ; } ; "/nests/:nestId" : { path: "/nests/:nestId" ; } & { params: { nestId: string ; } ; } ; } 䜿いやすい型を抜出するこずができたした 型安党に遷移先のリンクを生成する 䜿いやすい型が手に入ったので、これを䜿っお型安党にパスを生成できる utility を䜜っおいきたす export const pagePath = < T extends keyof RouteConf >( path: T , ...args: RouteConf [ T ] extends { params: any } ? [ RouteConf [ T ][ 'params' ]] : [] ) : string => { const [ params ] = args as [ Record < string , string > | undefined ] return params === undefined ? path : Object .entries ( params ) .reduce ( ( s: string , [ key , value ] ) => s.replace ( `: ${ key } ` , value ), path ) } これで pagePath 関数を通すこずで型安党に遷移先のルヌティングを曞くこずができるようになりたした Link タグの to には pagePath の関数でパスを蚭定したす < ul > < li > < Link to= {pagePath('/')} > Home </ Link > </ li > < li > < Link to= {pagePath('/example')} > Example </ Link > </ li > < li > < Link to= {pagePath('/nests/:nestId', { nestId: '20' })} > Nests 20 </ Link > </ li > </ ul > useNavigate からの遷移でも同様に const navigate = useNavigate () const onClick = () => { navigate ( pagePath ( '/nests/:nestId' , { nestId: '20' } )) } ずするこずで、型安党なナビゲヌションを実珟するこずができたした その他の型安党ルヌティング ずいうこずで、React Router をそのたた䜿いながら型安党なナビゲヌションを実珟できたしたが、ルヌティングの宣蚀自䜓型を拟うこずを前提に䜜られおないので察応するのがそこそこ倧倉でした たた、ク゚リパラメタに぀いおも React Router のルヌティング宣蚀にはク゚リの型を曞くようなむンタフェヌスがないので拟うこずができたせん したがっお、本栌的に型安党を目指したい堎合は 型情報を拟うこずを前提にしたむンタフェヌスでルヌティングを宣蚀し、React Router に枡せる routes を吐き出すようなアプロヌチ react-router-typesafe-routes 等 型情報を拟うこずを前提にしたルヌティングラむブラリ Rocon 等 を䜿うのが良いず思いたす 䞀方、ルヌティングのむンタフェヌスを倉えおしたうず React Router 等のメゞャヌなラむブラリず比范しおメンテナスが滞ったずきや、バヌゞョンアップ時のマむグレヌションが぀らくなる偎面はありたす 今回玹介した「React Router のむンタフェヌスに乗っかりながら、可胜な範囲で型安党性を保蚌するアプロヌチ」の堎合、むンタフェヌス倉曎時のマむグレヌションも公匏のマむグレヌションに乗っかれば良いだけなので無難な遞択肢にはなるのかなず思いたす できればアプリケヌションコヌドにはこの蟺りを入れたくないので、願わくば、公匏や著名なずころからラむブラリずしお出おくれるず嬉しいんですが... たずめ satiesfies operator ず React Router v6.4 のオブゞェクト圢匏のルヌティングで暙準的な蚘法をそのたた䜿っお型安党なナビゲヌションを実珟するこずができるようになりたした たた、実際に最䜎限の実装䟋を玹介したした それでは良い型安党ラむフを