2023/05/17(水) Qiita Conference 2023
ాਓʢ!U@XBEBʣαόϯφศΓࣗಈςετʹؔ͢Δ࿈ࡌͰಘΒΕͨݟͷ·ͱΊ൛📷🙆 🙆 2JJUB$POGFSFODF.BZ
View Slide
ΞοϓσʔτΛॏͶΔߨԋͷ݄൛Ͱ͢ʢ࿈ࡌୈճ·ͰऩʣIUUQTTQFBLFSEFDLDPNUXBEBίϥϜ࿈ࡌͷୈճ·Ͱऩ͍ͯ͠·͢
ߨԋͷจࣈى͜͠ࠓޙެ։༧ఆͰ͢ެ։͞ΕͨΒTQFBLFSEFDLͷಉҰ63-ͰࢿྉΛΞοϓσʔτ͠·͢
t-wadat_wadatwada📷🙆 📹🙅🙆ࣗݾհ#QiitaConference
ٕज़ॻͷग़൛ʹؔΘ͍ͬͯ·͢
αόϯφศΓʜʜʁ
IUUQTUXBEBIBUFOBCMPHKQFOUSZXEQSFTTTBWBOOBDPMVNO8%#13&44ʹίϥϜΛ࿈ࡌ͍ͯ͠·͢
ΑΖ͓͘͠ئ͍͠·͢📷🙆 🙆 2JJUB$POGFSFODF
ֶश༻ςετِཅੑͱِӄੑςεταΠζςετμϒϧςετϐϥϛουࣗಈςετͷαΠζμϯઓུ🦁"HFOEB࿈ࡌ֤ճͷςʔϚ
ֶͼΛࣗಈςετͱͯ͠ॻ͘ଈ࣌ੑͱ࠶ݱੑ
ֶशྫ1)1ͷ%BUF5JNFͱ%BUF5JNF*NNVUBCMFIUUQTXXXQIQOFUNBOVBMKBDMBTTEBUFUJNFJNNVUBCMFQIQ
/*** @test* @group learning*/public function DateTimeのaddは自身の状態を変更しつつ自身を返す(): void{$halloween = new \DateTime('2021-10-31');$oneYear = \DateInterval::createFromDateString('1 year');$halloween2022 = $halloween->add($oneYear);$this->assertSame($halloween, $halloween2022);$this->assertEquals('2022-10-31', $halloween->format('Y-m-d'));$this->assertEquals('2022-10-31', $halloween2022->format('Y-m-d'));}/*** @test* @group learning*/public function DateTimeImmutableのaddは自身の状態を変更せず新しい状態を伴う新しいインスタンスを返す(): void{$halloween = new \DateTimeImmutable('2021-10-31');$oneYear = \DateInterval::createFromDateString('1 year');$halloween2022 = $halloween->add($oneYear);$this->assertNotSame($halloween, $halloween2022);$this->assertEquals('2021-10-31', $halloween->format('Y-m-d'));$this->assertEquals('2022-10-31', $halloween2022->format('Y-m-d'));}%BUF5JNFͱ%BUF5JNF*NNVUBCMFͷҧ͍Λֶशςετʹ͢Δֶशςετʢֶͼ͕తͷςετʣΛݟ͚ΔͨΊʹMFBSOJOHλάΛ͚͍ͭͯ·ֶ͕͢͜͜ͼֶ͕͜͜ͼ
ٙΛςετʹ͢Δ
/*** @test* @group learning*/public function 同じ時刻を指している場合はタイムゾーンが異なっても等価とみなされる(): void{$utc = new DateTimeImmutable('2021-12-24T15:00:00', new DateTimeZone('UTC'));$jst = new DateTimeImmutable('2021-12-25T00:00:00', new DateTimeZone('Asia/Tokyo'));$this->assertTrue($utc == $jst);}ٙΛςετʹ͢Δςετʹฉ͍ͯΈΕ͍͍
ڻ͖Λςετʹ͢Δྫ͑ʜʜ
ίϯετϥΫλҰճ͔͠ݺͳ͍ͱࡨ͍֮ͯͨ͠ʁㅟㅟㅟㅟㅟㅟㅟㅟㅟㅟㅟㅟㅟㅟㅟҰମ͍͔ͭΒ
/*** @test* @group learning*/public function コンストラクタをもう一度呼ぶと破壊的変更ができてしまう(): void{$dt = new \DateTimeImmutable('2021-12-24');$this->assertSame('2021-12-24', $dt->format('Y-m-d'));$dt->__construct('2022-01-01');$this->assertSame('2022-01-01', $dt->format('Y-m-d'));}ͳΜʜʜͩͱʜʜʂʁ໌ࣔతʹݺͯ͠·͏༨ஊ͜ͷςετίʔυΛ͖͔͚ͬʹQIQTSDʹJTTVFͱͯ͠ใࠂ͞Εɺ͕ٞߦΘΕ·ͨ͠ɻIUUQTHJUIVCDPNQIQQIQTSDJTTVFT༨ஊ͜ͷςετίʔυΛ͖͔͚ͬʹ੩తղੳπʔϧ1)14UBOͱ1TBMNʹػೳఏҊ͕ߦΘΕɺ1)14UBOʹ!NVOP@͞Μ͕࡞ͨ͠QVMMSFRVFTU͕࠾༻͞ΕɺϦϦʔε͞Ε·ͨ͠ɻIUUQTHJUIVCDPNQIQTUBOQIQTUBOTSDQVMM
ֶश༻ςετِཅੑͱِӄੑςεταΠζςετμϒϧςετϐϥϛουࣗಈςετͷαΠζμϯઓུ"HFOEB࿈ࡌ֤ճͷςʔϚ🦁
ࣗಈςετͷ৴པੑΛΉ͠ΉݱΛཧղ͢Δ
ςετࣗಈԽͱاۀͷۀͷҼՌؔIUUQTXXXBNB[PODPKQEQςετͷࣗಈԽʹ͓͍ͯɺ*5ύϑΥʔϚϯεͷ ༧ଌईͱͳΓ͏Δ͜ͱ͕໌ͨ͠ͷ࣍ͷͭ ৴པੑͷߴ͍ࣗಈςετΛඋ͑Δ͜ͱ ։ൃऀओମͰड͚ೖΕςετΛ࡞ɾཧ͠ɺ खݩͷ։ൃڥͰ؆୯ʹ࠶ݱɾमਖ਼Ͱ͖Δ͜ͱʰ-FBOͱ%FW0QTͷՊֶʱQʢ˞༁ΛҰ෦มߋʣ
IUUQTXXXBNB[PODPKQEQςετʹ߹֨ͨ͠ιϑτΣΞͰ͋ΕϦϦʔεՄೳɺෆ߹֨Ͱ͋Εॏେͳෆ۩߹͕͋ΔɺͱνʔϜ͕֬৴Ͱ͖ΔΑ͏ͳςετΛ࣮ࢪ͍ͯ͠Δ͜ͱ ޡݕʢِཅੑGBMTFQPTJUJWFʣݟಀ͠ʢِӄੑGBMTFOFHBUJWFʣ͕ଟ͘ɺ৴པੑʹ͚ܽΔςετεΠʔτ͕͋·Γʹଟ͗͢Δ ৴པͷߴ͍ςετεΠʔτΛ࡞Γ্͛Δܧଓతͳྗͱ ࢿՁ͕͋Δʰ-FBOͱ%FW0QTͷՊֶʱQʢ˞༁ΛҰ෦มߋʣ৴པੑͷߴ͍ࣗಈςετΛඋ͑Δ͜ͱ
ِཅੑͱِӄੑIUUQTHJIZPKQEFWTFSJBMTBWBOOBMFUUFS
ِཅੑͱِӄੑͷύλʔϯw ِཅੑw ੬͍ςετ CSJUUMFUFTU GSBHJMFUFTUw ৴པෆೳςετflBLZUFTUw ِӄੑw ۭৼΓw ΧόϨοδෆw ςετରϩδοΫͷςετίʔυͷ࿙Εग़͠
// プロダクトコードclass Item {// コンストラクタ割愛tax_amount() {const rate = (this.tax_rate / 100);return (this.price / (1 + rate)) * rate;}}// テストコードit('税込価格から税額を返す', () => {const item = new Item('技評茶', 130, 8);const expected = (130 / (1 + (8 / 100))) * (8 / 100);assert.equal(item.tax_amount(), expected);});ྫςετରϩδοΫͷςετίʔυͷ࿙Εग़͠ԁະຬͷ͕ൃੜ͢Δόά͕͋Δςετίʔυͷํಉ͡ϩδοΫͰظΛܭࢉ͍ͯ͠ΔͷͰςετ͕ޭͯ͠͠·͏
৴པෆೳੑʢflBLJOFTTʣ͕ʹۙ͢ΔͱɺςετՁΛࣦ͍࢝ΊΔIUUQTXXXPSFJMMZDPKQCPPLTʰ(PPHMFͷιϑτΣΞΤϯδχΞϦϯάʱQ
ࣗಈςετͱ$*ʹϑΟοτ͢Δ໌֬ͳςετྨج४
օ͞Μʹ͓͍͠·͢🙋🙋🙋σʔλϕʔεʹΞΫηε͢ΔͷϢχοτςετ :FT/PωοτϫʔΫʹΞΫηε͢ΔͷϢχοτςετ :FT/PϑΝΠϧʹΞΫηε͢ΔͷϢχοτςετ :FT/Pݱࡏ࣌ࠁʹΞΫηε͢ΔͷϢχοτςετ :FT/PґଘઌͷΫϥεʹຊΛ͏ͷϢχοτςετ :FT/P
IUUQTNBSUJOGPXMFSDPNCMJLJ6OJU5FTUIUNM6OJU5FTUͷ6OJUͬͯԿʁ
5FTU4J[FΑΓᐆດ͞ͷগͳ͍ྨ
IUUQTUFTUJOHHPPHMFCMPHDPNUFTUTJ[FTIUNM5FTU4J[F
4NBMM ʢ୯Ұϓϩηεʣ.FEJVN ʢ୯ҰϚγϯʣ-BSHF ʢ੍ͳ͠ʣ6OJUൺେ͍ʹਪආ͚͍͕͔ͨͨ͠ͳ͍ͱ͖࠷ѱ͕ͩΑ͘ݟ͔͚Δ*OUFHSBUJPOൺॻ͚ΔͳΒίεύྑ͠ී௨Ͱ͖Εආ͚͍ͨ&&ൺݪཧ্ෆՄೳʹ͍͕ۙখ͍͞γεςϜͳΒՄೳʁখ͍͞γεςϜͳΒՄೳී௨͔ͭ$6+ʹߜΓ͍ͨ5FTU4DPQF5FTU4J[F5FTU4DPQFͱ5FTU4J[F
4NBMM ʢ୯Ұϓϩηεʣ.FEJVN ʢ୯ҰϚγϯʣ-BSHF ʢ੍ͳ͠ʣ6OJUൺେ͍ʹਪආ͚͍͕͔ͨͨ͠ͳ͍ͱ͖࠷ѱ͕ͩΑ͘ݟ͔͚Δ*OUFHSBUJPOൺॻ͚ΔͳΒίεύྑ͠ී௨Ͱ͖Εආ͚͍ͨ&&ൺݪཧ্ෆՄೳʹ͍͕ۙখ͍͞γεςϜͳΒՄೳʁখ͍͞γεςϜͳΒՄೳී௨͔ͭ$6+ʹߜΓ͍ͨ5FTU4DPQF5FTU4J[F5FTU4DPQFͱ5FTU4J[Fίεύྑ͠ίεύѱ͠
࣮ੑͱܾఆੑͷτϨʔυΦϑΛཧղ͢Δ
IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNMςετμϒϧࣗಈςετ༻ͷِ
IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNMςετμϒϧͷྨʢY651ʣ
ςετμϒϧͷརͱҙIUUQTXXXBNB[PODPKQEQw རw ςετ͠ʹ͍͘ͷΛςετՄೳʹ͢Δw ςετͷͱܾఆੑΛ্ͤ͞Δw ҙw ςετ͕੬͘ͳΓɺมߋΛ͛Δʢརͷཪฦ͠ʣw ςετͷِӄੑΛট͘ʢࣗ࡞ࣗԋςετʣ
ࣗಈςετͷ৴པੑΛதظతʹอͭ࠷దͳόϥϯε
ϢχοτΠϯςάϨʔγϣϯ&&ίετ࣮ੑςετέʔεߴߴܾఆੑςετϐϥϛου
ςετϐϥϛουͱΞΠεΫϦʔϜίʔϯΞϯνύλʔϯIUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF
ࠞཚʮϢχοτʯʮΠϯςάϨʔγϣϯʯͷղऍͷϒϨ͔Βੜ͕ͪ͡
ϢχοτΠϯςάϨʔγϣϯ&&ίετ࣮ੑςετέʔεߴߴܾఆੑϒϨͷগͳ͍ςετͷྨج४ʜʜʁ
ίετ࣮ੑߴߴܾఆੑϒϨͷগͳ͍ςετͷྨج४ˠςεταΠζ4NBMM.FEJVN-BSHFςετέʔε
IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF4NBMM.FEJVN-BSHFखಈςετͰɺଟ͘ͷݱͰΞΠεΫϦʔϜίʔϯ͔Β࢝·ΔʢͦΕѱ͍͜ͱͰͳ͍ʣ
Ͳ͏ͬͯΞΠεΫϦʔϜίʔϯΛϐϥϛουʹ͢Δ͔IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF4NBMM.FEJVN-BSHFखಈςετ4NBMM.FEJVN-BSHF
IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF4NBMM.FEJVN-BSHFखಈςετ-BSHF͔Β.FEJVN
IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNM-BSHF͔Β.FEJVN'BLF0CKFDU'BLFࣗಈςετ༻ͷସ࣮ɻ%ZOBNP%#ʹର͢Δ%ZOBNP%#MPDBMMPDBLTUBDL͕දྫɻίϯςφͰಈ࡞ͤ͞ΒΕΕςεταΠζ͕.FEJVNʹऩ·Δɻ
IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF4NBMM.FEJVN-BSHFखಈςετ.FEJVN͔Β4NBMM
.FEJVN͔Β4NBMM)VNCMF0CKFDUIUUQTXXXBNB[PODPKQEQςετ༰қੑΛԼ͍͛ͯΔཁૉΛബ͘Γग़͠ɺςετՄೳൣғΛ͘औΔجຊύλʔϯ
ΞΠεΫϦʔϜίʔϯ͔ΒϐϥϛουIUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF4NBMM.FEJVN-BSHFखಈςετ4NBMM.FEJVN-BSHF
ֶश༻ςετِཅੑͱِӄੑςεταΠζςετμϒϧςετϐϥϛουࣗಈςετͷαΠζμϯઓུ🦁🦁🦁🦁🦁͜Ε·ͰͷݟΛ·ͱΊΔͱ
4NBMM.FEJVN-BSHFίετ࣮ੑςετέʔεߴߴܾఆੑ·ͱΊςετμϒϧͰαΠζμϯͯ͠ɺ֤αΠζΛϐϥϛουܕʹஔ͠ɺςετશମͷ৴པੑΛҡ࣋͢Δςετμϒϧςετμϒϧςετ༰қੑઃܭυϝΠϯઃܭ
͓ΘΓʹ
ࣦ৬ͷةػྑॻ͗͢ΔIUUQTCPPLNZOBWJKQFDQSPEVDUTEFUBJMJE
ࣦ৬ͷةػ͍͔ʹࢲͷݴ͍ͦ͏ͳ͜ͱΛݴ͏"*IUUQTUXJUUFSDPNLBXBTJNBTUBUVT
IUUQTHJIZPKQNBHB[JOFXEQSFTTTVTQFOEFE൵͍͓͠Βͤ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠📷🙆 🙆 2JJUB$POGFSFODF