Slide 1

Slide 1 text

© DMM.com !LHNZTIJO TIJCVZBBQL LPUMJOͰ΋KBWBͰ΋ ݕग़Ͱ͖Δ $VTUPN-JOUͷ࡞Γํ

Slide 2

Slide 2 text

© DMM.com X w LHNZTIJOఝٶ ͗͘Έ΍ w "OESPJEΤϯδχΞ w %..DPNϥϘ$50ࣨॴଐ w ೥݄͔Β ࣗݾ঺հ

Slide 3

Slide 3 text

© DMM.com X BHFOEB

Slide 4

Slide 4 text

© DMM.com X w LPUMJOΛ࢖ͬͨ"OESPJEϓϩδΣΫτͰMJOUΛ͔͚Δ ʹ͸ʁ w $VTUPN-JOUΛ࡞Δʹ͸ʁ w BOESPJEMJOUͰ$VTUPN-JOUΛ࡞ͬͯΈΔ w ࡞ͬͨBOESPJEMJOUͷ$VTUPN-JOUΛςετ͢Δ w ࡞ͬͨBOESPJEMJOUͷ$VTUPN-JOUΛ࢖͏ w ·ͱΊ BHFOEB

Slide 5

Slide 5 text

© DMM.com X LPUMJOΛ࢖ͬͨ "OESPJEϓϩδΣΫτͰ MJOUΛ͔͚Δʹ͸ʁ

Slide 6

Slide 6 text

© DMM.com X LPUMJOΛ࢖ͬͨ"OESPJEϓϩδΣΫτͰMJOUΛ͔͚Δʹ͸ʁ Ҏલ͸ ओʹ ͭͷํ๏͔͠ͳ͔ͬͨ w LUMJOU w IUUQTHJUIVCDPNTIZJLPLUMJOU w EFUFLU w IUUQTHJUIVCDPNBSUVSCPTDIEFUFLU

Slide 7

Slide 7 text

© DMM.com X LPUMJOΛ࢖ͬͨ"OESPJEϓϩδΣΫτͰMJOUΛ͔͚Δʹ͸ʁ ͓ͦΒ͘ BOESPJEHSBMEFQMVHJO͔Β w LUMJOU w IUUQTHJUIVCDPNTIZJLPLUMJOU w EFUFLU w IUUQTHJUIVCDPNBSUVSCPTDIEFUFLU w BOESPJEMJOU ศٓͷͨΊɺBOESPJEMJOUͱݺͼ·͢ ‏/FX w IUUQTHJUIVCDPNHPPHMFTBNQMFTBOESPJE DVTUPNMJOUSVMFT αϯϓϧ

Slide 8

Slide 8 text

© DMM.com X w ެ͕ࣜ࡞ͬͯΔ w AHSBEMFXMJOUAͰ૸Δ w ΧελϜ-JOUΛ࡞Δࡍʹܕ৘ใΛ࢖ͬͨ-JOU΋࡞Ε Δ w ΧελϜ-JOUΛ࡞ΔࡍʹKBWB΋νΣοΫͰ͖Δ BOESPJEMJOUͷ͍͍ͱ͜Ζ

Slide 9

Slide 9 text

© DMM.com X ॴײ ओ؍ LUMJOU 4UZMFدΓɻEFUFLUͱେ͖ͳࠩ͸ͳ͍ɻ ͨͩɺϧʔϧͷҰ෦ແࢹͱ͔͕Ͱ͖ͳ͍ɻ FEJUPSDPOpHͰҰ෦͸ม͑ΕΔ EFUFLU 4UZMFدΓɻLUMJOUͱେ͖ͳࠩ͸ͳ͍ɻ BOESPJEMJOU 4UZMF΋ϩδοΫͷ֬ೝͳͲ΋Ͱ͖Δɻ ͨͩ͠ɺEFUFLU΍LUMJOUͰ༻ҙ͍ͯ͠Δ ඪ४ϧʔϧʹ֘౰͢Δ΋ͷ͸ɺ·ͩͳ͍໛༷ "4ͷJOTQFDUJPOʹ͸͋Δ

Slide 10

Slide 10 text

© DMM.com X ͲΕ࢖͏ʁ ओ؍ ౰෼͸BOESPJEMJOUͱ LUMJOUPSEFUFLU ͷซ༻ w BOESPJEMJOU͸ඪ४ͰೖͬͯΔͷͰ֎͢ͱ͍͏બ୒ࢶ͸ͳ͍ w LUMJOU΍EFUFLUͰελΠϧͷνΣοΫΛ͢Δ w ࣗ෼͸LUMJOUΛ࢖͍ͬͯΔ w ελΠϧدΓͷ$VTUPN-JOU͸LUMJOUͰ࡞͍ͬͯΔ w LUMJOU͸ݸผʹϧʔϧΛແޮʹͨ͠ΓͰ͖ͳ͍ͷͰɺEFUFLU ͷํ͕͍͍ͷͰ͸ʁͱࢥ͍࢝Ίͯ͸͍Δɻ w LUMJOU΋EFUFLU΋$VTUPN-JOU͸खܰʹγϡοͱ࡞ΕΔ w BOESPJEMJOUͰ΋͠ࠓޙελΠϧपΓͷϧʔϧ͕ॆ࣮͖ͯͨ͠Βɺ ͦͷ࣌ʹLUMJOU΍EFUFLU͸֎͢͜ͱΛߟ͑Δ

Slide 11

Slide 11 text

© DMM.com X $VTUPN-JOUΛ࡞Δʹ͸ʁ

Slide 12

Slide 12 text

© DMM.com X ·ͣ͸"45 ˺14* Λ஌Δ 'JMF 1"$,"(& %*3&$5*7& $-"44 FMFNFOU DMBTT 8)*5&@41"$& FMFNFOU
 *%&/5*'*&3 8)*5&@41"$& $-"44@#0%: package yourpackage class Hoge { fun fuga(): Int = 2 + 3 } πϦʔߏ଄Ͱղऍ͞ΕΔ

Slide 13

Slide 13 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢Δ$VTUPN-JOUΛ࡞Δ࣌ fuga(1, 2) fuga( 1, 2 ) /( 0,

Slide 14

Slide 14 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢Δ$VTUPN-JOUΛ࡞Δ࣌ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 /(ͷ࣌΋0,ͷ࣌΋ 14*ͷπϦʔ͸͜ͷΑ͏ʹͳΔ Ұ෦୺ંͬͯ·͢

Slide 15

Slide 15 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢Δ$VTUPN-JOUΛ࡞Δ࣌ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 0, վߦίʔυؚ͕·Ε͍ͯΔ!

Slide 16

Slide 16 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢Δ$VTUPN-JOUΛ࡞Δ࣌ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 /( վߦίʔυؚ͕·Ε͍ͯͳ͍"

Slide 17

Slide 17 text

© DMM.com X ͨͱ͑͹ɺҾ਺ͰA A͕͋ͬͨΒઈରվߦ͢Δ$VTUPN-JOUΛ࡞Δ࣌ $VTUPN-JOUͷϩδοΫ͸ɺԼهΛ֬ೝ͢Δ w Լهͷߏ଄ʹͳ͍ͬͯΔͱ͖ʹ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 w ࡾͭ໨ͷ8)*5&@41"$&ʹվߦίʔυΛؚ·ΕΔ͜ͱ EFUFLUͰ΋LUMJOUͰ΋BOESPJEMJOUͰ΋ͲΕͰ΋ɺ ɹɹɹɹɹɹɹɹɹ$VTUPN-JOU͸͜ͷΑ͏ʹͯ͠࡞͍͖ͬͯ·͢

Slide 18

Slide 18 text

© DMM.com X ͳΜͱͳ͘Θ͔͚ͬͨͲɺ ͦ΋ͦ΋πϦʔ͕Ͳ͏ͳͬͯΔͱ͔Θ͔ΒΜʜ

Slide 19

Slide 19 text

© DMM.com X େৎ෉ɺ๻΋Θ͔Γ·ͤΜ

Slide 20

Slide 20 text

© DMM.com X 1TJ7JFXFS࢖͍·͠ΐ͏ IUUQTQMVHJOTKFUCSBJOTDPNQMVHJOQTJWJFXFS

Slide 21

Slide 21 text

© DMM.com X BOESPJEMJOUͰ $VTUPN-JOUΛ࡞ͬͯΈΔ

Slide 22

Slide 22 text

© DMM.com X ͜͏͍͏ͷΛ࡞ͬͯݟ·͢ 3Y+BWBΛ࢖ͬͯͯɺ %JTQPTBCMFΛద੾ʹॲཧͯ͠ͳ͍ͱܯࠂग़͢$VTUPN-JOU

Slide 23

Slide 23 text

© DMM.com X खॱ ϓϩδΣΫτΛ࡞Δ %FUFDUPSΛ࡞Δ *TTVFΛ࡞Δ 3FHJTUSZΛ࡞Δ 3FHJTUSZΛCVJMEHSBEMFʹهड़

Slide 24

Slide 24 text

© DMM.com X ̍ϓϩδΣΫτΛ࡞Δ "OESPJE4UVEJP΍*OUFMMJK*EFBΛ։͍ͯ 'JMF/FX/FX1SPKFDU ͢Δ͚ͩɻ ͨͩɺHPPHMFTBNQMFTʹςϯϓϨʔτͷΑ͏ͳ΋ͷ͕ ͋ΔͷͰɺͦΕʹͳΒ͏ͷ͕ૣ͍ IUUQTHJUIVCDPNHPPHMFTBNQMFTBOESPJEDVTUPN MJOUSVMFTUSFFNBTUFSBOESPJETUVEJP

Slide 25

Slide 25 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { @Override public List> getApplicableUastTypes() { return Collections.singletonList(UQualifiedReferenceExpression.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new UElementHandler() { @Override public void visitQualifiedReferenceExpression( ɹɹɹɹɹɹɹ UQualifiedReferenceExpression node ɹɹɹɹɹɹɹ) { : ॲཧ } }; } } ׬੒ܗ

Slide 26

Slide 26 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { @Override public List> getApplicableUastTypes() { return Collections.singletonList(UQualifiedReferenceExpression.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new UElementHandler() { @Override public void visitQualifiedReferenceExpression( ɹɹɹɹɹɹɹ UQualifiedReferenceExpression node ɹɹɹɹɹɹɹ) { : ॲཧ } }; } } %FUFDUPSΛFYUFOETɺ6BTU4DBOOFSΛJNQMFNFOUTɻ 6BTU͸6OJpFE"45ͷུɻ

Slide 27

Slide 27 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { @Override public List> getApplicableUastTypes() { return Collections.singletonList(UQualifiedReferenceExpression.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new UElementHandler() { @Override public void visitQualifiedReferenceExpression( ɹɹɹɹɹɹɹ UQualifiedReferenceExpression node ɹɹɹɹɹɹɹ) { : ॲཧ } }; } } DSFBUF6BTU)BOEMFSΛPWFSSJEF͢Δɻ ͭ·Γ6*&MFNFOU)BOEMFSΛ࣮૷͢Δɻ

Slide 28

Slide 28 text

© DMM.com X 6*&MFNFOU)BOEMFSͱ͸ USFFͷ্͔ΒॱʹTDBO͍ͯͬͯ͠ɺ֤छOPEF͕ݟ͔ͭΔͨ ͼʹWJTJUϝιου͕ݺ͹ΕΔਓɻ ֤छWJTJUϝιουΛPWFSSJEFͯ͠࢖͏ɻ 7"-6& "3(6.&/5-*45 7"-6& "3(6.&/5 $0.." 8)*5&41"$& 7"-6& "3(6.&/5 WJTJU WJTJU WJTJU WJTJU WJTJU WJTJU

Slide 29

Slide 29 text

© DMM.com X ࠓճ͸ ࠓճ͸1TJ7JXFSΛݟΔݶΓɺ%05@26"-*'*&%@&913&44*0/ ͕དྷͨ࣌ʹ֬ೝ͢Δ͚ͩͰࡁΈͦ͏ͳͷͰɺ WJTJU2VBMJpFE3FGFSFODF&YQSFTTJPOͷΈΛPWFSJSEF͢Δɻ

Slide 30

Slide 30 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { @Override public List> getApplicableUastTypes() { return Collections.singletonList(UQualifiedReferenceExpression.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new UElementHandler() { @Override public void visitQualifiedReferenceExpression( ɹɹɹɹɹɹɹ UQualifiedReferenceExpression node ɹɹɹɹɹɹɹ) { : ॲཧ } }; } } WJTJUର৅ͷOPEFͷΫϥεҰཡΛHFU"QQMJDBCMF6BTU5ZQFTͰ ฦ٫͢Δɻ͜ΕΛ͠ͳ͍ͱWJTJUϝιου͕ݺ͹Ε·ͤΜ

Slide 31

Slide 31 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } WJTJU2VBMJpFE3FGFSFODF&YQSFTTJPOͷத਎Λઆ໌͠·͢ɻ

Slide 32

Slide 32 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } ਌͕#MPDLA\^AͰɺ

Slide 33

Slide 33 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } ϝιουνΣʔϯͷ࠷ޙ͕ATVCTDSJCF AͰ

Slide 34

Slide 34 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } ͦͷTVCTDJSCFϝιουͷฦΓ஋͕JPSFBDUJWFYEJTQPTBCMFT%JTQPTBCMFͷ࣌ ‐͜Ε͕LUMJOUͱEFUFLUͰ͸ࠓͷॴͰ͖·ͤΜ

Slide 35

Slide 35 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // kotlin if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().toString().equals("BLOCK") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType() .getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); return; } Ϩϙʔτ͢Δʂ ܯࠂ͕ग़Δ

Slide 36

Slide 36 text

© DMM.com X ̎%FUFDUPSΛ࡞Δ // java if (node.getPsi() != null && node.getPsi().getContext() != null && node.getPsi().getContext().getContext() != null && node.getPsi().getContext().getContext().toString() .equals(“PsiCodeBlock") && node.getSelector().asRenderString().startsWith("subscribe(") && node.getSelector().getExpressionType() != null && node.getSelector().getExpressionType().getCanonicalText() .equals("io.reactivex.disposables.Disposable")) { context.report( ISSUE, node, context.getLocation(node), "Should handle Disposable” ); } KBWBͷ৔߹΋ॻ͖·͢ɻ6BTU4DBOOFS͸LPUMJOͱKBWBͰ۠ผͳ͘WJTJUͯ͘͠Ε·͢ɻ ͨͩ͠ɺLPUMJOͷ࣌ͱߏ଄͸େମಉ͡Ͱ͕͢ɺ14*ͷܕ͕ҧ͏ͷͰผ్ॻ͘ඞཁ͕͋Γ·͢ɻ

Slide 37

Slide 37 text

© DMM.com X ̏*TTVFΛ࡞Δ public class NotHandledDisposableDetector extends Detector implements UastScanner { public static final Issue ISSUE = Issue.create( "NotHandledDisposable", "Not Handled Disposable", "Disposable should be called dispose.", Category.CORRECTNESS, 6, Severity.ERROR, new Implementation( NotHandledDisposableDetector.class, Scope.JAVA_FILE_SCOPE ) ); *%΍આ໌ɺΧςΰϦ৘ใΛ࣋ͬͨTUBUJDͳ*TTVFΠϯελϯεΛ࡞Γ·͢ɻ ৔ॴ͸Ͳ͜Ͱ΋͍͍͚Ͳɺطଘͷ-JOUΛݟΔݶΓ%FUFDUPSΫϥεʹॻ͍ͯΔͱ͜Ζ͕΄ͱΜͲ Ͱ͢ɻ

Slide 38

Slide 38 text

© DMM.com X ̐3FHJTUSZΛ࡞Δ public class CustomIssueRegistry extends IssueRegistry { @Override public List getIssues() { return Collections.singletonList( NotHandledDisposableDetector.ISSUE ); } } ࡞ͬͨ*TTVFΛొ࿥͢Δ3FHJTUPSZΫϥεΛ࡞Γ·͢ɻ *TTVF͸ෳ਺ొ࿥Ͱ͖·͢ɻ

Slide 39

Slide 39 text

© DMM.com X ̑3FHJTUSZΛCVJMEHSBEMFʹهड़ jar { manifest { attributes("Lint-Registry-v2": "com.kgmyshin.lint.CustomIssueRegistry") } } A-JOU3FHJTUSZ7Aʹઌ΄Ͳ࡞ͬͨ3FHJTUSZΛઃఆ͠·͢ɻ A7AΛ๨Εͳ͍Α͏ʹɻ

Slide 40

Slide 40 text

© DMM.com X ͜ΕͰɺ$VTUPN-JOUͷ׬੒Ͱ͢ʂ

Slide 41

Slide 41 text

© DMM.com X ࡞ͬͨBOESPJEMJOUͷ $VTUPN-JOUΛςετ͢Δ

Slide 42

Slide 42 text

© DMM.com X ςετͷॻ͖ํ public void ςετϝιου໊() { @Language("kotlin") String content = "ʢର৅ίʔυʣ"; lint().files( kotlin(content) ).run().expect("Τϥʔݕग़࣌΋͘͠͸੒ޭ࣌ͷจݴ") } ςετ͸͜ͷΑ͏ʹॻ͖·͢ɻ

Slide 43

Slide 43 text

© DMM.com X ςετͷॻ͖ํ public void ςετϝιου໊() { @Language("kotlin") String content = "ʢର৅ίʔυʣ"; lint().files( kotlin(content) ).run().expect("Τϥʔݕग़࣌΋͘͠͸੒ޭ࣌ͷจݴ") } ର৅ίʔυΛจࣈྻͰ༻ҙɻ ௕͘ͳΔ͜ͱ͕ଟ͍ͱࢥ͏ͷͰɺϑΝΠϧಡΈࠐΈʹ͢Δͷ͕٢ɻ

Slide 44

Slide 44 text

© DMM.com X ςετͷॻ͖ํ public void ςετϝιου໊() { @Language("kotlin") String content = "ʢର৅ίʔυʣ"; lint().files( kotlin(content) ).run().expect("Τϥʔݕग़࣌΋͘͠͸੒ޭ࣌ͷจݴ") } LPUMJOϑΝΠϧͱͯ͠౉ͯ͠ɺΤϥʔจݴ͕͋ͬͯΔ͔Ͳ͏ ͔ΛAFYQFDUAϝιουͰ֬ೝ͢Δɻ

Slide 45

Slide 45 text

© DMM.com X ςετͷॻ͖ํ public void ςετϝιου໊() { @Language(“JAVA") String content = "ʢର৅ίʔυʣ"; lint().files( java(content) ).run().expect("Τϥʔݕग़࣌΋͘͠͸੒ޭ࣌ͷจݴ") } KBWBͷͱ͖͸ɺԼهՕॴ͕KBWBʹͳΓ·͢ɻ

Slide 46

Slide 46 text

© DMM.com X ࡞ͬͨBOESPJEMJOUͷ $VTUPN-JOUΛ࢖͏

Slide 47

Slide 47 text

© DMM.com X ࡞ͬͨ$VTUPN-JOUͷ࢖͍ํ dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.1.10' lintChecks project(":checks") } ಉҰϓϩδΣΫτʹ͋Δ৔߹͸ɺԼهͷΑ͏ʹEFQFOEFODJFTʹ MJOU$IFDLTQSPKFDU $VTUPN-JOUϞδϡʔϧ Λ௥Ճ

Slide 48

Slide 48 text

© DMM.com X ࡞ͬͨ$VTUPN-JOUͷ࢖͍ํ dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.1.10' lintChecks files("lint/custom-lint.jar") } ଞͷϓϩδΣΫτͳͲͰͷ࠶ར༻໨తͰKBSͷΈ͔͠ͳ͍৔߹͸ MJOU$IFDLTpMFT KBSͷύε Λ௥Ճ

Slide 49

Slide 49 text

© DMM.com X ࡞ͬͨ$VTUPN-JOUͷ࢖͍ํ ./gradlew lint : Errors found: /../custom-lint-rules/library/src/main/java/test/pkg/MainJava.java:8: Error: Should handle Disposable [NotHandledDisposable] Single.just("test").subscribe(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /../custom-lint-rules/library/src/main/java/test/pkg/MainKt.kt:8: Error: Should handle Disposable [NotHandledDisposable] Single.just("aa").subscribe() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ : ແࣄಈ͖·ͨ͠ʂ

Slide 50

Slide 50 text

© DMM.com X ·ͱΊ

Slide 51

Slide 51 text

© DMM.com X ·ͱΊ w LPUMJOͰMJOUΛ͔͚Δʹ͸ͭͷํ๏͕͋Δ w LUMJOUͰ΋EFUFLUͰ΋BOESPJEMJOUͷ৔߹Ͱ΋ɺ $VTUPN-JOU࡞Δ࣌͸"45 ˺14* Λ஌Δඞཁ͕͋ Δ͜ͱΛઆ໌ w BOESPJEMJOUͷ$VTUPN-JOUͷ࡞ΓํΛઆ໌

Slide 52

Slide 52 text

͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ