Slide 1

Slide 1 text

#SFBLJOH$IBOHF <ഁյతมߋ> $MPTJOH,FZOPUF גࣜձࣾ%3&$0. !LPJD&4. *OD 4BU ฏ੒3VCZձٞ

Slide 2

Slide 2 text

!LPJD,PJDIJ*50 w 3VCP$PQ$PNNJUUFS w "30SBDMFFOIBODFE BEBQUFS$PNNJUUFS w $PNNVOJUZ.BOBHFS BU&4. *OD

Slide 3

Slide 3 text

8SJUF 3FWJFX $PEF&WFSZ%BZ

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

#VOEMFS 1SZ 34QFD 3VCP$PQ CZFCVH 3VCZ,BJHJ %3&$0.͞Μϒʔεʹͯ

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

044ίϛϡχςΟͱͷڞੜΛࢧԉ Support coexistence with OSS community

Slide 9

Slide 9 text

͋ͱ͸෼͔Γ·͢Ͷʁ ࠾༻ ೥Ҏ্ͷ3BJMTΞϓϦ։ൃͷ࣮੷&4. l3BJMT044Λ௨͡੒௕͍ͨ͠ϓϩάϥϚʔz @koicまでどうぞ

Slide 10

Slide 10 text

IUUQTIFJTFJSCHJUIVCJPLBJHJ

Slide 11

Slide 11 text

IUUQTIFJTFJSCHJUIVCJPLBJHJ

Slide 12

Slide 12 text

#SFBLJOH$IBOHF <ഁյతมߋ> $MPTJOH,FZOPUF גࣜձࣾ%3&$0. ,PJDIJ*50&4. *OD 4BU ฏ੒3VCZձٞ

Slide 13

Slide 13 text

͜ͷߨԋͰಘΒΕΔ͔΋͠Εͳ͍͜ͱ w ςετͱCVOEMFVQEBUFͷॏཁ ੑͷ࠶ೝࣝ w 3VCP$PQͷࣼΊ্ͷ࢖͍ํ w ࢲ͔Βݟͨ044ͷੈք؍ w ഁյతมߋͷͨΊʹ͋ͳ͕ͨͰ͖Δ ͔΋͠Εͳ͍͜ͱ

Slide 14

Slide 14 text

w ഁյతมߋͱ͸Կ͔ʁ w ެ෍ࡁΈΠϯλϑΣʔεΛ࢖͏ w ඇਪ঑ܯࠂόʔδϣϯΛܦ༝͢Δ w ഁյతมߋΛ৐Γӽ͑Δ w ΦʔϓϯιʔείϛϡχςΟ ΞδΣϯμ

Slide 15

Slide 15 text

ഁյతมߋ ͱ͸Կ͔ʁ

Slide 16

Slide 16 text

CVHTSVCZMBOHPSHJTTVFT 3FBMLFZXPSEBSHVNFOU

Slide 17

Slide 17 text

IUUQTXXXSVCZMBOHPSHKBOFXTSVCZQSFWJFXSFMFBTFE

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

To be continued…

Slide 20

Slide 20 text

CVHTSVCZMBOHPSHJTTVFT 3FHFYQ\NBUDI NBUDI ^XJUIBOJMBSHVNFOUBSF EFQSFDBUFEBOEXJMMSBJTFB5ZQF&SSPSJO3VCZ

Slide 21

Slide 21 text

҆ఆ൛ͷ3VCZ[ % rbenv shell 2.6.5 && ruby -e 'p /re/.match?(nil)' false

Slide 22

Slide 22 text

։ൃ൛ͷ3VCZ % rbenv shell 2.6.5 && ruby -e 'p /re/.match?(nil)' false % rbenv shell 2.7.0-preview2 && ruby -e 'p /re/.match? (nil)' Traceback (most recent call last): 1: from -e:1:in `' -e:1:in `match?': no implicit conversion of nil into String (TypeError) QSFWJFX

Slide 23

Slide 23 text

։ൃ൛ͷ3VCZ % rbenv shell 2.6.5 && ruby -e 'p /re/.match?(nil)' false % rbenv shell 2.7.0-preview2 && ruby -e 'p /re/.match? (nil)' Traceback (most recent call last): 1: from -e:1:in `' -e:1:in `match?': no implicit conversion of nil into String (TypeError) % rbenv shell 2.7.0-preview3 && ruby -e 'p /re/.match? (nil)' -e:1: warning: given argument is nil; this will raise a TypeError in the next release false QSFWJFX

Slide 24

Slide 24 text

IUUQTCMPHBHJMFFTNDPKQFOUSZSBJMTPTTQBUDINFFUVQ ύονձͰ΋࿩୊ʹ

Slide 25

Slide 25 text

IUUQTUXJUUFSDPNLBNJQPTUBUVT

Slide 26

Slide 26 text

IUUQTUXJUUFSDPNLBNJQPTUBUVT

Slide 27

Slide 27 text

IUUQTUXJUUFSDPNOBMTITUBUVT

Slide 28

Slide 28 text

IUUQTUXJUUFSDPNZVLJIJSP@NBU[TUBUVT

Slide 29

Slide 29 text

IUUQTCVHTSVCZMBOHPSHJTTVFT 3FWFSU

Slide 30

Slide 30 text

ഁյతมߋ ͱ͸Կ͔ʁ

Slide 31

Slide 31 text

w CVOEMFVQEBUFޙ w 3VCZͷόʔδϣϯΛ͋͛ͨޙ w ͦͷ΄͔ϛυϧ΢ΣΞΛߋ৽ͨ͠ޙ ར༻ίʔυ΁ͷޙํޓ׵Λͳ͘͢มߋ ҎલͱҟͳΔ݁ՌΛҾ͖ى͜͠͏Δมߋ ‑

Slide 32

Slide 32 text

w ެ։͞Εͨ"1*ͷ໊લ͕มΘΔ w ެ։͞Εͨ"1*ͷҾ਺͕มΘΔ w ެ։͞Εͨ"1*ͷ໭Γ஋͕มΘΔ w ެ։͞Εͨ"1*ͷৼΔ෣͍͕มΘΔ w όάpYͱඇޓ׵มߋ͸ظ଴ͷҧ͍ ͲΜͳഁյతมߋ͕͋Δͷ͔ʁ

Slide 33

Slide 33 text

ެ։"1* ඇެ։"1*

Slide 34

Slide 34 text

%FQFOEPO 1VCMJTIFE"1* 公開APIへの依存

Slide 35

Slide 35 text

IUUQTCMJLJKBHJUIVCJP1VCMJTIFE*OUFSGBDF

Slide 36

Slide 36 text

0CKFDU0SJFOUFE 1SPHSBNJOH

Slide 37

Slide 37 text

ŠŠŠŠŠŠŠŠŠŠ҆ఆʹґଘͤΑ SDP: Stable Dependency Principle

Slide 38

Slide 38 text

w ιϑτ΢ΣΞ͸มԽ͠ଓ͚Δ w ҆ఆͨ͠"1*ͱෆ҆ఆͳ"1*͕͋Δ w ઃܭ͸׬શʹݻఆͰ͖ͳ͍ͨΊɺෆ ҆ఆΛڐ͢࢓૊Έ͕ඞཁ w ෆ҆ఆͳ"1*͕ѱ͍ͷͰ͸ͳ͘ɺෆ ҆ఆͳ"1*ʹґଘ͢Δͷ͕ѱ͍͜ͱ 4%1҆ఆґଘͷ๏ଇ

Slide 39

Slide 39 text

w ಺෦తͳ"1*ͱ໌ࣔ͞Ε͍ͯΔ"1* ͸࢖Θͳ͍ w 3BJMTʹ͓͍ͯ͸ϝιουίϝϯτ ͕͋ΔEPDʹ൓ө͞ΕΔϝιου͕ ެ։"1*ͱͳΔ w ඇެ։"1*ʹґଘ͢ΔͱͲ͏ͳΔʁ 3VCZ3VCZPO3BJMT

Slide 40

Slide 40 text

%FQFOEPO *OUFSOBM"1* ⾮公開APIへの依存

Slide 41

Slide 41 text

8JUIHSFBUQPXFS DPNFTHSFBU SFTQPOTJCJMJUZ ⼤いなる⼒には⼤いなる責任が伴う

Slide 42

Slide 42 text

MTFHBMZBSE SVCZ@QBSTFSSCBEEWPJE@TUNUUPJOTFSU@DPNNFOUT MPPQ

Slide 43

Slide 43 text

SVCZSVCZ!FGCDB

Slide 44

Slide 44 text

3FNPWFBOJOUFSOBM"1* ಺෦"1* શ࡟আ

Slide 45

Slide 45 text

SFRVJSFFSSPS ಺෦"1*

Slide 46

Slide 46 text

಺෦"1*΁ͷґଘΛճආ͢Δ

Slide 47

Slide 47 text

SBJMTSBJMT 3FNPWFVTFMFTT A.JHSBUPSTDIFNB@NJHSBUJPOT@UBCMF@OBNFA

Slide 48

Slide 48 text

಺෦"1*

Slide 49

Slide 49 text

಺෦"1* 3BJMTͰ͸ϝιουίϝϯτ͕ه͞Ε͍ͯͳ͍΋ͷ͸ඇެ։ "1*ͱ͍͏ѻ͍ͱͳ͍ͬͯΔ

Slide 50

Slide 50 text

࡟আࡁ"1* ͷஔ׵

Slide 51

Slide 51 text

% ag 'Migrator\.schema_migrations_table_name' `ghq root` HIR؅ཧͷMPDBMSFQPΛ۲ࢗ͠ݕࡧ Ͳ͏ͩΖ͏ʁ

Slide 52

Slide 52 text

% ag 'Migrator\.schema_migrations_table_name' `ghq root` HIR؅ཧͷMPDBMSFQPΛ۲ࢗ͠ݕࡧ ݁Ռͱ͍͔ͯͭ͘͠ώοτͨ͠ ‑

Slide 53

Slide 53 text

಺෦"1*΁ͷґଘͷ࣮ྫ IUUQTHJUIVCDPNFTNJODBEIPRQVMM

Slide 54

Slide 54 text

಺෦"1*΁ͷґଘͷ࣮ྫ IUUQTHJUIVCDPNBNBUTVEBEBUBCBTF@SFXJOEFSQVMM

Slide 55

Slide 55 text

w ಺෦"1*͸ϥΠϒϥϦఏڙऀ͕࣮૷ ʹԠͯ͡มߋ͠͏Δ w ͭ·Γಥવͦͷ"1*͕ͳ͘ͳͬͯ /P.FUIPE&SSPS͕ى͖ΔͳͲ w ྫ͑͹3BJMTΛΞοϓσʔτͨ͠Β ະରԠґଘ(FNͰΤϥʔ͕ى͖Δ %PO`UEFQFOEPOJOUFSOBM"1*

Slide 56

Slide 56 text

ඇਪ঑ܯࠂͷఏҊ͕͞ΕΔ 削除の前に⾮推奨警告しませんか。 バックリ ンクに⽰された多くのGemが使⽤してる。

Slide 57

Slide 57 text

w ຊདྷ͸಺෦"1*ʹґଘ͢Δͷ͕ྑ͘ ͳ͍͕ɺใࠂ݅਺͕ͦΕͳΓʹ͋ͬ ͨͱϝϯςφʔʹײ͡ΒΕͨ໛༷ w ͓ͦΒ͔͘ͳΓಛघέʔε w ҰํͰެ։"1*΁ͷมߋ͸Ϣʔβʔ ӨڹΛߟྀ͢΂͖ ඇਪ঑ܯࠂ

Slide 58

Slide 58 text

ඇਪ঑ܯࠂͷ௥Ճ IUUQTHJUIVCDPNSBJMTSBJMTQVMM

Slide 59

Slide 59 text

ඇਪ঑ܯࠂʹΑΔઆ໌ IUUQTHJUIVCDPNKSVCZBDUJWFSFDPSEKECDBEBQUFSQVMM

Slide 60

Slide 60 text

w ॲཧܥ΍ϥΠϒϥϦ͕ܯࠂΛग़͍ͯ ΔόʔδϣϯΛܦ༝ͯ͠ɺܯࠂΛ௵ ͔ͯ͠Β࣍ͷόʔδϣϯʹ্͛Δ w ͳΔ΂͘ϋΠδϟϯϓΛආ͚Δ w ೔ࠒ͔ΒCVOEMFVQEBUFΛ͠ ͯɺςετΛ࣮ߦ͢Δ ΞϓϦέʔγϣϯ։ൃऀͷᅂΈ

Slide 61

Slide 61 text

ഁյతมߋ ͱ͸Կ͔ʁ ෼͔Γ· ͔ͨ͠ʁ

Slide 62

Slide 62 text

w ͦ΋ͦ΋ιϑτ΢ΣΞ։ൃ͸೉͍͠ w ΋ͬͱ࢖͍΍͍ͩ͢Ζ͏ઃܭ͕͋Ε ͹ɺͰ͖Ε͹ͦ͏͍ͨ͠ ᷤ౻ w ιϑτ΢ΣΞ͸ਓ͕࡞͍ͬͯΔ w ͭ·Γެ։"1*Ͱ΋ᷤ౻ͷ຤ɺഁյ ͞ΕΔ ͢Δ ͜ͱ͕͋Δ ެ։"1*Λ࢖͑͹໰୊͸ى͖ͳ͍ʁ

Slide 63

Slide 63 text

'BLFS #SFBLJOH$IBOHF #Z&YBNQMF

Slide 64

Slide 64 text

No content

Slide 65

Slide 65 text

w ͋Δ೔ɺ3BJMTΞϓϦέʔγϣϯΛ CVOEMFVQEBUFͯ͠ςετΛ࣮ ߦͨ͠ΒಥવͷΤϥʔ͕ى͖Δ 'BLFSͰى͖ͨഁյతมߋ

Slide 66

Slide 66 text

'BLFSZ[ Faker::Address.zip_code('NY') # => "25771"

Slide 67

Slide 67 text

'BLFS[ Faker::Address.zip_code('NY') % bundle exec ruby example.rb Traceback (most recent call last): 1: from example.rb:3:in `' /Users/koic/.rbenv/versions/2.6.3/lib/ruby/gems/ 2.6.0/gems/faker-2.1.2/lib/faker/default/ address.rb:32:in `zip_code': wrong number of arguments (given 1, expected 0) (ArgumentError)

Slide 68

Slide 68 text

'BLFS[ ղܾ൛ -Faker::Address.zip_code('NY') +Faker::Address.zip_code(state_abbreviation: 'NY') LXBSHT ʹ͢Δ

Slide 69

Slide 69 text

w ࣗ෼ͷ৔߹͸ॳखʹHFNEJGGΛ࢖ͬ ͯࠩ෼Λ֬ೝͨ͠Γɺίϛοτϝοηʔ δʹ࢒ͨ͠Γ͍ͯ͠ΔͷͰͦͷϦϯΫ ΛݟΔ VQTUSFBNͷࠩ෼ΛݟΔ % gemdiff (snip) faker: 2.8.1 > 2.8.0 https://github.com/faker-ruby/faker/compare/ v2.8.0...v2.8.1

Slide 70

Slide 70 text

มߋཤྺͱ ͍͏ཏ਑൫ IUUQKBXJLJQFEJBPSHXJLJ&""&""&##&&##"NFEJB'JMF$BOUJOP1MBOJTQIFSFQOH IUUQTHJUIVCDPNGBLFSSVCZGBLFSCMPC W$)"/(&-0(NEJNQPSUBOUOPUF

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

"1*

Slide 73

Slide 73 text

w "SHVNFOU&SSPS͸ݪҼͱͯ͠෼͔ Γ΍͍͕͢ɺͲͷΑ͏ͳҾ਺͕ਖ਼͍͠ ͔෼͔Βͳ͔ͬͨ w QPTJUJPOBMҾ਺͔ΒΩʔϫʔυҾ਺΁ ͷมߋͰΩʔϫʔυ͕͙͢ʹ෼͔Βͳ ͔ͬͨ w "1*ͷҾ਺෼ ໰୊఺

Slide 74

Slide 74 text

w ࣗ෼͕౿Μͩ໘౗ͳ͜ͱ͸ɺଞͷਓ ʹͱͬͯ΋໘౗͔΋͠Εͳ͍ w (FNͷଟ͘͸3VCZͰॻ͔Ε͍ͯ Δ w ύονΛૹΔͷʹࢧোͷ͋ΔϥΠη ϯεʹग़ձͬͨ͜ͱ͕ͳ͍ ෆศͩͱࢥͬͨΒఏҊ͢Ε͹ྑ͍

Slide 75

Slide 75 text

w ΞοϓάϨʔυޙͷ࣮ߦ࣌Ͱ͙͢ʹ Τϥʔʹ͢ΔͷͰ͸ͳ͘ɺઌʹͲͷ Α͏ͳΠϯλϑΣʔεʹมΘΔͷ͔ ܯࠂΛग़͢ ղܾҊͱͯ͠ߟ͑ͨ͜ͱ

Slide 76

Slide 76 text

GBLFSSVCZGBLFS "EEXBSOGPSQPTJUJPOBMBSHVNFOUTXIFOVTJOH 'BLFS

Slide 77

Slide 77 text

$POUFYU Կނඞཁ͔

Slide 78

Slide 78 text

)PX ࣮૷ϙΠϯτ

Slide 79

Slide 79 text

.FSJU ͲΜͳಘ͕

Slide 80

Slide 80 text

&YBNQMF ࣮ྫ

Slide 81

Slide 81 text

ίʔυEJGG جຊతͳมߋ ޓ׵*'ͷఏڙ

Slide 82

Slide 82 text

ίʔυEJGG جຊతͳมߋ چ"1*΁ͷܯࠂ

Slide 83

Slide 83 text

ίʔυEJGG جຊతͳมߋ w legacy_sourceͱͯ͠ݩͷҾ਺Ͱ΋ ड͚ೖΕΔΑ͏ʹ͢Δ w legacy_source͕౉͞Εͨ৔߹͸ܯ ࠂΛදࣔͯ͠ɺͦͷ஋Λ༏ઌͯ͠࢖͏

Slide 84

Slide 84 text

ͦΕΛ"1*

Slide 85

Slide 85 text

def saying(legacy_source = NOT_GIVEN, source: nil) if legacy_source != NOT_GIVEN warn_with_uplevel 'Passing `source` with the \ 1st argument of `Dune.saying` is deprecated. \ Use keyword argument like \ `Dune.saying(source: ...)` instead.', uplevel: 1 source = legacy_source end end "1*෼ͷରԠͱ͸

Slide 86

Slide 86 text

def saying(legacy_source = NOT_GIVEN, source: nil) if legacy_source != NOT_GIVEN warn_with_uplevel 'Passing `source` with the \ 1st argument of `Dune.saying` is deprecated. \ Use keyword argument like \ `Dune.saying(source: ...)` instead.', uplevel: 1 source = legacy_source end end ϝιου໊ "1*෼ͷରԠͱ͸

Slide 87

Slide 87 text

def saying(legacy_source = NOT_GIVEN, source: nil) if legacy_source != NOT_GIVEN warn_with_uplevel 'Passing `source` with the \ 1st argument of `Dune.saying` is deprecated. \ Use keyword argument like \ `Dune.saying(source: ...)` instead.', uplevel: 1 source = legacy_source end end Ҿ਺໊ "1*෼ͷରԠͱ͸

Slide 88

Slide 88 text

def saying(legacy_source = NOT_GIVEN, source: nil) if legacy_source != NOT_GIVEN warn_with_uplevel 'Passing `source` with the \ 1st argument of `Dune.saying` is deprecated. \ Use keyword argument like \ `Dune.saying(source: ...)` instead.', uplevel: 1 source = legacy_source end end Ҿ਺ͷ਺ "1*෼ͷରԠͱ͸

Slide 89

Slide 89 text

def saying(legacy_source = NOT_GIVEN, source: nil) if legacy_source != NOT_GIVEN warn_with_uplevel 'Passing `source` with the \ 1st argument of `Dune.saying` is deprecated. \ Use keyword argument like \ `Dune.saying(source: ...)` instead.', uplevel: 1 source = legacy_source end end σϑΥϧτ஋ "1*෼ͷରԠͱ͸

Slide 90

Slide 90 text

def saying(legacy_source = NOT_GIVEN, source: nil) if legacy_source != NOT_GIVEN warn_with_uplevel 'Passing `source` with the \ 1st argument of `Dune.saying` is deprecated. \ Use keyword argument like \ `Dune.saying(source: ...)` instead.', uplevel: 1 source = legacy_source end end ܯࠂจ "1*෼ͷରԠͱ͸

Slide 91

Slide 91 text

"1* ख࡞ۀ͸ ͭΒ͍

Slide 92

Slide 92 text

ୡਓϓϩάϥϚʔ΁ͷجૅٕज़ ςεςΟϯά %FWFMPQFS5FTUJOH ࣗಈԽ 1SPKFDU"VUPNBUJPO όʔδϣϯ؅ཧ 7FSTJPO$POUSPM

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

w LXBSHTʹมΘΔલͷ'BLFSͷίϛο τϋογϡΛखʹೖΕΔ w खݩͷ'BLFSϦϙδτϦΛͦͷόʔδϣ ϯʹ໭͢ w 'BLFSελΠϧ΁ͷҠߦΠϯλϑΣʔ εʹBVUPDPSSFDU͢Δ$PQΛ࡞Δ w 'BLFSʹ$PQΛద༻ͨ͠ύονΛૹΔ ͜ͷඇਪ঑ܯࠂΛ࡞ΔͨΊߦͬͨ͜ͱ

Slide 95

Slide 95 text

w LXBSHTʹมΘΔલͷ'BLFSͷίϛο τϋογϡΛखʹೖΕΔ w खݩͷ'BLFSϦϙδτϦΛͦͷόʔδϣ ϯʹ໭͢ w 'BLFSελΠϧ΁ͷҠߦΠϯλϑΣʔ εʹBVUPDPSSFDU͢Δ$PQΛ࡞Δ w 'BLFSʹ$PQΛద༻ͨ͠ύονΛૹΔ ͜ͷඇਪ঑ܯࠂΛ࡞ΔͨΊߦͬͨ͜ͱ

Slide 96

Slide 96 text

w 3VCP$PQ͸ظ଴͍ͯ͠ͳ͍ελΠ ϧͷίʔυΛظ଴͍ͯ͠Δίʔυʹ ࣗಈमਖ਼͢ΔػೳΛඋ͍͑ͯΔ w 3VCP$PQ͕ఏڙ͍ͯ͠Δ$PQΫ ϥεΛܧঝ͢Δ͜ͱͰΦϦδφϧͷ $PQΛ࡞Δ͜ͱ͕Ͱ͖Δ 3VCP$PQ͓͞Β͍

Slide 97

Slide 97 text

w ϩʔΧϧϦϙδτϦͷΈͷϒϥϯν Ͱॻ͖ͳ͙ͬͨ΋ͷΛൃ۷͠·ͨ͠ w ͲΜͳҠߦεΫϦϓτΛॻ͍͍ͯͨ ͷ͔ൈਮͯ͠งғؾΛ఻͑·͢ w ϝϯςφϯεΛ΄΅ߟ͍͑ͯͳ͍ɺ γϣοτͷίʔυʹͯޚ༰ࣻئ ΦϒδΣΫτࢦ޲lεΫϦϓτzݴޠ

Slide 98

Slide 98 text

ԶDPQ͕ظ଴͢Δ࢓༷ # bad # def email( # name: nil, # separators: nil # ) # # good # def email( # legacy_name = NOT_GIVEN, # legacy_separators = NOT_GIVEN, # name: nil, # separators: nil # ) ΩʔϫʔυҾ਺ͷΈ Ͱߏ੒͞Ε͍ͯΔ

Slide 99

Slide 99 text

CBEέʔεΛଊ͑Δ࣮૷ྫ class BreakingChangeArguments < Cop def on_def(node) return unless node.arguments.all? {|argument| argument.kwarg_type? || argument.kwoptarg_type? } node.arguments.reverse_each do |argument| message = format( MSG, name: argument.children.first ) add_offense(argument, message: message) end end end

Slide 100

Slide 100 text

CBEέʔεΛଊ͑Δ࣮૷ྫ class BreakingChangeArguments < Cop def on_def(node) return unless node.arguments.all? {|argument| argument.kwarg_type? || argument.kwoptarg_type? } node.arguments.reverse_each do |argument| message = format( MSG, name: argument.children.first ) add_offense(argument, message: message) end end end EFGϊʔυͷॲཧ

Slide 101

Slide 101 text

CBEέʔεΛଊ͑Δ࣮૷ྫ class BreakingChangeArguments < Cop def on_def(node) return unless node.arguments.all? {|argument| argument.kwarg_type? || argument.kwoptarg_type? } node.arguments.reverse_each do |argument| message = format( MSG, name: argument.children.first ) add_offense(argument, message: message) end end end ܯࠂΛग़͢"1*

Slide 102

Slide 102 text

CBEέʔεΛଊ͑Δ࣮૷ྫ class BreakingChangeArguments < Cop def on_def(node) return unless node.arguments.all? {|argument| argument.kwarg_type? || argument.kwoptarg_type? } node.arguments.reverse_each do |argument| message = format( MSG, name: argument.children.first ) add_offense(argument, message: message) end end end ܯࠂ͠ͳ͍৚݅

Slide 103

Slide 103 text

CBEέʔεΛଊ͑Δ࣮૷ྫ class BreakingChangeArguments < Cop def on_def(node) return unless node.arguments.all? {|argument| argument.kwarg_type? || argument.kwoptarg_type? } node.arguments.reverse_each do |argument| message = format( MSG, name: argument.children.first ) add_offense(argument, message: message) end end end ܯࠂ͠ͳ͍৚݅ ϊʔυͷλΠϓ % ruby-parse -e 'def do_something(foo:, bar: 1); end' (def :do_something (args (kwarg :foo) (kwoptarg :bar (int 1))) nil)

Slide 104

Slide 104 text

class BreakingChangeArguments < Cop def on_def(node) return unless node.arguments.all? {|argument| argument.kwarg_type? || argument.kwoptarg_type? } node.arguments.reverse_each do |argument| message = format( MSG, name: argument.children.first ) add_offense(argument, message: message) end end end ܯࠂ͠ͳ͍৚݅ % ruby-parse -e 'def do_something(foo:, bar: 1); end' (def :do_something (args (kwarg :foo) (kwoptarg :bar (int 1))) nil) CBEέʔεΛଊ͑Δ࣮૷ྫ ϊʔυͷλΠϓ

Slide 105

Slide 105 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ def autocorrect(node) kwarg = node.children.first argument_index = node.parent.parent.arguments.map {|argument| argument.children.first }.index(kwarg) + 1 index = case argument_index when 1; '1st' when 2; '2nd' when 3; '3rd' else "#{argument_index}th" end

Slide 106

Slide 106 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ def autocorrect(node) kwarg = node.children.first argument_index = node.parent.parent.arguments.map {|argument| argument.children.first }.index(kwarg) + 1 index = case argument_index when 1; '1st' when 2; '2nd' when 3; '3rd' else "#{argument_index}th" end ࣗಈमਖ਼ ΁ͷίʔϧόοΫ ఆٛ

Slide 107

Slide 107 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ def autocorrect(node) kwarg = node.children.first argument_index = node.parent.parent.arguments.map {|argument| argument.children.first }.index(kwarg) + 1 index = case argument_index when 1; '1st' when 2; '2nd' when 3; '3rd' else "#{argument_index}th" end LXBSHͷ ϊʔυ

Slide 108

Slide 108 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ def autocorrect(node) kwarg = node.children.first argument_index = node.parent.parent.arguments.map {|argument| argument.children.first }.index(kwarg) + 1 index = case argument_index when 1; '1st' when 2; '2nd' when 3; '3rd' else "#{argument_index}th" end LXBSHͷ Ҿ਺Ґஔ

Slide 109

Slide 109 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ legacy_argument = "legacy_#{kwarg}" class_name = find_class_name(node) method_name = node.parent.parent.method_name condition += <<-RUBY if #{legacy_argument} != NOT_GIVEN warn_with_uplevel 'Passing `#{kwarg}` with the #{index} argument of `#{class_name}.#{method_name}` is deprecated. Use keyword argument like `#{class_name}.#{method_name} (#{kwarg}: ...)` instead.', uplevel: 1 #{kwarg} = #{legacy_argument} end RUBY

Slide 110

Slide 110 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ legacy_argument = "legacy_#{kwarg}" class_name = find_class_name(node) method_name = node.parent.parent.method_name condition += <<-RUBY if #{legacy_argument} != NOT_GIVEN warn_with_uplevel 'Passing `#{kwarg}` with the #{index} argument of `#{class_name}.#{method_name}` is deprecated. Use keyword argument like `#{class_name}.#{method_name} (#{kwarg}: ...)` instead.', uplevel: 1 #{kwarg} = #{legacy_argument} end RUBY ޓ׵ม਺ͷ࡞੒

Slide 111

Slide 111 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ legacy_argument = "legacy_#{kwarg}" class_name = find_class_name(node) method_name = node.parent.parent.method_name condition += <<-RUBY if #{legacy_argument} != NOT_GIVEN warn_with_uplevel 'Passing `#{kwarg}` with the #{index} argument of `#{class_name}.#{method_name}` is deprecated. Use keyword argument like `#{class_name}.#{method_name} (#{kwarg}: ...)` instead.', uplevel: 1 #{kwarg} = #{legacy_argument} end RUBY private def find_class_name(node) if node.class_type? return node.identifier.source end find_class_name(node.parent) end

Slide 112

Slide 112 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ legacy_argument = "legacy_#{kwarg}" class_name = find_class_name(node) method_name = node.parent.parent.method_name condition += <<-RUBY if #{legacy_argument} != NOT_GIVEN warn_with_uplevel 'Passing `#{kwarg}` with the #{index} argument of `#{class_name}.#{method_name}` is deprecated. Use keyword argument like `#{class_name}.#{method_name} (#{kwarg}: ...)` instead.', uplevel: 1 #{kwarg} = #{legacy_argument} end RUBY ࣗಈमਖ਼ίʔυͷ ஔ׵จࣈྻ

Slide 113

Slide 113 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ lambda do |corrector| corrector.insert_before( arguments_range(node), "#{legacy_argument} = NOT_GIVEN, " ) corrector.insert_before( node.parent.parent.children.last.source_range, condition ) end

Slide 114

Slide 114 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ lambda do |corrector| corrector.insert_before( arguments_range(node), "#{legacy_argument} = NOT_GIVEN, " ) corrector.insert_before( node.parent.parent.children.last.source_range, condition ) end मਖ਼ίʔυ΁ ͷஔ׵

Slide 115

Slide 115 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ lambda do |corrector| corrector.insert_before( arguments_range(node), "#{legacy_argument} = NOT_GIVEN, " ) corrector.insert_before( node.parent.parent.children.last.source_range, condition ) end ޓ׵Ҿ਺ͷૠೖ

Slide 116

Slide 116 text

CBEέʔεΛࣗಈमਖ਼͢Δ࣮૷ྫ lambda do |corrector| corrector.insert_before( arguments_range(node), "#{legacy_argument} = NOT_GIVEN, " ) corrector.insert_before( node.parent.parent.children.last.source_range, condition ) end ܯࠂ৚݅ͷૠೖ

Slide 117

Slide 117 text

No content

Slide 118

Slide 118 text

͓Ϛʔδ

Slide 119

Slide 119 text

ŠŠŠŠŠŠŠŠŠŠϢʔβʔͷ൓Ԡ Feedback

Slide 120

Slide 120 text

GBLFSSVCZGBLFS USJHHFSTEFQSFDBUJPOXBSOJOHTGSPNJOTJEFUIF HFN

Slide 121

Slide 121 text

⾮推奨警告の量が半端なくて⼤変だったよ

Slide 122

Slide 122 text

w ,ಥવͷΤϥʔΛճආ͢Δඇਪ঑ ܯࠂ͕׆༻͞ΕͨΑ͏Ͱ͋Δ w 1ͷഁյతมߋΛ௚ܸ͢Δ ͱͭΒͦ͏Ͱ͋Δ w 5ࣗಈमਖ਼ՄೳͳπʔϧΛఏڙ͠ ͯΞοϓάϨʔυ΁ͷ௧ΈΛݮΒ͢ ϑΟʔυόοΫʹରͯ͠ߟ͑ͨ͜ͱ

Slide 123

Slide 123 text

LPJDSVCPDPQGBLFS "3VCP$PQFYUFOTJPOGPS'BLFS

Slide 124

Slide 124 text

w ͔ͭͯ34QFD͔Β34QFD΁ ͷҠߦͰ࢖ͬͨ5SBOTQFDʹӨڹ Λड͚ͯ࡞ͬͨ(FN w 'BLFSʹඇਪ঑ܯࠂΛೖΕΔ13Λ ࡞ΔաఔͰ͍ͭͰʹฒߦͯ͠࡞Ζ͏ ͱ͍ͯͨ͠Α͏ͳ ͏Ζ֮͑ Ұܳ͸։ൃΛՃ଎͢Δ

Slide 125

Slide 125 text

No content

Slide 126

Slide 126 text

No content

Slide 127

Slide 127 text

ઌͷ࣮૷ͱࣅͨ Α͏ͳ΋ͷͳͷ Ͱ࣮૷ղઆׂѪ

Slide 128

Slide 128 text

l (FN͸࡞͚ͬͨͩͰউख ʹ޿·ΔΘ͚Ͱ͸ͳ͘࢖Θ ΕΔͨΊͷͻͱ޻෉ॏཁ !BNBUTVEB

Slide 129

Slide 129 text

Slide 130

Slide 130 text

IUUQTXXXNPVOUBJOHPBUTPGUXBSFDPNCMPHBSFPGGFBUVSFTSFBMMZSBSFMZPSOFWFSVTFE

Slide 131

Slide 131 text

ࢲ͕ࢥ͍͍ͭͨ ͜ͷ՝୊ʹର͠ ࠷ڧͷએ఻ํ๏

Slide 132

Slide 132 text

VQTUSFBN ʹऔΓࠐΜ Ͱ΋Β͏

Slide 133

Slide 133 text

GBLFSSVCZGBLFS *ODMVEFSVCPDPQGBLFSBVUPDPSSFDUJOEFQSFDBUJPO

Slide 134

Slide 134 text

No content

Slide 135

Slide 135 text

$POUFYU લྫΛग़͢

Slide 136

Slide 136 text

)PX ղܾࡦ

Slide 137

Slide 137 text

&YBNQMF ࣮ྫ

Slide 138

Slide 138 text

.FSJU ͲΜͳಘ͕

Slide 139

Slide 139 text

৺഑ͩͬͨ఺

Slide 140

Slide 140 text

No content

Slide 141

Slide 141 text

͓Ϛʔδ

Slide 142

Slide 142 text

ŠŠŠŠŠŠŠŠŠŠŠŠŠŠͦͷޙ Afterwards

Slide 143

Slide 143 text

GBLFSSVCZGBLFS 6TJOHLXBSHTGPSNFUIPETUIBUBDDFQUPOMZPOF BSHVNFOUJTJOF⒏DJFOU

Slide 144

Slide 144 text

引数ひとつにkwargsはやりすぎじゃね?

Slide 145

Slide 145 text

8*1GPS'BLFS

Slide 146

Slide 146 text

8*1GPS'BLFS To be continued…

Slide 147

Slide 147 text

w ࠷ॳ͔Βऑ఺ͷͳ͍ઃܭΛ͢Δͷ͸೉͍͠ w ιϑτ΢ΣΞΛΑΓྑ͍ܗʹ͢ΔͨΊʹɺࢭΉΛ ಘͣޙํޓ׵Λؾʹ͔͚ͭͭ΋ఘΊΔ৔߹͕͋Δ w CVOEMFVQEBUFͰখ͞ͳϦϓϨʔεΛ܁Γฦ ͢͜ͱͰେ͖ͳϦϓϨʔεΛ๷͙ w มߋൣғ͕ڱ͍ํ͕ݪҼͷಛఆ͕༰қ w ͋ͳͨͱ·ΘΓ͸ݹ͍όʔδϣϯ͔৽͍͠όʔδϣ ϯͲͪΒΛ࢖͏ͷ͕޷ΈͰ͔͢ʁ ഁյతมߋΛӽ͑Δ

Slide 148

Slide 148 text

όʔδϣϯӽ͑ lޙੈʹ࢒͢΋ͷz ະདྷ΁

Slide 149

Slide 149 text

w ͋ͳͨʹΑͬͯෆඞཁ͔ͩͬͨ΋͠Εͳ͍ ഁյతͳมߋΛࢭΊΔ͜ͱ͕Ͱ͖Δ͔΋͠ Εͳ͍ w ͋ͳͨʹΑͬͯഁյతͳมߋ΁ͷμϝʔδ Λ؇࿨Ͱ͖Δ͔΋͠Εͳ͍ w ·ͣ͸खݩͷඇਪ঑ܯࠂΛݟͯΈΑ͏ w ຤͸ΈΜͳͰ3VCZ΁ͷΞοϓ άϨʔυࣗຫΛ͍͖ͯ͠·͠ΐ͏ ͋ͳ͕ͨίϛϡχςΟ

Slide 150

Slide 150 text

l ίϛϡχςΟͱ͸୭͔ɻ΋ͪΖ Μɺ͋ͳͨͷ͜ͱͩɻ͋ͳ͕ͨ ίϛϡχςΟͰ͋ΓɺͦΕҎ֎ ʹίϛϡχςΟ͸͍ͳ͍ɻ͋ͳ ͨͷΑ͏ͳਓʑͷू·ΓΛɺί ϛϡχςΟͱݺͿͷͩɻ IUUQTNBHB[JOFSVCZJTUOFUBSUJDMFT'PSF8PSEIUNM Community is yourself

Slide 151

Slide 151 text

No content