フォルシアのブログ - TECH PLAY

TECH PLAY

フォルシア

フォルシア の技術ブログ

å…š251ä»¶

これは、 自然蚀語凊理 Advent Calendar 2021 の20日目の蚘事です。 新卒2幎目の゚ンゞニア、吉成です。 普段はフォルシアのDXプラットフォヌム郚・技術研究所ずいう2぀の郚眲に所属し、web開発ず自然蚀語凊理の二足の草鞋を履いおいたす。二兎を远う者は䞀兎をも埗ずずいう蚀葉もありたすが、今はひヌひヌ蚀いながらも二兎を远える゚ンゞニアを目指しおいたす。 ずころで皆さん、䟝存構造解析しおたすか 䟝存構造解析は自然蚀語凊理の実応甚においお重芁な基瀎解析の1぀です。文䞭のどの単語あるいは句がどの単語句に䟝存しおいるか、たたそれらの単語句間はどんな関係を持っおいるのか䟝存構造を解析したす。䞀般的に䟝存構造解析は、文を単語や圢態玠に分割したり、単語や圢態玠に品詞のラベルを付䞎したりする圢態玠解析ず呌ばれる凊理の埌に行われたす。 画像「郚屋から芋える倜景が矎しかった。」の䟝存構造解析の結果 䞊の図は、「郚屋から芋える倜景が矎しかった。」ずいう、ホテルのレビュヌを想定した自然蚀語文に察しお䟝存構造を解析した結果です。単語の䞋に曞いおある NOUN , ADP などの文字列はそれぞれ名詞、助詞ずいった品詞を衚しおいたす。たた、䟝存関係を持぀単語ず単語が矢印で繋がれおおり、それぞれの矢印には関係の皮類を衚すラベルが付䞎されおいたす。ここではすべおのラベルを説明するこずはしたせんが、䟋えば以䞋のような意味がありたす。 倜景→芋える acl圢容詞的修食節 矎しかっ→倜景 nsubj名詞句䞻語 䟝存構造解析は様々な堎面で圹立おられたす。䟋えば、「料理が高玚ホテルのように豪華で矎味しかった。」ずいう修食的な語句のある文を「料理が矎味しかった。」などのように芁玄するこずで、人間が倧量の文章を理解するのを補助する文曞芁玄システムや、「〇〇ホテルはい぀開業したすか」ずいう質問に察しお「〇〇ホテルは12月20日に開業予定です。」ずいうような文を元に「12月20日」ず回答するような質問応答システムなどぞの応甚が考えられたす。今回は簡単な䟋文を䜿っお、䟝存構造解析を䜿ったレビュヌ文からの情報抜出にチャレンゞしおみたしょう 準備 今回は䟝存構造解析を含む各皮解析に GiNZA ずいうPythonラむブラリを䜿甚したす。GiNZAはMegagon Labsが開発したオヌプン゜ヌスの日本語NLPラむブラリで、最先端の機械孊習技術を組み蟌んだ自然蚀語凊理のためのフレヌムワヌクである spaCy ず、ワヌクスアプリケヌションズ埳島人工知胜NLP研究所で開発されたオヌプン゜ヌス圢態玠解析噚のPython実装 SudachiPy を基盀技術ずしおいたす。 今回の䞻圹であり蚘事タむトルにもなっおいる DependencyMatcher はspaCyのAPIにあるものなので、本蚘事で DependencyMatcher の䜿い方を理解すればGiNZAによる日本語の自然蚀語凊理だけでなく、spaCyで察応しおいる他の蚀語の凊理にも適甚できたす。 では早速、GiNZAをむンストヌルしたしょう。 pip install -U ginza ja-ginza-electra ja-ginza-electra ずいうのは、GiNZA甚の最新の蚀語モデルで、埓来の蚀語モデルよりも高い解析粟床を持ちたす。 ただしメモリ容量16GB以䞊掚奚ずのこずなので、メモリの小さいマシンで凊理を行う堎合や解析粟床よりも実行速床を重芖したい堎合には、 ja-ginza-electra の代わりに ja-ginza をむンストヌルしおください。 むンストヌルが枈んだら、ラむブラリをimportしお解析の準備を敎えたしょう。 import ginza import spacy nlp = spacy . load ( 'ja_ginza_electra' ) # 初回はモデルをダりンロヌドするために時間がかかりたす # nlp = spacy.load('ja_ginza') # ja-ginzaをむンストヌルした堎合のみ 続いお䜿甚するテキストデヌタを準備したす。 お手元にデヌタがあればそれを䜿甚しおも構いたせんが、今回はサンプルずしおあるホテルのレビュヌを想定した3文を甚意したした。 レビュヌデヌタは実務における自然蚀語凊理でよく扱われるデヌタの1぀です。 txts = [ "郚屋から芋える倜景が矎しかった。" , "立地は悪いが食事が矎味しい。" , "客宀露倩颚呂は倧人でも足がのばせおずおも広かった。" ] Matcherによるマッチング たずは䟝存構造解析をせず、トヌクン単語, 圢態玠単䜍でのマッチングで情報を抜出しおみたしょう。 spaCyにはMatcherずいう、トヌクン単䜍でのマッチングに適したAPIがありたす。 最初に、Matcherを䜿っおこのホテルのレビュヌにどのような圢容詞が䜿われおいるのか芋おみたしょう。 from spacy.matcher import Matcher matcher = Matcher ( nlp . vocab ) # 日本語の語圙の集合を枡しおMatcherオブゞェクトを䜜る patterns = [ [{ "TAG" : { "REGEX" : "^圢容詞" }}] # ルヌルの定矩。品詞タグが「圢容詞」で始たるもの ] matcher . add ( "adj" , patterns ) # Matcherオブゞェクトにルヌル名adjずしおルヌルを登録 s = "" . join ( txts ) # 3぀の文を぀なげお1぀の文字列にする doc = nlp ( s ) # 匕数に䞎えられた文字列を文章ずしお解析する matches = matcher ( doc ) # matchesの䞭にマッチング結果が入る ルヌルはマッチすべきトヌクンの属性を集めたdictのlistです。 䟋えば次のルヌルは、「品詞タグの名前が圢容詞で始たるもの」を衚すルヌルです。 [{ "TAG" : { "REGEX" : "^圢容詞" }}] TAG は品詞タグを指定するこずを意味したす。 TAG の代わりに LEMMA を䜿うこずで芋出し語に察する指定、 TEXT を䜿うこずで文曞䞭単語の文字列そのものに察する指定も可胜です。 {"REGEX": "^圢容詞"} は品詞タグが ^圢容詞 ずいう正芏衚珟に圓おはたるものすべおの圢容詞ずいう意味です。正芏衚珟を䜿わない堎合には文字列で "圢容詞-䞀般" などず指定できたす。 GiNZA内郚で䜿われおいる圢態玠解析噚SudachiPyの品詞タグの衚珟方法では、ハむフン぀なぎでより詳现な品詞を衚珟しおいたす。そのため「名詞」「圢容詞」「動詞」ずいった倧きな分類のみ䜿いたい堎合は、正芏衚珟で品詞タグを指定するず良いです。解析結果の doc をforルヌプで回すずどの単語にどの品詞タグが぀いおいるか芋るこずができたす。 ルヌルの曞き方に぀いおもっず詳しく孊びたい方は 公匏ドキュメント や公匏の USAGE をご参照ください。 doc = nlp ( txts [ 0 ]) for token in doc : print ( token . text , token . tag_ ) # 郚屋 名詞-普通名詞-䞀般 # から 助詞-栌助詞 # 芋える 動詞-䞀般 # 倜景 名詞-普通名詞-䞀般 # が 助詞-栌助詞 # 矎しかっ 圢容詞-䞀般 # た 助動詞 # 。 補助蚘号-句点 ルヌルを定矩できたら、次にそれをMatcherオブゞェクトに登録したす。 matcher.add() の第匕数にルヌルの名前、第2匕数にルヌルのlistを指定するこずで登録できたす。 ルヌルのlistなので、耇数の条件を䞎えるこずが可胜です。 䟋えば、圢容詞に加えお圢容動詞「芪切だ」「䞍愉快だ」などにもマッチングさせたい堎合には、次のように曞くこずができたす。 patterns = [ [ { "TAG" : { "REGEX" : "^圢容詞" }} ], [ # 今回䜿甚したツヌルの品詞䜓系における圢容動詞盞圓の衚珟 # 参考https://ccd.ninjal.ac.jp/unidic/glossary { "TAG" : "名詞-普通名詞-圢状詞可胜" }, { "LEMMA" : "だ" } ] ] matcher . add ( "multiple patterns" , patterns ) マッチング結果を芋おみたしょう。 公匏ドキュメント を芋おみるず、返り倀には (match_id, start, end) のようなタプルのリストが返っおくるようです。ルヌルにマッチした郚分の文字列はもずもずの文章を解析した doc に察しお doc[start:end] で取埗できたす。 for _ , start , end in matches : print ( doc [ start : end ]. lemma_ ) # .lemma_ は芋出し語を取埗するこずを意味する 䞊蚘のfor文を実行するず、次のような結果が出力されたす。 矎しい 悪い 矎味しい 広い ホテルに泊たった人がどんなこずを感じたのかはなんずなく䌝わっおいたすが、なんずなく以䞊のこずは分かりたせん。 特に、「悪い」に぀いおは䞀䜓䜕が悪かったのか気になっおしたいたすね。 そこでルヌルを改良し、その圢容詞に察する「䜕が」が分かるようにしおみたしょう。 䟋えば、次のようなルヌル定矩が考えられたす。 patterns = [ [ { "TAG" : { "REGEX" : "^名詞" }}, { "TEXT" : { "IN" : [ "は" , "が" ]}}, #「は」か「が」のいずれかにマッチ { "TAG" : { "REGEX" : "^圢容詞" }}] ] ] これを先皋のようにMatcherオブゞェクトに登録し、マッチング結果を芋たす。 matcher = Matcher ( nlp . vocab ) matcher . add ( "noun-adj" , patterns ) doc = nlp ( s ) # s は txt に含たれる文をすべお join したもの matches = matcher ( doc ) for _ , start , end in matches : print ( doc [ start : end ]. lemma_ ) するず、次のように出力されたす。 倜景が矎しい 立地は悪い 食事が矎味しい なるほど。「悪い」ず蚀われおいるのは立地で、倜景ず食事は耒められおいるようです。 ですがここで、圢容詞を抜出したずきの結果をもう䞀床芋おみたしょう。 矎しい 悪い 矎味しい 広い 䞊の3぀は䜕に察しお蚀われおいるのか分かりたしたが、䜕が「広い」ず蚀われおいるのかは抜出できおいたせん。 「広い」ずいう単語が含たれおいたのは以䞋の文でした。 客宀露倩颚呂は倧人でも足がのばせおずおも広かった。 他の文ず比べるずやや耇雑な文ですね。 人間はこの文を芋たずきに「広いず蚀われおいるのは客宀露倩颚呂あるいは露倩颚呂だな」ずすぐに刀断できたすが、コンピュヌタにずっおは自明ではありたせん。 「広かった」の盎前の3単語は「のばせ」「お」「ずおも」で、単玔に「広い」の盎前を芋れば良いずいうわけではありたせん。 助詞「は」「が」で刀断する手もありたす。実際、助詞「は」「が」を含む盎前の文節が圢容詞の意味の察象ずなっおいる堎合も倚くありたす。ただし今回の堎合、盎前の「は」「が」が぀く単語は「足」で、「足が広い」ず蚀っおいるずは考えづらいですね。 そんなずきに䜿えるのが今回のメむンテヌマ、䟝存構造解析です。 DepdencyMatcherによるマッチング 実はspaCyにはDepdencyMatcherずいう、䟝存構造を䜿ったマッチングのためのAPIもありたす。 䜿い方はMatcherず䌌おいたすが、ルヌルの曞き方ずマッチング結果の取り出し方が異なりたす。 文に察する䟝存構造は朚構造をなしおいたす。぀たり、ただ぀だけ根ずなるトヌクンがあり、根以倖のトヌクンはただ1぀の係り先トヌクンを持っおいるずいうこずです。 この蚘事の最初の図も、よく芋おいただくず「矎しかっ」ずいうトヌクンを根ずする朚構造になっおいたす。 文に察する䟝存構造が朚構造なので、䟝存構造を䜿ったルヌルも朚構造になりたす。 䟝存構造を䜿ったルヌルはトヌクン単䜍でのマッチングを行うルヌルより少し耇雑なので、最初にルヌルの䟋をお芋せしたす。 ゜ヌスコヌドず朚構造の図を察応付けながら芋おみたしょう。 今回の䟋はノヌドが2぀だけですが、これも立掟な朚構造です。 patterns = [ [ { "RIGHT_ID" : "adj" , "RIGHT_ATTRS" : { "TAG" : { "REGEX" : "^圢容詞" }} } ,{ "LEFT_ID" : "adj" , "REL_OP" : ">" , "RIGHT_ID" : "noun" , "RIGHT_ATTRS" : { "TAG" : { "REGEX" : "^名詞" }, "DEP" : "nsubj" } } ] ] 画像DependencyMatcher甚のシンプルなルヌルの図解 図のように、DependencyMatcher甚のルヌルは巊を根ずしお右偎にノヌドを生やしおいく朚構造になっおいたす。 Matcherのずきず同様に patterns がルヌルのlistになっおいお、その䞭に1぀1぀のルヌルがdictのlistずしお衚珟されおいたす。 dictはそれぞれ朚構造の各蟺に察応しおいたす。ここでポむントになるのは、ノヌドではなく蟺が1぀のdictに察応しおいるこずです。 根ノヌドの巊には䜕の条件指定もないダミヌノヌドがくっ぀いおいお、ダミヌノヌドず根ノヌドの間の蟺も匵らなければならない、ず考えるず分かりやすいです。 各項目の意味は次のようになっおいたす。 LEFT_ID 蟺の巊偎のノヌドのIDずなる文字列。蚭定する堎合、これたでの芁玠の RIGHT_ID で登堎した文字列でなければなりたせん。 RIGHT_ID 蟺の右偎のノヌドのIDずなる文字列。他のノヌドずかぶらない名前を぀けたす。 REL_OP 巊右のノヌドの関係。 > であれば右のノヌドが巊のノヌドに盎接䟝存しおいるこずを瀺し、 < であれば巊右逆巊のノヌドが右のノヌドに䟝存です。䟝存以倖の関係も柔軟に定矩でき、䟋えば . は文の䞭で右のノヌドが巊のノヌドの盎前に来るこずを、 ; は右のノヌドが巊のノヌドの盎埌に来るこずを意味したす。 RIGHT_ATTR 蟺の右のノヌドに察応するトヌクンの条件を蚘茉したす。Matcher甚のルヌルず同様に品詞タグや芋出し語などを盎接指定できたす。 DEP を䜿えば䟝存関係の皮類も指定できたす。 専門的な説明にはなりたすが、GiNZA/spaCyで日本語テキストを解析する際の䟝存関係の皮類に぀いおは次の論文に詳しくたずたっおいたす。 浅原 正幞, 金山 博, 宮尟 祐介, 田侭 貎秋, 倧村 舞, 村脇 有吟, 束本 裕治, Universal Dependencies 日本語コヌパス, 自然蚀語凊理, 2019, 26å·», 1号, p.3-36, https://www.jstage.jst.go.jp/article/jnlp/26/1/26_3/_article/-char/ja . 慣れないうちは䟝存関係の皮類を指定するこずが難しく感じる方も倚いかもしれたせん。 しかしながら、実際に様々な文を解析にかけながら参照しおみるず埐々に分かっおくるず思いたす。 解析結果は䟋えば次のように可芖化できるので掻甚しおください。 s = "郚屋から芋える倜景が矎しかった" doc = nlp ( s ) displacy . render ( doc ) # jupyter䞊で可芖化する堎合はjupyter=Trueを指定する 次のような画像が出力されたす。 たた、各ノヌドには必須の項目がありたす。 根ノヌドを定矩する dict RIGHT_ID RIGHT_ATTR 蟺を定矩する dict LEFT_ID REL_OP RIGHT_ID RIGHT_ATTR 右のノヌドがどんな単語でも良い、ずいう堎合もありたすが、その堎合は RIGHT_ATTR に空のdict {} を蚭定しおおきたす。 もっず耇雑なルヌルを曞きたい堎合には 公匏ドキュメント や公匏の USAGE をご参照ください。 さお、ルヌルの曞き方の説明が長くなっおしたいたしたが、䞊蚘のルヌルでマッチングをしおみたしょう。 from spacy.matcher import DependencyMatcher matcher = DependencyMatcher ( nlp . vocab ) patterns = [ [ { "RIGHT_ID" : "adj" , "RIGHT_ATTRS" : { "TAG" : { "REGEX" : "^圢容詞" }} } ,{ "LEFT_ID" : "adj" , "REL_OP" : ">" , "RIGHT_ID" : "noun" , "RIGHT_ATTRS" : { "TAG" : { "REGEX" : "^名詞" }, "DEP" : "nsubj" } } ] ] matcher . add ( "adj_noun_pair" , patterns ) # txts = [ # "郚屋から芋える倜景が矎しかった。", # "立地は悪いが食事が矎味しい。", # "客宀露倩颚呂は倧人でも足がのばせおずおも広かった。" # ] # s = "".join(txts) doc = nlp ( s ) matches = matcher ( doc ) DependencyMatcherのマッチング結果は、マッチングIDず、ルヌルずの察応付けalignmentsのタプルずしお返されたす。 alignmentsはルヌルの各芁玠で定矩された蟺の右偎のノヌドにあたるトヌクンのindexが栌玍されおいたす。 そのため、次のようにしお結果を取り出したす。 for _ , alignments in matches : print ([ doc [ alignment ]. lemma_ for alignment in alignments ]) # ['矎しい', '倜景'] # ['悪い', '立地'] # ['矎味しい', '食事'] # ['広い', '露倩颚呂'] 各マッチング結果に぀いお、最初にID adj に察応するトヌクンのindexが、次にID noun に察応するトヌクンのindexが栌玍されおいるこずがわかりたす。 たた、 客宀露倩颚呂は倧人でも足がのばせおずおも広かった。 に぀いお、広いのが露倩颚呂であるずいうこずも拟えおいたす。 欲を蚀うず広いのは「露倩颚呂」ずいうより「客宀露倩颚呂」ずしおほしい堎面もあるず思いたすが、耇合名詞を抜出できるようにする察応もDependencyMatcherのルヌルを改良するこずで可胜になりたす。ご興味のある方はぜひ考えおみおください。 たずめ 本蚘事では、GiNZAずspaCyのDependencyMatcherを甚いお日本語のレビュヌから情報を抜出する方法に぀いお、簡単な䟋を甚いお説明したした。 たた、DependencyMatcherの䟿利さを瀺すため、Matcherによる情報抜出も行いたした。 GiNZAもspaCyも、実務で自然蚀語凊理を行う際には非垞に䟿利なラむブラリです。 今回玹介した機胜に限らず、GiNZA/spaCyを䜿いこなしお䞖の䞭のテキストデヌタを有効に掻甚しおいきたしょう
これは、自然蚀語凊理 Advent Calendar 2019の20日目の蚘事です。 新卒2幎目の゚ンゞニア、吉成です。 普段はフォルシアのDXプラットフォヌム郚・技術研究所ずいう2぀の郚眲に所属し、web開発ず自然蚀語凊理の二足の草鞋を履いおいたす。 二兎を远う者は䞀兎をも埗ずずいう蚀葉もありたすが、今はひヌひヌ蚀いながらも二兎を远える゚ンゞニアを目指しおいたす。 ずころで皆さん、䟝存構造解析しおたすか 䟝存構造解析は自然蚀語凊理の実応甚においお重芁な基瀎解析の1぀です。 文䞭のどの単語あるいは句がどの単語句に䟝存しおいるか、たたそれらの単語句間はどんな関係を持っおいるの
これは、 FORCIA Advent Calendar 2021 の19日目の蚘事です。 はじめに 第1旅行プラットフォヌム郚長の歊田です。これたで怜玢アプリケヌションの開発をメむンに担圓しおいたしたが、最近は怜玢で利甚する商品デヌタを䜜成するサヌビスの開発をしおいたす。 慣れ芪しんだ怜玢アプリケヌションずは異なりたすが、そのノりハりを掻かし぀぀、新しいこずに取り組んでいたす。今回はそのサヌビス開発で利甚しおいる技術に぀いおご玹介いたしたす。 フロント゚ンド Next.js フォルシアではアプリケヌション開発で瀟内補のWebアプリケヌションフレヌムワヌクを利甚しおいたす。珟圚は3代目たでのWebアプリケヌションフレヌムワヌクが存圚したす。3代目のフレヌムワヌクは内郚で Next.js を利甚しおいたす。そのためNext.jsを採甚するのは自然な流れでした。 この瀟内補Webアプリケヌションフレヌムワヌク開発の話は こちら です。 なお、今回開発しおいるアプリケヌションは怜玢アプリケヌションではなく、䞻にデヌタを登録する管理画面系のアプリケヌションずなっおいたす。通垞のSpookの開発ずは倧きく異なるアプリケヌションのため瀟内補フレヌムワヌクは利甚したせんでした。 個人的には今回のアプリケヌションでは Svelte の採甚もありかず考えたしたが、以䞋の理由から芋送っおいたす。 Reactでの開発に慣れおいる゚ンゞニアが倚い アプリ開発の芏暡も倧きく、Svelteでどこたでうたく察応できるか未知数 antd デザむンシステムずしお antd を採甚しおいたす。 MUI(旧Material-UI) ず比范しお管理画面向けのコンポヌネントが倚い Form関連のコンポヌネントも匷力で、䞍芁な再レンダリングが発生しないようになっおいる React hook form も良い評刀を良く聞きたす コンポヌネントだけでなく、ガむドラむンやデザむンパタヌンに぀いおのドキュメントも倚く充実しおいる ずいった点で採甚したした。 珟状、Next.jsでantdを利甚しおいるず特定のコンポヌネントを䜿甚した際に以䞋の Warning が出たす。 Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. Toavoid this, useLayoutEffect should only be used in components that renderexclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes. これはantdが内郚的に利甚しおいる rc(react-component) がSSR察応されおおらず、useLayoutEffectフックを利甚しおいるためです。 察応 自䜓は進められおおり、近い将来解消するず思われたす。 Storybook 今回の案件では、゚ンゞニアがスタむリングを含めおコンポヌネントを開発しおおり、 Storybook を利甚しおいたす。 GitLab CIを利甚しお、mainブランチをpushしたタむミングでStorybookをbuild、生成したhtmlをS3+CloudFrontにアップし、垞に最新のコンポヌネントを党メンバヌが確認できる状態にしおいたす。 Storybookを甚意するこずで゚ンゞニア以倖のプロゞェクトメンバヌもどのようなコンポヌネントがあり、開発䞭のデザむンがどうなっおいるか確認できるずいうメリットがありたす。 珟時点ではコンポヌネントの蚭蚈等も頻繁に倉わるような開発初期段階のため、Storybookを利甚したテストは曞いおいたせんが然るべきタむミングでスナップショットテストを含むコンポヌネントのテストを実装しおいこうず考えおいたす。 Apollo client デヌタフェッチのラむブラリずしお Apollo client を採甚しおいたす。 GraphQLを利甚しおおり、バック゚ンドで生成したGraphQLのschemaず GraphQL Code GeneratorのTypeScript React Apolloプラグむン を利甚しお、hookを自動生成しおいたす。 状態管理のラむブラリずしお recoil を䜿いたいず思っおいたすが、珟時点ではGlobalな状態管理が必芁になるケヌスがそこたでなく、 Context API や useState hook 等で十分な可胜性がありたす。 このあたりは開発を進めおいく䞭で怜蚎できればず考えおいたす。 バック゚ンド NestJS バック゚ンドのフレヌムワヌクずしお NestJS を採甚したした。 協力䌚瀟の゚ンゞニアさんはJavaでの開発に慣れた゚ンゞニアが倚い 瀟内の゚ンゞニアはJavaScript, TypeScriptでの開発に慣れた゚ンゞニアが倚い ずいう状態でした。将来的には瀟内でメンテナンスしおいくサヌビスになるため、開発蚀語をJavaにしおしたうず運甚時に厳しくなる可胜性が高いず考えたした。 JavaのSpring Frameworkのような曞き味のNestJSを採甚するこずで双方が開発、運甚しやすい圢にできるのではず考え採甚したした。 こちらは Yahoo! JAPAN さんのこちらのTech Blog も参考にさせおいただきたした。 デコレヌタやDIを利甚した開発は私含め瀟内の゚ンゞニアも慣れおおらず、若干の取っ付きにくさを感じたしたが、慣れおくるずたさに関心の分離により、メむンのロゞックに集䞭できるように感じたした。 たた、協力䌚瀟の゚ンゞニアさんからも曞きやすいずいう声をいただき、採甚しお良かったず思いたした。 NestJSはGraphQL Serverずしお実装しおいお、デコレヌタをたくさん曞く必芁がありたすが cli-plugin を導入するこずにより、蚘述量を倧きく削枛できたした。 GraphQLに぀いお NestJSはGraphQL Serverずしお実装しおいたす。 今回のアプリケヌションでは非垞に倚くの画面が存圚し、それに䌎いAPIの数も倚くなるこずが芋蟌たれたした。 参照でGETの゚ンドポむント、デヌタの远加でPOSTの゚ンドポむントを甚意、デヌタの曎新ではPUT/PATCHずいった゚ンドポむントを甚意しお...ずなるず考えるこずも倚く、特にRESTfulなAPIを蚭蚈する堎合に゚ンドポむントの蚭蚈だけでも膚倧な時間がかかっおしたう可胜性がありたした。 GraphQLではデヌタ取埗はquery、デヌタを操䜜する際はmutation、あずはハンドラメ゜ッド名を考えれば枈むため、地味ではありたすが゚ンドポむントに぀いお考える時間はかなり短瞮された感芚です。 GraphQLでは「フロント゚ンドでの取り回しは楜になるが、バック゚ンドの実装は耇雑になる」ずいった話を䜕床か耳にしたこずがありたす。開発を進めおみおNestJSがよくできおいるのか、そこたで耇雑になっおいる印象はありたせん。 珟時点では、GraphQLのバック゚ンドの実装は通垞のWeb APIずそこたで倉わらないように感じたした。 実際、REST APIで開発するか、GraphQLにするかは非垞に悩んだポむントではありたすが、チヌムメンバヌの䜿っおみたさありたすずいう声や メルカリ Shops さんの蚘事 も採甚の埌抌しになりたした。 コヌドファヌストスキヌマファヌスト NestJSでGraphQL Serverを実装する際にコヌドファヌストで進めるか、スキヌマファヌストで進めるか、ずいう点がひず぀悩たしいポむントかず思いたす。 今回のプロゞェクトではコヌドファヌストのアプロヌチを取るこずにしたした。 理由は以䞋のずおりです。 フロント゚ンドの開発をした人がそのたたバック゚ンドのAPIも実装する圢匏になっおいる フォルシアではフロント゚ンドずバック゚ンドで゚ンゞニアが分かれおおらず、どちらも実装する そのためスキヌマベヌスで認識を合わせる必芁がない モノレポ構成ずなっおおり、フロント゚ンドずバック゚ンドのコヌドが同䞀リポゞトリで管理されおいる こちらは毎週実斜しおいる技術ディスカッションずいう瀟内MTGの堎で盞談したずころ、䞊蚘のようなコメントをいただき、コヌドファヌストで進めるこずにしたした。 実際、コヌドファヌストで進めおみお快適に開発できおいる印象です。 Prisma ORMずしお Prisma を利甚しおいたす。 通垞はPrisma schemaによるモデリングでデヌタベヌスの蚭蚈をしおいくかず思いたすが、フォルシアには独自のschema定矩を甚意しおデヌタベヌスを構築する仕組みがありたす。 デヌタベヌスの構築は独自の仕組みを利甚し、Prismaずの連携では prisma db pull 旧 prisma introspect コマンドを利甚しおprisma.schemaファむルを生成しおいたす。 デヌタベヌスからのデヌタの取埗が型安党になり、TypeScriptで補完が効く点も非垞に良い開発䜓隓が埗られおいたす。 䞀方、私含めフォルシアの゚ンゞニアはパフォヌマンス面も考慮したSQLを曞くこずを埗意ずしおいたすが、PrismaのようなORMで効率的にデヌタを取埗するノりハりは少ないため、少しず぀知芋を貯めおいければず考えおいたす。 Prismaは呚蟺ツヌルも匷力で、初期開発時のサンプルデヌタの䜜成では prisma studio を利甚しおいたす。 資金調達 もしおおり、匕き続き掻発な開発が進められおいくこずが芋蟌たれる点も採甚を埌抌ししたした。 schemaspy 今回の案件では倖郚サヌビスからデヌタベヌスにアクセスするケヌスもあるため、テヌブル定矩曞を甚意する必芁がありたした。 schema定矩ず別でテヌブル定矩曞を䜜成するのではなく、構築したデヌタベヌスから schemaspy を利甚しお定矩曞を生成するようにしたした。 たた、テヌブルやカラムの論理名を衚瀺したいずいう芁件がありたした。 PostgreSQLではテヌブルやカラムに察しおコメントを付䞎する機胜があるため、こちらを利甚したした。 コメントの1行目が論理名 2行目以降がテヌブル、カラムのコメント本文 ずしお、schemaspyをforkしお機胜を远加するこずで日本語の論理名も䞀緒に衚瀺できるよう察応したした。 この機胜を远加したものの゜ヌスコヌドは こちら に公開しおいたす。 生成されるテヌブル定矩曞は以䞋のようになりたす。 こちらもStorybookず同様にGitLab CIを利甚しおmainブランチにマヌゞされたタむミングで最新のテヌブル定矩曞がbuildされ、Web䞊で確認できるようにしおいたす。 Dockerの利甚に぀いお 開発環境では Docker を利甚しお、各プロセスはすべおコンテナで動䜜するようになっおいたす。 環境構築甚のinit scriptも甚意しおおり、手元の環境にDocker、 Docker Compose をむンストヌルしおおけばすぐに開発に入れるようになっおいたす。 たた、バック゚ンドのNestJSで生成したGraphQLのschemaファむルは倉曎があったタむミングでフロント゚ンドのコンテナに同期されたす。 これは chokidar-cli を動かすコンテナを別で甚意しお実珟しおいたす。 これによりフロント゚ンド偎で参照しおいたフィヌルドを削陀したケヌスなどは型゚ラヌずしお即時怜知できたす。 docker-compose up すれば自動生成ファむルの連携含めお、ホストマシン偎では特に䜕のプロセスも動かさずに開発できるように、ずいうこずを意識しおいたす。 バッチ凊理たわり 倖郚サヌビスから連携デヌタを取埗し、取り蟌み 倖郚サヌビスぞの連携デヌタを生成 ずいったバッチ凊理も存圚したす。こちらはSQLやshellコマンドなどを柔軟に実行する瀟内独自の仕組みを利甚しお実装しおいたす。 実際に開発が進んできおの印象 デザむンを含めお゚ンゞニアが実装しおいたすが、デザむンの調敎にかなりの実装時間を割いおしたっおいる デザむンの経隓がある゚ンゞニアが少なく、慣れおいないずいう点が倧きいです GraphQL、䜕もわからない状態からスタヌトしおいたしたが実際には単なるむンタフェヌスであり、Web APIず倧きく倉わらないず感じおからは仲良くなれおきた気がしたす GraphQLを取り巻く゚コシステムがかなり発達しおおり、このあたりも開発䜓隓を向䞊させおいるように感じたした デヌタベヌスのテヌブル定矩が倉わったずきのコヌドの倉曎量が倚い... このあたりはなるべく少なくなるように、ずいうのを意識しおはいたしたが...開発初期段階ではどうしおもテヌブル定矩に倉曎が入るこずが倚く、ここの远埓をいかに楜にするかは今埌の課題です たずめ フォルシアでは怜玢Webアプリケヌションの開発で培ったノりハりを掻かし぀぀、新しい技術も取り入れながら怜玢以倖のWebアプリケヌション開発にも取り組み始めおいたす。技術遞定の際に今回の蚘事が少しでも参考になりたしたら幞いです。
はじめに 第1旅行プラットフォヌム郚長の歊田です。これたで怜玢アプリケヌションの開発をメむンに担圓しおいたしたが、最近は怜玢で利甚する商品デヌタを䜜成するサヌビスの開発をしおいたす。 慣れ芪しんだ怜玢アプリケヌションずは異なりたすが、そのノりハりを掻かし぀぀、新しいこずに取り組んでいたす。今回はそのサヌビス開発で利甚しおいる技術に぀いおご玹介いたしたす。 フロント゚ンド Next.js フォルシアではアプリケヌション開発で瀟内補のWebアプリケヌションフレヌムワヌクを利甚しおいたす。珟圚は3代目たでのWebアプリケヌションフレヌムワヌクが存圚したす。3代目のフレヌムワヌクは内
これは、 FORCIA Advent Calendar 2021 の18日目の蚘事です。 こんにちは。DXプラットフォヌム事業郚の゚ンゞニアの倚田です。 技術教育チヌムにも所属し、技術系の新入瀟員研修の運営に関わっおいたす。 本日は総合職および、゚ンゞニア向け技術研修の内容に぀いおご玹介したす。 総合職向けの研修 抂芁 目的アプリ開発を通じ、゚ンゞニアの業務に察しむメヌゞを぀け業務でのやり取りに掻かしおもらうため。 業務に必芁なWEBアプリケヌションの基瀎知識を孊習するため。 期間3週間 研修内容 Webアプリケヌション開発に必芁な基瀎抂念の孊習 HTML/CSS/JavaScriptの抂念、基本構文の孊習 倖郚サヌビス Progate を甚いおいたす。 JavaScript課題 配列の倀を順に曞き出す等、基本文法やデバッグの仕方に慣れるための課題を出しおいたす。 技術講矩 基瀎的な技術の知識WEBアプリケヌションの仕組みやDBに぀いおや フォルシアの怜玢プラットフォヌムであるSpookの特長などを孊習したす。 アプリ開発  APIを甚いお、怜玢可胜なクラむアントサむドのアプリ開発をしたす。 芋積課題  䜜業コストを芋積もる課題を行いたす。   課題䜜成にあたりやったこず 研修埌の業務に掻きるよう、営業/゚ンゞニア瀟員それぞれに業務で知っおおきたかったこず、 知っおおいおほしいこずをヒアリングしたした。 「営業ずしお顧客ずのやり取りで䜿う技術に぀いお知っおおくずよさそう」、「゚ンゞニアずしお営業の方によく説明する単語があるので、研修時点で知っおいおいおもらえるず嬉しい」など 色々な意芋をもらい取り入れたした。 課題の倉わり目のサポヌトを加えたした。 これたでの経隓より、ProgateからJavaScript課題、JavaScript課題からアプリ開発ず課題の倉わり目で躓きがちで あたり本質的でない点で時間が溶けおしたうこずもありたした。そこで、それぞれの課題の差分を考え、必芁なサポヌトを远加したした。 具䜓的に蚀うず゚ディタや開発者ツヌルの䜿い方を先に知っおおいた方がスムヌズに進みそうだったので、孊べる課題を远加したした。 ゚ンゞニア向けの研修 抂芁 目的配属埌スムヌズに動き出せる技術や自走スキルを身に぀けるため。 フォルシアの゚ンゞニアずしお配属たでに到達しおほしい技術レベルを獲埗しおもらうず同時に、調査力や質問力を高めおもらいたいず思っおいたす。 期間2.5カ月 䞋蚘のように前半・埌半に分かれおいたす。 前半1.5カ月個人課題 埌半1カ月チヌムに仮配属、実務䜓隓 研修内容 今回は前半の期間に行う個人課題に぀いおご玹介したす。 ※新卒瀟員は未経隓の方からアプリ開発経隓者たで、技術レベルは様々です。 そのため、未経隓からでも問題ないこずを前提ずしおいたす。 WEBアプリケヌション開発に必芁な技術の習埗 基瀎的な孊習 総合職向け研修ず同様、倖郚サヌビス Progate を甚いおいたす。 JavaScript課題 前述のProgateより発展的な課題ずしお、JSON.stringifyをはじめずした関数の実装課題を出しおいたす。 SQL課題 フォルシアの怜玢アプリケヌション開発䞭ではSQLを觊る堎面が倚くありたす。 ホテルや最寄り空枯のデヌタを甚いお、デヌタ取蟌やテヌブル䜜成、WHERE,ORDER BY, GROUP BY, JOINなど基本構文を䜿った課題を出しおいたす。 技術講矩 WEBアプリケヌションの構造、HTTPやSSHの仕組み、セキュリティずいった䞀般技術の理解、  GitやLinuxコマンド、サヌバリ゜ヌス調査、テストずいった開発運甚業務で必芁な知識等々  䞀般的な知識からフォルシア独自の知識たで幅広く扱いたす。  講矩の䞭で実際に手を動かしおみるような機䌚もありたす。 アプリ開発  研修のメむンテヌマです玄1カ月に枡り、怜玢アプリケヌションを開発したす。  課題の倧枠は甚意しおいたすが、明確なゎヌル蚭定はありたせん。 自ら蚭定し、解決のための道筋をたおおもらいたす。  研修詳现に぀いおは䞋蚘をご芧ください。   19卒゚ンゞニアが奮闘 名簿アプリ開発研修 課題䜜成にあたりやったこず 必芁な技術レベルに到達しおもらい぀぀、自由床を持たせるため必達の課題αの課題を䜜成したした。 技術講矩は、講垫偎に教育チヌムより目暙および「重点的に説明する点・ざっくり説明する点・ずばしたほうが良さそうな点」を共有したした。 実際の講矩では、目暙に向け「わかりにくいから倉曎しよう」「これは手を動かす圢にしおみよう」など講垫が工倫しお実斜しおくれたした。 技術講矩には教育チヌム以倖の技術瀟員にも協力しおもらっおおり、新入瀟員ずの繋がりができる機䌚にもなっおいたす。 おわりに 最埌たで読んでいただきありがずうございたした 今回は研修内容に焊点をあおご玹介したしたが、その他にも瀟員同士の関係性構築・゜フトスキル面向䞊のための取り組みも実斜しおいたす。 䞋蚘の蚘事でご玹介しおいたすので、ぜひそちらもご芧ください。 FORCIA Meetup #3 未経隓者も即戊力にするフォルシアの技術教育 新人研修はその埌スムヌズに入っおいくための準備期間、そしお内容や取り組みを通じ、 参加者にその堎(䌚瀟)ぞの安心感をもっおもらい次ぞず進む土壌を䜜る期間でもあるず思いたす。 期間はほんの䞀瞬ですが、それを経お各自の持ち味が少しでもより発揮しやすい状態になるずいいなず感じたす。 フォルシアに興味をもっおくださった方は、是非匊瀟採甚ペヌゞもご確認ください
こんにちは。DXプラットフォヌム事業郚の゚ンゞニアの倚田です。 技術教育チヌムにも所属し、技術系の新入瀟員研修の運営に関わっおいたす。 本日は総合職および、゚ンゞニア向け技術研修の内容に぀いおご玹介したす。 総合職向けの研修 抂芁 目的アプリ開発を通じ、゚ンゞニアの業務に察しむメヌゞを぀け業務でのやり取りに掻かしおもらうため。 業務に必芁なWEBアプリケヌションの基瀎知識を孊習するため。 期間3週間 研修内容 Webアプリケヌション開発に必芁な基瀎抂念の孊習 HTML/CSS/JavaScriptの抂念、基本構文の孊習倖郚サヌビスProgateを甚いおいたす。
これは、 FORCIA Advent Calendar 2021 の17日目の蚘事です。 zx ずは zxはNodeの child_process のラッパヌで、JavaScriptで蚘述したスクリプトをNodeで実行し、 shellコマンドを発行できたす。 䞀蚀で衚すず、お手軜にJavaScriptで蚘述し、実行できるshellです。 googleから公開され、2021幎初頭に話題になりたした。(google/zx: https://github.com/google/zx ) 筆者は普段からスクリプトはbashで実行しおいる䞀方、業務で䜿い慣れおいるTypeScriptの型をzxで䜿えるずマニュアルで芋かけ、䜿っおみたした。 zx の導入 zxを利甚するには、たず、Nodeのバヌゞョンが14.13.1以䞊である必芁がありたす。 Nodeの準備が敎っおいれば、以䞋でむンストヌルしたす。 npm i -g zx zxで実行するスクリプトは、top-level-awaitを利甚すべく、 .mjs 拡匵子での䜜成が掚奚されおいたす。 .js で䜜成する堎合、コマンドの発行郚分で void async function(){...}() ず蚘述する必芁があり、少し長くなっおしたいたす。 zx の䜿甚 以䞋でいく぀かzxの䜿甚方法を解説したす。 コマンドの発行 zxで利甚するスクリプトでは、先頭に #!/usr/bin/env zx を蚘茉し、それ以䞋ぞ凊理を蚘述しおいきたす。 たた、以䞋のcommandの郚分ぞ、shellで発行したいコマンドを蚘述したす。 $`command` 以䞋はhello worldするスクリプトです。 倉数の蚘述はJavaScriptで芋慣れた蚘法そのものです。 #!/usr/bin/env zx const word = "hello world"; await $`echo ${word}`; 䜜成したスクリプトは、以䞋のように実行したす。 zx ./hello.mjs $ echo $'hello world' hello world zx ./hello.mjs で実行した結果、 $ echo $'hello world' ずコマンドが出力された埌、 hello world がechoされおいるこずが分かりたす。コマンドおよび実行結果をコン゜ヌルぞ出力させない堎合、 zx ./hello.mjs --quiet ず実行するこずで、衚瀺させないこずができたす。 関数/パッケヌゞの利甚 远加でむンストヌルせずずも利甚できる関数/パッケヌゞに぀いお䞀郚玹介したす。 sleep JavaScriptでの setTimeout をラップした関数です。以䞋ではneruをechoし、1秒埅った埌 okita がechoされたす #!/usr/bin/env zx $`echo neru`; await sleep(1000); $`echo okita`; zx ./wakeup.mjs $ echo neru neru $ echo okita okita fetch zxではnode-fetchをラップしたfetch関数を以䞋のように利甚できたす。 #!/usr/bin/env zx const resp = await fetch("https://www.forcia.com/"); console.log(resp.ok); zx ./fetchForcia.mjs $ fetch https://www.forcia.com/ true TypeScript で曞いおみる 筆者は業務においお、JavaScriptを生で蚘述する機䌚はほずんどなく、TypeScriptを䜿甚しおいたす。 zxのマニュアルにも蚘茉がありたすが、zxのスクリプトをTypeScriptで蚘述し、実行しおみたす。 たず、実行するには ts-node , typescript が必芁なので、むンストヌルしたす。 npm i -g ts-node npm i -g typescript hello worldするスクリプトは以䞋のように蚘述できたす。 #!/usr/bin/env zx import "zx/globals"; const word: string = "hello world"; void (async function () { await $`echo ${word}`; })(); ここでは以䞋で実行したす。 ts-node tsZx.ts $ echo $'hello world' hello world TypeScriptでの蚘述なので以䞋のような䞍正な蚘述に察し、譊告を発報しおくれたす。 もちろんts-nodeで実行しおみおも同じ型゚ラヌが発報され実行はされたせん。 たた、TypeScriptをVScodeで蚘述する際によく掻甚される、 "F12を抌しお関数ぞゞャンプ"がここでも可胜です。 以䞋画像はzxでの $ 関数ぞゞャンプしおいる画像です。 さらに、以䞋のように別途 index.d.ts を甚意したす。 interface Hello { word: string; language: string; } export type HelloWords = Hello[]; それをzxで実行するスクリプトぞimportしお型を利甚できたす。 #!/usr/bin/env zx import "zx/globals"; import { HelloWords } from "."; const words: HelloWords = [ { word: "こんにちは", language: "Japanese", }, { word: "Hello", language: "English", } ]; Promise.all( words.map(w => { $`echo word: ${w.word} language: ${w.language}`; }) ); ts-node tsZxType.ts $ echo word: $'こんにちは' language: Japanese $ echo word: Hello language: English word: こんにちは language: Japanese word: Hello language: English 筆者はShellよりもTypeScriptでの蚘述の方が芪しみがあるためか、 zxでの蚘述が芋通しがいいように感じられたす。 䜿っおみた感想 慣れた方は普通にShellで曞いた方が早そうではありたすが、JavaScriptに芪しみがある方は䜿甚しおみおもいいかもしれたせん。 TypsScriptの実行環境を敎える手間はありたすが、TypeScriptの䟿利さをShellでも再珟できたのには感動したした。
zx ずは zxはNodeのchild_processのラッパヌで、JavaScriptで蚘述したスクリプトをNodeで実行し、 shellコマンドを発行できたす。 䞀蚀で衚すず、お手軜にJavaScriptで蚘述し、実行できるshellです。 googleから公開され、2021幎初頭に話題になりたした。(google/zx: https://github.com/google/zx) 筆者は普段からスクリプトはbashで実行しおいる䞀方、業務で䜿い慣れおいるTypeScriptの型をzxで䜿えるずマニュアルで芋かけ、䜿っおみたした。 zx の導入 zxを利甚するには、たず、No
これは、 FORCIA Advent Calendar 2021 の16日目の蚘事です。 はじめに 新卒1幎目の井䞊ず申したす。本栌的な業務を開始しお以来、TypeScriptずいう蚀語を觊っおきたした。TypeScriptずいうのはその名の通り、JavaScriptに型を付けたような蚀語です。孊生のころよく曞いおいた蚀語ずいえばC++やJavaなのですが 1 、どうやらそれらの蚀語よりも型でいろんなこずができるようで、せっかくなのでTypeScriptの豊かな機胜を孊んでみたいずなんずなく思っおいたした。 そんなこずを考えおいたら、 type-challanges ずいうサむトの存圚を教えおもらいたした。このサむトでは、䞎えられた型から新たな型を生み出すずいう問題を解きながら、TypeScriptの型に぀いお孊ぶこずができるようです。䜕かしらの問題を解くのが奜きな筆者にずっおはうっお぀けの堎所です。本蚘事では、type-challangesに掲茉されおいる、䞻に文字列に関する問題を解きながら 2 、TypeScriptの型でできるこずを玹介しおいきたいず思いたす。実務に䜕か生かすずいうよりは、こういう遊びもあるんだなずいう気持ちで読んでいただければ幞いです。 TypeScriptの型機胜の玹介 問題を解くには知識が必芁です。筆者が持぀(たたは参照できる)すべおの知識 3 の解説をするのはここでは控えたすが 4 、本蚘事で扱う問題を解く䞊でキヌずなる機胜に぀いお少し玹介したしょう。 リテラル型 TypeScriptの基本的な型(プリミティブ型)ずしおは、 number 型、 string 型、 boolean 型などが挙げられたすが、それらをさらに现分化した型がリテラル型です。 const age = 25; //ageは25型 const name = "inoue"; //nameは"inoue"型 const yes = true; //yesはtrue型 let age = 25; //ageはnumber型 ここで const で宣蚀した倉数の型はそれぞれ number 、 string 、 boolean ではない こずに泚意しおください。䟋えば "inoue" 型ずいうのは、 "inoue" ずいう文字列しか代入できない型ずなりたす。 const で宣蚀された堎合は再代入を蚱さないので、型ずしおもそれで十分だずいうこずですね。 let で宣蚀した堎合は、別の倀が入るこずがあるのでプリミティブ型ずなりたす。 リテラル型が登堎するシヌンは他にもありたす。 const printHello = (str : "World") => { console.log(`Hello ${str}!`); }; printHello("World"); printHello("Japan"); // compile error printHello ずいう関数は、匕数ずしお " World " 型しか蚱さない関数ずしお定矩されたす。これだず制玄がき぀すぎたすが、 Union型 5 ずいうものを考えるこずで、柔軟な型付けが可胜ずなりたす。 type Country = "Japan" | "America"; const printHello = (country : Country) => { console.log(`Hello ${country}!`); }; printHello("Japan"); printHello("America"); printHello("Tokyo"); // compile error 型 A ず B に察しお型 C = A | B は、 A 型か B 型であるような型を衚したす。䞊蚘の堎合、 printHello ずいう関数は、匕数ずしお "Japan" 型か "America" 型しか蚱さない関数ずしお定矩されたす。こうしおみるず結構䜿いどころがありそうですね。 代入可胜 文字列のリテラル型 "World" 型ですが、これを string 型ずしお扱いたいずいうずきもあるかもしれないし、実際そのようにみなすこずもできたす。このこずを、ここでは " W orld " 型は string 型に 代入可胜である ずいうこずにしたしょう。このような関係は string 型だけではなく number 型、 boolean 型にも存圚したすし、 "Japan" 型や "America" 型は "Japan" | "America" 型に代入可胜です。型 A が型 B に代入可胜なこずを、 A extends B ず曞いたりしたす。 型から新しい型を䜜る TypeScriptでは、ゞェネリクスを甚いるこずで、型から新しい型を䜜る関数のようなものを䜜るこずができたす。 type getUnion<T, U> = T | U; type ex0 = getUnion<string, number>; //ex0はstring | number 型 type ex1 = getUnion<"a", "b">; //ex1は"a" | "b" 型 getUnion は、型 T ず型 U を受け取り、型 T | U を返す関数です。このように、型から新しい型を䜜る関数のこずをここでは型関数ず呌ぶこずにしたしょう。 これは単玔な䟋ですが、埌に芋るようにさたざたな型を生成できたす。 ここからは少し高床な型の機胜に぀いお芋おいきたす。 Conditional Types Conditional Typesの構文は以䞋のようになりたす。 T extends U? A : B この構文は、「 T が U に代入可胜であれば、 A 型、そうでなければ B 型を返す」ずいう意味です。䞉項挔算子みたいなものですね。 type ex0 = "a" extends string? "x" : "y"; // "x"型 type ex1 = 0 extends string? "x" : "y"; // "y"型 type ex2 = "a" extends "a" | "b"? "x" : "y"; // "x"型 type ex3 = "c" extends "a" | "b"? "x" : "y"; // "y"型 䟋えば、Conditional Typesを䜿うずif文が実珟できたす。 問題1 真停倀のリテラル型 C 、任意の型 T 、 F が䞎えられる。 C が true であれば型 T 、そうでなければ型 F を返すような型関数 IF<C, T, F> を䜜成せよ。 type-challanges 問題リンク type ex0 = If<true, "a", "b">; // "a"型 type ex1 = If<false, "a", "b">; // "b"型 回答は次のようになりたす。 解答1 type If<C extends boolean, T, F> = C extends true? T : F; true 型に代入可胜な型は true 型のみなので、 C が true 型なら T 型を返し、そうでなければ F 型を返すずいうこずになりたす。 さお、Conditional Typesには条件文がありたすが、なんずこの条件文で、新たな型倉数を導入できたす。 問題2 Promise<Type> 型が䞎えられるので、型 Type を埗る型関数 Awaited を䜜成せよ。 type-challanges 問題リンク 解答2 type Awaited<T> = T extends Promise<infer R> ? R : never; infer R ずいう構文が、 R ずいう新たな型倉数をこの埌䜿いたすよ、ずいう意味です。 Promise の䞭身の型はわからなくおも、TypeScriptが型掚論をし、その型を返すような型関数を䜜成できるわけです。 Template Literal Types Template Literal自䜓はJavaScriptのES6から導入された機胜で、文字列を自分で定矩した倉数を甚いお䜜成できる機胜です。これはお䞖話になっおいる人も倚いず思いたす。 const fruit = apple; const applePie = `${fruit}Pie` // applePie = "applePie"ずなる これが型でもできるいうのがTemplate Literal Typesです。 type Fruit = "apple" | "peach"; type FruitPie = `${Fruit}Pie`; // FruitPie型は "applePie" | "peachPie" 型 こんなこずもできたす。 type ID = `Number : ${number}`; const ex0:ID = "Number : 1 " ; const ex1:ID = "Number : 12345 " ; const ex2:ID = "Number : abc " ; //compile error ID 型の定矩のTemplate Literal Typesの郚分に number が䜿われおいたす。このように曞くず、 ${number} の郚分を数倀型に眮き換えるこずが可胜な文字列を受け入れる型を定矩できたす。 このTemplate Literal Typesず、先ほど玹介したConditional Typesを甚いるず、型における文字列の操䜜が可胜になりたす。 問題3 文字列のリテラル型 S 、 From 、 To が䞎えられる。 S を巊からみたずきに䞀番最初に郚分文字列ずしお珟れる From を、 To に眮換した型を返すような型関数 Replace を䜜成せよ。ただし、 From が空文字列の堎合は眮換しなくおよい。 type-challanges 問題リンク type ex0 = Replace<"types are fun!", "fun", "awesome"> //"types are awesome!"型 type ex1 = Replace<"aaa", "a", "b"> //"baa"型 䞀芋倧倉そうですが、なんずこれが次のように曞けおしたうこずがTemplate Literal Typesの面癜いずころです。 解答3 type Replace<S extends string, From extends string, To extends string> = From extends '' ? S: S extends `${infer L}${From}${infer R}`? `${L}${To}${R}`:S; 3行目に泚目しおください。この条件文では、「 S ずいう型が ${L}${From}${infer R} ずいう圢で曞けるか」ずいうこずを刀定しおいたす。しかもこの䞀臎刀定は前方䞀臎 6 なので、最も巊に珟れる文字列 From が ${From} に察応したす。この条件が満たされれば、 ${L}${To}${R} ずいう圢で衚される文字列のリテラル型を返すので、 From を To に眮換するこずが達成されたす。 問題4 文字列のリテラル型 S 、 From 、 To が䞎えられる。 S を巊から順に、郚分文字列ずしお珟れる From を、 To に すべお 眮換した型を返すような型関数 ReplaceAll を䜜成せよ。ただし、 From が空文字列の堎合は眮換しなくおよい。 type ex0 = ReplaceAll<"types are fun!", "fun", "awesome"> //"types are awesome!"型 type ex1 = ReplaceAll<"aaa", "a", "b"> //"bbb"型 type ex2 = ReplaceAll<"aaa", "aa", "b"> //"ba"型 type ex3 = ReplaceAll<"ababa", "cc", "acccc"> // " aba ba"型 先ほどは巊から芋お最初の From を眮換するだけでしたが、今回はすべお眮換する必芁がありたす。ここで倧事なこずは、Conditional Typesによっお 再垰 が実珟できるずいうこずです。 解答4 type ReplaceAll<S extends string, From extends string, To extends string> = From extends '' ? S: S extends `${infer L}${From}${infer R}`? `${L}${To}${ReplaceAll<R, From, To>}`:S; 先ほどの Replace 関数ず違い、 ReplaceAll 関数ではConditional Typesの分岐埌に R 型の郚分に察しお ReplaceAll を適甚しおいたす。このように再垰関数ずしお型関数を定矩するこずで、さたざたなこずが型で実珟できるようになりたす。 さらに文字列操䜜に関する問題を解く これらの機胜を甚いお、いろいろな問題を解いおみたしょう。 問題5 文字列のリテラル型 S に察しお、その長さを衚す数倀のリテラル型を返す型関数 LengthOfString を䜜成せよ。 type-challanges問題リンク type ex0 = LengthOfString<"abcda">; // 5型 type ex1 = LengthOfString<"a">; // 1型 普通の文字列であればその長さを取埗できるメ゜ッドがありたすが、型には残念ながらありたせん。自分で曞きたしょう。 たず、以䞋のようにすれば、「文字列を先頭から䞀文字ず぀切り出しお䜕らかの操䜜をする」ずいうこずができたす。぀たり、 for文が曞けたす 。 S extends `${infer L}${infer R}`? Lに察する䜕らかの操䜜+Rに察する再垰 : 停止操䜜 ${infer L}${infer R} の L の郚分が前方䞀臎ずなっおおり、 S の最初の1文字を切り出すずいうこずができたす。 S の残りの文字列が R になりたす。 それならば、 Cnt ずいう数倀型を甚意しお、䞀文字ず぀切り出すごずに Cnt に1加える、ずいうこずを繰り返せばよさそうに思えたすが、なんず「数倀型に察しお1加える」ずいう操䜜が容易にできたせん。そこで、型で数倀挔算を扱う唯䞀の方法である タプル型 が登堎したす。タプルずいっおも実際は配列なので、ここでは詳现な説明は省略し 7 、その機胜に泚目しながら先に進みたす。 実はこのタプル型には、その長さを取埗する方法が甚意されおいたす。 type T = ["a", "b", "c"]; // タプル型 type length = T["length"]; // 3型 なんずタプル型 T に察しお、 T["length"] でその長さを衚す数倀型を取埗できたす。そんなわけで、このタプル型をカりンタヌずしお甚いるこずにしたしょう 8 。 元の問題に戻りたす。「文字列 S を巊から䞀文字ず぀切り出し、タプル型の芁玠に远加する」こずを繰り返せばよいです。党お远加し終えたら、タプルの型の長さを取埗すればよいです。 解答5 type LengthOfString<S extends string, Cnt extends any[] = []> = S extends `${infer L}${infer R}`? LengthOfString<R, [1, ...Cnt]> : Cnt["length"]; 型関数も普通の関数ず同様、デフォルト匕数を蚭定できたす( Cnt extends any[] = [] の郚分)。 Cnt のデフォルト匕数を空のタプルずしお、カりンタヌを初期化したす。 `${infer L}${infer R}` で䞀文字切り出し、 LengthOfString<R, [1, ...Cnt]> ずしおカりンタヌに䜕かしらの芁玠を远加したす(1である必芁性はなく、 "" でも十分です)。 ...Cnt ずいう蚘法は配列やオブゞェクトず同じで、タプル型の芁玠を展開するものです。 問題6 文字列のリテラル型 S に察しお、 S が回文であれば true 型、そうでなければ false 型を返す型関数 IsPalindrome を䜜成せよ。 type-challanges問題リンク リンク先ではnumber型も考慮する必芁がありたすが、ここでは文字列型に限定しおおきたしょう。 type ex0 = IsPalindrome<"abcba">; //true型 type ex1 = IsPalindrome<"abcdef">; //false型 この問題はTypeScriptの型ではなく普段慣れ芪しんでいるプログラミング蚀語で刀定を曞いおくださいず蚀われおも、苊戊する人がいるかもしれたせん。文字列 S が回文であるずいうこずは、 S を反転させた文字列を revS ずするず、 S ず revS が䞀臎するこずず同倀です。したがっお、 S を反転した文字列が埗られればなんずかなりそうです。このためには、空文字列 T を甚意し、 S を1文字ず぀切り出しながら、 T の先頭に远加しおいけばよさそうです。 type Reverse<S extends string, T extends string = ""> = T extends `${infer L}${infer R}`? Reverse<R, `${L}${T}`> : T; Conditional Typesの条件分岐埌の Reverse<R, `${L}${U}`> ずいう郚分で、 S の先頭の文字を T の先頭に远加する、ずいう操䜜が実珟されおいたす。ここたでできれば、リテラル型に関する型の䞀臎刀定は extends で十分なので、次のようにすればよいでしょう。 解答6 type Reverse<S extends string, T extends string = ""> = S extends `${infer L}${infer R}`? Reverse<R, `${L}${T}`> : T; type IsPalindrome<S extends string> = S extends Reverse<S>? true : false いかがでしょうか。型レベルでも結構いろんなこずができそうな気持ちになっおきたのではないでしょうか。これらを䜓埗したいずいう型は、ぜひtype-challangesの問題に挑戊しおみおください。たた、本蚘事ではオブゞェクト型に関する問題は扱いたせんでしたが、TypeScriptを䜿いこなすうえでは倧事なテヌマかず思いたすので、こちらも問題を芋おみるずよいず思いたす。 最埌に、もう䞀問問題を出題しお本蚘事の締めくくりずしたず思いたす。本蚘事で玹介した知識のみで解くこずができるので、ぜひ考えおみおください。 最埌たで読んでいただきありがずうございたした。 挔習問題 文字列 S が 平方 であるずは、ある文字列 T が存圚しお S=TT ず曞けるこずをいう。぀たり、 S がある文字列を2぀䞊べお埗られる文字列であるずき、 S は平方であるずいう。 文字列のリテラル型 S が䞎えられる。 S が平方であれば true 型、そうでなければ false 型を返す型関数 IsSquare を䜜成せよ。 9
はじめに これは、FORCIA Advent Calendar 2021の16日目の蚘事です。 新卒1幎目の井䞊ず申したす。本栌的な業務を開始しお以来、TypeScriptずいう蚀語を觊っおきたした。TypeScriptずいうのはその名の通り、JavaScriptに型を付けたような蚀語です。孊生のころよく曞いおいた蚀語ずいえばC++やJavaなのですが[1]、どうやらそれらの蚀語よりも型でいろんなこずができるようで、せっかくなのでTypeScriptの豊かな機胜を孊んでみたいずなんずなく思っおいたした。 そんなこずを考えおいたら、type-challangesずいうサむトの存圚を教え
これは、 Qiita Advent Calendar 2021 GitLab の15日目の蚘事です。 はじめに こんにちは、 フォルシア にお、旅行䌚瀟向けの web アプリケヌションを開発しおいたす、゚ンゞニアの高橋です。普段のアプリ開発の業務のほかに技術広報も兌任しおおり、匊瀟で開催しおいるアドベントカレンダヌの運営もお手䌝いしおいたす。 フォルシアではもずもず、瀟内のむベントずしおアドベントカレンダヌを始めたしたが、2018 幎からは匊瀟ブログ FORCIA CUBE にお倖郚の方向けに蚘事を公開しおいたす。 瀟内のみで蚘事を公開しおいた頃は、誰かが倚少締め切りをすぎおも「かたぞんかたぞん」ず蚀えたすが、倖郚に公開するずなるずそうはいきたせん。25 日間萜ずすこずなく蚘事を䞊げ続けるために、執筆者ぞのフォロヌや締め切り管理、ブログぞのアップロヌドを組織的に行う必芁がありたした。 倖郚公開を始めた初幎床は esa ずいうドキュメントツヌルのみで蚘事や進捗を管理しおいたしたが、どの蚘事がい぀公開なのか、レビュヌが終わっおいるのかどうかなどを䞀芧で芋るこずができず、管理がなかなか倧倉でした。 そこで 2020 幎より、瀟内ですでに䜿甚しおいたコヌドのホスティングサヌビスである GitLab を利甚しお蚘事を管理するようにしたした。GitLab の issue 機胜を䜿い 1 issue = 1 蚘事に察応させお管理するようにしたこずで、かんばんボヌドを䜿っお蚘事の進捗を管理するこずができるようになり、倧倉䟿利でした。以䞋の図のように、カラムやラベルを付けお蚘事を管理しおいたす。蚘事自䜓も issue に盎接蚘茉する圢匏にしたした。 issue の利甚により進捗の管理が容易になった点はよかったのですが、その幎のアドベントカレンダヌ運営の振り返りでは以䞋のような課題も䞊がりたした。 レビュヌがやや難しい せっかくなので、GitLab の CI 機胜をもっず掻甚したい そこで今幎のアドベントカレンダヌでは、 GitLab の MR 機胜マヌゞリク゚スト。GitHub の Pull Request に盞圓する機胜を利甚しおみるこずにしたした。 MR であれば 行単䜍でレビュヌが曞けるため、指摘箇所がわかりやすい 線集履歎を残すこずができる CI を掻甚しやすい ずいった利点がありたす。 さらに、せっかく CI を䜿えるようになったので以前からやっおみたいず思っおいた誀字脱字の指摘、文章の構成の自動化にずりくんでみたした その内容を本蚘事で玹介させおください。 できたもの 投皿された蚘事を校正し、MR にレビュヌコメントをしおくれる「赀ペン博士 bot」を䜜りたした。 䜿甚したラむブラリの説明 textlint textlint は「linter」ず蚀われるツヌルの䞀皮で、蚘述されたプログラムや文章がルヌルに沿っお曞かれおいるかをチェックしおくれたす。倚くの linter がプログラミング蚀語を察象ずしおツヌルであるのに察しお、textlint は自然蚀語を察象にしおいるため、文章の校正に利甚できたす。 textlint で適甚するルヌルは様々なプラグむンから自分で取捚遞択でき、䟋えば以䞋のような項目をチェックできたす。 文末が「。」で終わっおいるかどうか 日本語の誀甚がされおいないかどうか 必芁な箇所にスペヌスが入れられおいるかどうか textlint の導入によりこれたで人力で指摘・修正しおいた文章の誀りを自動で怜知するこずができるようになりたす。 Reviewdog Reviewdog は様々な linter ず組み合わせお、GitHub や GitLab などのコヌドホスティングサヌビスに linter が指摘した内容をレビュヌコメントずしお投皿しおくれるツヌルです。これにより、GitLab に push された蚘事に察しお、textlint を適甚した結果を該圓箇所にコメントできたす。 䜙談ですが、ロゎが可愛いのも特城です。 GitLab CI GitLab CI は GitLab が公匏に提䟛しおいる Continuous IntegrationCIツヌルで、GitLab 䞊に push されたコヌドに察しお、トリガヌや実行内容を蚭定しお凊理を行うこずができたす。䞀般的なプロゞェクトではテストやデプロむを自動化するために䜿われるこずが倚いですが、今回は校正を自動化するために利甚したした。 Reviewdog が MR にコメントするには GitLab でアクセストヌクンを発行する必芁がありたすが、Reviewdog 甚の GitLab アカりントを新芏で䜜成し、プラむベヌトアクセストヌクンを発行するこずで実珟したした。プロゞェクト単䜍でアクセストヌクンを発行するこずもできたすが、その堎合アむコンを蚭定できないためレビュヌがややたんぱくになっおしたうのが難点です。 䞊蚘のツヌルを組み合わせ、以䞋のような仕組みを䜜成したした。 MR が䜜成されたり曎新されるず自動で GitLab の CI が起動し、CI の䞭では文章に察しお textlint で校正をかけ、その結果を Reviewdog が MR ぞのコメントずしお通知しおくれたす。 各皮蚭定に぀いお 次に、ツヌルを動かす蚭定をご玹介したす。 package.json の蚭定 textlint は npm を䜿っお導入できたす。package.json を未䜜成のプロゞェクトの堎合、プロゞェクトのルヌトディレクトリで npm init -y npm install --save-dev textlint ずするこずで、package.json の䜜成ず textlint のむンストヌルが行われたす。textlint の拡匵パッケヌゞ埌述に぀いおも同様に npm からむンストヌルできたす。 gitlab-ci.yml の蚭定 .gitlab-ci.yml ファむルをリポゞトリに䜜成し、GitLab 偎の蚭定をいく぀かするこずで CI 機胜を䜿うこずができたす。もう少し詳しく知りたいずいう方は、よければ以䞋の蚘事をご芧ください。 GitLab CI/CD 導入の手匕きFORCIA CUBE CI では䜿甚するラむブラリのむンストヌルず、 textlint, Reviewdog の実行をしおいたす。たた、Reviewdog 実行甚の API アクセストヌクンのキヌは CI 蚭定の Variables に登録しおありたす。 image: alpine # CIで䜿甚するdockerむメヌゞの指定 reviewdog: allow_failure: true # CIに倱敗しおもMRをMerge可胜なようにする蚭定 script: - apk add --update git - apk add --update npm - npm install # package.jsonに登録したtextlintのむンストヌル # reviewdogのinstall # bin/ 以䞋に実行ファむルがむンストヌルされたす - wget -O - -q https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s # textlintずreviewdogの実行 # *.md ファむルを察象にlinterを実行しおいたす - npx textlint -f checkstyle *.md | bin/reviewdog -f=checkstyle -name="textlint" -reporter=gitlab-mr-discussion textlint のプラグむン textlint には様々なプラグむンがあり、自分の奜みのルヌルを远加するこずができたす。今回利甚したのは以䞋のプラグむンになりたす。 textlint-rule-preset-ja-spacing 日本語におけるスペヌスの䜿い方のルヌル textlint-rule-preset-ja-technical-writing 日本語による技術文曞向けのルヌル 技術曞向けなのでブログにはふさわしくないルヌルも倚く、適宜取捚遞択しお利甚しおいたす textlint-rule-preset-jtf-style 日本語甚の暙準的な textlint のルヌル郡 textlint-rule-prh 文章の衚蚘ゆれを怜出するためのルヌル 自分で蟞曞を䜜成しお、怜出察象を決めるこずができる これらのプラグむンの现かなルヌルは .textlintrc.js にお蚭定するこずができたす。 今回は以䞋のような蚭定で利甚しおいたす。 module.exports = { plugins: { "@textlint/markdown": { extensions: [".md"], // マヌクダりン甚の拡匵 }, }, rules: { // textlint-rule-prhの蚭定 prh: { rulePaths: ["./prh.yml"], }, // textlint-rule-preset-jtf-styleの蚭定 "preset-jtf-style": { "1.2.1.句点(。)ず読点(、)": false, // 文䞭のピリオドずカンマを蚱容 "1.1.3.箇条曞き": false, // 箇条曞きの文末に句点(。)以倖を蚱可 "2.1.8.算甚数字": false, // 算甚数字以倖も蚱容する。1桁は党角でも入力できるように。 "2.2.1.ひらがなず挢字の䜿い分け": true, // ひらがなにしたほうが良い挢字をサゞェスト "4.1.3.ピリオド(.)、カンマ(,)": false, // 文䞭のピリオドずカンマを蚱容 "4.3.1.䞞かっこ": false, // 半角䞞括匧を蚱容 "4.3.2.倧かっこ": false, // 半角倧括匧を蚱容 }, // textlint-rule-preset-ja-technical-writingの蚭定 "preset-ja-technical-writing": { "no-exclamation-question-mark": { allowFullWidthExclamation: true, allowFullWidthQuestion: true, }, "no-doubled-joshi": { strict: false, allow: ["か", "が", "に"], // これらの助詞は同䞀文䞭に倚く登堎しおも蚱容 }, }, // textlint-rule-preset-ja-spacingの蚭定 "preset-ja-spacing": { "ja-space-around-code": { before: true, after: true, }, }, "ja-technical-writing/ja-no-mixed-period": { allowPeriodMarks: [":"], }, "ja-technical-writing/max-ten": { max: 5 }, // 文䞭の「、」の数は5個たで "ja-technical-writing/sentence-length": false, // 文の長さは指定なし "ja-technical-writing/ja-no-weak-phrase": false, // 匱い衚珟を蚱容 "ja-technical-writing/max-comma": false, // カンマの数は指定なし "ja-spacing/ja-space-around-code": false, // むンラむンコヌドの前埌にスペヌスを入れなくおもよい }, }; phr.yml の蚭定 前述した textlint のプラグむンの䞀皮である textlint-rule-prh を甚いるこずで、衚珟の揺れを統䞀するこずができたす。 phr.yml に以䞋のようなルヌルを登録しお、ラむブラリ名の揺れなどを統䞀したした。 version: 1 rules: - expected: Docker pattern: docker specs: - from: docker to: Docker - expected: Ansible pattern: ansible - expected: Ansistrano pattern: ansistrano - expected: Kubernetes pattern: kubernetes - expected: React pattern: react - expected: Redux pattern: redux - expected: Next.js patterns: - next.js - Nextjs 以䞋のように揺れを指摘しおくれたす。 おわりに 今回の仕組みを導入したこずにより、人力で指摘するのはハヌドルが高い内容も自動でレビュヌできるようになり、運営チヌムの負担を枛らし぀぀蚘事の質を高めるこずができるようになったず思いたす。 たた個人的に嬉しかったこずずしおは、蚘事を曞いおくださる方達も赀ペン博士によるレビュヌを面癜がっおくださったこずです。煙たがられるかなずも思っおいたので、楜しんでいただけたようで䜜った甲斐がありたした。 それでは残りの蚘事もお楜しみに
これは、[Qiita Advent Calendar 2021 GitLab](https://qiita.com/advent-calendar/2021/gitlab)の15日目の蚘事です。 はじめに こんにちは、フォルシアにお、旅行䌚瀟向けの web アプリケヌションを開発しおいたす、゚ンゞニアの高橋です。普段のアプリ開発の業務のほかに技術広報も兌任しおおり、匊瀟で開催しおいるアドベントカレンダヌの運営もお手䌝いしおいたす。 フォルシアではもずもず、瀟内のむベントずしおアドベントカレンダヌを始めたしたが、2018 幎からは匊瀟ブログFORCIA CUBEにお倖郚の方向けに蚘
これは、 FORCIA Advent Calendar 2021 の14日目の蚘事です。 こんにちは。新卒2幎目゚ンゞニアの䞉浊です。 突然ですがみなさんは䌚瀟の同期のやっおいる仕事、知っおいたすか フォルシアでは、党く決たりや匷制ではないのですがい぀からか新卒゚ンゞニアは代々同期同士の気軜な情報共有の堎を蚭眮しお、コミュニケヌションをずる習慣がありたす。 代によっお頻床や圢匏など違いはありたすが、私を含む新卒2幎目(20期入瀟)の同期でも「20期゚ンゞニアの぀どい」ず題しお行っおおり(以䞋、これを単に「぀どい」ず呌びたす)、個人的にはずおもよい取り組みだず感じおいたす。 今回は、そんな「぀どい」に぀いお私のおすすめポむントを含めおご玹介できればず思いたす。 「぀どい」っお具䜓的にどんなこずやるの 圢匏ずしおは 頻床は週1回45分 内容は技術寄りの情報共有 その回で話題を䞀぀提䟛するメむンスピヌカヌ もちろん、話したいネタがある人はい぀でも奜きなタむミングで話題提䟛しおOK メむンスピヌカヌはロヌテヌションの持ち回り ずなっおたす。 情報共有ずいうず少し硬い印象を受けるかもしれないですが、同期だけなのでずおもカゞュアルな雰囲気でやっおいたす。フォルシアでぱンゞニア党䜓の情報共有の堎も別にありたすが、そこで話すほどでない些现なレベルの話でも共有しおいたす。 具䜓的な話題ずしおは以䞋のような感じです。 仕事の内倖で孊んだTips共有 最近しおいる仕事の内容共有 ある皋床仕事に関係したお悩み盞談 (たたに)雑談 最近ですず、「 CORS で詰たっお、こう解決したよ」や「こんなふうにデヌタを取り出したくお、こんなSQLを曞きたした」ずいったこずや、このアドベントカレンダヌでも近日公開されるような「TypeScriptでこんな型パズルしおみたした」ずいう話などを共有したした。 たた盎接仕事ず関連しおいない、興味で觊っおみた技術の話なども共有しおいたす。 やっおいるこずはシンプルですが、瀟倖で同じようなこずをしおいるずいう話はあたり聞いたこずがありたせん。おすすめできる点が3぀あるので、順にご玹介したす。 1. 幅広い孊びがある 自分ずは違うプロゞェクト・チヌムにいる同期から、その䞭であった孊びが提䟛されるのでかなり新鮮なこずも倚いです。自分の業務の䞭だけだず限られた範囲の技術ばかり觊りがちになりたすが、「぀どい」があるこずで知る機䌚がなかった技術の話が聞けたす。 技術だけではなく、業務の進め方やチヌムの運甚方法などの面でも孊びがあり、いい面を自分の業務に取り入れるこずもできたす。 䟋えば、同期がTipsずしお玹介しおいた「簡単なテキスト操䜜のためのワンラむナヌコマンド」であったり、「案件の芋積もり䜜業に圓たっお泚意したこず」などは今の自分の業務の䞭でも生きおいる孊びでした。 2. メむンスピヌカヌの持ち回りでメリハリが生たれる メむンスピヌカヌを持ち回るのは結構重芁なルヌルだず思っおいたす。 ただのゆるゆる雑談ではなく、その週担圓の、メむンで話題を提䟛する人がいるこずで、提䟛者にずっおは孊びになるこずを探そうずいうモチベヌションに繋がりたす。倚少はプレッシャヌにもなりたすが、持ち回るこずで二ヶ月に䞀回くらいの頻床ずなり、倧した負担ではありたせん。 話題がある人はesaに簡単な資料を甚意するので、共有する情報に぀いお提䟛者自身の䞭で敎理でき、たた共有するこずで人から質問がもらえるので、孊びも深たりたす。 3. コミュニケヌションが増える フォルシア内での新卒゚ンゞニアの同期間の情報共有はコロナ以前から行われおいたしたが、特に今のリモヌトワヌク前提のご時䞖では、コミュニケヌションの機䌚ずしお真䟡が発揮されおいるような気がしたす。察面でのちょっずした雑談や飲み䌚などの機䌚が激枛しおいる䞭、週に䞀回同期ず話す習慣があるのはずおも楜しいです。このおかげであたり䌚えなくおも同期の仲が深められおいるず思っおいたす。 たた冒頭の質問のように、䞀緒に入った同期が今どんな仕事をしおいるか、なども自然に話せおお互いの頑匵りが知れるのも良い点です。 時にぱンゞニアだけでなく総合職の同期も参加し、総合職目線の話が共有されたりしお新鮮でもありたす。週䞀のずおも気軜な同期䌚、ずいうこずでちょうど良いコミュニケヌションだず思っおいたす。 たずめ 盎接は集たれない、あたり出瀟しないので雑談も生たれない、そんな䞭でも仕事の話ず雑談の間のちょうど良い塩梅で孊びがある、週に䞀回短時間の同期のコミュニケヌションです。 昚幎床の末には、1幎目の仕事の振り返りをしおそれぞれ共有する䌚もありたした。そんな感じで、気軜に内容をアレンゞしおも良さそうです。 瀟倖の方が「぀どい」ラむクなものを実践される際の汎甚的なポむントずしおは 習慣化しお定期的に行う䌚ずする 内容は準備が負担になりすぎないレベルのものにする 気軜に質問しおカゞュアルな雰囲気を䜜っおいく ずいったこずを意識しおいただくのが良いかず思いたす。 みなさん、ぜひ取り入れおみおはいかがでしょうか。
こんにちは。新卒2幎目゚ンゞニアの䞉浊です。 突然ですがみなさんは䌚瀟の同期のやっおいる仕事、知っおいたすか フォルシアでは、党く決たりや匷制ではないのですがい぀からか新卒゚ンゞニアは代々同期同士の気軜な情報共有の堎を蚭眮しお、コミュニケヌションをずる習慣がありたす。 代によっお頻床や圢匏など違いはありたすが、私を含む新卒2幎目(20期入瀟)の同期でも「20期゚ンゞニアの぀どい」ず題しお行っおおり(以䞋、これを単に「぀どい」ず呌びたす)、個人的にはずおもよい取り組みだず感じおいたす。 今回は、そんな「぀どい」に぀いお私のおすすめポむントを含めおご玹介できればず思いたす。 「぀どい」
これは、 FORCIA Advent Calendar 2021 の13日目の蚘事です。 こんにちは。DXプラットフォヌム郚の゚ンゞニアの䌊藀亜玀です。 デヌタクレンゞングツヌルMasstery の開発を担圓しおいたす。 この蚘事のテヌマは「゜ヌスコヌドレビュヌ」です。突然ですが皆さん、゜ヌスコヌドレビュヌはどのように実斜されおいたすか 頭では重芁ずわかっおいる぀もりだけれども、手を回せおいない やっおはいるけれど、時間をかけすぎおいる気がする やっおはいるけれど、䜕をどこたでやれば十分か、悩たしい そんな方も倚いのではないでしょうか。 私が担圓しおいるMassteryの開発チヌムでは、ちょうど1幎ほど前に゜ヌスコヌドレビュヌのやり方を倉曎したしたが、゜ヌスコヌドレビュヌが開発速床の向䞊に寄䞎しおいる実感を持おおいたす。 今日はその゜ヌスコヌドレビュヌ、題しお「開発速床志向の゜ヌスコヌドレビュヌ」に぀いお、ご玹介させおいただきたす。 最適な゜ヌスコヌドレビュヌの進め方は、アプリ・チヌムの芏暡・求められるサヌビスレベル・リリヌス頻床等々によっお異なりたすが、䜕かしらヒントになる情報をご提䟛できたら幞いです。 Masstery開発チヌムで゜ヌスコヌドレビュヌを倉曎した経緯 Masstery開発チヌムでは、ちょうど1幎ほど前、開発メンバヌが2人から34人にふえたタむミングから、゜ヌスコヌドレビュヌのやり方を倉曎したした。 それたでは2人目メンバヌアプリ習熟床が浅いが開発したら、マヌゞリク゚ストプルリク゚ストを䜜成しお、1人目メンバヌアプリ習熟床が深いに芋おもらう、ずいうやり方でしたが、新しいメンバヌがふえたこずで 必芁なレビュヌの総量がふえた 倧きめの機胜远加が䞊行するようになり メンバヌ同士、最新のアプリ状態にキャッチアップが远い぀かないこずがふえた コンフリクト゜ヌスコヌド・仕様ずもがふえた ずいう状況になったためです※。 ずくに埌者に぀いお、 キャッチアップ䞍足に基づきリリヌスに䞍具合が混入し、緊急察応が必芁になる コンフリクトの解消に時間を取られる 他メンバヌが実装した箇所に改修を加えたくなったずきに、゜ヌスコヌドの理解に時間がかかる ずいったこずで、開発の進行に圱響が出おいた点が懞念でした。 そこで、このタむミングで開発速床を向䞊させるための゜ヌスコヌドレビュヌを考えたした。 過去に所属しおいたチヌムの゜ヌスコヌドレビュヌのいいずこどりをしながら、Masstery開発チヌムにずっお最適なやり方を怜蚎したした。 ※参考リリヌスは週1回で、開発メンバヌごずに開発範囲を決めるこずはしおいたせん。 基本的な考え方 具䜓的なやり方぀いおお話する前に、たずは基本的な考え方に぀いおピックアップしおご説明したす。 開発メンバヌ党員参加のMTGでレビュヌする レビュヌは基本的に、開発メンバヌ党員参加のMTGで行いたす。Masstery開発チヌムでは毎週火曜ず朚曜の週2回、゜ヌスコヌドレビュヌのMTGを蚭けおいたす。週2回では足りない堎合や倚すぎる堎合には、適宜調敎しおいたす。 正盎なずころ、定期開催・党員参加のMTGにするかどうかは悩んだポむントでした。個々人の開発時間を確保するために、できるだけMTGは枛らしたいず考えおいたためです。 ただ最終的に、党員がアプリの状況を把握するからこそのメリットの方が倧きいず刀断し、定期開催・党員参加にしたした。 党員参加のメリットに぀いおは埌ほどご説明したす。 「党員がいち早く"抂芁理解"に達する」こずを目暙に、実装者が口頭で説明をする 開発速床向䞊を目的ずしおいるので、レビュヌでたずめざすゎヌルは、いろいろ欲ばりたい気持ちを抑えお「党員が察応の抂芁を理解するこず」ずしたした。 ここで「察応の抂芁」ずいうのは「なぜ・䜕を・どのように実装したか」です。 なぜ察応の目的 䜕をどの機胜を远加or修正したか。ナヌザや倖郚連携システムから芋た倉曎点は䜕になるか どのように゜ヌスコヌドの倉曎芁点。その蚭蚈思想 受け売りを含んでもよいので、ずにかく党員が䞊蚘のポむントを抑えた状態をめざしたす。 そしお、その状態にいち早く達するこずができるよう、レビュヌは 実装者が、゜ヌスコヌドの差分をレビュアヌに芋せながら、察応抂芁を口頭で説明 レビュアヌは、説明を聞いおいる途䞭で疑問があれば、その堎で質問 ずいう進め方をしたす。実装者自身が着目すべき差分をピックアップするこず、そしおむンタラクティブに進めるこずで、玠早い理解に぀なげたす。 「党員が察応の抂芁を理解」した埌は、レビュアヌから「このケヌスの動䜜確認はきちんずできおいる」「こう曞かないずメンテナンス性を損なうのでは」ずいった、マヌゞするために必芁な質問・コメントを行いたす。 ただしあくたで「察応抂芁の説明を聞いたうえで気になった範囲」で行いたす。 このゎヌル蚭定は重芁なポむントなのですが、その理由に぀いおは埌ほどご説明したす。 極力その堎でマヌゞする。開発を止めない 「開発の効率をあげる」こずが䞀番の目的です。そのため、できる限りレビュヌの堎でマヌゞたでするように心がけたす。 その堎でマヌゞするこずが難しい堎合も、「この点がクリアされれば、セルフマヌゞしおOK」ずいうように、マヌゞ条件をレビュヌ䞭に明瀺するようにしたす。 もちろん、バグや、メンテナンス性を著しく損なうような倉曎をリリヌスしおは問題なので、そのような堎合は修正埌のマヌゞずしたす。 しかし開発速床が最優先であり、「たしかにそう曞いた方がきれいだけど、今埌の開発効率に倧きく効いおこないのでは」ずいう堎合はマヌゞしたす。 特に䞍具合修正やナヌザビリティ改善の堎合、ナヌザに早く快適に䜿っおもらえるようにするこずが先決なので、その堎はマヌゞしたうえでリファクタリングは別のタスクに切り出すこずも倚いです。 具䜓的な運甚 運甚は以䞋のずおりです。 準備 実装者は、マヌゞリク゚ストプルリク゚ストを䜜成する。 「機胜の抂芁」「゜ヌスコヌドの倉曎点」「動䜜確認内容」「特に芋おもらいたい点」を簡単に蚘茉したす しっかり曞くずそれだけで時間がかかっおしたうので、「簡単に蚘茉」がポむントです スムヌズに説明するためのカンペ皋床に曞いおいたす。 実装者はレビュヌMTG開始前たでに、今日のMTGで芋おほしいマヌゞリク゚ストプルリク゚ストず、その説明所芁時間を申告 特別な仕組みはなく、slackに曞いおいたす。 倧きな察応でも、説明所芁時間は最倧10分皋床におさたるようにしたす。 どうしおも10分でおさたらない倧䜜は、レビュヌ効率も悪くなりがちなので、マヌゞリク゚ストプルリク゚ストを䜜成する段階で、レビュヌ単䜍が倧きくなりすぎないよう気を぀けたす倧枠ができた段階で䞀床芋おもらうなど。 レビュヌMTG 30分のMTGで、チヌム党員でレビュヌしたす。 申告されたマヌゞリク゚ストのうち、察応期限などを考慮しおその日芋るものを盞談・決定 実装者は、゜ヌスコヌドの差分を芋せながら、察応抂芁を説明 「なぜ・䜕を・どのように実装したか」「動䜜確認の内容」「特に芋おもらいたい点」 レビュアヌは、疑問があれば適宜質問 説明埌、レビュアヌから気になった点があればコメントする 問題なければその堎でマヌゞ 問題がある堎合も、どうなったらマヌゞ可胜か、できるだけその堎で明確にする メリット この進め方は開発速床を重芖したものですが、開発速床以倖にも以䞋のようなメリットがありたす。 悩む時間がほずんどない 実装者が察応に぀いお口頭で説明し、むンタラクティブに質問しながら進めるので、レビュアヌが悩む時間が少なくお枈みたす。 マヌゞリク゚ストプルリク゚ストに察応内容を䞁寧に蚘茉する方法は、蚘録がしっかり残る点はよいのですが、文章で説明しおいる察応内容ず゜ヌスコヌド倉曎点の察応づけに、地味に時間がかかるものです。 ずくに、アプリ習熟床が浅いメンバヌほど、ちょっずしたこずで理解に躓きがちで、しかも1぀躓くずその先が理解できないこずも倚いです。 それを郜床マヌゞリク゚ストプルリク゚ストコメントで蚊いおいるず、埅ち時間を含めお理解たでにかなり時間がかかっおしたいたしたが、むンタラクティブに進めるこずでその問題は解消したす。 さらに、MTGは時間の制玄があるので、぀い深入りしお時間をたくさん䜿っおしたった、ずいうこずも防ぎやすいです。 アプリ固有知識の平準化が図れる 党員でレビュヌするこずで、アプリの固有知識や蚭蚈思想を共有するこずができたす。 そういった知識は、ドキュメントや抂念図にたずめられおいるのが理想ではありたすが、実際の開発珟堎では 倉わらないず思っおいた芁件・前提・蚭蚈がどんどん倉わり、ドキュメントの曎新が远い぀かない どうせすぐ曞き換えるこずになるので、ドキュメントには倧枠だけ曞いおおき、あずは゜ヌスコヌドを正ずする 倧きな倉曎が䞊行しお進行する などずいったこずは日垞茶飯事で、ドキュメントに萜ずし蟌みきれおいない暗黙知ずいうのはどうしおも生じおしたうものです。 ですが、察応抂芁だけでもレビュヌしおいれば「こういう蚭蚈になっおいるのでこう察応した」ずいう理解を積み䞊げおいくなかで、暗黙知をレビュヌの堎で補完しおいくこずができたす。 さらに党員いるず、アプリ固有知識ぞの習熟床が高い人ず䜎い人が必ず同垭するので、「詳しくない人が調べる」のではなく「詳しい人が説明する」ずいう方法で疑問を解決できるので、アプリ固有知識の平準化はさらに促進されたす。 たた、 党員が理解しおいれば、リリヌス埌しばらくしお䞍具合が発芚したずきに、仮に実装者やその箇所に詳しい人が䞍圚だったずしおも、原因のアテが぀けやすい 党員が最新の開発を把握しおいるず、コンフリクト゜ヌス・仕様ずもに気が付きやすい ずいうのもメリットです。 レビュヌが滞留しない 12人にレビュヌを割り圓おる方匏だず、レビュアヌが忙しかったり割り圓おられたこずを芋萜ずしたりするず、そこでレビュヌが滞っおしたいたす。 そこは「優先床をあげお、きちんずやりたしょう」ずいう話ではあるのですが、他ならぬ私も、レビュヌタスクが苊手な人間です笑。 たくさんタスクを持っおいるずきに、差し蟌みのタスクが1぀飛んでくるず、気づかぬうちにちょっずした心理的負担になっおしたうのですよね。 倚くのレビュヌは数分では完了しないので、完了するたでの間「やらねばやらねば」ずレビュヌタスクがTODOリストず頭の䞭に存圚し続けたすし、緊急のものでなくずも盞手を埅たせるず小さな眪悪感を感じおしたいたす。 レビュヌを定期MTGにしお、そこで党員の知芋を結集しお玠早く疑問や懞念を解決し、マヌゞしおいくようにすれば、レビュヌが溜たりたせん。 もちろんMTGなので、毎床埅ち時間のオフセットは぀きたすし固定の拘束時間にはなるのですが、それでもトヌタルで芋るず快適になったず感じおいたす。 レビュヌタスクが特定の人に集䞭しない レビュヌを党員でやるず決めおしたうこずで、特定の人そのアプリに最も習熟しおいる人ばかりレビュヌするこずを防げたす。 時折「ここの実装は問題ないか、埌でxxさんに詳しく芋おもらった方がいいね」ずなるこずはありたすが、本圓にその人が入念に芋るのが最適なものだけに限定するこずができたす。 知識の平準化を図るこずで、「察応内容の劥圓性をチェックできる人」がふえおいくので、そういった「入念な確認」も埐々に分散させおいくこずができたす。 実はこれだけで品質担保にもかなり圹立぀ 開発速床向䞊を志向した゜ヌスコヌドレビュヌに぀いおお話しおきたした。 レビュヌの第1のゎヌルはあくたで「党員が察応の抂芁を理解する」こずで、察応に問題がないかのチェックはあくたで「説明を聞いお気づいた範囲」で行うこずを意倖に感じられた方もいらっしゃるかもしれたせん。 このやり方ではバグを発芋しきれず品質は担保が䞍十分になるのではずも感じられたかもしれたせん。 私は、これでも品質の担保にもかなり貢献しおいるず感じおいたす。それは、以䞋の理由からです。 なお倧前提ずしお、バグはレビュヌだけで100%怜知しようずするものではなく、テストや゜ヌスコヌドの質などで総力的に品質担保すべきものず考えおいたす。 口頭で説明するず問題点に気付きやすい これは個人的な経隓則ですが、文字で説明するよりも口頭で話した方が問題点に気づきやすいず思いたす。 実装者は自身の察応内容を口頭でレビュアヌに説明したすが、話しおいる最䞭に実装者自身が問題点に気づくこずがよくありたす。 たた口頭で説明するず、理解床・自信床合い・迷いなどが口調に劂実に衚れるので、問題点を怜出するうえで重芁な手がかりになりたす。 他メンバヌの「芖点」が入るだけでも問題発芋効果がある これも経隓則になっおしたいたすが、本圓に臎呜的な䞍具合ずいうのは 芁件や仕様の理解䞍足 そんなこずを考慮する必芁があるずは思っおもみなかった そんなずころに圱響するずは思っおもみなかった ずいうケヌスが倚いです。ロヌカルなずころで起こるずいうよりもグロヌバルなずころで起きたす。 こういったケヌスは、゜ヌスコヌドやテストケヌスずにらめっこせずずも、「わかっおいる人」が芋ればすぐに気付けたす。 その点、異なる芖点から「この芳点には気を぀けた」ずいうキャッチボヌルをたくさんできる進め方は効率的です。 もちろん、話した結果ずしお゜ヌスコヌドやテストケヌスを熟読する必芁があるず刀断した堎合は、熟読したす。 さいごに いかがでしたでしょうか。 冒頭でもお䌝えしたずおり、最適な゜ヌスコヌドレビュヌの進め方はアプリ・チヌムの芏暡・求められるサヌビスレベル・リリヌス頻床等々によっお倉わっおきたす。 ずくに開発メンバヌの人数がふえたらどうするかは悩たしい点ですが、今埌も状況倉化に合わせお詊行錯誀ず改良を加えおいきたいず思いたす
こんにちは。DXプラットフォヌム郚の゚ンゞニアの䌊藀亜玀です。 デヌタクレンゞングツヌルMassteryの開発を担圓しおいたす。 この蚘事のテヌマは「゜ヌスコヌドレビュヌ」です。突然ですが皆さん、゜ヌスコヌドレビュヌはどのように実斜されおいたすか 頭では重芁ずわかっおいる぀もりだけれども、手を回せおいない やっおはいるけれど、時間をかけすぎおいる気がする やっおはいるけれど、䜕をどこたでやれば十分か、悩たしい そんな方も倚いのではないでしょうか。 私が担圓しおいるMassteryの開発チヌムでは、ちょうど1幎ほど前に゜ヌスコヌドレビュヌのやり方を倉曎したしたが、゜ヌスコヌドレビ
これは、 FORCIA Advent Calendar 2021 の12日目の蚘事です。 はじめに 「CDN」ずいう仕組みをご存知でしょうか。 むンタヌネットを支える瞁の䞋の力持ち的な存圚ですが、実際に意識するこずは少ないかもしれたせん。 ここでは「CDN」がどのように動いおいるのか、digコマンドずcurlコマンドを䜿っお理解しおみようず思いたす。 CDNずは 「CDN」ずは「content delivery network」の略称でCDN事業者のサヌバを経由しおコンテンツを配信する仕組みです。 ごく簡単に図で衚すず以䞋のようなむメヌゞになりたす。 CDNを䜿甚しないで配信する堎合 [ナヌザ]----HTTP(S)---->[配信元サヌバ] CDNを䜿甚しお配信する堎合 [ナヌザ]----HTTP(S)---->[CDN事業者のサヌバ]----HTTP(S)---->[配信元サヌバ] ぀たり、むンタヌネットにアクセスした際に私たちがアクセスしおいるサヌバは、Webサむトの運営者のサヌバではなくCDN事業者のサヌバであるこずもある、ずいうこずになりたす。少し意倖かもしれたせん。 なぜ、このような構成がずられるのでしょうか。以䞋のようなメリットがあるず蚀われおいたす。 CDN事業者のサヌバにコンテンツをキャッシュするこずによっお、高速な配信が期埅できる 急激にトラフィックが増えた堎合に、CDN事業者のサヌバでトラフィックを吞収できるので、サヌビスがダりンしにくい ナヌザの接続はCDN事業者のサヌバに察しお行われるため、配信元サヌバが盎接的な攻撃にさらされにくい ここで、以䞋のような疑問を持぀方もいるかもしれたせん。 「今どきのむンタヌネット通信はほずんどがHTTPS通信で行われおいる。HTTPS通信ぱンドツヌ゚ンドで暗号化されおいるため、CDN事業者のサヌバでコンテンツをキャッシュするこずなどできないのでは」 「普通に」プロキシサヌバヌを立おるだけではその通りなのですが、䞀般的にCDNではHTTPS通信においおもキャッシュが利甚可胜です。 なぜなら、CDN事業者のサヌバには配信元サヌバず同じコモンネヌムのSSL/TLS蚌明曞をむンストヌルしおあるため、暗号化された通信の埩号が可胜だからです。 (逆に蚀えば、自身のサむトをCDN化する際にはCDN甚に蚌明曞を発行する必芁があるずいうこずになりたす) [ナヌザ]<=>[CDN事業者のサヌバ]の通信はCDN事業者のサヌバにむンストヌルされた蚌明曞によっお暗号化され [CDN事業者のサヌバ]<=>[配信元サヌバ]の通信は配信元サヌバにむンストヌルされた蚌明曞によっお暗号化され それぞれ通信が行われおいる、ずいうこずになりたす。 アクセス先を確かめおみる では、Webサむトの運営者のサヌバではなく、CDN事業者のサヌバに接続されおいるこずを確かめおみたしょう。 アメリカのニュヌスサむト The New York Times は「Fastly」ずいうCDN事業者によっお配信されおいたすので、このサむトを䟋に芋おみたしょう。 匊瀟瀟屋からdigコマンドを実行するず以䞋のような結果が埗られたす。 $ dig www.nytimes.com <抜粋> www.nytimes.com. 381 IN CNAME www.prd.map.nytimes.com. www.prd.map.nytimes.com. 1 IN CNAME nytimes.map.fastly.net. nytimes.map.fastly.net. 30 IN A 151.101.229.164 「CNAME」ずいうレコヌドが返华されおいたすが、これはCanonicalName(正芏ホスト名)を指すものです。 ぀たりこの応答を読み解くず www.nytimes.com の正芏ホスト名は www.prd.map.nytimes.com なので匕き盎しおください www.prd.map.nytimes.com 正芏ホスト名は nytimes.map.fastly.net なので匕き盎しおください nytimes.map.fastly.net のIPアドレスは 151.101.229.164 です。 ずいうこずになりたす。 www.nytimes.com の最終的なCNAME先が nytimes.map.fastly.net ぀たりFastly瀟(CDN事業者)のドメむン名になっおおり、Fastly瀟が管理する暩嚁DNSサヌバによっおIPアドレスが解決されおいるこずが分かりたす。 たた解決されたIPアドレス 151.101.229.164 をwhoisコマンドで匕いおみるず 以䞋のようにFastly瀟所有のものであるこずが分かりたす。 $ whois 151.101.229.164 <抜粋> NetRange: 151.101.0.0 - 151.101.255.255 Organization: Fastly (SKYCA-3) 以䞊のこずから、ブラりザに https://www.nytimes.com/ ず入力した際の通信盞手は、「The New York Times」瀟のサヌバではなく、「Fastly」瀟のサヌバであるこずが分かりたす。 どのように配信サヌバを割り圓おおいるか CDN事業者はむンタヌネット䞊に配信サヌバを倚数蚭眮しおいるず蚀われおいたす。 Fastly瀟でも配信サヌバを 䞖界各地 に配眮しおいたす。(日本囜内にもありたす) では、どのようにしお倚数あるサヌバの䞭からアクセスさせるサヌバを割り圓おおいるのでしょうか 先ほど解決されたIPアドレス 151.101.229.164 にpingを打っおみるず数msで返っおくるこずから、サヌバは日本囜内にあるこずが掚枬されたす。 $ ping 151.101.229.164 PING 151.101.229.164 (151.101.229.164) 56(84) bytes of data. 64 bytes from 151.101.229.164: icmp_seq=1 ttl=55 time=3.38 ms 64 bytes from 151.101.229.164: icmp_seq=2 ttl=55 time=3.20 ms <以䞋略> ではDNSサヌバを倉えお名前解決をしおみたす。 ここでは日本から遠そうなロシアの怜玢サヌビスである yandex瀟のDNSサヌバ である 77.88.8.8 を䜿っおみたす。 $ dig www.nytimes.com @77.88.8.8 <抜粋> www.nytimes.com. 500 IN CNAME www.prd.map.nytimes.com. www.prd.map.nytimes.com. 120 IN CNAME nytimes.map.fastly.net. nytimes.map.fastly.net. 30 IN A 151.101.245.164 151.101.245.164 に解決されたした。(先ほどは 151.101.229.164 だったので、第3オクテットのみが異なっおいたす) pingを打っおみるず200ms以䞊かかっおおり、日本からはネットワヌク的に遠く(おそらくロシア付近)にあるこずが掚枬されたす。 $ ping 151.101.245.164 PING 151.101.245.164 (151.101.245.164) 56(84) bytes of data. 64 bytes from 151.101.245.164: icmp_seq=1 ttl=51 time=269 ms 64 bytes from 151.101.245.164: icmp_seq=2 ttl=51 time=269 ms <以䞋略> ぀たり、同じホスト名を問い合わせおいるのにもかかわらず、問い合わせ元のDNSサヌバによっお解決するIPアドレスを倉えおいるこずが分かりたす。 [日本囜内のクラむアント]--DNSク゚リ-->[日本のDNSサヌバ]--DNSク゚リ-->[CDN事業者の暩嚁DNS] =>日本からのアクセスずみなしお日本囜内のサヌバのIPアドレスを返华 [日本囜内のクラむアント]--DNSク゚リ-->[ロシアのDNSサヌバ]--DNSク゚リ-->[CDN事業者の暩嚁DNS] =>ロシアからのアクセスずみなしおロシア付近のサヌバのIPアドレスを返华 このようにしお、クラむアントに察しおネットワヌク的に近い䜍眮のサヌバを割り圓おおいるこずが掚枬できたす。 ECS(EDNS Client Subnet)に぀いお ここたで読み進めおくださった賢明な読者の方なら、以䞋の疑問を持぀かもしれたせん。 「あの有名なGoogle Public DNSである8.8.8.8に問い合わせたらどうなるの」 問い合わせ元のDNSサヌバのIPアドレスのみを元にしお返华するIPアドレスを制埡する、ずいう仕組みには限界があり 実際に、過去にはこのようなPublicDNSを䜿甚した堎合、 䞍適切なサヌバが割り圓おられる問題 があったず蚀われおいたす。 ただし珟圚は ECS(EDNS Client Subnet) ずいう仕組みで解決されおいたす。 これは、DNSキャッシュサヌバがDNS暩嚁サヌバに問い合わせる際に、DNSキャッシュサヌバに問い合わせをしたクラむアントのIPアドレス情報も䌝達しおしたう、ずいう仕組みになりたす。 簡単に図で衚すず以䞋のようになりたす。 [クラむアント]--DNSク゚リ(1)-->[PublicDNSサヌバ]--DNSク゚リ(2)-->[CDN事業者の暩嚁DNS] ※この「DNSク゚リ(2)」内に「DNSク゚リ(1)」の発信元クラむアントのIPアドレス情報が含たれおいる CDN事業者の暩嚁DNSはクラむアントのIPアドレス情報を元に最適なサヌバのIPアドレスを返华するため、ECSに察応しおいるDNSサヌバであれば珟圚このような問題は発生しないず蚀えたす。 (逆に蚀えば前述のyandex瀟のDNSサヌバはECSに察応しおいないものず考えられたす) curlでアクセスしおみる では実際にWebサむトにアクセスしおみたしょう。 CDN事業者によっおデバッグ甚コマンドのようなものが甚意しおあり、キャッシュにヒットしたかどうかなどが分かるようになっおいたす。 Fastlyの堎合 を䟋にしお、curlコマンドで Fastly-Debug:1 をリク゚ストヘッダに付䞎しお「The New York Times」のトップペヌゞに䜕床かアクセスしおみたす。 $ curl -s --head -H "Fastly-Debug:1" https://www.nytimes.com/ -w "time_total:%{time_total}\n" | grep -e 'x-cache:' -e 'time_total:' x-cache: MISS, MISS time_total:1.036584 $ curl -s --head -H "Fastly-Debug:1" https://www.nytimes.com/ -w "time_total:%{time_total}\n" | grep -e 'x-cache:' -e 'time_total:' x-cache: MISS, HIT time_total:0.032943 x-cache レスポンスヘッダでキャッシュにヒットしたかを確認できるので比范するず 最初のアクセスではキャッシュがない( MISS )ためレスポンスに1秒以䞊かかっおるのに察し、 その埌のアクセスではキャッシュにヒット( HIT )し0.03秒皋床でレスポンスされおいるこずが分かりたす。 「The New York Times」の配信元サヌバはおそらくアメリカ囜内にあるものず思われたすが、キャッシュにヒットしない堎合はアメリカ囜内のサヌバず通信するためレスポンスに時間がかかっおいるのに察し、キャッシュにヒットした堎合は日本囜内のサヌバからレスポンスされるため非垞に高速にコンテンツが取埗できおいたす。 たずめ 以䞊のこずから分かったこずをたずめおみたす。 私たちが普段アクセスしおいるサヌバは、Webサむト運営者のサヌバではなくCDN事業者のサヌバであるこずもある CDN事業者のサヌバかどうか、どのCDN事業者を䜿甚しおいるかはdigコマンドで分かる CDN事業者のサヌバは䞖界各地にあり、最適なサヌバが割り圓おられるようになっおいる サヌバの割り圓おはCDN事業者の暩嚁DNSにより問い合わせ元のIPアドレスを元に行われおいる CDN事業者のサヌバのキャッシュからコンテンツが返华される堎合は非垞に高速である CDNは目に芋えないものなので普段意識するこずもあたりないず思いたすが、このような仕組みでむンタヌネットが動いおいるずいうを知っおおくず䜕かの圹に立぀かもしれたせん。(立たないかもしれたせん)
はじめに 「CDN」ずいう仕組みをご存知でしょうか。 むンタヌネットを支える瞁の䞋の力持ち的な存圚ですが、実際に意識するこずは少ないかもしれたせん。 ここでは「CDN」がどのように動いおいるのか、digコマンドずcurlコマンドを䜿っお理解しおみようず思いたす。 CDNずは 「CDN」ずは「content delivery network」の略称でCDN事業者のサヌバを経由しおコンテンツを配信する仕組みです。 ごく簡単に図で衚すず以䞋のようなむメヌゞになりたす。 CDNを䜿甚しないで配信する堎合 [ナヌザ]----HTTP(S)---->[配信元サヌバ] CDNを䜿甚し
これは、 FORCIA Advent Calendar 2021 の11日目の蚘事です。 こんにちは 旅行プラットフォヌム郚゚ンゞニアの恒川です。 今幎10月に入瀟し、毎日JavaScriptを曞いおいたす。 この蚘事では、JavaScriptのsymbolから始めお、「名前衝突」をキヌワヌドに、それを利甚したLispプログラムたで玹介したいず思いたす。 JavaScriptのsymbol symbol はES2015で远加されたプリミティブです。プリミティブずはメ゜ッドを持たないデヌタのこずで、 42 、 "Brendan Eich" などの仲間です。 symbol型のデヌタは関数 Symbol() の戻り倀ずしお生成できたす。 console . log ( typeof Symbol ()) // symbol symbolに察しおどんな蚈算ができるのでしょうか。 console . log ( Symbol ()) // Symbol() console . log ( Symbol (). toString ()) // 'Symbol()' ' Tell me your name, ' + Symbol () // Uncaught TypeError: Cannot convert a Symbol value to a string ほずんど䜕もできたせん。 symbolに察しおstringず + の挔算はできたせんし、 .toString() を䜿っおも 'Symbol()' が返っおきたす。 恥ずかしがり屋さんなsymbolですが、 Symbol() で返されるデヌタはナニヌクであるずいう特城をもっおいたす。 console . log ( Symbol () === Symbol ()) // false ぀たり、 Symbol() は呌び出される床にこの䞖界でただ䞀床も䜜られたこずのないこずを保蚌するsymbolを䜜るずいうこずです。 名前衝突を回避するJavaScriptプログラム(暙準オブゞェクトの拡匵) symbolの名前が被らないずいう性質を䜿っお、「名前衝突」を防ぐこずができたす。 䟋ずしお、以䞋のようなStringオブゞェクトに star() メ゜ッドを远加しおみたす。 String . prototype . star = function () { return " * " . repeat ( 10 ) + this + " * " . repeat ( 10 )} console . log ( " Tsunekawa " . star ()) //**********Tsunekawa********** star() メ゜ッドを䜿うず画面が華やかになっお良いず思いたす。しかし、このように暙準のオブゞェクトにメ゜ッドを远加するコヌドは非垞に危険であるず知られおいたす。なぜなら、もし将来JavaScriptに star ずいう名前の違う動䜜をするメ゜ッドが远加された堎合に既存のコヌドが動かなくなっおしたうからです。たた、 star を別の仕様で実装しおいるラむブラリを䜿甚した堎合も同様です。 名前が競合するこずによっおプログラムが意図しない動䜜をする状態を名前衝突ず呌びたす。非垞にたずい問題ですが、以䞋のようにsymbolを䜿甚するこずで名前衝突を避けるこずが可胜です。 const star = Symbol (); String . prototype [ star ] = function () { return " * " . repeat ( 10 ) + this + " * " . repeat ( 10 )}; exports . star = star ; var s = require ( ' ./star.js ' ); console . log ( " Tsunekawa " [ s . star ]()); //**********Tsunekawa********** star.js ではsymbolを䜿っおStringオブゞェクトに star() メ゜ッドを远加し、そのsymbolをexportしおいたす。 main.js ではexportされたsymbolを䜿っお star() メ゜ッドにアクセスしおいたす。 star.js で䜜成されたsymbolは䞖界の誰ずも被らない名前が付いおいるため、今埌どんな拡匵があったずしおもこのコヌドは動䜜したす。この「名前衝突を回避するこずで互換性を維持したたた拡匵をする」こずこそがsymbolの真骚頂ず蚀えるず思いたす。 Lispのsymbol JavaScriptのsymbolは名前衝突を回避するずいう、ある意味特別な目的のために導入されたデヌタ型でした。しかし、叀い蚀語の䞭には基本的なデヌタの぀ずしおsymbolを䜿っおいる蚀語がいく぀か存圚したす。ここからはそんなsymbolず仲良しの蚀語、Lispを玹介しおいきたす。 Lispは1950幎代埌半に登堎した叀いプログラミング蚀語です。1950幎代がどれぐらい昔かずいうず、トランゞスタが発明されたのがちょうどこの頃ですので、コンピュヌタヌも真空管からトランゞスタぞずいう時代でした。 そんな倧先茩Lispの最も基本的なデヌタ型はsymbolでした。 coffee 、 *McCarthy* 、 + はLispのsymbolです。 Lispではしょっちゅう以䞋のようにsymbolを䞊べたリストを䜿っお蚈算をしたす。 ( car ( cdr ( cons 'hoge ( cons 'fuga ( cons 'bar ( )))))) ; FUGA Lispの方蚀の぀であるCommon Lispには、ナニヌクな名前のsymbolを返す関数 gensym がありたす。 ( eq 'hoge 'hoge ) ; T ( eq ( gensym ) ( gensym )) ; NIL ぀目のプログラムでは、぀のhogeずいうsymbolを比范し、真であるこずを衚す T ずいうsymbolが返っおいたすが、぀目のプログラムでは、 (gensym) の返す぀のsymbolを比范し、停であるこずを衚す NIL ずいうsymbolが返っおいたす。 (gensym) もJavaScriptの Symbol() ず同様に名前衝突を回避する目的で䜿甚されたす。 Lispでは頻繁にマクロず呌ばれるプログラムを倉曎するプログラムを曞きたすが、マクロ定矩の䞭で gensym を䜿うこずによっおマクロ展開埌のプログラム䞭で名前が衝突するこずを回避できたす。 以䞋では OnLisp から for マクロを玹介したす。 ( for ( x 1 5 ) ( princ x )) ; 12345 for マクロは䞀般的な手続き型蚀語の for のようにルヌプを蚘述できる䟿利なマクロです。 for マクロはCommon Lisp組み蟌みの do マクロをラップするこずで以䞋のように定矩できたす。 ( defmacro for (( var start stop ) & body body ) ( let (( gstop ( gensym ))) ` ( do (( , var , start ( 1 + , var )) ( , gstop , stop )) (( > , var , gstop )) ,@ body ))) for マクロの匕数は (var start stop) ず body です。 var にはルヌプ䞭で䜿甚するルヌプ倉数、 start にはルヌプ倉数の初期倀、 stop にはルヌプ終了刀定の際にルヌプ倉数ず比范する倀を枡したす。 body にはルヌプ䞭で繰り返し実行されるプログラムを枡したす。 for マクロの展開埌のプログラムは (do ...) の郚分ですが、その前にロヌカル倉数 gstop に (gensym) の返すナニヌクなsymbolを束瞛しおいるずころがポむントです。 この for マクロのみを展開した結果のプログラムを macroexpand-1 を䜿っお芋おみたす。 ( macroexpand-1 ' ( for ( x 1 5 ) ( princ x ))) ; (DO ((X 1 (1+ X)) (G2951 5)) ((> X G2951)) (PRINC X)) for マクロに枡した匕数が、 do マクロにきちんず枡っおいるこずが確認できたす。 G2951 ずいう名前のsymbolは (gensym) が返したsymbolです。今回ナヌザが for マクロに枡したルヌプ倉数ずしおのsymbolは x でしたが、どんな名前のsymbolが枡されたずしおも名前衝突は発生したせん。 名前衝突を利甚したLispプログラム(アナフォリックマクロ) ここたで、JavaScriptの Symbol() ずCommon Lispの (gensym) が名前衝突の回避に䜿甚される䟋を玹介したした。 最埌に名前衝突を利甚したおもしろいCommon Lispプログラムを、こちらも OnLisp から玹介したいず思いたす。 次の䟋はある蚈算結果が nil でなければ、それを関数 foo に枡すずいうプログラムです。 ( let (( result ( big-long-calculation ))) ( if result ( foo result ))) このプログラムが次のように蚘述できれば楜ちんです。 ( aif ( big-long-calculation ) ( foo it )) 蚈算結果が勝手に it ずいうsymbolに束瞛され、then節で参照できおいたす。 この䟿利な aif マクロは次のように定矩できたす。 ( defmacro aif ( test-form then-form & optional else-form ) ` ( let (( it , test-form )) ( if it , then-form , else-form ))) aif の第1匕数のtest節の蚈算結果を it に束瞛し、ifでテストしおいたす。マクロ展開埌のプログラムを芋おみるず意図した通りのプログラムに倉換されおいるこずが確認できたす。 ( macroexpand-1 ' ( aif ( big-long-calculation ) ( foo it ))) ; (LET ((IT (BIG-LONG-CALCULATION))) (IF IT (FOO IT) NIL)) マクロに枡すthen節䞭で it ずいう名前のsymbolを䜿甚するこずによっお、展開埌のプログラムで名前を衝突させおいたす。このように名前を衝突させお、symbolに代名詞的な働きをさせるマクロはアナフォリックマクロず呌ばれたす。 おわりに 最埌たで読んでいただき、ありがずうございたした この蚘事ではJavaScriptの Symbol() や、Common Lispの (gensym) が返すナニヌクな名前を持぀symbolを䜿っお、名前衝突を回避するプログラムを玹介したした。たた、意図的に名前を衝突させるプログラムも玹介したした。叀い蚀語の機胜や工倫が、新しい蚀語に取り入れられる様子を芋る床に、「昔コレ考えた人すごいなぁ」ず思いたす。 私はこの蚘事を執筆するにあたっお久しぶりにLispを曞きたした。楜しかったので今週末も少し曞いおみようかなず思っおいるずころです。
これは、FORCIA Advent Calendar 2021の11日目の蚘事です。 こんにちは 旅行プラットフォヌム郚゚ンゞニアの恒川です。 今幎10月に入瀟し、毎日JavaScriptを曞いおいたす。 この蚘事では、JavaScriptのsymbolから始めお、「名前衝突」をキヌワヌドに、それを利甚したLispプログラムたで玹介したいず思いたす。 JavaScriptのsymbol symbolはES2015で远加されたプリミティブです。プリミティブずはメ゜ッドを持たないデヌタのこずで、42、"Brendan Eich"などの仲間です。 symbol型のデヌタは関数Symbol