ãã©ãããã©ãŒã éš DevEx ããŒã ã®æ²³äºã§ãã 8æã«åŒç€ŸãµãŒãã¹ TUNAGïŒããã°ïŒã§äœ¿ã£ãŠãã Ruby on Rails ã®ããŒãžã§ã³ã 6.1 ãã 7.0 ã«äžããã®ã§å
±æããŸãã ãã£ãããš äžè¬çãªããŒãžã§ã³ã¢ããã®ãããŒã«ã€ããŠã¯å€ãã®èšäºããããŸãã®ã§ãããã§ã¯åœ±é¿ã倧ããã£ã仿§å€æŽã®å¯Ÿå¿æ¹æ³ã«ã€ããŠç޹ä»ããŸãã ãã©ãŒãããæå®ãªãã® to_s to_s ã«ãã©ãŒããããæž¡ãããšãéæšå¥šåãããŸããã ãã®å€æŽã«ãããåŒæ°ãªãã® to_s ã®æåãå€ãã£ãŠããŸãåé¡ããããŸããã ããã§ã圱é¿ãåããã¯ã©ã¹ã«ã€ã㊠to_s ããªãŒããŒã©ã€ããããã©ãŒãããããããŸã§ãšå€ãããªãããã«ãã€ã€ãèŠåãåºãããšã§åŸããçŽãã¹ãç®æãèŠã€ããããããŸããã class ActiveSupport :: TimeWithZone alias original_to_s to_s if Rails :: VERSION :: MAJOR == 6 # Rails6ã§ã¯NOT_SETãå®çŸ©ãããŠããªãã®ã§ããã§å®çŸ©ãã NOT_SET = :default end def to_s (format = NOT_SET ) if format == NOT_SET # åŒæ°ãªãã®to_sã¯ActiveSupportåŽã§warningãããªãã®ã§ãããã§warningãã ActiveSupport :: Deprecation .warn( ' Since Rails7, the format of ActiveSupport::TimeWithZone#to_s with no arguments has changed. To output the same format as before, please use #to_formatted_s instead. ' ) to_formatted_s else original_to_s(format) end end end ãšãã察å¿ãããŠç¡äº Rails ã®ããŒãžã§ã³ã 7.0.6 ã«äžããçŽåŸã7.0.7 ããªãªãŒã¹ãããäžèšãšåã察å¿ãå
¥ããŸããã github.com ãã®ããä»ãã Rails 7.0 ã«äžããå Žåã¯äžèšå¯Ÿå¿ã¯äžèŠãªã®ã§ãããèšé²ãšããŠæ®ããŠãããŸãã relation.merge relation1.merge(relation2) ãšããæžãæ¹ããããšãã«ãåãã«ã©ã ã«é¢ãã WHERE æ¡ä»¶ã AND ã§çµåãããããrelation2 ã®æ¡ä»¶ã§äžæžããããããããšãã仿§ã«ãªã£ãŠããŸããã Rails 7.0 ãã㯠Hash#merge ãšåãããã«åžžã«äžæžãããã仿§ã«å€æŽãããŸããã # Rails 6.1 ïŒINå¥ã¯ããŒãžããåŽã®ç倿¡ä»¶ã«ãã£ãŠçœ®ãæããããïŒ Author .where( id : [david.id, mary.id]).merge( Author .where( id : bob)) # => [bob] # Rails 6.1 ïŒç«¶åããæ¡ä»¶ãã©ã¡ããååšãã: éæšå¥šïŒ Author .where( id : david.id..mary.id).merge( Author .where( id : bob)) # => [] # Rails 7.0 ïŒINå¥ã®æ¯ãèãã¯åãã§ãããŒãžãããåŽã®æ¡ä»¶ãåžžã«çœ®ãæããããïŒ Author .where( id : [david.id, mary.id]).merge( Author .where( id : bob)) # => [bob] Author .where( id : david.id..mary.id).merge( Author .where( id : bob)) # => [bob] Ruby on Rails 7.0 リリースノート - Railsガイド AND ãšã㊠merge ã䜿ã£ãŠããå ŽåïŒäžèšã³ãŒãäŸãç«¶åããæ¡ä»¶ãã©ã¡ããååšãã: éæšå¥šãã®ãã¿ãŒã³ïŒã®å¯Ÿå¿ãšããŠã relation.and ãäœ¿ãæ¹æ³ããããŸãã github.com relation.and ã®æ³šæç¹ãšããŠã¯ã relation.or ãšåãããã«ãã¯ãšãªã®æ§é ãåãã§ãªããšãšã©ãŒã«ãªããšããããšããããŸãã ä»å TUNAG ã§å¯Ÿå¿ãå¿
èŠã ã£ãã±ãŒã¹ã¯ãAND ãšã㊠merge ã䜿ã£ãŠããã±ãŒã¹ã§ããã€2ã€ã®ãªã¬ãŒã·ã§ã³ã®æ§é ãåãã«ããããšãé£ããç¶æ³ã§ããã æçµçã«ãã¯ãšãªãä¿®æ£ã㊠WHERE æ¡ä»¶ã被ããªãããã«ããããšã§ã merge ã䜿ã£ãŠãæåãå€ãããªãããã«ããŸããã timestamp åã® precision Rails 7 ãã datetime åã® precision ã®ããã©ã«ãå€ã«å€æŽããããŸããã 以åã¯ç¡æå®ã ãš DB ããã©ã«ãã ã£ãã®ãã7 ããã¯ç¡æå®ã ãš precision: 6 ãnil ãæå®ãããš DB ããã©ã«ãã«ãªããšãã仿§ã«ãªããŸããã schema.rb ã䜿ã£ãŠããå Žåã¯äºææ§ç¶æã®ææ®µãããããã§ãããåŒç€Ÿã§ã¯ ridgepole ã䜿ã£ãŠããã以äžã®äŸã® after ã®ããã«ã¹ããŒãã®ä¿®æ£ãå¿
èŠã§ããã # before t.datetime :column_a # ç¡æå®: DB ã®ããã©ã«ã precision t.datetime :column_b , precision : 6 # after t.datetime :column_a , precision : nil # nil æå®: DB ã®ããã©ã«ã precision t.datetime :column_b # ç¡æå®: precision == 6 åè: https://github.com/ridgepole/ridgepole/blob/8b7ea6844a118deb6c4cf9bedcab00a37a56a1f9/README.md?plain=1#L16-L18 å®å
šã«ããŒãžã§ã³ã¢ãããè¡ãããã« åå Rails ã 5.0 ãã 6.1 ã«ãããšãã¯ã倧éã®ä¿®æ£ãå«ãã Pull Request ãããŒãžããéçšã«ãªã£ãŠããããã1é±é以äžç€Ÿå
éå®ã§åãããªã©æ
éãªãªãªãŒã¹äœæ¥ãæ±ããããŠããŸããã äžæ¹ã§ä»åã¯ãäºåã«ããŒãžã§ã³ã¢ããã§ãã gem ãæŽæ°ããããRails ã®ããŒãžã§ã³åå²ãçšã㊠Rails 6 ã®ãã¡ãã 7 ã§ãåããããªä¿®æ£ãããããšã现ããä¿®æ£ãç©ã¿éããŠãããŸãããïŒPull Request ã®æ°ã¯ gem ã®ã¢ããããŒãã§ 20 ä»¶ãã³ãŒãã®ä¿®æ£ã§ 30 ä»¶ã»ã©ãïŒ CI ç°å¢ã§æ€ç¥ã§ãããã®ã¯å
ã«å¯Ÿå¿ããäžã§ãããã«ãã¹ãã§ã«ããŒã§ããŠããªãç®æãæŸãããã ActiveSupport::Deprecations ãæŽ»çšããŠãproduction ç°å¢ã§éæšå¥šãªã³ãŒããå®è¡ãããããšãæ€ç¥ã§ããããã«ããŸããã # config/environments/production.rb ActiveSupport :: Deprecation .disallowed_behavior = [ :log ] ActiveSupport :: Deprecation .disallowed_warnings = [ / some_method / , ] çµæãšããŠãååè¡ã£ããããªéåãªãªãªãŒã¹äœæ¥ãšãããã®ã¯ãªããéåžžã®æ©èœè¿œå ãšåããããªæèŠã§ããŒãžã§ã³ã¢ãããè¡ãããšãã§ããŸããã ãŸãšã æ¬èšäºã§ã¯ãåŒç€ŸãµãŒãã¹ TUNAG ã Rails 7.0 ã«ããŒãžã§ã³ã¢ããããéã«çŽé¢ããäž»èŠãªä»æ§å€æŽãšãããã«å¯Ÿããå
·äœçãªå¯Ÿå¿çã玹ä»ããŸããã èšäºãå
¬éããã¿ã€ãã³ã°ã§æ¢ã« Rails 7.1 Beta 1 ããªãªãŒã¹ãããŠããŸããããæ¬¡åããã¯æŽã«ã¿ã€ã ãªãŒã«æ
å ±ãæäŸã§ãããããæ°ããããŒãžã§ã³ã«åããŠç¶ç¶çã«åãçµãã§ãããŸãã æåŸã«ãã¹ã¿ã¡ã³ã§ã¯ãšã³ãžãã¢ãåéããŠããŸããèå³ããã£ãŠããã ããŸãããããã²äžèšãããå¿åãã ããã herp.careers
ä»åã¹ã¿ã¡ã³ã¯9æ14æ¥ãããã«ãµãŒã«æžè°·ã¬ãŒãã³ã§ïŒæ¥ééå¬ãããDroidKaigiã«åããŠã¹ãã³ãµãŒãšããŠåå ãããŸãããæ¬ããã°ã§ã¯ã€ãã³ãã®æ§åãã¹ãã³ãµãŒããŒã¹ã®æ§åãã¬ããŒãããŠãããŸãã éçºéšã¢ãã€ã«ã¢ããªGã§Androidã¢ããªéçºãããŠããã«ãŒã( @khaki_ngy )ã§ãã ã¹ã¿ã¡ã³ãšããŠã®ã¹ãã³ãµãŒã ãã§ãªããèªåå人ãšããŠããªãã©ã€ã³ã§ã®DroidKaigiã«åå ããã®ã¯åããŠã ã£ãã®ã§ããã®ç¹ã§ã®ææ³ãå«ããŠã¬ããŒãããŠãããããšæããŸãïŒ ã¹ãã³ãµãŒããŒã¹ã«ã€ã㊠ããŒã¹ã®æ§å ä»åãã¹ãã³ãµãŒããŒã¹ã§ã¯Androidã®ããŽãåœãŠãã¯ã€ãºã宿œããŸããã ãã©ã³ããåŒããŠãããåºãæ°åã®Androidã®ããŒãžã§ã³ã®ããŽãåœãŠãŠããããšãããã®ã§ããæ£è§£ããæ¹ã«ã¯æœéžãåŒããŠãããåœéžããæ¹ã«ã¯Ankerã®å
é»ããŒãããã¬ãŒã³ãããŠãŸããã ä»å宿œããããŽã¯ã€ãºç»å ããŽã¯ã€ãºã®åç ãã®ã¯ã€ãºãå€ãããŒãžã§ã³ã§ããã°ããã»ã©ãã€ããŒããŒãžã§ã³ãå€ãååšããã®ã§ãé£æåºŠã®é«ãã¯ã€ãºã«ãªã£ãŠããŸããç¬ãèªåããã£ãŠã¿ãŠAndroid1,2,3ãããã®ããŽã¯ãããµãã ãªããšããã®ã宿ããŸãããããæ°å¹Žã®ããŒãžã§ã³ã§ã¯ããŽãããããçšæãããŠããªãããšããããå°ãå¯ããã§ããã çããã¯ãã®ããŽã®äžèЧãèŠãŠAndroidã®ããŒãžã§ã³æ°ãæ³åã§ããŸãããïŒ ãŸãã¹ã¿ã¡ã³ã®æäŸããŠãããTUNAGãã®ãã¢ãããŒã¹ã§å±éããŠããŸããã ã¹ã¿ã¡ã³ã®ååšã¯ãŸã ãŸã ããç¥ãããŠããããäºæ¥å
容ãå£é ã§èª¬æããŠãäžã
ã€ã¡ãŒãžããããŠããããªãã®ã§ã¯ãšæããŠããŸããã ããã§ä»åã¯ããŒã¹ã§ã®TUNAGã®ãã¢ãå±ç€ºããŸããã ãã¢ã®æ§å æéäžã¯å€ãã®äººããã¢ãè§Šã£ãŠãã ãããå€ãã®æ¹ã«TUNAGã®ããšãç¥ã£ãŠãããæ©äŒãšãªããŸããïŒ ããŒã¹ã«ãè¶ããã ããããããšãããããŸããïŒ æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ãã @stmn_inc ã®ããŒã¹ç޹ä»ã§ãïŒ äŒç€Ÿç޹ä»ã®ã»ãAndroidããŽã¯ã€ãºã§åå ã§ããæœéžããã¢ããªã®ãã¢ãCTO/EMãšã®é¢è«äºçŽããããŠããŸãïŒ æ¯éãè¶³ãéãã§ã¿ãŠãã ããïŒïŒ #DroidKaigi pic.twitter.com/cUAtFmRTXO — DroidKaigi (@DroidKaigi) 2023幎9æ15æ¥ ããããããã£ãDroidKaigi ããããã¯DroidKaigiã«åããŠåå ãããèªåãæãããããããããã£ãDroidKaigiã«ã€ããŠç޹ä»ããŠããããšæããŸãã ã¹ãã³ãµãŒããŒã¹ã®ã¹ã¿ã³ãã©ãªãŒ DroidKaigiã§ã¯åã¹ãã³ãµãŒããŒã¹ã«ããããã¹ã¿ã³ããé
眮ãããŠãããããã䜿ã£ãã¹ã¿ã³ãã©ãªãŒã宿œããŠããŸããã Day2çµäºæç¹ã§ã®ã¹ã¿ã³ãã«ãŒã ã¹ã¿ã³ãã©ãªãŒãéããŠåå è
ã®æ¹ãæ°è»œã«ã¹ãã³ãµãŒããŒã¹ã蚪ããããšãã§ãããããªä»çµã¿ãçšæãããŠããã®ã¯ãåå è
ç®ç·ã§ãã¹ãã³ãµãŒç®ç·ã§ãå¬ããã£ãã§ãïŒèªåãåå è
ãšããŠã¯ãã¹ãã³ãµãŒããŒã¹ã«èå³ã¯ãããã©ã話ããã£ããããªããŠæããªãšæããããšãæã
ãã£ãã®ã§ã楜ãã¿ãªããåãããšãã§ããã®ã¯ãšãŠãè¯ãã£ãã§ãïŒ ã¹ãã³ãµãŒã§ããã¹ã¿ã¡ã³ãäŸã«æŒããã¹ã¿ã³ããæŒããŠããŸãããã¹ã¿ã¡ã³ã¯ã POWER ãã§ããç¬ èªåãããŒã¹ã«ããæã¯ãããã¯ãŒãŒãŒãŒãŒïŒããšå«ã³ãªããæŒãããŠããã ããŸããðª ã¹ã¿ã³ãã©ãªãŒã§æ§ã
ãªæ¯åãããã ããã®ãå¬ããã£ãã§ãïŒåŸããããŠãªãäŒç»âš ã¹ã¿ã³ãã©ãªãŒã§ã²ããããåã
ã»ãã·ã§ã³ã«ãŒã ã®ååã坿ã ã»ãã·ã§ã³ã«ãŒã å㯠Android Studio ã®ããŒãžã§ã³åããåãããŠããŸããã Arctic Fox Bumble bee Chipmunk Dolphin Electric Eel äŒå Žã§ãããã«ãµãŒã«æžè°·ã¬ãŒãã³ã®ããŒã«ã®ã¢ã«ãã¡ãããA~EãããŒã¹ã«ããŒãžã§ã³åãåœãŠãããŠããã®ãããŸããªãŒãšæããŸããð ãã£ã©ã¯ã¿ãŒãããªã³ãããããã¡ã åããŒãžã§ã³ã®ã€ã©ã¹ãããã£ããã§ããð¥° ç¡æã®ãã€ã«äœéš DroidKaigiã§ã¯ç¡æã®ãã€ã«äœéšã宿œããŠããŸããïŒ DroidKaigiã®ããŽãããã€ãããã®ããŽãæããŠãããããšãã§ããèªåãæ©æã«äžŠãã§æããŠããããŸããã 坿ãïŒïŒð» DroidKaigiããŽãšããã€ãããã®ãã€ã« èªåèªèº«ãã¡ããã©ãã€ã«ã«èå³ããã£ãã®ã§æåã®ãã£ãããšããŠæé«ã§ããïŒ ãã€ã«ãããŠããšäžæè°ãšãã³ã·ã§ã³äžãããŸããâ€ïžâð¥ åå ã¡ã³ããŒã®ææ³ èªå以å€ã«åå ããAndridãšã³ãžãã¢ããã®ææ³ã玹ä»ããŸãïŒ ã«ãŒã ããããã¯å人çãªææ³ã«ãªããŸãã DroidKaigiãã¡ããã¡ã楜ããã£ãã§ãïŒæ®æ®µåå€å±ã«ãããšããã ãããããã®Androidãšã³ãžãã¢ã®æ¹ã«äŒãæ©äŒããªãã®ã§ãããã ãã§æåããŸããð ãŸã ã¹ã¿ã¡ã³ã®èªç¥ã¯é«ãããã§ã¯ãªãããŸãå€ãã®äººã«ã¹ã¿ã¡ã³ãTUNAGãç¥ã£ãŠãããæ©äŒã«ãªãããšãŠãå¬ããã£ãã§ãïŒ ä»å¹Žã¯ååå ã»åã¹ãã³ãµãŒã§ããããæ¥å¹Žã¯åã¹ããŒã«ãŒã®å®çžŸãè§£çŠã§ããããã«ããããŒã¶ã«ãåºããïŒãšæ°æã¡ãå
¥ããŸããð¥ éŽæš ã«ãŒããããšåããåå€å±ã§Androidã¢ããªéçºãããŠããéŽæšã§ãã ä»ååããŠã®ãªãã©ã€ã³åå ã§è¡ãã®æ°å¹¹ç·ã§ã¯ãšãŠãããããããŠããŸããã ã»ãã·ã§ã³ã¡ã€ã³ã§ã®åå ãããŠããŸããããåããŒã¹ã§ä»ã®äŒæ¥ã®è©±ãèãããšãã§ããã®ã¯ãªãã©ã€ã³ãªãã§ã¯ã®ãšãŠã貎éãªæ©äŒã ã£ããšæã£ãŠããŸãã åŒç€ŸããŒã¹ã«ãããããã®æ¹ã«æ¥ãŠããã ããŠè²ã
ãªæ¹ãšã話ããã§ããŠãšãŠã楜ããã£ãã§ãã æåŸã« DroidKaigiã¯ãã®ç޹仿ã«ã ãšã³ãžãã¢ã䞻圹 ã®Androidã«ã³ãã¡ã¬ã³ã¹ããšããããã«ãåå ããããšã³ãžãã¢ã«åããŠæ§ã
ãªåãçµã¿ããããŠããŠãã¹ãã³ãµãŒãšããŠãåå è
ãšããŠããšãŠã楜ããã£ãã§ãïŒ ãŸãæèŠªäŒãªã©ã§å€ãã®æ¹ãšã話ãããŠãããããã®åæ°ãããããŸããã ãŸãïŒå¹ŽéããããåžåãããŠæ¥å¹Žãã®å Žæã§ç¶ãã話ããããã«é 匵ããããšæããŸããïŒ æ¡çšæ
å ± ã¹ã¿ã¡ã³ã§ã¯Androidãšã³ãžãã¢ãå«ããã¢ãã€ã«ã¢ããªéçºã®ãšã³ãžãã¢ãåéããŠããŸãïŒ èå³ã®ããããã¯ã«ãžã¥ã¢ã«é¢æ¥ããã©ããïŒ herp.careers
å
šå¡ã§ã®éååç ããã«ã¡ã¯ïŒæ®æ®µã¯TUANG Androidã¢ããªãéçºãããŠããã«ãŒãïŒ @khaki_ngy ïŒã§ãã å
æ¥ãæ©çš²ç°å€§åŠè¥¿æ©çš²ç°ãã£ã³ãã¹ã§éå¬ãããiOSDCã«ã¹ãã³ãµãŒãšããŠã¹ã¿ã¡ã³ãåå ããŸããã ãããªiOSDCã®æ§åãã¬ããŒãããŠãããããšæããŸãð ididblog ïŒïŒ iOSDCãšã¯ã幎ã«äžåºŠéå¬ãããiOSéçºæå€§ã®ã«ã³ãã¡ã¬ã³ã¹ïŒãç¥ãïŒã§ãã ä»å¹Žã¯ãªãã©ã€ã³ã®åå 人æ°å¶éãè§£é€ãããéåžžã«ã¯ã€ã¯ã€ããé°å²æ°ã§éå¬ãããŠããŸããã äŒå Žã®é°å²æ° äŒå Žã§ã¯ã»ãã·ã§ã³ããŒã¹ã®ã»ãããã¹ã¿ãŒã»ãã·ã§ã³ãã¢ã³ã«ã³ãã¡ã¬ã³ã¹ãã¹ãã³ãµãŒããŒã¹ãªã©ããããåå è
å士ã®äº€æµãçãã«è¡ãããŠããŸããã ä»åãã¹ã¿ã¡ã³ã®ã¹ãã³ãµãŒããŒã¹ã®ãšãªã¢ã¯ãã¹ã¿ãŒã»ãã·ã§ã³ãªã©ãè¡ãããã¹ããŒã¹ã§ããããã®ã¹ããŒã¹ã§ã¯æã¯ããŒããã倿¹ã¯å¯¿åžããèåãªã©æ§ã
ãªããŒãã®æäŸãããçµå§ã¯ã€ã¯ã€ãšããé°å²æ°ã§ããïŒ æã®ããŒãã ãæŒéãã®è»œé£ 沢山ã®ããŸãæ£ ã¹ã¿ã¡ã³ã¯ä»åãåããŠã®ã¹ãã³ãµãŒã ã£ãã®ã§ãåãã¯åå è
ã®æ¹ã«éãŸã£ãŠããããã®ãäžå®ãæããŠããŸããããèªç¶ãšäººãéãŸã空éãäœãããŠãããéå¶ã®æ¹ã
ã®å·¥å€«ãæããŸãããããããšãããããŸãïŒ ã¹ãã³ãµãŒã»ãã·ã§ã³ã«ã€ã㊠ä»åã¹ã¿ã¡ã³ã¯ã¹ãã³ãµãŒã»ãã·ã§ã³ã宿œããŸããïŒ ã¹ãã³ãµãŒã»ãã·ã§ã³ã®æ§å ãVIPERã¢ããªã«SwiftUIãå°å
¥ããããViewå±€ã®è²¬åãããåé¢ã§ãã話ã ãšé¡ããŠãã¹ã¿ã¡ã³ã®iOSãšã³ãžãã¢ã®ãããïŒ @38Punkd ïŒããé·å¹ŽVIPERã¢ããªãšããŠéçšããŠããTUNAGã¢ããªã«SwifUIãå°å
¥ããèæ¯ãããã®äžã§ä¹ãè¶ããŠããåé¡ãªã©ã玹ä»ããŸããã è³æãå
¬éãããŠããã®ã§ããã¡ããã芧ãã ããïŒ ãŸãã¹ã¿ã¡ã³ããã¯ããã°ã§ãç»å£ã®å
容ã軜ã玹ä»ããŠããŸãã®ã§ã ãã¡ã ãã芧ãã ããã ã¹ãã³ãµãŒããŒã¹ã«ã€ã㊠ä»åã¹ã¿ã¡ã³ã¯åããŠiOSDCã«ã¹ãã³ãµãŒãšããŠåºå±ããŸãããéå»ã« RSGT ãªã©ã§ããŒã¹åºå±ã®çµéšã¯ãããŸããããä»åã®ããã«ãã£ãããšæºåãã圢ã§ã®ã¹ãã³ãµãŒããŒã¹ãåºå±ããã®ã¯ã¹ã¿ã¡ã³ãšããŠåããŠã®è©Šã¿ã§ããã ã¹ã¿ã¡ã³ããŒã¹ã®æ§å ä»åã®ããŒã¹åºå±ã§ã¯ãæšãã®ã¢ãŒããã¯ãã£ã¢ã³ã±ãŒããã宿œããŸããã æšãã®ã¢ãŒããã¯ãã£ã¢ã³ã±ãŒãã§ã¯ãçŸåšäœ¿çšããŠãããã©ããã«é¢ããããèªåã® æšã ã®ã¢ãŒããã¯ãã£ãçããã«äŒºããŸããã ã¢ãŒããã¯ãã£ã¢ã³ã±ãŒãã®çµæ ãã®ã¢ã³ã±ãŒãã¯å€ãã®åå è
ã®æ¹ãããæç¥šãããã ãéåžžã«çãäžãããŸããã çµæãšããŠã¯ãåèš276åã®æ¹ã«æç¥šããŠããã ããŸããã ãŸãåã¢ãŒããã¯ãã£æ¯ã®æç¥šæ°ã¯ä»¥äžã®ããã«ãªããŸããã ð¥1äœ MVVM: 95祚 ð¥2äœ VIPER: 38祚 ð¥3äœ MVC: 37祚 4äœ TCA: 27祚 5äœ MVP: 19祚 6äœ Redux: 12祚 ãªã©âŠ 1äœã®MVVMã«é¢ããŠã¯ãæç¥šããå Žæããªããªãã»ã©ã®äººæ°ã§ãããå
ã
RxSwiftãå©çšãããªã¢ã¯ãã£ãããã°ã©ãã³ã°ãšããŠMVVMã¯å©çšãããŠããå°è±¡ã¯ãããŸããããè¿å¹Žã®SwiftUIã®ç»å Žã§ããã®äººæ°ãåŸæŒãããŠããããã«æããŸããã 2äœã¯VIPERãšããããšã§ãä»åVIPERã«é¢ããã¹ãã³ãµãŒã»ãã·ã§ã³ãè¡ãã¹ã¿ã¡ã³ãšããŠã¯ãçŸå³ããçµæã«ãªããŸãããè€éãªã¢ããªã«ãªããšVIPERã®å©çšãèãããšãã声ãå€ãããã ããŸãããã¹ã¿ã¡ã³ã§ã®VIPERå°å
¥ã®èæ¯ã¯ ãã¡ãã®ããã° ã«ãŸãšããããŠããã®ã§ã確èªãã ããã ä»åã¯ã¹ãã³ãµãŒã»ãã·ã§ã³ã§VIPERã¢ãŒããã¯ãã£ã®è©±ãããããšããã£ãŠããæšãã®ã¢ãŒããã¯ãã£ã¢ã³ã±ãŒãããè¡ããŸãããã¢ã³ã±ãŒãã«çããŠããã ããåå è
ã®æ¹ãšã話ãããäžã§ãã¢ãŒããã¯ãã£ã®éžå®ãå°å
¥ã«ã¯ãããã¯ãããšã®èæ¯ããããã©ãã§ãæ©ãã ãèŠæ©ããªããã¢ãŒããã¯ãã£ãå
¥ããŠãããã ãªããšããã®ãæããŸãããæ¹ããŠã¢ã³ã±ãŒãã«ãåçããŠããã ããåå è
ã®çããããããšãããããŸããïŒ æåŸã« iOSDCã«ã¹ãã³ãµãŒåŽãšããŠåå ããããšã§ãéå¶ã¹ã¿ããæ¹ã®å·¥å€«ãããç¥ãããšãã§ããŸããããåå è
ã®æ¹ãšã®äº€æµã沢山ããããšãã§ããŸããã ïŒæ¥éã¹ãã³ãµãŒããŒã¹ã§ã®å¯Ÿå¿ã¯å°ãç²ããŸãããããã以äžã«ã¹ãã³ãµãŒãšããŠiOSDCããµããŒãããããšãã§ããŠããã£ããšæããŠããŸãïŒ åå ã¡ã³ããŒã®ææ³ ä»ååå ããã¡ã³ããŒããã®ææ³ãã芧ãã ãã æåïŒiOSïŒ ã³ãã以åã«ã¯äœåºŠãåå ããŠããiOSDCãžãä»ååããŠã¹ãã³ãµãŒåå ããŸããã iOSã¢ããªéçºãçæ¥ãšããŠãã1ãšã³ãžãã¢ãšããŠãæ¥æ¬æå€§ã®iOSéçºè
ã³ãã¥ããã£ãžå°ãã§ãè²¢ç®ã§ããã®ã§ããã°å€§å€å¬ããæããŸãã éå»åå ããŠããæã«ã¯ãšã³ãžãã¢ãšããŠã§ããããä»ã¯ãšã³ãžãã¢ãªã³ã°ãããŒãžã£ãšãªãã以åãšã¯ãŸãç°ãªãç®ç·ãæã£ãŠåå ããããšã«ãªããŸããã ä¹
ã
ã«äŒã£ãæ¹éã¯ç§ãšåãããã«ããžã·ã§ã³ãå€ãã£ãŠããããåŠçãã¯ãããšãããæ°äžä»£ã®iOSãšã³ãžãã¢åºãŠããããšãããŸããŸå€åãèã§æããããææ
šæ·±ããããã倧å€å¬ããæããŸããã ãããïŒiOSïŒ ã¹ãã³ãµãŒã»ãã·ã§ã³ã§çºè¡šãæ
åœããŸããããããããšéæšã§ãã å®ã¯ç§ã¯ããããã£ãã«ã³ãã¡ã¬ã³ã¹ãžã®åå ã¯ãä»åãåããŠã§ããã ä»åã®iOSDCããã³ããåŸåã®ãªãã©ã€ã³éå¬ãšããããšããããäŒå Žã¯ã©ã®ãããªé°å²æ°ãªã®ããããŸãæ³åãã€ããŠããŸããã§ããããéåžžã«å€ãã®æ¹ã飿¥ã«ã³ãã¡ã¬ã³ã¹ã«åå ãããå€ã¯ç倧ã«äº€æµäŒãéãããçãåœå
æå€§èŠæš¡ã®ã«ã³ãã¡ã¬ã³ã¹ã®é°å²æ°ããèã§æããããŸããã ã¹ãã³ãµãŒã»ãã·ã§ã³ã«ã€ããŠã¯ãiOSDCååå ã®ç§ãã»ãã·ã§ã³ãããããšã«å¯ŸããŠãç§èªèº«äžå®ã§ããããåŒç€Ÿã®ã¡ã³ããŒãäœåºŠãç·Žç¿ã«ä»ãåã£ãŠãããåœæ¥ã¯å¿
èŠä»¥äžã«ç·åŒµããããšãªããã»ãã·ã§ã³ãçµããããšãã§ããŸãã(ã¡ã³ããŒã«æè¬ïŒð)ã ã¹ãã³ãµãŒã»ãã·ã§ã³ãããŒã¹åºåºã®åéã«ãé©å®ä»ã®æ¹ã®ã»ãã·ã§ã³ãèŽãã«è¡ã£ãŠããŸããã ç§ã¯ãã®äžã§ãã giginet ããã®ã Swift Packageã䜿ã£ã巚倧ãªäŸåã°ã©ãã®ãã£ãã·ã¥æŠç¥ ãã®å
容ããç¹ã«å匷ã«ãªããŸããã Swift Package Manager(以éãSPM)ã¯Xcodeã§ç°¡åã«ããã±ãŒãžç®¡çã§ããçŽ æŽãããæ©èœã§ãããSPMã®æ©èœãæãªãããšãªããæ°ãã«ãã£ãã·ã¥æ©æ§ãæããããã«ãé床ãéããã詊ã¿ã¯ãéçºå¹çãäžããç»æçãªæ¹æ³ã ãšæããŸããã ä»ã«ãããããã®åŠã³ãããã»ãã·ã§ã³ãèŽãããšãã§ãããšã³ãžãã¢ãšããŠå€§ãã«æé·ããæ©äŒã«ãªããŸããã ä»åãiOSDCååå ã§ã¯ãããŸããããã»ãã·ã§ã³ããããŒã¹ã亀æµäŒãéããŠå€ãã®æ¹ãšäº€æµã§ããŸããã ã«ã³ãã¡ã¬ã³ã¹ãéããŠãããã¯ãŒã¯ãå¢ãããããšããäžçªã®è¯ãã ãšæããŠããŸãã ã«ãŒãïŒAndroidïŒ ã¬ããŒãã§ã€ãã³ããã¹ãã³ãµãŒããŒã¹ã§ã®ç޹ä»ã¯äžã§ããã®ã§ãå人çãªææ³ããŸãšããŠããããšæããŸãïŒèªåãšããŠã¯å¯Ÿé¢ã§ã®ã«ã³ãã¡ã¬ã³ã¹ã¯2019幎㮠try! Swift 以æ¥ã ã£ãã®ã§ããšãŠã楜ãã¿ã«ããŠããŸããã åœæåŠçã®é ã«åå ããæãšã¯ç°ãªãããšã³ãžãã¢å士ã®ç¹ãããå¢ããŠãSNSã§äº€æµã®ãããšã³ãžãã¢ã®æ¹ãšçŽæ¥è©±ãããšãã§ããæ©äŒãšãªããšãŠã楜ããã£ãã§ããç¹ã«èªåã¯åå€å±æ¬ç€Ÿã«å€ããŠããããšããããæ®æ®µæ±äº¬ã«ããªãããšããã£ãŠãåºåãã«é£¢ããŠããã®ãããããªããšæããŸããð
èªåãiOSDCã§ç¹ã«é©ããã®ãã¢ã³ã«ã³ãã¡ã¬ã³ã¹ã§ããã¢ã³ã«ã³ãã¡ã¬ã³ã¹ãšã¯åå è
äž»å°ã®äŒè°ã§ãã¿ããªã§è©±ãããããšãè¡ãããã¯ãŒã¯ã·ã§ãããªã©ãäºåã«ãã¯ã€ãããŒãã«èšå
¥ããŠãéãŸã£ã人å士ã§ã¯ã€ã¯ã€ããŠããŸããã èªåã¯Swift6ã®æ©èœã§ããã æææš© ã«ã€ããŠã¿ããªã§è©±ãããã®åã«åå ãããŸãããèªåã¯æ®æ®µã¯AndroidéçºãããŠããã®ã§ãiOSã®ææ°æè¡ã«ã¯çãç¶æ
ã§ããããã æåããçããããããã§ã¯ãªããåå è
å
šå¡ãè°è«ãããŠãçè§£ãæ·±ããŠããå Žãšãªã£ãŠããããã®å Žæã§å
±ã«åŠã¶ããšãã§ããŠè¯ãã£ããšæããŠããŸããããããã¯ã察é¢ãªãã§ã¯ã®ç©ºéã ãªãšæããŸããã ãŸãä»åã®åå ãéããŠãiOSDCãšããã³ãã¥ããã£ã«åå ã§ããŠããã£ããšæ¹ããŠæããŸãããæ¬æäžã§è¿°ã¹ãããã«ããã¹ã¿ãŒã»ãã·ã§ã³ãã¹ãã³ãµãŒããŒã¹ãçãäžãããããªä»çµã¿äœãã ã£ãããLTã§ã®äŒå Žå
šäœã§ã®çãäžãã®ä»çµã¿ãªã©ãæ§ã
ãªãšããã«éå¶ã¹ã¿ããã®æ¹ã®å·¥å€«ãæããŸãããèªåãéå¶ããŠããã³ãã¥ããã£ã«å¯ŸããŠãããã£ãšè¯ãã³ãã¥ããã£ãäœããããšã¢ãããŒã·ã§ã³ãäžãããŸãããéå¶ã¹ã¿ããã®æ¹ã
ã®æºåã«ã¯é ãäžããã°ããã§ããæ¬åœã«æé«ã®ã«ã³ãã¡ã¬ã³ã¹ãããããšãããããŸããïŒ
æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã¯ã2023幎9æ14æ¥ãã16æ¥ãŸã§ã®3æ¥éããã«ãµãŒã«æžè°·ã¬ãŒãã³ãšãªã³ã©ã€ã³é
ä¿¡ã«ãŠéå¬ããããDroidKaigi 2023ãã«ããŽãŒã«ãã¹ãã³ãµãŒãšããŠåè³ããã€ãã³ããçãäžããŸãã 2023.droidkaigi.jp æ¬ãšã³ããªãŒã§ã¯ãã¹ãã³ãµãŒããŒã¹ãããã«ãã£ããã©ã€ã€ãŒã«ã€ããŠã玹ä»ããããŸãã ã¹ãã³ãµãŒããŒã¹ã®ãçŽ¹ä» ãªãã©ã€ã³äŒå Žã®ã¹ãã³ãµãŒããŒã¹ã¯ãã¹ã¿ã¡ã³ã«ã©ãŒã®ããŒãã«ã¯ãã¹ããããŒã¹ã¯ãªãŒã³ãã®ãŒãæãç®å°ã§ãã äŒå Žå
ã§äŒè©±ã®ãã¿ã«ãªããããªã³ã³ãã³ãããçšæããŠããŸãããšã³ãžãã¢ã¡ã³ããŒãããŒã¹ã«ç«ã¡ãŸãã®ã§ãäŒå Žã«æ¥ãããæ¹ã¯ãã²ãç«ã¡å¯ããã ããã ããã«ãã£ã°ããºã»ãã©ã€ã€ãŒã®ãçŽ¹ä» ã¹ãã³ãµãŒããŒã¹ã§ã¯è€æ°çš®é¡ã®ããã«ãã£é
åžäºå®ãDroidKaigi ã«ã¡ãªãã ãã¶ã€ã³ã®ããã«ãã£ãçšæããŠããŸãã å®éã«ããŒã¹ã§èŠãŠããã ãããã®ã§ãæ¬ãšã³ããªãŒã§ã¯ãŒããããšå
¬éãããŠããã ããŸãã ãã®ã»ãã«ããæœéžã§åœãã豪è¯ãªããã«ãã£ããããŸãã®ã§ãæ¯éã²ãããã«ããŠãã ããã åå è
ã®æ¹ãåãåãé
åžç©ã«ã¯ããã¡ãã®ãã©ã€ã€ãŒãåå°ãããŠããŸãã ãšã³ãžãã¢çµç¹ã«ã€ããŠã®ç°¡åãªç޹ä»ãããã®ã§ãæ¯éãäžèªãã ããïŒ ãããã« DroidKaigi 2023 ãªãã©ã€ã³äŒå Žã«åå ããã¢ãã€ã«Gã®çŽè¿ã®åãçµã¿ã«ã€ããŠã¯ããã¡ãã®èšäºã§ã玹ä»ããŠããŸãã tech.stmn.co.jp Androidãšã³ãžãã¢ã®çæ§ãšäº€æµã§ããã®ã楜ãã¿ã«ããŠããŸãïŒ3æ¥é楜ãã¿ãŸãããïŒ ã«ã³ãã¡ã¬ã³ã¹æ
å ± åç§° : DroidKaigi 2023 äž»å¬ : äžè¬ç€Ÿå£æ³äººDroidKaigi é嬿¥æ : 2023幎9æ14æ¥ (æš)ã9æ16æ¥(å) å Žæ : ãã«ãµãŒã«æžè°·ã¬ãŒãã³ + YouTube åå æ¹æ³ã詳现ã«ã€ããŠã¯ã å
¬åŒãµã€ã ãã芧ãã ããã æ¡çšæ
å ± ãŸãã¹ã¿ã¡ã³ã§ã¯ãAndroidãšã³ãžãã¢ã«éããå
šæè¡é åã§ããããã¯ããæé·ãããŠãããšãã¹ããŒããåéããŠããŸããããèå³ãæã£ãŠããã ããããäžèšãããå¿åãã ããïŒ herp.careers
ã¢ã€ã³ã³ã®åºå
žïŒ https://icons8.com ããã«ã¡ã¯ãæ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã§iOSãšã³ãžãã¢ãããŠããéæš ( @38Punkd )ã§ãã å
æ¥ã®æçš¿ ã«ãã£ãéããã¹ã¿ã¡ã³ã¯ iOSDC Japan 2023 ã«ãŽãŒã«ãã¹ãã³ãµãŒãšããŠåè³ããŸããç§ã¯ãã®ã¹ãã³ãµãŒã»ãã·ã§ã³æ ãšããŠç»å£ããŸãããã®èšäºã§ã¯ãåœæ¥çºè¡šããå
容ãå°ãå
åºãããŠã玹ä»ã§ããã°ãšæããŸãã fortee.jp ç§ãã¡ã¯ TUNAG ãšãããããã¯ãããWebã»iOSã»Androidã®3ãã©ãããã©ãŒã äžã§æäŸããŠããŸããiOSã¢ããªã§ã¯ VIPER ã¢ãŒããã¯ãã£ãå°å
¥ããŠããŸããå
·äœçãªå°å
¥æ¹æ³ã«ã€ããŠã¯ãåŒç€Ÿã§ä»¥åã«è©Šè¡é¯èª€ããæ§åã以äžã®èšäºã§è§£èª¬ãããŠããŸãã®ã§ãæ°ã«ãªãæ¹ã¯èªãã§ã¿ãŠãã ããã tech.stmn.co.jp TUNAG iOSã¢ããªã®ãµããŒã察象ããŒãžã§ã³ã®äžéããä»å¹ŽããiOS 13ã«å€æŽããã®ã§ã13ãã䜿çšå¯èœã«ãªã SwiftUI ã®å°å
¥ãæ¬æ Œçã«æ€èšããŸããã å®éã«SwiftUIãå°å
¥ããã«è³ã£ãã®ã§ããããããŸã§VIPERã§æ§ç¯ããŠããã¢ããªã«å¯ŸããŠãSwfiftUIãå°å
¥ããäžã§äœãå
·äœçã«æ€èšããããã玹ä»ããŸãã SwiftUIãšã¯ 2019幎ã«Apple瀟ãæäŸéå§ãã宣èšçUIãã¬ãŒã ã¯ãŒã¯ã®ããšã§ããXcodeã®GUIã§ SwiftUI ãéžæããŠãã¡ã€ã«ãæ°èŠäœæãããšã以äžã®ãããªViewãåæçæãããŸãã struct SwiftUIView : View { var body : some View { Text( "Hello World!!" ) } } SwiftUIã«ã¯2ã€ã®å€§ããªç¹åŸŽããããŸãã ããŒã¿ãã€ã³ãã®ä»çµã¿ãæã€ UIKitãšäºææ§ããã ããããã«ã€ããŠç°¡åã«è£è¶³ããŸãã ããŒã¿ãã€ã³ãã®ä»çµã¿ãæã€ SwiftUIã¯å
ã®ã³ãŒãã§ç€ºããããã«ãç»é¢ã«è¡šç€ºããViewãæ§ç¯ããéšåã View ãããã³ã«ã«æºæ ããæ§é äœã§è¡šçŸããŸãã SwiftUI Viewã®ç»é¢æŽæ°ãããã«ã¯ã ObservableObject ãããã³ã«ã«æºæ ãããç¶æ
管ççšã¯ã©ã¹ãçšæããŸãã ããããããã ViewModel ã«çžåœãããã®ViewModelã®å€ãæŽæ°ããããšSwiftUI Viewã®è©²åœã®ViewãèªåæŽæ°ããããããSwiftUIã¯ããèªäœãMVVMã®ç¹æ§ãæã¡ãŸãã UIKitãšäºææ§ããã SwiftUIã®ViewãUIKitäžã§äœ¿ãããã®ã©ãããŒã¯ã©ã¹ UIHostingController UIKitã®ViewãSwiftUIäžã§äœ¿ãããã®ã©ãããŒã¯ã©ã¹ UIViewRepresentable ãçšæãããŠããŸãã ã©ã¡ãã®ãªããžã§ã¯ãããUIKitã»SwiftUIãã€ã³ããŒãããã°ãiOS 13以äžãªãã©ãããã§ãåŒã³åºãããããSwiftUIã¯UIKitãšäºææ§ãéåžžã«é«ããšèšããŸãã å®éã«VIPERã«SwiftUIãå°å
¥ããäžã§æ€èšããããš ãããŸã§UIKitãçšã㊠UIViewController äžã§Viewãæ§ç¯ããŠããã®ã§ãSwiftUIãå°å
¥ããããšã§ã¢ã³ã³ã³ãããŒã©ãã«ãªç¹ãåºãŠããªããããŸããããŒã¿ãã€ã³ãã®ä»çµã¿ãæã€SwiftUIãVIPERã«éŠŽæãããçã®çžæ§ãèæ
®ããå¿
èŠããããŸãã ãã®çžæ§ã«ã€ããŠå€§ããåãããšã以äž2ç¹ãèæ
®ããå¿
èŠããããŸãã UIViewControllerãSwiftUIã® ã©ã€ããµã€ã¯ã« ããã³ããªã³ã°ã§ããã UIViewControllerãSwiftUIã® ã€ãã³ã ããã³ããªã³ã°ã§ããã 1ç¹ç®ã«ã€ããŠã詳ãã説æããŸãã 1. UIViewControllerãSwiftUIã® ã©ã€ããµã€ã¯ã« ããã³ããªã³ã°ã§ããã âSwiftUIã®ã©ã€ããµã€ã¯ã«â ã¯ãããã«3ã€ã®å
·è±¡ã«åããŠèããããŸãã 1-1. SwiftUI Viewèªèº« ã®ã©ã€ããµã€ã¯ã« 1-2. SwiftUI Viewã®ããŒã¿ãã€ã³ãããã ObservableObject ãããã³ã«ã®ã©ã€ããµã€ã¯ã« 1-3. SwiftUI ViewãUIKitã§äœ¿ãããã®ã©ãã㌠UIHostingController ã®ã©ã€ããµã€ã¯ã« 1ã€ç®ã«ã€ããŠãæ·±æããŸãã 1-1. SwiftUIã® Viewèªèº« ã®ã©ã€ããµã€ã¯ã«ããã³ããªã³ã°ã§ããã Viewã®ã©ã€ããµã€ã¯ã«ãšã¯ãViewãã€ã³ã¹ã¿ã³ã¹çæãããåŸã«ç»é¢ãšããŠäœ¿ããããã®åŸã€ã³ã¹ã¿ã³ã¹ç Žæ£ããããŸã§ã®äžé£ã®æµãã®ããšãæããŸãã UIViewControllerã®ã©ã€ããµã€ã¯ã«ã«å¯ŸããŠãUIKitã§ã¯å€ãã®ã¡ãœãããæäŸãããŠããŸãã åºå
žïŒ https://developer.apple.com/documentation/uikit/uiviewcontroller 察ããŠSwiftUIã§ã¯ã viewDidAppear ãš ViewDidDisappear ã«çžåœããã onAppear ãš onDisappear ã¡ãœããã®2ã€ã ããæäŸãããŠããŸãã ãããããã®onAppearãšonDisappearã¡ãœããã¯ãããã€ãã®ã±ãŒã¹ã«ãããŠã¯åŒã°ããªãããšããããŸãã ãŸããããç»é¢ã®ã©ã€ããµã€ã¯ã«ã¡ãœãããåŒã¶ã«ã¯ããã®ç»é¢ãžã®é·ç§»ããžãã¯ãå¿
èŠã§ããiOS 15ãŸã§ã¯ãUIKitã® UINavigationController ã«çžåœããSwiftUIã® NavigationView ããSwiftUI Viewéã®ç»é¢é·ç§»ããžãã¯ãæ
ããŸããïŒiOS 16ããã¯ã NavigationStack ã䜿ããããã«ãªããŸãïŒã ãã®NavigationViewã¯ãæåãæ¯èŒçäžå®å®ã§ãããšèšãããŠããŸãã ããããèžãŸããŠãã©ã€ããµã€ã¯ã«ã¡ãœãããåŒã¶ããã®ç»é¢é·ç§»ããžãã¯ã¯ãçŸæç¹ã§ã¯SwiftUIã®æ©æ§ã«ä»»ããã®ã§ã¯ãªããUIViewControllerã«ä»»ãã倿ãããŸããã ç¶ããŠãSwiftUI Viewã¯ã€ã³ã¹ã¿ã³ã¹çæã®ã¿ã€ãã³ã°ã«ã€ããŠã¯ã©ãã§ãããããSwiftUI Viewãæºæ ããViewãããã³ã«ã«ã¯ã id ã¡ãœãããããã©ã«ãå®è£
ãããŠããŸãã åºå
žïŒ https://developer.apple.com/documentation/swiftui/view/id(_:) SwiftUI Viewãã€ã³ã¹ã¿ã³ã¹çæãããã¿ã€ãã³ã°ã¯ãèªèº«ã®ä¿æããIDãçæã»æŽæ°ãããæã ãšåãããŸãã 以äžãããSwiftUIã®Viewèªèº«ã®ã©ã€ããµã€ã¯ã«ããã³ããªã³ã°ãããã«ã¯ã3ç¹ãèæ
®ããã°è¯ããšèšããŸãã UIViewControllerã«æ¯ã¹ãŠãSwiftUI Viewã®ã©ã€ããµã€ã¯ã«ã¡ãœããã®çš®é¡ã¯å°ãªãããã€å®å
šã«ã€ã³ãŒã«ã§ã¯ãªã ç»é¢é·ç§»ããžãã¯ã¯ãSwiftUIã®æ©æ§ã¯äœ¿ãããUIViewControllerã«ä»»ãã SwiftUI Viewã®ã€ã³ã¹ã¿ã³ã¹çæã®ã¿ã€ãã³ã°ã¯idã®å€åãããªã¬ãŒã«ãããšè¯ã ã€ãŸããç»é¢é·ç§»ããžãã¯ã¯UIViewControllerã«ä»»ããŠãSwiftUI Viewã®è²¬åã¯ãèŠãç®ã®éšåã®ã¿ãæ
ãããæ¹ãè¯ããããšèšããŸãã ç¶ããŠãå
ã»ã©åæãã3ã€ã®å
·è±¡ã®ãã¡ã2ã€ç®ã«ã€ããŠã§ãã 1-2. ObservableObject ãããã³ã«ã®ã©ã€ããµã€ã¯ã«ããã³ããªã³ã°ã§ããã SwiftUI ã§Viewã®ç¶æ
管çãããã«ã¯ãObservableObjectãããã³ã«ã«å ããŠã @StateObject ã @ObservedObject ãçšããŸãã ã©ã¡ãããObservableObjectãããã³ã«ã«æºæ ããŠããã¯ã©ã¹å
ã®å€å€åããç£èŠã§ããããã«ããããã®ããããã£ã©ãããŒã§ãã äž¡è
ã®éãã¯ã @StateObjectã¯ãä¿æããViewã«å¯ŸããŠãã€ã³ã¹ã¿ã³ã¹ã 1ã€ã ã çæãããã®ã«å¯ŸããŠã @ObservedObjectã¯ãä¿æããViewã®ã©ã€ããµã€ã¯ã«ã«äŸåãã 芪Viewã®åæç»ã§ã€ã³ã¹ã¿ã³ã¹ã¯åçæããã ãšããç¹ã§ãã ç§ãã¡ã®ãããã¯ã TUNAG ã¯ãiOS 13ãããµããŒã察象ã§ããã@StateObjectã¯iOS 14ãããã䜿ããŸããããªã®ã§ã@ObservedObjectã䜿ãããšãå¿
é ã«ãªããŸãã çµè«ãšããŠã¯ã@ObservedObjectã¯èŠªViewã®ã©ã€ããµã€ã¯ã«ã«äŸåããã®ã§ã ç»é¢åäœã®ã©ã€ããµã€ã¯ã«ãšäžèŽããã ãšããã³ããªã³ã°ãããããšããèãã«è³ããŸããã ããªãã¡ã @ObservedObjectãä¿æããã¯ã©ã¹ = UIViewController ãšããã°ãObservableObjectãããã³ã«ã®ã©ã€ããµã€ã¯ã«ããã³ããªã³ã°ãããããšèšããŸãã æåŸã«ã3ã€ç®ã«ã€ããŠã§ãã 1-3. SwiftUI ViewãUIKitã§äœ¿ãããã®ã©ãããŒUIHostingControllerã®ã©ã€ããµã€ã¯ã«ããã³ããªã³ã°ã§ããã ããã«ã€ããŠã¯ãUIHostingControllerã¯UIViewControllerãç¶æ¿ããŠããã®ã§ãã©ã€ããµã€ã¯ã«ã芪ViewControllerã«å§è²( didMove ã¡ãœããã§å¯èœ)ã§ããŸãã åºå
žïŒ https://developer.apple.com/documentation/swiftui/uihostingcontroller ã€ãŸãã芪ViewControllerã®ã©ã€ããµã€ã¯ã«ã«ãã£ãŠãSwiftUI Viewã®ã©ã€ããµã€ã¯ã«ãã³ã³ãããŒã«ã§ããŸãã ãããŸã§ãUIViewControllerãSwiftUIã®ã©ã€ããµã€ã¯ã«ããã³ããªã³ã°ã§ãããã«ã€ããŠã説æããŠããŸããã ã§ã¯ãSwiftUIã®ã€ãã³ããã³ããªã³ã°ã«ã€ããŠã¯ã©ãã§ããããã UIViewControllerãSwiftUIã® ã€ãã³ã ããã³ããªã³ã°ã§ããã SwiftUI Viewå
ã§çºçããã€ãã³ããäŸãã°ãã¿ã³ã¿ããã¯ãã¿ããæã®åŠçãèšè¿°ã§ããŸãïŒåœããåãšèšãã°åœããåã§ããïŒã ãã®åŠçãå¥ã®ã¯ã©ã¹ã«äŒæãããã°ãSwiftUI Viewã®ã€ãã³ãããã³ããªã³ã°ã§ããŸããå
·äœçã«ã¯ã以äžã®ããã«å®äºãã³ãã©ããããªã²ãŒãçã§ãã³ããªã³ã°ã§ããŸãã struct ViewScreen : View { var tapHandler : (() -> Void ) ? var body : some View { Button { tapHandler?() } label : { Text( "Tap Me !!" ) } } } ãŸãšã SwiftUIã®æ§è³ªãåããŠãVIPERã«SwiftUIãå°å
¥ããäžã§æ€èšããäºãã玹ä»ããŸããã UIViewControllerãSwiftUIã®ã©ã€ããµã€ã¯ã«ããã³ããªã³ã°ã§ããã 1-1. SwiftUI Viewèªèº«ã®ã©ã€ããµã€ã¯ã« 1-2. SwiftUI Viewã®ããŒã¿ãã€ã³ããããObservableObjectãããã³ã«ã®ã©ã€ããµã€ã¯ã« 1-3. SwiftUI ViewãUIKitã§äœ¿ãããã®ã©ãããŒUIHostingControllerã®ã©ã€ããµã€ã¯ã« UIViewControllerãSwiftUIã®ã€ãã³ãããã³ããªã³ã°ã§ããã 以äžãèžãŸããŠãæçµçã«SwiftUIãå°å
¥ããäžã§ã®èŠä»¶ãå®ããŸããã ç»é¢é·ç§»ãUIViewControllerã«æ
ããããããUIViewController.view = SwiftUI View ã®æ§é ãäœã ObservableObjectã«æºæ ããã¯ã©ã¹(ViewModel)ã®ã€ã³ã¹ã¿ã³ã¹(@ObservedObject)ãUIViewControllerã«ä¿æããã ãã®2ã€ã®èŠä»¶ãå
ã«ãå®éã«VIPERã«SwiftUIãå°å
¥ããæ¹æ³ãã³ãŒãã§ç€ºããã°ãšæããŸããã ãããã㯠iOSDC Japan 2023 åœæ¥ã以äžã¹ã±ãžã¥ãŒã«ã§ã玹ä»ã§ããã°ãšæããŸãïŒïŒ ç»å£ã»åºå±æ
å ± æ¥æïŒ2023幎9æ3æ¥ 15:05ãïŒ20åïŒ å Žæ : æ©çš²ç°å€§åŠ çå·¥åŠéšè¥¿æ©çš²ç°ãã£ã³ãã¹ TrackïŒC åœæ¥ã¯ã¹ãã³ãµãŒã»ãã·ã§ã³ã ãã§ãªããããŒã¹ãåºå±ããŸãã®ã§ãæ°è»œã«éã³ã«æ¥ãŠãã ããïŒ åœæ¥ãäŒãã§ããäºã楜ãã¿ã«ããŠããŸãïŒïŒ tech.stmn.co.jp æ¡çšæ
å ± ã¹ã¿ã¡ã³ã§ã¯ãiOSãšã³ãžãã¢ã«éããå
šæè¡é åã§ããããã¯ããæé·ãããŠãããšãã¹ããŒããåéããŠããŸããããèå³ãæã£ãŠããã ããããäžèšãããå¿åãã ããïŒ herp.careers
æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ ã§ããã³ããšã³ããšã³ãžãã¢ãããŠãã ç¥å°Ÿ ã§ããæ®æ®µã¯ããšã³ã²ãŒãžã¡ã³ããã©ãããã©ãŒã ã TUNAG ãã®éçºãããŠããŸãã TUNAGã§ã¯ã2023幎1æããWebããã³ããšã³ãã®ãªãã¬ã€ã¹ãããžã§ã¯ããå§ãŸããä»ããããžã§ã¯ããé²è¡äžã§ããçŸåšã®Webããã³ããšã³ãã§ã¯æè¡éžå®ã®éžæè¢ãå€ããéžå®ã«ããã£ãŠã®æ€èšäºé
ããšãŠãå€ããšæããŸãã ãã®èšäºã§ã¯ããªãã¬ã€ã¹ã®éã«æ¡çšããæè¡ã®éžå®çç±ãèšèšã«ã€ããŠãŸãšããã®ã§ããã®èšäºãéããŠãèªãã§ãã ãã£ãæ¹ã®ã圹ã«ç«ãŠãã°å¬ããã§ãã ãŸãããªãã¬ã€ã¹ã®èæ¯ãã€ã³ãã©ã«ã€ããŠã¯å¥èšäºã«ãªã£ãŠããã®ã§ããã¡ããã芧ãã ããã tech.stmn.co.jp æè¡æ§æ / éžå®çç± React / Next.js / TypeScript React Next.js TypeScript SWR aspida msw storybook / chromatic styled-components hygen eslint / prettier / stylelint ãã£ã¬ã¯ããªæ§æ apis features pages / screens ui éçšããŠã¿ãŠåãã£ãå¬ããã»ã€ãã å¬ãã ã€ãã ããã¥ã¡ã³ãã®éçš ä»åŸã®ããš ãããã« æè¡æ§æ / éžå®çç± React / Next.js / TypeScript ããŒã¹ãšãªãæè¡ãšããŠãReact / Next.js / TypeScriptãæ¡çšããŸããã React 瀟å
ã®ãããã¯ãã¯Reactãå€ã䜿çšããŠããã瀟å
ã«ç¥èŠãæã€ãšã³ãžãã¢ãå€ãã£ããããããã¯ç¹ã«è°è«ã¯ãªã決å®ããŸããã Next.js Next.jsãæ¡çšããçç±ã¯ããã€ããããŸãã以äžãäž»ãªéžå®çç±ã§ãã ã«ãŒãã£ã³ã°ãCode Splittingãªã©ããã©ã«ãã§åãã£ãŠããæ©èœã®æ©æµãåãããã£ãããš äžéšã®æ©èœã§SSRã䜿ãããã£ãããšãããããã¯ãã®æ§è³ªäžãæ§ã
ãªæ©èœããããããããã«åãããŠã¬ã³ããªã³ã°æ¹æ³ãéžæã§ããäœå°ãããããšã«ã¡ãªãããæãããã TypeScript ããã¡ã¯ãã¹ã¿ã³ããŒãã«ãªã£ãŠãããããæ¡çšããªãçç±ããªãæ¡çšãããŸããã SWR ããŒã¿ååŸã©ã€ãã©ãª&ç¶æ
管çã©ã€ãã©ãªãšããŠãSWRãæ¡çšããŸããã ãªãã¬ã€ã¹åã®ç°å¢ã§ã¯ãReduxã䜿çšããŠããŸããããã³ãŒãéã®å€ããåŠç¿ã³ã¹ãã®é«ãããReduxã®æ¡çšã¯ããŸããã§ããã ãŸããReduxã§ç®¡çããŠããç¶æ
ã®ã»ãšãã©ãAPIããååŸããããŒã¿ã§ãã£ãçºãSWRã§åé¡ããªãã£ãã®ãæ¡çšçç±ã§ãã SWR以å€ã«ãåããããªã©ã€ãã©ãªãšã㊠TanStack Query ã RTK Query ããããŸãã ãã®äžã§SWRãæ¡çšããçç±ã¯ãéçºå
ãVercelã®ããNext.jsã®æ°æ©èœãåºãæã«äžçªæ©ã察å¿ãããã ãããšããããšãRTK QueryãSuspenseã«å¯Ÿå¿ããŠããªãã£ãçãæããããŸãã aspida ããã¯ãšã³ããšããŠRailsã䜿ã£ãŠã¹ããŒãé§åã§éçºããŠãããããOpenAPIããHTTPã¯ã©ã€ã¢ã³ããšãªã¯ãšã¹ã / ã¬ã¹ãã³ã¹ã®åãèªåçæããŠéçºå¹çã®åäžãå³ã£ãŠããŸãã ãã®ããã®ã©ã€ãã©ãªãšããŠãaspidaãæ¡çšããŸããã åããããªã©ã€ãã©ãªãšããŠã Orval ã openapi-typescript ãåè£ã«äžãããŸãããã©ã®ã©ã€ãã©ãªã§ããOpenAPIããHTTPã¯ã©ã€ã¢ã³ããšãªã¯ãšã¹ã / ã¬ã¹ãã³ã¹ã®åãèªåçæããšããèŠä»¶ãæºãããŠããŸããããaspidaã瀟å
ã§äžçªç¥èŠããã£ãããæ¡çšããŸããã msw ã¢ãã¯ãµãŒããŒãšããŠmswãæ¡çšããŸããã aspidaã§èªåçæããã¬ã¹ãã³ã¹ã®åãšçµã¿åãããããšã§ãåå®å
šãªã¢ãã¯ãµãŒããŒãç«ãŠãŠããŸãã ãã®ãããã§ãOpenAPIãããã°ãAPIã®å®è£
ãåŸ
ããã«ãã»ãšãã©ã®ããã³ããšã³ãã®éçºãå®äºããããšãåºæ¥ãã®ã§éçºå¹çãçäžããããŸããã éçºã ãã§ãªããã¹ãã«ã掻çšããŠããŸãã storybook / chromatic çŸåšã®ããã³ããšã³ãéçºã«ãããŠãå¿
é ãšãèšããstorybookãæ¡çšãããã¹ãã£ã³ã°å
ãšVisual Regression Testing(VRT)ã®ããã«chromaticãæ¡çšããŸããã storybookã¯ãã«ã¿ãã°ã«ãªããšããã¡ãªããã ãã§ãªããã¢ãã¯ãµãŒããŒããç«ãŠãããšãªããã¬ãŒã³ããŒã·ã§ãã«ãªã³ã³ããŒãã³ãã®éçºãå§ããããå©ç¹ããããŸãã ãŸããstorybookãå°å
¥ãããã©ããã®ãŸãŸã¡ã³ããã³ã¹ãè¡ãããªããšãã話ã¯ãããè³ã«ããã®ã§ããããªããªãããã«ãstoriesã¯hygenã§èªåçæããããã«ããŠããŸãã ããããããšã§ãpropsã远å ããã ãã§storybookã«èŒããããšãã§ããå®è£
ã³ã¹ããã»ãšãã©ãªããããç¶ç¶çã«éçšã§ããŠããŸãã styled-components CSSã©ã€ãã©ãªãšããŠcss-in-jsã®styled-componentsãæ¡çšããŸããã éžå®çç±ãšããŠã¯ãæ§ç°å¢ã§äœ¿çšããŠããã®ã§ç¥èŠãããã䜿ãæ
£ããŠãããšããã®ã倧ããã§ãã ã§ãããããã«é¢ããŠã¯Next.jsã®App Routerãstableã«ãªã£ãçŸåšã«ãããŠã¯ãé©åãªæè¡éžå®ã§ã¯ãªãã£ããšæã£ãŠããŸãã(åœæã¯ã®ãªã®ãªexperimentalã§ãã) çŸåšã¯ Pages Routerã䜿ã£ãŠãããããç¹ã«åé¡ã«ãªã£ãŠããŸããããå°æ¥çã«App Routerã«ç§»è¡ããã¿ã€ãã³ã°ã§ãæ¹ããŠCSSã©ã€ãã©ãªéžå®ãçŽããããšæã£ãŠããŸãã hygen ã³ã³ããŒãã³ãã®éåœ¢äœæã®ããã«hygenãæ¡çšããŸããã åŸè¿°ã§ãã£ã¬ã¯ããªæ§æã«ã€ããŠæžããŸãããçŸåšã¯ãã®ãã¡features, ui, pages, screens, usecasesã¯hygenã§é圢ãèªåçæã§ããããã«ããŠããŸãã åãã¯ãéçºå¹çã®åäžã®ããã®éåœ¢äœæã ãšèããŠããŸããããçŸåšã¯é圢ã«ãã£ãŠãã£ã¬ã¯ããªæ§æã厩ãã«ãããšããã¡ãªããã®æ¹ã倧ãããšæããŠããŸãã ä»åŸãé圢åã§ãããã®ã¯ç©æ¥µçã«ããŠãããæ¹éãå€ãã£ãå Žåã¯ãhygenã®é圢ãã¡ã³ããã³ã¹ãããšããããšãç¶ç¶çã«ããŠãããããšæããŸãã eslint / prettier / stylelint éçè§£æãšã㊠eslintãã³ãŒããã©ãŒããã¿ãŒãšããŠprettier / stylelint ãå°å
¥ããŠããŸãã husky ã§ã³ãããåã«å®è¡ããããšã§ãã«ãŒã«ã«éåããã³ãŒããå«ãŸããã®ãé²ãã§ããŸãã ããã«ããæ©æµã¯ã³ãŒãã¬ãã¥ãŒæã«ãããŠã倧ããã§ãã ãã³ã¡ã³ãããçšã§ã¯ãªããã©æ°ã«ãªãããšãã£ããã®ãããããã®ããŒã«ã§åŒŸãããšã§ã¬ãã¥ã¯ãŒãã¬ãã¥ã€ãŒãããããŒã«ãªããŸãã çŸåšã¯ãã¬ãã¥ãŒå
容ã§ã«ãŒã«ã決ãããããã®ã¯ãèŠçŽã§ã¯ãªãããããã§èªåä¿®æ£ããããã«ããŠããŸãã å
·äœçã«ã¯ã以äžã®ãããªãã©ã°ã€ã³ãã«ãŒã«ãèšå®ããŠããŸã(å
šãŠã§ã¯ãããŸãã) ãã©ã°ã€ã³ eslint-plugin-import importæã®äžŠã³æ¿ã eslint-plugin-unused-imports importããŠããã䜿çšãããŠããªããã®ãåé€ eslintã®ã«ãŒã« react/jsx-boolean-value äŸ: propsã isOpen={true} ã®å Žå isOpen ã«çç¥ãã react/jsx-curly-brace-presence äŸ: propsã®stringã title={'text'} ã®å Žåãæ³¢æ¬åŒ§ã¯äžèŠãªã®ã§ title='text' ã«å€æŽãã react/self-closing-comp ã³ã³ããŒãã³ãã«childrenããªãå Žåãã¿ã°ãçç¥èšæ³ã«å€æŽãã 以äžãæè¡æ§æãšéžå®çç±ã§ããã ãã£ã¬ã¯ããªæ§æ â src â â apis // APIå±€ â â constants // å
±éã®å®æ° â â features // ç¹å®ã®æ©èœãå®çŸããã³ã³ããŒãã³ã â â â Todo â â â â hooks // æ©èœãå®çŸããã«ã¹ã¿ã ãã㯠â â â â logics // æ©èœãå®çŸããããã®ããžãã¯(ããŒã¿æŽåœ¢ãªã©) â â â â presentations // ãã¬ãŒã³ããŒã·ã§ãã«ãªã³ã³ããŒãã³ã â â â â â index.tsx. // æ£åžžç³» â â â â â loading.tsx // ããŒãã£ã³ã° â â â â â error.tsx // ãšã©ãŒ â â â â tests // çµ±åãã¹ã â â â â index.stories.tsx // storybook â â â index.tsx // hooksãšpresentationsã®ç¹ã蟌㿠â â pages // Next.js ã®ã«ãŒãã£ã³ã° â â screens // featuresã³ã³ããŒãã³ããããŒãžå
šäœã«é
眮ãããURLã®ã¯ãšãªãã©ã¡ãŒã¿ååŸ â â ui // å
±éã®ã³ã³ããŒãã³ã â â usecases // å
±éã®hooks â â utils // å
±éã®ããžã㯠çŸåšã®ãã£ã¬ã¯ããªæ§æã¯ãã®ããã«ãªã£ãŠããŸãã (ä»ã«ãtestConfigs(ãã¹ãã®èšå®)ãªã©çްãããã®ã¯ãããŸãã岿ããŠããŸã) ãã®äžããããã€ãããã¯ã¢ããããŠç޹ä»ãããŠããã ããŸãã apis åºæ¬çã«aspidaçã䜿ã£ãŠèªåçæãããã®ã眮ããŠãããã»ãšãã©ã¯ yarn prepare ã«scriptãå
¥ããŠããã®ã§ãããã§èªåçæããããã«ããŠããŸãã å
·äœçã«ã¯ä»¥äžã眮ããŠããŸãã HTTP ã¯ã©ã€ã¢ã³ã ã¬ã¹ãã³ã¹ã®å OpenAPIã®exampleããæãåºããã¢ãã¯ããŒã¿ mswã®ã¢ã㯠features featuresã§ã¯ã以äžã®2çš®é¡ã®ã³ã³ããŒãã³ãã«åããããšã§è²¬åãæç¢ºã«ããŠããŸãã å¯äœçšãæã€ã³ã³ããŒãã³ã(Container Component) å¯äœçšãæããªãçŽç²é¢æ°ã®ã³ã³ããŒãã³ã(Presentational Component) å¯äœçšãæã€ã³ã³ããŒãã³ã(Container Component) ãã®ã³ã³ããŒãã³ãã¯ãåãfeatureå
ã®hooksãlogicsãsrc/utlilsãsrc/usecasesãªã©ã䜿ã£ãŠæ©èœãå®çŸããPresentational Componentã«æµã蟌ã圹å²ããããŸãã ãã®ãããã©ã®ããã«è¡šç€ºãããã(èŠãç®)ã¯ç¥ããŸããã ããã«å¯äœçšãéäžãããããšã§ãå€ãã®ã³ã³ããŒãã³ããå¯äœçšãæããªãçŽç²é¢æ°ã®ã³ã³ããŒãã³ã(Presentational Component)ã«ããããšãç®çã§ãã å¯äœçšãæããªãçŽç²é¢æ°ã®ã³ã³ããŒãã³ã(Presentational Component) å¯äœçšãæããªãã³ã³ããŒãã³ãã§ãèŠãç®ã«è²¬åãæã¡ãŸãã ãã®ã³ã³ããŒãã³ãã«æž¡ã£ãŠããpropsãã©ã®ãããªããžãã¯ã§äœãããŠããã®ãã«ã€ããŠã¯ç¥ããŸããã pages / screens pages pagesã¯ã«ãŒãã£ã³ã°ã®ã¿ã«è²¬åãæã¡ãããŒãžã«è¡šç€ºããå
容ã¯ç¥ããã察å¿ããscreensãåŒã³åºãããšã®ã¿ãè¡ãªã£ãŠããŸãã screens å®éã«ããŒãžã«è¡šç€ºããå
容ã§ãã åºæ¬çã«ã¯featuresã䞊ã¹ãããšãè¡ããŸãããããŒãžã«äŸåããŠããURLã®ã¯ãšãªãã©ã¡ãŒã¿ã®ååŸãããã§è¡ããŸãã ui å
±éã§äœ¿ããUIã³ã³ããŒãã³ãã眮ããŸãã å®éã«ã¯ãTUNAGã«ã¯ãã¶ã€ã³ã·ã¹ãã ããããåºæ¬çã«ã¯ãããã«UIã³ã³ããŒãã³ããããã®ã§ããã®ãã£ã¬ã¯ããªã«çœ®ããã®ã¯å€ããããŸããã ãã ããã¶ã€ã³ã·ã¹ãã ã«èŒããã倿ã§ããŠããªããã®(ãã¶ã€ã³ãæªç¢ºå®ãªã©)ã¯äžæçã«ããã®ãã£ã¬ã¯ããªã«çœ®ããéæããã¶ã€ã³ã·ã¹ãã ãžã®ç§»è¡ãæ€èšããŠããŸãã éçšããŠã¿ãŠåãã£ãå¬ããã»ã€ãã å¬ãã 責åãæç¢ºã§å¯èªæ§ãé«ã åã³ã³ããŒãã³ãã®è²¬åãæç¢ºã«ãªã£ãŠããã®ãšäŸåé¢ä¿ãäžæ¹åã§ã·ã³ãã«ãªã®ã§å¯èªæ§ãéåžžã«é«ãã§ãã çŸåšã¯ãã£ãŠããŸããããä»åŸéçºããäžã§å¿
èŠã«ãªãã°ãã³ã³ããŒãã³ãéã®äŸåé¢ä¿ãeslintã§å¶éããããšãèããŠããŸãã èªåçæã§ã³ãŒãèšè¿°éãå°ãªã & æ§æã厩ãã«ãã hygenãšaspidaã䜿ã£ãŠèªåçæã§ããç®æãå€ãã®ã§ãå®è£
éãå°ãªããªããŸããã ãŸããããã«ãã£ãŠããã³ããšã³ãã®éçºã«ãªããŠããªãã¡ã³ããŒã§ãã£ãŠãã¹ã ãŒãºã«å®è£
ããããšãåºæ¥ãŠããŸãã çŸåšã¯ãªãã¬ã€ã¹äžã®ãããéçºããããŒã ã¯éãããŠããŸãããä»åŸãããç¹å®ã®ããŒã ã ããããã³ããšã³ããéçºããããã§ã¯ãªãã®ã§ããã®æ®µéããèªåçæããããŸã§å
å®ãããããŠããã®ã¯ãšãŠãè¯ãããšã ãšæããŸãã SWRãè€æ°ãªã¯ãšã¹ãã1ã€ã«ãŸãšããŠãããã®ã§ããµãŒããŒã®è² è·ãäžããã«ã1ã€ã®featureã§æ©èœãå®çµã§ãã SWRã®ãããªããŒã¿ååŸã©ã€ãã©ãªã䜿ããã«2ã€ã®ç°ãªãfeatureããåãAPIã«ãªã¯ãšã¹ããããå Žåã2åãªã¯ãšã¹ããè¡ãããŸãã ä»®ã«ããã®APIã®åŠçãéããµãŒããŒã®è² è·ã軜æžããããã«1床ã®ãªã¯ãšã¹ãã«å¶éããããšãªã£ãå Žåã®è§£æ±ºçãšããŠãã°ããŒãã«ã«ç¶æ
管çãããšããæ¹æ³ããããšæããŸãã ãã ããããªããšfeatureã®å€ãšã®äŸåé¢ä¿ãçãŸããŠããŸããè€éã«ãªãæãããã®ã§ãã§ããã°é¿ãããå®è£
ã§ãã SWRã¯ããã©ã«ã2ç§éã¯åãkeyã«å¯Ÿããè€æ°ãªã¯ãšã¹ãã1ã€ã«ãŸãšããŠãããæ©èœãæã£ãŠããŸãã ãããæŽ»çšããããšã§è€æ°ã®ç°ãªãfeatureããã®åãAPIãžã®ãªã¯ãšã¹ãã1æ¬ã«ãŸãšããã°ããŒãã«ã«ç¶æ
管çããããšããªããåç¬ã®featureã®ã¿ã§æ©èœãå®çµãããããšãã§ããŸããã ãã®çµæãå®è£
ãã·ã³ãã«ã«ãªããšãŠãå©ãã£ãŠããŸãã ã€ãã å¯äœçšããŸãšããŠããããpropsã®ãã±ããªã¬ãŒãå€ã featuresã§ã¯ãå¯äœçšãéäžãããããšã§ãã»ãšãã©ããã¬ãŒã³ããŒã·ã§ãã«ãªã³ã³ããŒãã³ãã§æ§æããããšãã§ããŠããäžæ¹ã§ã衚瀺ã«å¿
èŠãªpropsãäžããæµã蟌ãããšãå€ããããã±ããªã¬ãŒãå€ããªããŸãã ããã«é¢ããŠã¯ãçŸåšã¯èš±å®¹ããããã«ããŠããŸãããè€éãªæ©èœã§ããã°ããã»ã©propsãå€ããªãã®ã§ããã®å Žåã®å¯Ÿå¿ã¯ä»åŸå¿
èŠã«ãªãããã ãªãšæã£ãŠããŸãã ãŸããstateãfeatureã®ãããã®ã³ã³ããŒãã³ã(Container Component)ã«ãŸãšããŠããããšã§äžèŠãªã³ã³ããŒãã³ããŸã§åã¬ã³ããªã³ã°ããããããã«ãªã£ãŠããŸãã çŸåšãåã¬ã³ããªã³ã°ã§ãŠãŒã¶ããªãã£ã«é¢ããã»ã©ã®ããã©ãŒãã³ã¹ãžã®æªåœ±é¿ã¯ãããŸãããããããã£ããšããŠãã¡ã¢åããããšã§å¯Ÿå¿ã§ããã®ã§ã¯ãªãããšæã£ãŠããŸãã ããã¥ã¡ã³ãã®éçš ADR(Architecture Decision Records)ãREADMEãWikiã宿çã«ããŒã ã§ã¡ã³ããã³ã¹ããããã«ããŠããŸãã ããããããšã§æ°ããã¡ã³ããŒãéçºã«å ããæã«ãããã«éçºãå§ããããç¶æ
ãäœããããšæã£ãŠããŸãã ãŸããæè¡ã«ã¯æµè¡ãå»ããããããããã€ããã®æè¡ãæšãŠãæãããŸãããã®æã«æšãŠãããããããã«ADRãšããŠæè¡ã®éžå®çç±ãææžã«æ®ãããã«ããŠããŸãã ãã®ä»ã«ã宿çã«ã¡ã³ããã³ã¹ããããšã§ãä»ã®éçºã¡ã³ããŒãçè§£ã«ç¹ãããŸãããèŠè¿ãããšã§èª²é¡ãèŠã€ããããšã«ãç¹ããã®ã§ããããããç¶ç¶ããŠãããããšæããŸãã ä»åŸã®ããš App Routerã®å¯Ÿå¿ çŸåšã¯Pages Routerã䜿ã£ãŠããŸãããNext.jsã®ããŒãžã§ã³ã¯ææ°ã«ãªã£ãŠããããApp Routerã䜿ããç¶æ³ã§ãã ã§ãããApp Routerã®å¯Ÿå¿ããããããæ°ç°å¢ãžã®ãªãã¬ã€ã¹ãåªå
ããããšããèãã§ãçŸåšã¯Pages Routerã§ãªãã¬ã€ã¹ãè¡ã£ãŠããŸãã ãã ãNext.jsã®é²åã¯App Routerãäžå¿ã«ãªã£ãŠãããšæãã®ã§ãããããã¯App Routerã®å¯Ÿå¿ãããããšæã£ãŠããŸãã SuspenseãšErrorBoundary çŸåšã¯äžéšã®æ©èœã§SuspenseãšErrorBoundaryã䜿ã£ãŠããŸãã ãã®2ã€ã䜿ãããšã§featureå
ã®å®è£
ãã·ã³ãã«ã«ãªããããè¿ããã¡ã«å
šãŠã®featureã§å¯Ÿå¿ããããšæã£ãŠããŸãã ãããã« ãããŸã§èªãã§ããã ãããããšãããããŸãã ãšãŠãé·ããªã£ãŠããŸããŸããããTUNAGãã®ãªãã¬ã€ã¹ã®éã®æè¡éžå®çç±ãèšèšã«ã€ããŠããŸãšããããŠããã ããŸããã ãªãã¬ã€ã¹ãããžã§ã¯ãã¯å§ãŸã£ãã°ããã§ããŸã ãŸã ããããšäºæ³ããŠããŸãã ãã®ãããªé·æã®ãããžã§ã¯ããæåãããããã«ãæ¥ã
ãæ¹åãéããŠãããããšæããŸãã æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã§ã¯ãšã³ãžãã¢ãçµ¶è³åéäžã§ãïŒïŒ èå³ãæã£ãŠããã ããããäžèšã®ãªã³ã¯ãããå¿åãã ããïŒ ãåŸ
ã¡ããŠãããŸãïŒ herp.careers
ããã«ã¡ã¯ãã¹ã¿ã¡ã³ã®æå¶ã西å·ã§ãã æ®æ®µã¯ãšã³ã²ãŒãžã¡ã³ããã©ãããã©ãŒã ã TUNAG ãã®éçºãããŠããŸãã ãããžã§ã¯ãã®èæ¯ æè¡æ§æã»éžå® ãªãã¬ã€ã¹å ãªãã¬ã€ã¹åŸ æ§æå€æŽã«ãããæ³šæç¹ 1. æå³ããæ
å ±ããã£ãã·ã¥ãããŠããŸããªã¹ã¯ 2. ããŠã³ã¿ã€ã çºçã®ãªã¹ã¯ ãªãã¬ã€ã¹ã®ãã㌠æ¯ãè¿ã æåŸã« ãããžã§ã¯ãã®èæ¯ ãããŸã§TUNAGã¯ããããã¯ãã®æé·ã«æ³šåããŠããäžæ¹ã§ãå
éšå質ãéçºå¹çãªã©ã«é¢ãã課é¡ã®è§£æ¶ãåŸæã«ãŸãã£ãŠããŸããã TUNAGãæé·è»éã«ä¹ã£ãŠããäžã§ããšã³ãžãã¢çµç¹ãæ¡å€§ããã€ã€ãç¶ç¶çã«ãããã¯ãã®äŸ¡å€ãçŽ æ©ãäžã®äžã«å±ããŠããããã«ã¯ãéçºè
äœéš(以äžãDevEx)ã«é¢ããæ¹åãäžå¯æ¬ ã ãšèããŠããŸãã ãããŸã§TUNAGã®ããã³ããšã³ãã¯ãRuby on Rails(以äžãRails)ã«Reactãä¹ãã圢ã§éçºãè¡ã£ãŠããŸããããRailsã®ã€ã³ã¿ãŒãã§ã€ã¹ã«äŸåãããæ
ã«éçºå¹çã劚ããŠããããäžå
·åã®çºç確çãé«ããŠããŸããšãããšããåé¡ããããDevExãšããŠã¯æãŸãããªãç¶æ³ã§ããã ãŸããããã³ããšã³ãåç¬ã§ã®ãããã€ããããã€ã®åãæ»ããè¡ãããšãåºæ¥ãªããªã©ãCI/CDã«é¢ããŠãå€ãã®åé¡ãæ±ããŠããããªãªãŒã¹ã«å¯ŸããŠãã¬ãã·ã£ãŒãæããŠããŸããšã³ãžãã¢ãäžå®æ°ååšããŠããŸããã ç§ãã¡ã®ããŒã ã§ã¯DevExã®æ¹åããŸããŠãŒã¶ãŒäœéšã®åäžãç®çãšããŠã2023幎é ããæ¬æ Œçã«ããã³ããšã³ãç°å¢ããªãã¬ã€ã¹ãããããžã§ã¯ãã«åãçµãã§ããŸãã ãããŸã§ã¯äž»ã«Reactã§éçºãè¡ã£ãŠããŸããããReactã®å
¬åŒããŒãžã§ããã«ã¹ã¿ãã¯ãã¬ãŒã ã¯ãŒã¯ã§ãããNext.jsãããRemixããæšå¥šãããŠããããšããããé·æçãªèŠç¹ã§ã¯ãã®ãããªãã¬ãŒã ã¯ãŒã¯ãæ¡çšããããšã§ããŠãŒã¶ãŒäœéšãDevExã®åäžã«ç¹ããããšãã§ãããšèããä»åNext.jsãžã®ãªãã¬ã€ã¹ã決æããŸããã ãããžã§ã¯ããšããŠã¯ãŸã éåã°ã§ã¯ãããŸãããå
æ¥ã€ã³ãã©ã®åºç€å€æŽãå«ãã1stãªãªãŒã¹ãå®äºãããããšãã§ããŸããã ãã®èšäºã§ã¯ã€ã³ãã©ã«ç¹åããŠãæè¡éžå®ããªãã¬ã€ã¹ã®ãããŒããããžã§ã¯ãã®æ¯ãè¿ãã«ã€ããŠç޹ä»ããŸãã(ããã³ããšã³ãã®æè¡éžå®ãéçšã«é¢ããŠã¯ã ãã¡ãã®èšäº ãã芧ãã ããã) æè¡æ§æã»éžå® ããããã¯ãããã³ããšã³ãã®Next.jsãžã®ãªãã¬ã€ã¹ã®ããã«è¡ã£ããã€ã³ãã©åºç€ã®æ§æå€æŽã«ã€ããŠã玹ä»ããŸãã ãªãã¬ã€ã¹ååŸã®ã€ã³ãã©æ§æã¯ä»¥äžã®éãã§ããïŒâ»äžéšç°¡ç¥åããŠããŸãïŒ ãªãã¬ã€ã¹å ãªãã¬ã€ã¹åŸ ãªãã¬ã€ã¹åã®æ§æã§ã¯ALBã«çŽæ¥åããŠããŸãããããªãã¬ã€ã¹åŸã¯CloudFrontãåæ®µã«ããªãªãžã³ã«ALBãšVercelãé
眮ãã圢ã«å€æŽããŸããã ãã®ãªãã¬ã€ã¹ãããžã§ã¯ãã§ã¯ãããŒãžåäœã§ã®æ®µéçãªç§»è¡ãæ³å®ããŠãããæ§ç°å¢(Rails)ãšç§»è¡åŸã®ããŒãž(Next.js)ãå
±åãããå¿
èŠããããŸããããã®ãããæ®µéçã«ç§»è¡ãå¯èœãªæ§æãšããŠããŸãã æ°ãã«å段ã«é
眮ããCloudFrontã§ã¯ããã¹ãã¿ãŒã³ã«åºã¥ããALBïŒRailsïŒãšVercelïŒNext.jsïŒãžã®ãªã¯ãšã¹ããæ¯ãåããŠããŸããNext.jsãžã®ãªã¯ãšã¹ããã¹ã«ã¯ãmãããã¬ãã£ãã¯ã¹ãšããŠä»ããŠããŸãããŸããVercelã®å段ã«Proxyãèšçœ®ããããšã¯éæšå¥šãšãããŠããããšããæ§æãè€éã«ãªãããšãæ§æå€æŽã«äŒŽããªã¹ã¯ã倧ãããªãããšãããCloudFrontã®åœ¹å²ãæå°éã«ãããã£ãã·ã¥ãããªãæ§æã«ããŸããã ãŸãã瀟å
ãªãªãŒã¹æéäžãªã©ã«Next.jsãžã®ã¢ã¯ã»ã¹ãå¶éããç®çã§ãLambda@Edgeãšæ¯èŒããäžã§ãCloudFront Functionsãæ¡çšããŸãããäž»ãªéžå®çç±ã¯ä»¥äžã®éãã§ãã Lambda@Edgeã¯Regional Edge Cacheã§å®è¡ãããã®ã«å¯ŸããŠãCloudFront Functionsã¯Edge Locationã§å®è¡ããããããã¬ã¹ãã³ã¹ãããé«éã«è¿ããããš çšéã瀟å€IPã¢ãã¬ã¹ããã®ã¢ã¯ã»ã¹å¶éãšãã軜éãªåŠçã§ãã£ããããCloudFront Functionsã®æå€§å®è¡æéã®å¶é(1ms)ã«è§ŠããªãããšïŒLambda@Edgeã¯5ç§ïŒ Lambda@Edgeã¯ãªã¯ãšã¹ã100 äžä»¶ããã0.60 USD+å®è¡æéã®æéããããã®ã«å¯ŸããCloudFront Functionsã¯ãªã¯ãšã¹ã100 äžä»¶ããã0.10 USDãšå®äŸ¡ã§ããããš Next.jsã®ãã¹ãã£ã³ã°å
ãšããŠã¯ãS3ãåè£ã«äžãããŸããããNext.jsã®æ©èœããã«ã«æŽ»çšãããããããã³ããšã³ããšã³ãžãã¢ãèªåŸçã«äœæ¥ããããããããã«Vercelãéžå®ããŸããã ãããŠãCloudFrontãALBã®åæ®µã«æ°ãã«é
眮ããã«ããããCloudFrontçµç±ã®ã¢ã¯ã»ã¹ã§ããããšãä¿èšŒãããããCloudFrontã§ã«ã¹ã¿ã ããããŒãä»äžããALBã®ãªã¹ããŒã«ãŒã«ã§ãã®ããããŒã®æç¡ãå€å®ããããšã§ãALBãžã®çŽæ¥ã¢ã¯ã»ã¹ãå¶éããŠããŸãã æ§æå€æŽã«ãããæ³šæç¹ äžèšã®æ§æå€æŽãè¡ãã«ããã£ãŠã倧ãã2ã€ã®æ³šæç¹ããããŸããã 1. æå³ããæ
å ±ããã£ãã·ã¥ãããŠããŸããªã¹ã¯ åè¿°ããããã«ãä»åã®æ§æå€æŽã§CloudFrontã§ã®ãã£ãã·ã¥ã¯è¡ãªã£ãŠããŸãããããããCloudFrontãé
眮ããããšã§ãæ¬æ¥ãã£ãã·ã¥ãã¹ãã§ãªãæ
å ±ãæå³ãããã£ãã·ã¥ããããªã¹ã¯ããããŸããããã®ãªã¹ã¯ãåé¿ãããããCloudFrontã®èšå®ããNginxãVercelã®ãã£ãã·ã¥èšå®ã«ã€ããŠæ€èšŒããŸãããç¹ã«HTTPããããŒã®Cache-Controlã®å
容ã«ã€ããŠããã£ãã·ã¥ãã¹ãã§ãªãã¬ã¹ãã³ã¹ã«ã¯privateãå«ãŸããŠãããçã®ç¢ºèªãè¡ããŸããã CloudFrontã§ã¯ã 管çãã£ãã·ã¥ããªã·ãŒ ã®äžããããã£ãã·ã¥ãç¡å¹ã«ããããªã·ãŒã§ããCachingDisabledã䜿çšããŠããŸããä»åãCloudFrontã®ãã£ã¹ããªãã¥ãŒã·ã§ã³ã¯CloudFormationã§äœæããŠããã以äžã®ããã«èšå®ããŸããã CloudFrontDistribution : Type : 'AWS::CloudFront::Distribution' Properties : DistributionConfig : CacheBehaviors : - CachePolicyId : 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # Managed-CachingDisabled 2. ããŠã³ã¿ã€ã çºçã®ãªã¹ã¯ Route53ã®ãã©ãã£ãã¯ã®ã«ãŒãã£ã³ã°å
ãALBããCloudFrontã«åãæ¿ããéããCloudFrontã»CloudFront FunctionsãæŽæ°ããéã«ããŠã³ã¿ã€ã ãçºçããªãããšããAWSå
¬åŒããã¥ã¡ã³ããæ¬çªãšåãæ§æã«ããã¹ããŒãžã³ã°ç°å¢ã§ç¢ºèªããäžã§ãæ§æå€æŽãè¡ããŸããã å®éã®ãªãã¬ã€ã¹ã§ã¯ãããŠã³ã¿ã€ã ãçºçãããããšãªããæ§æå€æŽãæåãããããšãã§ããŸããã ãŸãäžèšïŒç¹ãæ€èšŒããäžã§ãæ§æå€æŽãè¡ãåã«ãäžéšã®ã¡ã³ããŒãCloudFrontã®IPã¢ãã¬ã¹ãhostsã«ç»é²ããããŒã«ã«ããCloudFrontã«æ¥ç¶ããŠåäœç¢ºèªãè¡ããŸããã ããã«ããããã®åé¡ãçºçããå Žåã«ã¯ããã«æ€ç¥ã»å¯Ÿå¿ã§ãããããã¢ã©ãŒããäºåã«èšå®ããŸãããèšå®ããã¢ã©ãŒãã¯ä»¥äžã®éãã§ãã 5xx ãšã©ãŒç ãã£ãã·ã¥ãããã¬ãŒã CloudFront ããã®ãã£ãã·ã¥ããã³ã³ãã³ããéä¿¡ãã察象ã®ãã¹ãŠã®ãã£ãã·ã¥å¯èœãªãªã¯ãšã¹ãã®å²å (%)ãä»åã®æ§æã§ã¯ãã£ãã·ã¥ãããªãããããã£ãã·ã¥ãããã¬ãŒãã0ãè¶
ããæã«ã¢ã©ãŒããéç¥ãããããã«èšå®ããŠããŸãã CloudFront Functionsã®ã³ã³ãã¥ãŒãã£ã³ã°äœ¿çšç 颿°ã®å®è¡ã«ããã£ãæé (æå€§èš±å®¹æéã«å¯ŸããããŒã»ã³ããŒãž)ãçŸç¶ã¯35%ååŸã§æšç§»ããŠããŸããã䜿çšçãå¢å ããå Žåã«åŠçå
容ãèŠçŽãããšãã§ãããããã¢ã©ãŒããèšå®ããŠããŸãã å ããŠãCloudFrontã®ãã°åæã®ããã«ãAthenaãçšãããã°æ€çŽ¢ç°å¢ãæŽåããŠããŸãã ãªãã¬ã€ã¹ã®ãã㌠åé ã«ãã玹ä»ããéãããªãã¬ã€ã¹ã®ãããžã§ã¯ãã¯çŸåšãç¶ããŠãããäž»èŠãªããŒãžããæ®µéçã«ç§»è¡ãé²ããŠããŸãã äžåºŠã®ãªãªãŒã¹ã§1ã€ã®ããŒãžå
šäœã眮ãæããŠããŸããšäžå
·åãçºçãããªã¹ã¯ãé«ãããã以äžã®ã¹ããããçµãŠçްãããããã€ãè¡ããªãããªãã¬ã€ã¹ãé²ããŠããŸãã Next.jsã®æ°ããŒãž(pages)ãäœæ ãã®æç¹ã§ã¯ã¢ããªã±ãŒã·ã§ã³å
ã«æ°ããŒãžãžã®å°ç·ã¯ååšããŸãã æ°ããŒãžãžã®ã¢ã¯ã»ã¹ã瀟å
IPã«éå®ãã ãã¡ãã®å¶åŸ¡ã¯äžè¿°ã®CloudFront Functionsã§è¡ã£ãŠããŸã æ°ããŒãžã«æ©èœãããã€ã现ããè¡ã åºæ¬çã«ãšã³ãžãã¢ã®åäœç¢ºèªä»¥å€ã®ç®çã§ã¯ãããŒãžãžã®ã¢ã¯ã»ã¹ããªãããä»®ã«äžå
·åãçºçããŠãã圱é¿ç¯å²ãæå°éã«æããããšãã§ããŠããŸã ã¹ã³ãŒããéå®ããŠãªãªãŒã¹(瀟å
ãªãªãŒã¹)ãè¡ã TUNAGã¯åŒç€Ÿã§ãå©çšããŠããããããŸãã¯ç€Ÿå
éå®ã§ãªãªãŒã¹ãè¡ã£ãŠããŸã ãã®éã«Railsã®ã³ã³ãããŒã©ãŒã§ãªãã€ã¬ã¯ãåŠçãå
¥ããã¢ããªã±ãŒã·ã§ã³å
ã§Rails(æ§ç°å¢)ã«ã¢ã¯ã»ã¹ããã£ãéã«ãæ°ç°å¢(Next.js)ã«ãªãã€ã¬ã¯ããããŠããŸã å
šäœã«ãªãªãŒã¹ãé©çšããã æåŸã®stepãšããŠäžèšã®ãªãã€ã¬ã¯ãåŠçãå
šäœã«é©çšãããŸãã åæã«CloudFront Functionsã§è¡ã£ãŠããã¢ã¯ã»ã¹å¶é(2)ã®èšå®ãåé€ããå
šãŠã®ãŠãŒã¶ãŒããã®ã¢ã¯ã»ã¹ãèš±å¯ããããã«å€æŽããŠããŸã äžèšã®ã¹ããããèžãããšã§ãäžå
·åã®å¯èœæ§ãæžãããã€éçºè
ãå®å¿ããŠãªãªãŒã¹ãè¡ãããšãã§ããŠããŸãã æ¯ãè¿ã ç¹°ãè¿ããšãªããŸãããããã³ããšã³ããªãã¬ã€ã¹ã®ç®çã¯ãDevExã®æ¹åãšãŠãŒã¶ãŒäœéšã®åäžã§ãããDevExã®æ¹åã«é¢ããŠã¯ãRailsãšã®äŸåããªããªãã·ã³ãã«ãªåœ¢ã§éçºãã§ããããã«ãªã£ãããšã§ã瀟å
ã®ãšã³ãžãã¢ããåã³ã®å£°ã沢山ããã£ãŠããŸãã ãŸãCI/CDã«é¢ããŠãã以åã®ç°å¢ãšæ¯èŒããŠçŽ10åã®ã¹ããŒãã§å®äºããŠããããŠãŒã¶ãŒãžã®äŸ¡å€ããªããªãŒãšãã芳ç¹ã§éåžžã«å€§ããªæ¹åãè¡ãããšãã§ããŸããã ãŸããããã€ã«éããŠãéçºè
ãå¿
èŠä»¥äžã«æ°ã匵ããªããã°ãªããªãåé¡ãè§£æ¶ããããããã€é »åºŠã倧å¹
ã«å¢å ãããããšãã§ããŸããã 以åã®ããŒãžãšæ¯èŒããŠè¡šç€ºé床ã«é¢ããããã©ãŒãã³ã¹ãåäžããŠããããŠãŒã¶ãŒäœéšãšããŠãè¯ã广ãåºãŠããŸãã äžæ¹ã§ãVercelã®æ©èœã«ã¯ãŸã 掻çšã®äœå°ããããããä»åŸãç¶ç¶ããŠãã£ããã¢ããããŠãããããšæããŸãã æåŸã« TUNAGã®ããã³ããšã³ããªãã¬ã€ã¹ã®èæ¯ãã€ã³ãã©ã®æè¡éžå®ããªãã¬ã€ã¹ã®ãããŒãæ¯ãè¿ãã«ã€ããŠç޹ä»ããŸãããåãæ§ã«ããã³ããšã³ãããªãã¬ã€ã¹ããéã«ãæ¬èšäºãå°ãã§ãåèã«ãªãã°å¹žãã§ãã æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã§ã¯ãšã³ãžãã¢ãçµ¶è³åéäžã§ãïŒïŒ èå³ãæã£ãŠããã ããããäžèšã®ãªã³ã¯ãããå¿åãã ããïŒ ãåŸ
ã¡ããŠãããŸãïŒ herp.careers
ããã«ã¡ã¯ããããã¯ãéçºéšãã¢ãã€ã«Gã§iOSããŒã ã®ãšã³ãžãã¢ãªã³ã°ãããŒãžã£ãããŠãã æåïŒ @asashin227 )ã§ãã 2022幎æ«ã« ã¹ã¯ã©ã äœå¶ã§ã®ã¢ãã€ã«ã¢ããªGã®å€é·ïŒ2022å¹ŽïŒ ãšããèšäºãå
¬éããŠããïŒã¶æã»ã©çµã¡ãããŸããŸãªå€åããããŸããã®ã§ãã玹ä»ã§ããã°ãšæããŸã TUNAG(ããã°)ã«ã€ã㊠2022幎2æã«ä»¥äžã®èšäºã§ã¹ã¿ã¡ã³ã®äž»åäºæ¥ã§ããTUNAGã®ç޹ä»ãããŸããã 2023幎ã®8ææç¹ã«ãããŠæšå¹Žæç¹ã§èŠããŠããªãã£ãéšåã®è§£å床ãäžãã£ãŠãããããæ¹ããŠTUNAGã«ã€ããŠç޹ä»ããããšæããŸãã tech.stmn.co.jp TUNAG(ããã°)ã¯ããšã³ã²ãŒãžã¡ã³ãçµå¶ã®å®è·µãéããŠäŒç€Ÿã®æé·ãæåãæ¯æŽãããã©ãããã©ãŒã ãšããŠå€§äŒæ¥ããäžå°äŒæ¥ãŸã§ããŸããŸèŠæš¡ã®äŒæ¥ãžå°å
¥ããŠããã ãããšã³ã²ãŒãžã¡ã³ãã®åäžãæ¯æŽããŠããŸããã åŒç€Ÿã®ã«ã¹ã¿ããŒãµã¯ã»ã¹ãšå°å
¥äŒæ¥ã®æ
åœè
æ§ã®éã§å¯ã«ã³ãã¥ãã±ãŒã·ã§ã³ããšãäžã§æ¥çš®ãæ¥æ
ã«ãã£ãŠããããšã³ã²ãŒãžã¡ã³ãã«å¯ŸããããŒãºãé«ãé åãèŠããŠããŸããã TUNAG(ããã°)ã®åŒ·ã¿ TUNAGã®æäŸããæ©èœã¯å€§ãŸãã«ä»¥äžã®2çš®é¡ã«åé¡ããããšãã§ããŸãã äŒæ¥ãšåŸæ¥å¡ãåŸæ¥å¡å士ã®ã€ãªããã匷åºã«ãã ãšã³ã²ãŒãžã¡ã³ãæ©èœ æ¥åDX ãå®çŸããå®åçãªæ©èœ ãã®æ©èœãããITãè¡ãå±ããŠãããããŸãå®ççãäœããšã³ã²ãŒãžã¡ã³ããç¶æã§ããªãããšãã課é¡ã«å¯ŸããŠTUNAGã®åŒ·ã¿ãæãçºæ®ã§ãããšèããŠããŸãã ç¹ã«ãã®èª²é¡ãæ±ããŠããã®ãã飲é£ãå°å£²ãç©æµãä»è·ã補é ããªã©ã®çŸå Žã§åãã ãã³ãã¹ã¯ã¯ãŒã«ãŒ ããåãæ¥çã§ãããã³ãã¹ã¯ã¯ãŒã«ãŒã®ã»ãšãã©ã¯ãç«ã¡ä»äºãªã©ãã¡ã€ã³ã§èœã¡çããç°å¢ã§PCå©çšãªã©ã¯ã§ãããçŽãšãã³ã«ããéå¹çãªãªãã¬ãŒã·ã§ã³ãããŸã å€ãæ®ã£ãŠããŸãããããŠé¢è·ãªã©ã®ãšã³ã²ãŒãžã¡ã³ãã«é¢ãã課é¡ã倧ããã§ãã æ¥æ¬ã®åŽå人å£ã®ïŒå²ãçŸå Žã§åããã³ãã¹ã¯ã¯ãŒã«ãŒãšèšãããŠããããã®åžå Žã«ãããŠTUNAGãåºããããšãâ äžäººã§ãå€ãã®äººã«ãæåãå±ãã幞ããåºããã âãšããäŒæ¥ç念ãå®çŸããããšã«ã倧ããè¿ã¥ããšèããŠããŸãã TUNAGç»é¢ã€ã¡ãŒãž ãã³ãã¹ã¯ã¯ãŒã«ãŒãšã¢ãã€ã«ã¢ããªã®èŠªåæ§ ã¹ã¿ã¡ã³ã§ã¯TUNAGã®åŒ·ã¿ãæã掻ããããã³ãã¹ã¯ã¯ãŒã«ãŒãã¡ã€ã³ã¿ãŒã²ãããšããŠçµç¹æ§é ããããã¯ãã®éçºãããŒã倧ããå€åãããããšã«ããŸããã ãã³ãã¹ã¯ã¯ãŒã«ãŒæ¥çã¯ãPCã䜿ããããŸãç«ã¡ä»äºäžå¿ã®ç°å¢ãªã®ã§SaaSã®å°å
¥ãé£ãããå
æ¬çãªæ¥åDXãïŒã€ã®ãããã¯ãã§å®çŸããããšãæ±ããããŸããå¥ã®èª²é¡ãšããŠã¯éæ£èŠéçšã®å²åãå€ããæ¯å¹Žæ°çŸäººåäœã§äººãå
¥ãæ¿ãããããªäŒæ¥ãå°ãªããããŸããã ãããã®èª²é¡ã«å¯ŸããŠãTUNAGã§ã¯çŸå Žã®æ¥åDXã人ãšçµç¹ã®ã€ãªããã匷åºã«ãããšã³ã²ãŒãžã¡ã³ããé«ããããšãã§ãããšèããŠããã ã¢ãã€ã«ã¢ããªã§ããã°ç«ã¡ä»äºäžå¿ã®è·å Žç°å¢ã§ãã¹ã ãŒãºãªå°å
¥ãšéçšãå®çŸã§ããŸã ã ä»åŸãTUNAGã¯ã ãã³ãã¹ã¯ã¯ãŒã«ãŒã®ãšã³ã²ãŒãžã¡ã³ãåäžããæ¥åDXãŸã§å®çŸããALL-in-One Product ããšããããžã·ã§ã³ã確ç«ãã ã¢ãã€ã«ã¢ããªãæåç·ã§ãã®éãåãéããŠãããŸã ã ã¢ãã€ã«ã¢ããªéçºäœå¶ãžã®æè³ ãã³ãã¹ã¯ã¯ãŒã«ãŒã®åŽåç°å¢ã«ãããŠã¹ããŒããã©ã³ãæã匷åãªã³ãã¥ãã±ãŒã·ã§ã³ããŒã«ã§ãããTUNAGã®åŒ·ã¿ãšäŸ¡å€ãæãå±ããããå°ç·ãã¢ãã€ã«ã¢ããªã§ããããšãããã£ãŠãããããä»å¹Žããçµç¹äœå¶ãéçºãããŒãåŸã
ã«ã¢ãã€ã«ãã¡ãŒã¹ããžã·ãããããŠããŸããã çŸåšæç¹ã§ãæ§ã
ãªå€åãèµ·ãã£ãŠããçã£åªäžãªã®ã§ãããã€ã玹ä»ããããšæããŸãã 人æ°ãåå¢ïŒ 2022幎æ«ã®èšäºã§ã¯ã¢ãã€ã«ãšã³ãžãã¢ã2ã3人ãšããç¶æ³ã§ãããã2023幎å€ã®çŸåšã§ã¯iOS, Androidãããã3åãã€ã®åèš6åã«ãªããŸããïŒ æ±äº¬æ ç¹ã§ã®æ¡çšæŽ»åãéå§ãããšã³ãžãã¢çµç¹ã®æ¡å€§ã«ãããŠæ¥å éããŠããŸãã çŸåšãããŒã èŠæš¡ãæé·ããç¶ããããã«ç©æ¥µçã«æ¡çšæŽ»åãè¡ãªã£ãŠããŸãïŒ ãšã³ãžãã¢ãªã³ã°ãããŒãžã£ãæ°ãã«2åæ¡çš äººæ°ã®è©±ã«ãé¢ä¿ãããŸãããããããã®ã¢ãã€ã«OSããšã«ãšã³ãžãã¢ãªã³ã°ãããŒãžã£ãã€ããŠããŸãã ç§èªèº«ã10幎ã»ã©iOSã¢ããªéçºã«é¢ãã£ãŠããŸãããç§ä»¥äžã«çµéšè±å¯ãªAndroidãšã³ãžãã¢ããšã³ãžãã¢ãªã³ã°ãããŒãžã£ãšããŠãããŒã ã®ãããžã¡ã³ãããå®è³ªçãªããã¯ãªãŒãã®åœ¹å²ãæã£ãŠããŸãã ã¢ãã€ã«GãšããŠã¯ä»ãŸã§ã«ãªãã»ã©åŒ·åãªãããžã¡ã³ãäœå¶ãæ§ç¯ã§ããŠãããšèªè² ããŠããŸãã ã¢ãã€ã«Gã®æäŒ ã¢ãã³æè¡ã®å°å
¥ iOSã§ã¯2023幎ã®é ããSwiftUIãåãå
¥ããéçºãžã·ããããŠããŸãã å
ã
VIPERã¢ãŒããã¯ãã£ã§éçºãè¡ãããŠãããããSwiftUIã®å°å
¥ã«éããŠãããã€ãã®èª²é¡ããããŸããããããŸã解決ããŠå°å
¥ã«è³ããŸããã ãã®è©±ã«ã€ããŠã¯iOSDC Japan 2023 æçµæ¥ã® ã¹ãã³ãµãŒã»ãã·ã§ã³ ã§ã話ãããŸãã®ã§ããã²èŠã«ããŠãã ããïŒ Androidã§ãJetpackComposeãå°å
¥ããŠãããäž¡OSã§å®£èšçUIã®å®è£
ãè¡ããŸãã æè¡çãªéžæè¢ãå¢ããããšã§å¹ççãªéçºãè¡ããç°å¢ãšãªã£ãŠããŸãã ãã£ããæ©èœã¯SwiftUIã§å®è£
ããŸãã ãšã³ãžãã¢æé·ã®ããã®æ°ããªå¶åºŠ ã¢ãã€ã«Gãå«ããããã¯ãéçºéšå
šäœã§ãæé·æ¯æŽãç®çãšããæ§ã
ãªå¶åºŠãæ¥éã«ã§ãå§ããŠããŸãã ç¡éæžç±è³Œå
¥å¶åºŠ ã«ã³ãã¡ã¬ã³ã¹åå è£å©(åå è²»ã»äº€éè²»ã»å®¿æ³è²»å
šé¡è£å© & å¶æ¥æ¥ã¯æ¥åæ±ã) æ ç¹éåºåŒµè£å©(æ±äº¬æ ç¹ãšåå€å±æ ç¹ã®ã³ãã¥ãã±ãŒã·ã§ã³ãæ¥åå¹çãä¿é²) ãããã®å¶åºŠã掻çšããããšã«ãã£ãŠå人ã ãã§ãªãããããã¯ãçµç¹å
šäœã®æè¡åäžãç¥èŠã®åžåãä¿é²ãããŠããããšããã§ã«å®æã§ãããã®ãšãªã£ãŠããŸãã ããããã®ã¢ãã€ã«Gã®ããã·ã§ã³ åè¿°ã®éããããã³ãã¹ã¯ã¯ãŒã«ãŒã®ãšã³ã²ãŒãžã¡ã³ãåäžããæ¥åDXãŸã§å®çŸããALL-in-One Productããç®æããŠããäžã§ãã¢ãã€ã«Gã®ããã·ã§ã³ã倧ããïŒã€ãããŸãã ã¢ãã€ã«ã¢ããªã®ãã«ãã€ãã£ãå ãããŸã§ãTUNAGã¯Webãã¡ã€ã³ã«éçºãé²ããŠããŠãããã¢ãã€ã«ã¢ããªã¯Webã®æ©èœãåã蟌ãåœ¢ã§æé·ããŠããŸããã å€ãã®æ©èœãWeb Viewã§è¡šçŸãããŠãããã¢ãã€ã«ãã€ãã£ããªUXããã¯é ãååšãšãªã£ãŠããŸã£ãŠããŸãã WebViewãæé€ãããã€ãã£ãå®è£
ã«åãæ¿ããããšã«ãã£ãŠã¢ãã€ã«ã¢ããªã ããããå®çŸå¯èœãªæäœé床ãã¬ã¹ãã³ã¹ã®è¯ããå®çŸã§ãããšèããŠããŸãã ã¢ãã€ã«ãã¡ãŒã¹ããªéçºã¹ã¿ã€ã«ãžã®ã·ãã ã¢ãã€ã«ã¢ããªã®ãã«ãã€ãã£ãåãé²ããããã«ã¯ãã¢ãã€ã«Gã«ãšã©ãŸããããããã¯ãå
šäœã®éçºã¹ã¿ã€ã«ãå€ããŠããå¿
èŠããããŸãã ãã§ã«ã¢ãã€ã«å
è¡ã®æ©èœéçºäœå¶ã«ã·ãããã€ã€ãããWebã§ã¯å®è£
ããã«ã¢ãã€ã«ã§ã®ã¿å®è£
ããæ©èœãéçºãé²ãã§ããŸãã ãã®ããã«ãããã¯ãäŒç»ããã¶ã€ããŒã«ãååããŠããããèšèšãã¶ã€ã³ãã§ãŒãºããã¢ãã€ã«ãšã³ãžãã¢ãã¬ãããªå
¥ã蟌ãã ãããžã§ã¯ãé²è¡ãå®çŸã§ããŠããŸãã æåŸã« ãããã¯ãã«ã³ãããŒåã«åããŠããŸãã«ç¬¬äºåµæ¥æã®ãããªå€é©ãèµ·ããŠããçã£åªäžã§ãã ãšã³ãžãã¢çµç¹ãžã®æè³å§¿å¢ã¯çŽè¿ã®ããã°æçš¿ãããæããŠããã ããã®ã§ã¯ãªãã§ããããã tech.stmn.co.jp tech.stmn.co.jp ããããã®ã¹ã¿ã¡ã³ã¯ããšã³ãžãã¢çµç¹ãžã®ããŸããŸãªæè³ãããã«åŒ·åããŠãããŸãããšã³ãžãã¢ã«ãšã£ãŠäžçªæ¥œãããã§ãŒãºã ãšèªä¿¡ãæã£ãŠãããç°å¢ãæãã€ã€ãããŸãã ã¢ãã€ã«Gãã¯ããããããã¯ãçµç¹å
šäœã®æ¡å€§ã®ãããä»åŸãæ§ã
ãªå€åãèµ·ããŠãããŸãã æ¥ã
ã®æé·ãèªåããšãšããŠæãããããã©ã€ãæã®ãããã®æéãåãç®æšãæã€ä»²éãšããŠæ¥œãã¿ãŸãããã ã¹ã¿ã¡ã³ã§ã¯ã¢ãã€ã«ãã¡ãŒã¹ããªãããã¯ãéçºãäžç·ã«çœåŒããŠããã仲éãåéããŠããŸãã ãiOSDC Japan 2023ãããDroidKaigi 2023ããžã®ã¹ãã³ãµãŒãè¡ã£ãŠããã®ã§ããã²ããŒã¹ã«ç«ã¡å¯ã£ãŠãã ãããšå¬ããã§ãïŒ tech.stmn.co.jp ããèå³ãæã£ãŠããã ãããã以äžã®ãªã³ã¯ãããå¿åãã ããïŒ ã«ãžã¥ã¢ã«é¢è«ããåŸ
ã¡ããŠããŸãïŒ herp.careers
æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã¯ã2023幎9æ1æ¥ãã3æ¥éã«ããããæ©çš²ç°å€§åŠçå·¥åŠéš 西æ©çš²ç°ãã£ã³ãã¹ãšãã³ãã³çæŸéäžã§éå¬ããããiOSDC Japan 2023ãã«ããŽãŒã«ãã¹ãã³ãµãŒãšããŠåè³ããã€ãã³ããçãäžããŸãã iosdc.jp æ¬ãšã³ããªãŒã§ã¯ãç»å£æ
å ±ãããã«ãã£ãåºå±ããŒã¹ã«ã€ããŠã玹ä»ããããŸãã ç»å£æ
å ± ã¹ãã³ãµãŒã»ãã·ã§ã³ã§ã¯ãiOSãšã³ãžãã¢ã®éæšãã VIPERã¢ããªã«SwiftUIãå°å
¥ããããViewå±€ã®è²¬åãããåé¢ã§ãã話 ããšããããŒãã§è©±ããŸãã ç»å£è
ã®ã³ã¡ã³ãïŒ å°å
¥ããããšãã£ãšæã£ãŠããSwiftUIããåŒç€Ÿãããã¯ãã®ç°å¢äžã§ã©ããã£ããå°å
¥ã§ããããæš¡çŽ¢ãæææ±ºå®ããéçšããäŒãããŸããçããã®SwiftUIå°å
¥ã®å±ã¿ã«ãªã話ãã§ããã°ãšæããŸãã®ã§ãæ¯éã»ãã·ã§ã³ã«ãè¶ãäžããïŒ fortee.jp ç»å£è
ïŒéæšïŒ @38Punkd ïŒ æ¥æïŒ2023幎9æ3æ¥ 15:05ãïŒ20åïŒ å ŽæïŒTrack C ã¹ãã³ãµãŒããŒã¹ã®ãçŽ¹ä» ãªãã©ã€ã³äŒå Žã®ã¹ãã³ãµãŒããŒã¹ã¯ãã¹ã¿ã¡ã³ã«ã©ãŒã®ããŒãã«ã¯ãã¹ããããŒã¹ã¯ãªãŒã³ãã®ãŒãæãç®å°ã§ãã äŒå Žå
ã§äŒè©±ã®ãã¿ã«ãªããããªã³ã³ãã³ããçšæããŠããŸãããšã³ãžãã¢ã¡ã³ããŒãããŒã¹ã«ç«ã¡ãŸãã®ã§ãäŒå Žã«æ¥ãããæ¹ã¯ãã²ãç«ã¡å¯ããã ããã ããã«ãã£ã°ããºã®ãçŽ¹ä» ããã«ãã£ä»ããã±ãããã賌å
¥ãããæ¹ã«ã¯ãããã«ãã£ããã¯ã¹ã®äžã«ã¹ã¿ã¡ã³ã®ãªãªãžãã«ãã«ãã¯ãã¹ãåå°ãããŸãã 13ã€ã³ãã®MacBook AirãiPhone13ãšäžŠã¹ããšããã®ãµã€ãºæ ã¹ã¿ã¡ã³éçºçµç¹ã®ããã·ã§ã³ã§ããããããã¯ãã§äºæ¥ã®æé·ãçœåŒããããè±èªã³ããŒã«ãããUnleash your potential, Let product leadãã®ããã¹ãããããã£ããã¶ã€ã³ã§ãã ãæå
ã®iPhoneããã¡ã¬ãã綺éºã«ããã®ã«ãã²ãå©çšãã ããïŒ åºå±ããŒã¹ã§ããªãã©ã€ã³éå®ããã«ãã£ãé
åžããäºå®ã§ããšã³ãžãã¢ãªãè²°ã£ãŠå¬ããã¢ã€ãã ããå°è
¹ã空ããæã«å¬ãããèåãªã©ãæºåããŠããŸãã ãããã« é嬿éäžã¯ã iOSDCããŒã¯ã³ ãã®çšæãããã®ã§ãiOSDCãã£ã¬ã³ãžã«åå ãããæ¹ã¯ãèŠéããªãïŒ iOSDCåå è
ã®çæ§ãšäº€æµã§ããã®ã楜ãã¿ã«ããŠããŸãïŒ3æ¥é楜ãã¿ãŸãããïŒ ã«ã³ãã¡ã¬ã³ã¹æ
å ± åç§° : iOSDC Japan 2023 äž»å¬ : iOSDC Japan 2023 å®è¡å§å¡äŒ ïŒå®è¡å§å¡é· é·è°·å·æºåžïŒ å
±å¬ïŒæ©çš²ç°å€§åŠ çå·¥åŠè¡é¢ã æ©çš²ç°å€§åŠã°ããŒãã«ç§åŠç¥èåç ç©¶æ ååïŒWASEDA-EDGE人æè²æããã°ã©ã ã Beyond 2020 NEXT PROJECT, NEW é嬿¥æ : 2023幎9æ1æ¥(é)ã9æ3æ¥(æ¥) å Žæ : æ©çš²ç°å€§åŠ çå·¥åŠéšè¥¿æ©çš²ç°ãã£ã³ãã¹ + ãã³ãã³çæŸé åå æ¹æ³ã詳现ã«ã€ããŠã¯ã å
¬åŒãµã€ã ãã芧ãã ããã æ¡çšæ
å ± ã¹ã¿ã¡ã³ã§ã¯ãiOSãšã³ãžãã¢ã«éããå
šæè¡é åã§ããããã¯ããæé·ãããŠãããšãã¹ããŒããåéããŠããŸããããèå³ãæã£ãŠããã ããããäžèšãããå¿åãã ããïŒ herp.careers
ããã«ã¡ã¯ãã¹ã¿ã¡ã³CTOã®æŸè°·( @uuushiro ) ã§ãã 7/25ã«ã åç°å人ãã (以äžãt_wadaãã)ããåŒã³ããã 質ãšã¹ããŒã ãã®ç€Ÿå
è¬æŒäŒãéå¬ããŸããïŒ t_wadaããã«ãäŸé Œãããã£ãã ã¹ã¿ã¡ã³ãæäŸããã ãšã³ã²ãŒãžã¡ã³ããã©ãããã©ãŒã TUNAG(ããã°) ãã¯ã¹ã¿ã¡ã³ã®åµæ¥äºæ¥ã§ããµãŒãã¹æäŸããçŽ7幎ãéããŸããããã®çŽ7幎éããããã¯ãæé·ã«æ³šåããŠããäžã§ãå
éšå質ãéçºå¹çãªã©ã«é¢ãã課é¡ãåŸæã«åã£ãŠããŸããã TUNAGãæé·è»éã«ä¹ã£ãŠããä»ãä»åŸããšã³ãžãã¢çµç¹ãã¹ã±ãŒã«ãããªãããç¶ç¶çã«ãããã¯ãã®äŸ¡å€ãçŽ æ©ãäžã®äžã«å±ããŠããããã«ãéçºè
äœéš(DevEx)ã«é¢ããæç¢ºãªæŠç¥ãäžå¯æ¬ ã ãšèããŠããããã®èª²é¡ã«éäžããŠåãçµãããã«ãä»å¹Žã®4æããCTO宀ã«DevEx(Developer eXperience)ããŒã ãç«ã¡äžãã2023幎7æçŸåšã§ã¯3åã®ããŒã ãšããŠæŽ»åããŠããŸãã TUNAGã«ãããRuby 3.0ã¢ããããŒããšéçºçµç¹ã®ä»åŸ ã¯ãããŸããŠã2023幎4æããããã¹ã¿ã¡ã³ã»TUNAGãããã¯ãéçºã«ãžã§ã€ã³ããŸããã@trowems23ã§ãã ã¹ã¿ã¡ã³ã®æè¡çè² åµè§£æ¶æŠç¥ ããã«ã¡ã¯ããªãã¡ã¯ã¿ãªã³ã°å€§å¥œããªããé§åã§ãã2023幎7æããæ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã«ãžã§ã€ã³ããŸããã ãŸããé·ããTUNAGã®éçºå¹çã劚ããŠããããã³ããšã³ãéçºç°å¢ã«ãããŠããä»å¹Žããè
°ãæ®ããŠææ¬çãªãªã¢ãŒããã¯ãã£ãããžã§ã¯ãã«åãçµãã§ããç¶æ³ã§ãã ãã®ããã«ã¹ã¿ã¡ã³ã§ã¯ã2023幎ã®ã¯ããããéçºå¹çãžã®åãåãæ¹ã倧ããå€ãããDevExããŒã ç«ã¡äžãããªã¢ãŒããã¯ãã£ãããžã§ã¯ããçºè¶³ããããšãå
éšå質ãéçºå¹çã«å¯ŸããŠå€§ããªå€åãçãŸããŠããŸãããã ãå
éšå質ãéçºå¹çãžã®åãåãæ¹ã¯ãç¹å®ã®ããŒã ããããžã§ã¯ãã ãã§å€§äºã«ããã䟡å€èгã§ã¯ãªããå
šãšã³ãžãã¢ã®å
±éã®èªèãšããŠããããã§ãã ãããªèãã®äžã§ãåç°å人ããã®ã質ãšã¹ããŒããã®è¬æŒã¯ããã¹ã¿ã¡ã³ã®ãããã倧åã«ããããšã³ãžãã¢ãªã³ã°äŸ¡å€èгã«ãããããŠããŠãçµç¹å
šäœã«ãããå
±éèªèã®æ§ç¯ãå éããŠãããã®ã§ã¯ããšèãããã®åºŠãäŸé ŒãããŠããã ããŸããã è¬æŒåœæ¥ ãšã³ãžãã¢ã ãã§ãªããåŒç€Ÿã®ä»£è¡šãä»ã®è·çš®ã¡ã³ããŒãåå ããå
šç€Ÿã§ãããã¯ãéå¶ã«ãããçè§£ãæ·±ããããšãã§ããŸããã å
·äœçãªè¬æŒã®å
容ã«ã€ããŠã¯ã以äžã®å
¬éãããŠããè³æãåèã«ããŠãã ããã speakerdeck.com ã»ãã·ã§ã³ãéããŠãå
éšå質ãšã¹ããŒãã¯ãã¬ãŒããªãã§ã¯ãªããå質ãé«ãããããã¹ããŒããäžããããšããããšãæ¹ããŠåŒ·ãæèããããšãã§ããŸãããããœãããŠã§ã¢ã®å
éšå質ã«ã€ããŠããå
·äœçãªåè³ªç¹æ§(ãã¹ãå®¹ææ§ãçè§£å®¹ææ§ã倿Žå®¹ææ§)ã§è¡šçŸããããšã§ãä»åŸã®å
éšå質ã«é¢ããè°è«ã®è³ªãäžããããã ãšæããŸããã ãŸãå
éšå質ãžã®æè³ã®æçåå²ç¹ã¯æå€ãšæ©ã(1ã¶æä»¥å
)ãã£ãŠãããšã®èšèãèããŠãçŸåšDevEx(Developer eXperience)ããŒã ãäžå¿ãšããŠå
éšå質ãžã®æè³ãè¡ã£ãŠããæŽ»åããæã£ããããè¿ãæªæ¥ã§å¹æãèŠããŠãããããšæåŸ
ã倧ãããªããŸãããæçåå²ç¹ãè¶
ããããšããæã
ãã©ã宿ããããšãã§ããã®ãã«ã€ããŠã¯ãèªçµç¹ã®äžã§å®éã«ãããã確ãããŠãããããšæããŸãã åå è
ã®ææ³ è¬æŒåŸã«ã¢ã³ã±ãŒãããšã£ãã®ã§ããããšãŠã奜è©ã§ããã以äžã«åå è
ã®ææ³ã®äžéšãåŒçšããŸãã ãªãã¡ã¯ã¿ããã¹ã倧äºã ããã£ãŠã®ã¯ããã£ãŠãŸããããªã倧äºãªã®ãã®èæ¯ãè£å®ãããŠèªåã®æææ±ºå®åºæºãå€ãã£ãããã«æããŸããã å
éšå質ã«åãå
¥ããããšã«ãã£ãŠåŸãããæ©æµãåçã§ããã®ã¯1ã¶æä»¥å
ãšãã話ããä»åŸãã¹ãããã£ããæžããŠããããšãžã®ã¢ãããŒã·ã§ã³ã«ãªããšèããã æéãèšãèš³ã«ããŠè³ªãèœãšããŠãããã®ã§ã¯ïŒãšããå
žåäŸã«ãªã£ãŠããã®ã§ããã®æèãå€ãããã®ãäžçªå€§ããã£ãã§ãã å
éšå質ãç ç²ã«ãããããçç±ãã質ãé«ãããããéãããšãçè§£ã§ãå匷ã«ãªããŸãããå
éšå質ãæéã«æç®ããŠèª¬æãããªã©bizãµã€ããšã®ã³ãã¥ãã±ãŒã·ã§ã³ã«ã掻ããããã ãšæããŸããã è¯ããšã³ãžãã¢ã¯è³ªãã¹ããŒããäž¡ç«ããŠãã ã¹ã©ã€ãã¯èªãã ããšãã£ãã®ã§ãããææ°ããŒãžã§ã³ã§å£é ã§ã®æ
å ±è£å®ããã£ãŠçè§£ãäžå±€æ·±ãŸããŸãããèªåã®èãæ¹ã«ã倧ããªåœ±é¿ããã£ãããã«æããŠããŸããä»åã®å
¬æŒèªäœãæè³ã ãšæãã®ã§ã¡ãããšå¹æãåºãããã«æ¥åã«åæ ããããšæããŸãã å質ãšã¹ããŒãã«ã€ããŠã®èªåã®æççãªç¥èããäœç³»çã«åŠã¹ãŸãããããããšãããããŸããïŒ ãã¬ãŒããªãã¹ã©ã€ããŒã¯å
ã
ã¹ã³ãŒãããåãããªããšã¯ç¥ã£ãŠãŸããããããããïŒã€ãããªãããšã«æ°ä»ããããŸãã ä»ãŸã§å質ãšã¹ããŒãã®ãã©ã³ã¹ãã©ãããŠãããããæ©ã¿ãã€ã³ãã§ãããã2ã€ã¯ãã¬ãŒããªãé¢ä¿ã«ç¡ããšããè©±ã§æ©ãå¿
èŠã®ç¡ãããšã ã£ããšããããšç¢ºèªã§ããã®ã§ã1ã¶æåŸã®èªåã«æ©æµãè¿ã£ãŠããããã«å
éšå質ãä»åŸãããæèããŠãããããšæã£ãã åç°å人ããæé«ã®è¬æŒãããããšãããããŸããïŒåç°ããã®èŠèãåãå
¥ããŠåãã¡ã¯ä»ããããã£ãšããŸããã£ãŠããããã§ãïŒ æã®çŸå ŽãæãåºããŠãä»ã®ç°å¢ã¯ãšãŠãè¯ãç°å¢ïŒæè¡åããç解床ãã人ããããžãã¹ãïŒã ãšæ¹ããŠæããŸããã èªåã®éçºãé²ããŠããäžã§ééã£ãŠãããæ©ãã§ããèãæ¹ãæŠãééã£ãŠããªãããšãæŠãåãããããšãã§ããšãŠãè¯ãæ©äŒã§ãããããããšãããããŸããïŒ ãã£ã±ã第äžè
èŠç¹èšã£ãŠãããããšã§ãã€ã¢ã¹ããã£ãŠçŽåŸãã人ã¯ããã®ã§ãããããè¬æŒãããã®ã¯ãããããã§ãããªã¢ã«ã«ã³ã¡ã³ããé£ã³äº€ãã®ãè¯ãã£ãã§ãã è¬æŒã¯2æéè¿ãã§ããããæåããæåŸãŸã§Slackãã£ã³ãã«ã¯å€§çããããã§ãåŠã³ã«ãªãã ãã§ãªãéåžžã«æ¥œããæéã«ãªããŸããããããŠãªã«ãããä»åã®ã質ãšã¹ããŒããã®è¬æŒã¯ãæã
ã¹ã¿ã¡ã³ã«ããããå
éšå質ã«å¯Ÿããå
±éèªèãã®æ§ç¯ãå éããŠããããšæããŠããŸããt_wadaããããããšãããããŸããïŒ æåŸã« ã¹ã¿ã¡ã³ã§ã¯ããœãããŠã§ã¢ã®å
éšå質ã«åãåããªãããããã¯ããæé·ãããŠãããšãã¹ããŒããåéããŠããŸãã ããèå³ãæã£ãŠããã ããããäžèšããå¿åãã ããïŒ herp.careers herp.careers
ããã¯ãªã«ïŒ ããã«ã¡ã¯ããªãã¡ã¯ã¿ãªã³ã°å€§å¥œã㪠ããé§å ã§ãã2023幎7æãã æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ ã«ãžã§ã€ã³ããŸããã ã³ãã¥ãã±ãŒã·ã§ã³ã«ã¯äŒè°äœãããã¹ãããŒã¹ãªã©æ§ã
ãªææ®µããããŸãã ãã®äžã§éè«ããªãéèŠã§ãããã«ã€ããŠãç§ã®èããèšãããã®ã§ãã 倧äºãªåæããç®çãšææ®µã®é¢ä¿ã 人ã
ã®æŽ»åã«ã¯ ç®ç ããããŸãããããŠç®çãæºããããã® ææ®µ ãè¿œãæ±ããŠããŸãïŒããã§ããææ®µãšã¯ã·ã¹ãã ã§ãã£ããæ
å ±ã§ãã£ããããç®çã®åœ¹ã«ç«ã€ãã®ããšèããŠãã ããïŒã ç®çãšææ®µã®é¢ä¿æ§ã次ã®å³ã§è¡šçŸããŸããç®çãšææ®µããããã®åã®éãªãã倧ããã»ã©ãç®çã«å¯ŸããŠçžå¿ããææ®µã§ããããšããããšãããã§ã¯è¡šããŸãã ãã®å³ã䜿ã£ãäŸãåºããŸãã ä»ã®ææãã ãã ãæããªã£ãŠããŸãããããæããè§£æ¶ãããããšããç®çã«å¯ŸããŠããæé¢šæ©ãç¹ãããããšã¢ã³ã³ãç¹ããããããæ°·ãé£ã¹ããã忥µã«éã蟌ãããªã©ã®ææ®µãèããããŸãã ããïŒ äžå³ã§ã¯ãæããè§£æ¶ãããããšããç®çã«å¯ŸããŠãããæ°·ããšããææ®µã¯ããŸãéãªã£ãŠããŸãããã©ããçžå¿ãããªãææ®µã®ããã§ããæããšæããŠãã人ã«è©³ããäºæ
ãå°ããŠã¿ããšãæè¿å·ãããã®ãé£ã¹éãã¡ãã£ãŠãããè
¹ã®èª¿åãè¯ããªããã ããé£ã¹ç©ä»¥å€ã§æ¶Œãããã®ãããã°ãªãããšããåçã§ããã ãã®äººã«ãšã£ãŠã¯ãèè
žã«è² æ
ããããã«æããè§£æ¶ããããã çã®ç®ç ã ã£ãã®ã§ãããã®ç®çã«æ²¿ããããšã¢ã³ã³ãæäŸãããšãããç®çãæºããããŸããã ãã®é¢ä¿æ§ã¯ãœãããŠã§ã¢éçºãåãã§ãã äŸãã°åŒç€Ÿã¹ã¿ã¡ã³ã®äž»èŠãµãŒãã¹ TUNAG ïŒããã°ïŒã¯ãäŒæ¥ã®ãšã³ã²ãŒãžã¡ã³ãã®æ§ç¯ãã€ãŸããäºããç¥ã£ãŠçè§£ããä¿¡é Œãåãçµç¹ãäœãããã®ç€Ÿå
ã³ãã¥ãã±ãŒã·ã§ã³ã掻æ§åããããããã¯ãã§ããã ãšã³ã²ãŒãžã¡ã³ããåäžããã ãç®çãæºããææ®µãšããŠãããã¯ããéçºããŠããŸãããããã®åã®éãªãã倧ãããªãããæ©èœéçºãæ©èœæ¹åãå³ãããŠããŸãã ãããŸã§ãåæã§ãã ããããå
ãæ¬é¡ã§ãã äŒè°äœã ãšéèŠãªæ
å ±ãåŸã«ãã ç§ã®çæ¥ã¯ãœãããŠã§ã¢èšèšã§ãããä»äºæãæ£ç¢ºãªèšèšã«ã¯é¡§å®¢èª²é¡ãé¡§å®¢èŠæ±ãªã©ãããžãã¹é¢ã®æ§ã
ãªæ
å ±ãå¿
èŠãšããŸãããã®ãããPdMã®ã»ãããžãã¹ãµã€ãã®çãããžã®çžè«ãã€ã³ã¿ãã¥ãŒãå¿
èŠãšããŸãã ãããããäœããã®é倧ãªå€æã«å¿
èŠãªæ
å ±ãåéããæŽ»åãã¯ãå¥ã«ç§ã«éããçããæ®æ®µããåœããåã®ããã«å®æœãããŠãããšæããŸãã ãããç§ã®çµéšäžã äŒè°äœã§ã® çžè«ãã€ã³ã¿ãã¥ãŒã§ãæ¬åœã«ã»ããéèŠãªæ
å ±ããåŸãããçµéšãããŸããããŸããã ããã§ã¯ãªãã éè«ã§ãµãšããæåã«ããããšåºãŠããã»ãªãã«éå€§ãªæ
å ±ãå«ãŸããŠããçµéšãå§åçã«å€ãã§ã ãããã¯ãªãã§ãããã æå³ããéèŠãªæ
å ±ãåãèœãšãããŠããŸã äŒè°ã«ã¯å¿
ãç®æšãèšå®ããŸãããâ¯â¯ã«ã€ããŠæææ±ºå®ããããâ¯â¯ã«ã€ããŠèªèãåãããããªã©ã§ãã ããã§ã¯ãç®çAã«é¢ããŠæææ±ºå®ããããäŒè°ã®ç®æšãšããŸããããŠããã®ãšãäœãèµ·ããã§ããããã äŒè°ã®ç®æšãå¹ççã«éæã§ãããããäŒè°ã®åå è
ã¯ãç®çAã«æ²¿ã£ãæºåãããŸãããŸããç®çAã«åã£ãäŒè©±ã亀ããããŸããã€ãŸãã æ§ã
ãªæ
å ±ã®å
ãç®çAã«æ²¿ã£ããã®ã ãã話é¡ã«äžããããã以å€ã®æ
å ±ã¯åãèœãšãããŸãã äžèŠå¹ççã§æ£ããã¢ãããŒãã®ããã«æããŸãããšãããããã§ã¯ãããŸããã é¡§å®¢ãæ¬åœã«å¿
èŠã ã£ããã® æåãªãé¡§å®¢ãæ¬åœã«å¿
èŠã ã£ããã®ãã®å³ïŒ Tree Swing Cartoon Pictures (early versions) ããåŒçšïŒã ãã®å³ã«æ¶æãããããã«ãé¡§å®¢ã®æ¬åœã®èŠæ±ãäœã§ããã®ãããããã¯ãéçºã«ãããŠåžžã«èãæ©ãŸãããã®ã§ãããã®ããæã
ã¯ä»®èª¬æ€èšŒãABãã¹ããªã©ã宿œã㊠顧客ã®çã®ç®ç ãæ¢ãã«è¡ããŸãã ãããŠçã®ç®çãæ¬åœã¯ç®çBãªã®ã«ãé¢ããããåœã®ç®çAãçã®ç®çã ãšåéãããŠããããšãåŸã
ã«ããŠãããŸãïŒãããã顧客ã®çã®ç®çãã¯ããããåãã£ãŠããã誰ãèŠåŽããªãïŒã åœã®ç®çAãããŒãã«æ®ããŠäŒè°ãé²ããå Žåãç®çAã«é¢ããæ
å ±ã¯è©±é¡ã«äžãããŸãããçã®ç®çBã«é¢ãã話é¡ã¯åãèœãšãããŠããŸããŸãã äŒè°ã®å¹çåãä»ã«ãªã£ãŠãæ¬åœã«å¿
èŠãªãã®ãæã«å
¥ããªãããŸãã¯å
¥ãã«ãããªã£ãŠããŸãã®ã§ãã éè«ã§ã¯ãæ
å ±ã®æªããåãèœãšãããçãã«ãã äžæ¹ã§éè«ã¯ç¹å®ã®ç®çããããŸããããã®ãããããŸããŸãªæ
å ±ã話é¡ã«äžããããããªããŸããäŒè°äœã§é¥ããã¡ãªãæå³ããªãæ
å ±ã®åãèœãšãããçãã«ãããªããŸãã ãã®ãããªç¹æ§ãããããã 話è
ã«ãšã£ãŠéèŠã ãšã¯èªèããŠããªããå®ã¯éèŠãªæ
å ± ããããããšè©±é¡ã«äžãããå€æç²ŸåºŠã®åçãªåäžã«è²¢ç®ããããšã«ãªãã®ã§ãã ããã㫠以äžè§£èª¬ããŸããããã«ãåŒç€Ÿã¹ã¿ã¡ã³ã§ã¯éè«ã®å¹èœãéèŠèŠããŠããŸãããããŠãµãŒãã¹ã®æ¹å驿°ã質ã®åäžã«åœ¹ç«ãŠãŠããŸãã åŒç€Ÿã¹ã¿ã¡ã³ã¯TUNAGãäžå¿ã«å³è©äžããã®æé·ãç¶ããŠããŸãã ãããŠãã®æé·ãããã«ä¿é²ãããããã«ãµãŒãã¹ã®èšèšæŠç¥ãçå®ããæšé²ããŠããèšç»ã§ãïŒ è©³ããæŠç¥ã¯ãã¡ãã ãã¹ã¿ã¡ã³ã®æè¡çè² åµè§£æ¶æŠç¥ã ïŒã 2023幎12ææã第1ååææ±ºç®èª¬æè³æ ãã ãã®å¢ãã§åŒç€Ÿã¹ã¿ã¡ã³ã¯ãããªãäºæ¥æ¡å€§ãç®æããæ¡çšæŽ»åãããæŽ»æ§åããŠãããŸããçŸåšåŸæ¥å¡æ°ã¯çŽ80åãä»ã®èŠæš¡ã®2åã3åã5åãšã¹ã±ãŒã«ãããŠãããŸãã ãšã³ãžãã¢çµ¶è³åéäžã§ããç§ãšäžç·ã«åããŠã¿ãããèå³ãããæ¹ã¯ããã²äžèšã«ã¢ã¯ã»ã¹ããŠã¿ãŠãã ããã herp.careers
1. ããã¯ãªã« ããã«ã¡ã¯ããªãã¡ã¯ã¿ãªã³ã°å€§å¥œã㪠ããé§å ã§ãã2023幎7æãã æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ ã«ãžã§ã€ã³ããŸããã ãã®èšäºã¯ãä»åŸã¹ã¿ã¡ã³ã«ãããŠãµãŒãã¹ã®æè¡çè² åµãè§£æ¶ããèšèšæŠç¥ã«ã€ããŠãŸãšãããã®ã§ãã 2. èæ¯ãèª²é¡ æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã¯2016å¹Žåµæ¥ãäž»èŠãµãŒãã¹ã§ãã TUNAG ïŒããã°ïŒã¯ãäŒæ¥ã®ãšã³ã²ãŒãžã¡ã³ãã®æ§ç¯ãã€ãŸããäºããç¥ã£ãŠçè§£ããä¿¡é Œãåãçµç¹ãäœãããã®ç€Ÿå
ã³ãã¥ãã±ãŒã·ã§ã³ã掻æ§åããããããã¯ãã§ããTUNAGã®ããã¯ãšã³ãã¯Ruby on Railsã§éçºãããããŒã³ããã7幎ããããã€ã€ãããŸãã ãããŸã§TUNAGã¯ããããã¯ããããã«äŒžã°ããã«æ³šåããŠããäžæ¹ãå
éšå質ãéçºå¹çãªã©ãéçºè
äœéšãã«é¢ãã課é¡ãåŸæã«åã£ãŠããŸãããæ¬æ¥ãããã¯ãããŒã ã¯ãŠãŒã¶ãŒã«ãšã£ãŠã®æ¬è³ªçãªäŸ¡å€ã«ã®ã¿ãã©ãŒã«ã¹ã§ããç¶æ³ãçæ³ã§ãããéçºè
äœéšãæªããšè¯ããŠãŒã¶ãŒäœéšãæäŸããããšãã§ããªããªã£ãŠãããŸãã éçºè
äœéšãæªåããã倧ããªèŠå ã®ã²ãšã€ãæè¡çè² åµã§ããå
·äœçã«ã¯ 倿Žå®¹ææ§ ã®äœäžã§ãã倿Žå®¹ææ§ãšã¯ããªãã¹ããã°ãåã蟌ãŸããçŽ æ©ãæ£ç¢ºã«ã³ãŒã倿Žã§ãã床åãã§ãã倿Žå®¹ææ§ãäœããšéçºçç£æ§ãäœäžããŠããŸããŸãã 3. èšèšæŠç¥è§£èª¬ ãµãŒãã¹ã®å€æŽå®¹ææ§ãåäžããéçºçç£æ§ã®ç¶ç¶çåäžãæããããã以äžã®å³ã«ç€ºãèšèšæšé²æŽ»åãç§äž»å°ã®ããšãããã宿œããŠãããŸãã %%{ init: { 'theme': 'base', 'themeVariables': { 'background': '#000000' } } }%% graph TD A[éçºçç£æ§ã®<br>ç¶ç¶çåäž] --- B[倿Žå®¹ææ§ã®<br>ç¶ç¶çåäž] B --- ãªãã¡ã¯ã¿ãªã³ã° B --- C[倿Žå®¹ææ§<br>èšèšã¹ãã«ã®åäž] ãªãã¡ã¯ã¿ãªã³ã° --- D[è²»çšå¯Ÿå¹æã®<br>é«ãç®æ] D --- ã³ã¢ãã¡ã€ã³ D --- H[è² åµã¬ãã«ã®é«ãç®æ] ã³ã¢ãã¡ã€ã³ --- äžé·æäºæ¥èšç» ã³ã¢ãã¡ã€ã³ --- E[æèè
ãžã®<br>ã€ã³ã¿ãã¥ãŒ] ã³ã¢ãã¡ã€ã³ --- ã³ã³ããã¹ããããäœæ H --- K[ããŒã«ã«ãã<br>è² åµèšæž¬] H --- G[倿Žå€±æçã®<br>é«ãç®æ] H --- I[倿Žã®èŠããç®æ] ã³ã³ããã¹ããããäœæ --- F[ãã¡ã€ã³ãšãã¹ããŒããžã®<br>ã€ã³ã¿ãã¥ãŒ] ã³ã³ããã¹ããããäœæ --- ãœãŒã¹ã³ãŒãè§£æ F --- ç®ç F --- ç»å ŽæŠå¿µ F --- ã¢ã¯ã¿ãŒ F --- ããã»ã¹ãµã€ã¯ã« C --- èšèšã¬ã€ãã©ã€ã³ C --- ãã³ãºãªã³ååŒ·äŒ èšèšã¬ã€ãã©ã€ã³ --- ããŒã¿ã¢ãã« èšèšã¬ã€ãã©ã€ã³ --- ã¢ãŒããã¯ã㣠ããªãå€å²ã«ããããã説æãé·ããªããŸããããã²æåŸãŸã§ãèªã¿ããã ããã°ãšæããŸãã 倿Žå®¹ææ§ã®åäžã«ã¯å€§ãã2è»žã®æŽ»åããããŸããæ¢åã®æè¡çè² åµãè§£æ¶ãããªãã¡ã¯ã¿ãªã³ã°ãšãä»åŸã®æ°ããªè² åµãææ¢ããããã®å€æŽå®¹ææ§èšèšã¹ãã«ã®åäžæŽ»åããããŸãã 3.1 ãªãã¡ã¯ã¿ãªã³ã° ãªãã¡ã¯ã¿ãªã³ã°ãšã¯ãå€éšããèŠãæåãå€ããã«ãããã°ã©ã æ§é ãæŽçããããšã§ãã倿Žå®¹ææ§ã®é«ãæ§é ã«æŽçããããšããªãã¡ã¯ã¿ãªã³ã°ã®ãŽãŒã«ã§ãããã®ããã倿Žå®¹ææ§ã®é«ãããã¹ãæ§é ãèšèšããããèšèšã®ããã«ãã¡ã€ã³ãåæããããšãå€å²ã«ãããããŸããŸãªæŽ»åãå¿
èŠã§ãã 3.1.1 è²»çšå¯Ÿå¹æã®é«ãç®æã®ç¹å® ãªãã¡ã¯ã¿ãªã³ã°ã¯ãã 宿œããã°ãããšããããã§ã¯ãããŸãããäŸãã°ç²æªãªã³ãŒãã§ãã£ãŠããä»åŸã»ãšãã©ä»æ§å€æŽã®èŠèŸŒã¿ããªãç®æãäžçæžåœãªãã¡ã¯ã¿ãªã³ã°ããŠæå³ããããã®ã§ããããïŒãªãã¡ã¯ã¿ãªã³ã°ã¯å°æ¥ã®å€æŽã³ã¹ããäœæžããæŽ»åã§ããåŸã£ãŠãå°æ¥ããŸã倿Žãããªãç®æããªãã¡ã¯ã¿ãªã³ã°ããŠãã³ã¹ãããããã ãã§åœ¹ã«ç«ã¡ãŸãããéçºãªãœãŒã¹ã¯æéãªã®ã§ãéããããªãœãŒã¹ã®äžã§ãªãã¡ã¯ã¿ãªã³ã°ã®è²»çšå¯Ÿå¹æã®é«ãç®æãçãå¿
èŠããããŸãã è²»çšå¯Ÿå¹æã®é«ãç®æã®ç¹å®ã«ã¯ãäž»ã«ä»¥äž2ã€ãè€åçã«èæ
®ããŠå€æããŸãã ã³ã¢ãã¡ã€ã³ è² åµã¬ãã«ã®é«ãç®æ 3.1.1.1 ã³ã¢ãã¡ã€ã³ ã©ããªååããµãŒãã¹ã«ãããããããŠãªã ïŒããšåŒã¹ããããªäžå¿ç䟡å€ããããŸããäžå¿ç䟡å€ãçºæ®ããäºæ¥é åãããã¡ã€ã³é§åèšèšã§ã¯ ã³ã¢ãã¡ã€ã³ ãšåŒã³ãŸããã³ã¢ãã¡ã€ã³ã¯å·®å¥åãå³ãããäŒæ¥ã®ç«¶äºåªäœæ§ãçºæ®ããé åã§ãããµãçãªé åãããæè³åªå
床ãé«ãã§ããåœç¶èšèšã³ã¹ããåæ§ã§ããç«¶äºåªäœæ§ãããé«ããããã«æè¡çè² åµãè§£æ¶ããéçºçç£æ§ãé«ããããšãèèŠã§ãã ãã ãããµãŒãã¹ã倧ãããªããšäœãäžå¿ç䟡å€ãªã®ãã ãã ãåãããªããªã£ãŠãããŸãããŸããæä»£ã«ãã£ãŠäººã
ã®é¢å¿äºã¯ç§»ãå€ãã£ãŠãããŸããç¹ã«ã³ããçŠååŸã§ãã©ã¹ãã£ãã¯ã«äžã®äžã®äŸ¡å€èгãå€åããã®ã¯çããã®èšæ¶ã«æ°ãããšããã ãšæããŸããäœãäžå¿ç䟡å€ãªã®ããèŠå®ããå¿
èŠããããŸãããã®ããã«ã¯ä»¥äžã®èª¿æ»ãåæãå¿
èŠã«ãªããŸãã äžé·æäºæ¥èšç» æèè
ãžã®ã€ã³ã¿ãã¥ãŒ ã³ã³ããã¹ããããäœæ 3.1.1.1.1 äžé·æäºæ¥èšç» äžé·æäºæ¥èšç»ãšã¯ãäžé·æçãªçµå¶ããžã§ã³ãå®çŸããããã«äºæ¥ãšããŠããã¹ãããšãèšç»ãããã®ã§ããäžé·æçã«ã©ã®ããã«äºæ¥äŸ¡å€ã䌞é·ããŠããã®ããé²ãã¹ãæ¹åæ§ãå®çŸ©ãããŸãããããŠãœãããŠã§ã¢ã®å€æŽå®¹ææ§ã¯ãäžé·æã«ããã£ãŠéçºçç£æ§ã«åœ±é¿ãåãŒããŸããã³ã¢ãã¡ã€ã³ãèŠå®ããããããŸã倿Žå®¹ææ§èšèšã®æè³äŸ¡å€ãèŠå®ããããã«ãäžé·æäºæ¥èšç»ã®inputã¯éèŠã§ãã 3.1.1.1.2 æèè
ãžã®ã€ã³ã¿ãã¥ãŒ äžé·æäºæ¥èšç»ã ãã§ãªããæèè
ããçã®å£°ãèãããšã倧äºã§ãããããã¯ããããŒãžã£ãŒã®ä»ãçµå¶ã¬ãã«ã«è¿ãã¡ã³ããŒã«å¯Ÿããã³ã¢ãã¡ã€ã³ã«çžåœããäºæ¥é åãäœã§ããã®ãã€ã³ã¿ãã¥ãŒããŸãã 3.1.1.1.3 ã³ã³ããã¹ããããäœæ ãœãããŠã§ã¢ãµãŒãã¹ã«ã¯ãäžå¿çååšãšãªãã¢ãã«ãå¿
ããšãã£ãŠããã»ã©ç»å ŽããŸããäŸãã°ECãµã€ãã«ãããååã¢ãã«ã§ãããã®ãããªã¢ãã«ã¯ããŸããŸãªç¶æ³ãããŸããŸãªãŠãŒã¹ã±ãŒã¹ã§çšããããŸããããããå
šãŠã®ç¶æ³ã«å¯Ÿå¿å¯èœãªãäžæå²©ã®äžèœã¢ãã«ãšããŠäœãäžããããšãããšãããžãã¯ãæ··ä¹±ããã倿Žãå°é£ã«ãªããªã©å€ãã®åŒå®³ãæããŸãïŒä»¥äžã¯åè·æå±æã®ã€ãã³ãç»å£åç»ãšè³æïŒã www.youtube.com speakerdeck.com ããã§ äžèœã¢ãã«ãšã¯ç°ãªãèšèšã¢ãããŒã ãå¿
èŠã§ããèæ¯ãç¶æ³ãç®çã倧ããç°ãªãäºæ¥ãã¡ã€ã³ã®åäœã§ãµãŒãã¹ããµãã·ã¹ãã ã«åè§£ããåãµãã·ã¹ãã ã« ç¹åããã¢ãã« ãšããŠèšèšããããšã®éèŠæ§ããã¡ã€ã³é§åèšèšã§ã¯èª¬ããŠããŸããç¶æ³å¥ã®åç¹ååã¢ãã«ãããããé©çšå¯èœãªç¯å²ããå¢çã¥ããããã³ã³ããã¹ãããšåŒã³ãŸãã ãã®ããã«ããŠã³ã³ããã¹ãããšã«åè§£ãããµãã·ã¹ãã ã®å
ãã³ã¢ãã¡ã€ã³ã«å¯Ÿå¿ãããµãã·ã¹ãã ãç¹å®ããã³ã¢ã«ã³ã¢ä»¥å€ã®ããžãã¯ã浞最ããªãããæç¢ºã«åºåä»ããããšã®éèŠæ§ããã¡ã€ã³é§åèšèšã§ã¯èª¬ããŠããŸãããããŸã§ãã£ãŠåããŠãªãã¡ã¯ã¿ãªã³ã°ã®ãéžæãšéäžãã宿œå¯èœãªãè²»çšå¯Ÿå¹æã®é«ãç®æã®ç¹å®ãå¯èœã«ãªããŸãã ã³ã³ããã¹ãå¢çãã©ãã«ããã®ãã¯ããŸããŸãªèгç¹ã§ã®åæãå¿
èŠã§ããäŸãã°ä»¥äžã§ãã ãã¡ã€ã³åæ ãœãŒã¹ã³ãŒãè§£æ 3.1.1.1.3.1 ãã¡ã€ã³åæ ã³ã³ããã¹ãããšã«ã©ããªéããããã®ã芳ç¹ã¯ããŸããŸã§ãããäŸãã°ä»¥äžã®ãããªç¹ã§éãããããšç§ã¯èããŸãã ç®ç ã¢ã¯ã¿ãŒ ç»å ŽæŠå¿µ ããã»ã¹ãµã€ã¯ã« ã³ã³ããã¹ãã®éã ãã®å³ã¯ECãµã€ããäŸã«ããã³ã³ããã¹ãã®å·®ç°ã説æããå³ã§ãã ãŸãã倧ããªç²åºŠã§ç®çãç°ãªããŸããã³ã³ããã¹ãããŸãããããªå·šå€§ãªäžæå²©ã¢ãã«ã¯ãå€ç®çã«äœ¿ãããŠããŸãã®ã§åäžè²¬ä»»ååéåãšèããããšãã§ããŸããã³ã³ããã¹ãç¹ååã¢ãã«ã®èšèšã¯ãåäžç®çã«å¯Ÿå¿ã§ããããã«èšèšããããšã§ããã€ãŸããç®çã倧ããç°ãªãå¢çãã³ã³ããã¹ãå¢çãšèããããšãã§ããŸãã ãŸããç®çãç°ãªããšãã¢ã¯ã¿ãŒãç»å ŽæŠå¿µã倧å¹
ã«éã£ãŠããŸããäŸãã°ã åšåº«ç®¡ç ã¢ã¯ã¿ãŒ : åºåè
ç»å ŽæŠå¿µ : å
¥åº«ãåºåº«ãå®å
šåšåº«é é
é ã¢ã¯ã¿ãŒ : é
鿥è
ç»å ŽæŠå¿µ : é
éå
ãé
éå
ãé
éç¶æ³ãé
éæ ãã®ããã«åšèŸºæŠå¿µãæŽçããããšãã³ã³ããã¹ãå¢çã®çºèŠã«ã€ãªãããŸãã ãŸããã³ã³ããã¹ãããšã«ããã»ã¹ãµã€ã¯ã«ãç°ãªããŸããåšåº«ç®¡çã§ã¯åºåè
ãå
¥åºåº«ã®ãµã€ã¯ã«ãåããŸããäžæ¹ã§é
éã§ã¯é
鿥è
ãæ¢±å
ããé
éå
ãŸã§é
éãããµã€ã¯ã«ãåããŸãããäºãã®ãµã€ã¯ã«ã¯äº€ããããšããããŸããã ãã®ãããªéããæ¢ãããããã¡ã€ã³ãšãã¹ããŒããžã®ã€ã³ã¿ãã¥ãŒãã€ãã³ãã¹ããŒãã³ã°ãªã©ã§ãã¡ã€ã³åæããŸãã 3.1.1.1.3.2 ãœãŒã¹ã³ãŒãè§£æ ã³ã³ããã¹ãã®éãã¯åœç¶ãœãŒã¹ã³ãŒãã«ãçŸããŸãã ããã¯ããçšåºŠç®åŠãã€ããŠèª¿æ»ããããšãå¯èœã§ããäŸãã°ã以äžã®ãããªã¢ãã«ã¯è€æ°ã®ã³ã³ããã¹ãã«ãŸããã£ãŠããããšããšãŠãå€ãã§ãã 巚倧ãªã¢ãã« ãµãŒãã¹ã®ã¯ãŒã¯ãããŒã®å§ãããçµãããŸã§ãããããªã¢ãã« ãã®ãããªã¢ãã«ã¯ãç¶æ
ã«ãã£ãŠä»¥äžã倧ããç°ãªãç¹åŸŽããããŸãã æŽæ°å¯Ÿè±¡ã®ããŒã¿ æ¯ãèã ãããã®å·®ç°ãã³ã³ããã¹ãå¢çã®æããããšãªããŸãã 3.1.1.2 è² åµã¬ãã«ã®é«ãç®æ ãªãã¡ã¯ã¿ãªã³ã°åªå
床ã®é«ãã®ã¯ã³ã¢ãã¡ã€ã³ã®ããžãã¯ã§ããããã®äžã§ãè² åµã¬ãã«ã®é«ãç®æãããåªå
床ãé«ãŸããŸããè² åµã¬ãã«ã®é«ãç®æã®å²ãåºãã«ã¯ãäŸãã°ä»¥äžã宿œããŸãã ããŒã«ã«ããè² åµèšæž¬ 倿Žå€±æçã®é«ãç®æã®ç¹å® 倿Žã®èŠããç®æã®ç¹å® 3.1.1.2.1 ããŒã«ã«ããè² åµèšæž¬ æè¡çè² åµã®åæã¯ããŒã«ã«ããèšæž¬å¯èœã§ããåŒç€Ÿã§ã¯ Code Climate Quality ãå©çšããŠãããŸããCode Climate Qualityã¯GitHubãšé£æºããè² åµããã¡ã€ã«ã®æŽæ°é »åºŠãèªåã§ã¹ã³ã¢ãªã³ã°ããŠãããŸããæè¡çè² åµãšå€æŽå®¹ææ§ã¯æªæ¥ã®å€æŽã³ã¹ãã«åœ±é¿ããŸããããè² åµã¬ãã«ãšæŽæ°é »åºŠã®åæ¹ãé«ããã®ã»ã©ãªãã¡ã¯ã¿ãªã³ã°ã®å¹æãé«ããšèããããŸãã 3.1.1.2.2 倿Žå€±æçã®é«ãç®æã®ç¹å® æ¬çªãããã€åŸã«ä¿®åŸ©ãèŠããã³ãŒãã®å²åã倿Žå€±æçãšãããŸãã倿Žå€±æçãèšæž¬ãã倱æã«é¢äžãããœãŒã¹ã³ãŒããå²ãåºããŸãã 3.1.1.2.3 倿Žã®èŠããç®æã®ç¹å® ãšã³ãžãã¢ã«ãšã£ãŠå€æŽã®èŠããç®æãç¹å®ããŸããã©ã®ãããã®ã³ãŒããåä»ãªã®ãããã€ã倿Žã«èŠæ
®ããŠããã®ããã¢ã³ã±ãŒããªã©ã§èãåºããŸãã 3.2 倿Žå®¹ææ§èšèšã¹ãã«ã®åäž è² åµã®å¢å ãææ¢ããã«ã¯ããšã³ãžãã¢ã®èšèšã¹ãã«åäžã倧äºã§ãã ã¬ã€ãã©ã€ã³ãªã©ããã¥ã¡ã³ããæããããå匷äŒãéå¬ãããªã©ãã³å
¥ããèŠããŸãã 3.2.1 èšèšã¬ã€ãã©ã€ã³ èšèšã«ã¯ãŽãŒã«ãå¿
èŠã§ãããŽãŒã«æ¹éãšãªãèšèšã¬ã€ãã©ã€ã³ãçå®ããŸãããŽãŒã«ãæ®ããããšã§ããã®ã®ã£ãããšããŠæè¡çè² åµãèªç¥ã§ããããã«ãªããŸãã å°ãªããšã以äž2ç¹ã®ã¬ã€ãã©ã€ã³ããŸãçšæããŸãã ããŒã¿ã¢ãã«èšèš ã¢ãŒããã¯ãã£èšèš 3.2.1.1 ããŒã¿ã¢ãã«èšèš DBã®ããŒãã«æ§é ãè² åµåããªããããããŒã¿ã¢ãã«ã®èšè𿹿³ãåããŸãšããŠããå¿
èŠããããŸããRailsã®å ŽåãããŒãã«ãš1:1ã«ãªãActiveRecordãããŸããŸãªã¬ã€ã€ãšå¯çµåã«ãªãããããããŒãã«æ§é ãå
šäœã«ãã€ã¬ã¯ãã«åœ±é¿ãåãŒããããç¹ã«èšèšã«æ³šæãæãå¿
èŠããããŸãã èšèšã«ã¯TMïŒTå圢ERææ³ïŒãçšããŸãã ã€ãã¥ãŒã¿ãã«ããŒã¿ã¢ãã«(å
¥éç·š) from Yoshitaka Kawashima www.slideshare.net 3.2.1.2 ã¢ãŒããã¯ãã£èšèš ã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£å
šäœã®åèšèšãå¿
èŠã§ãã Railsã¯MVCãã¬ãŒã ã¯ãŒã¯ã§ãããæ®éã¯Rails-wayãšåŒã°ãããäœæ³ã«åã£ãŠéçºãé²ããããŸãããããRailsã¯ãã¹ã¿ãŒãã¢ããæã®å éåãåŸãããçµå床ãç ç²ãããç ç²çã¢ãŒããã¯ãã£ããšåŒã°ããŠããŸãããã®ããéçºãé²ã¿æ°å¹Žããããšã¢ãã«ãè€æ°ã®æå³ãæã¡å§ããããææ°ã®ãã¡ã€ã³çè§£ã«å¯ŸããŠããŒãã«æ§é ãé³è
åããŠä¹é¢ãæ¿ãããªã£ããããŸããRails-wayã§ã¯è² åµã®è§£æ¶ãææ¢ãå°é£ã«ãªã£ãŠãããŸãã ãã®è§£æ±ºã®ãããã¢ãžã¥ã©ãŒã¢ããªã¹åããããšãç®æšã«ã以äžã®ãããªDDDããŒã¹ã®ã¢ãŒããã¯ãã£ãžã®ç§»è¡ãæ€èšããŠããŸãããã®ã¢ãŒããã¯ãã£ã®æå³ãæ¹éãå責åã®åœ¹å²ãèšè𿹿³ããšã³ãžãã¢ã«èª¬æãããããã¢ãŒããã¯ãã£èšèšã®ã¬ã€ãã©ã€ã³ãçå®ããŸãã %%{ init: { 'theme': 'base', 'themeVariables': { 'background': '#000000', 'primaryTextColor': '#6360DC' } } }%% classDiagram namespace Views { class View } namespace Models { class ActiveRecord } namespace Controllers { class Controller } namespace UseCases { class UseCase class QueryService { <<interface>> } class Dto } namespace Infras { class RepositoryImpl class QueryServiceImpl } namespace Domains { class Repository { <<interface>> } class Aggregate class Entity class ValueObject } ActiveRecord <.. RepositoryImpl ActiveRecord <.. QueryServiceImpl View ..> Controller Controller ..> UseCase Controller ..> QueryService UseCase ..> Aggregate UseCase ..> Repository Repository ..> Aggregate Aggregate --> Entity Aggregate --> ValueObject Entity --> ValueObject RepositoryImpl ..|> Repository QueryServiceImpl ..|> QueryService QueryService ..> Dto (â»1ïŒå
šäœã«å¯ŸããŠé©çšããã®ã§ã¯ãªããã³ã¢ãã¡ã€ã³ãªã©è² åµã«å¯ŸããŠç¹ã«æ³šæãæãå¿
èŠãããç®æã«ã€ããŠDDDããŒã¹ã«ç§»è¡ããŸããè² åµãæ°ã«ãªããªãç®æãèšèšã³ã¹ããããæšå³ãããŸããªãç®æã¯Rails-wayã§ãããŸãã) (â»2ïŒRubyã§ã¯interfaceã¯å¿ã®äžã«ãããªãã®ã§ãäžå³ã«ãããRepositoryãQueryServiceã®interfaceã¯å®éã«ã¯ååšããŸãããç¶æ³ã«ãã£ãŠã¯ããŒã«ãŒinterfaceã®ä»£çšãšããŠmoduleãå®è£
ããå ŽåããããŸãã) 3.2.2 ãã³ãºãªã³ååŒ·äŒ èšèšã¹ãã«ã®å€§å¹
ãªåäžã«ã¯ããªããšãã£ãŠãå®éã«æãåãããã³ãºãªã³å匷äŒãæ¬ ãããŸããã ããã°ã©ãã³ã°ã¯ãã ããã°ã©ãã³ã°å
¥éæžãèªãã ã ãã§ã¯ãå®åã«äœ¿ããããã°ã©ãã³ã°ã¹ãã«ã¯èº«ã«ã€ããŸããã仿§ãæºããããžãã¯æ§é ãèããŠå®è£
ããçµéšãå¿
èŠã§ããèšèšã¹ãã«ãåæ§ã§æ¬ãèªãã°èº«ã«ã€ããã®ã§ã¯ãªããæ³¥èãæ··ä¹±ããããžãã¯ãã©ã®ããã«æŽçããã°å€æŽã容æãªæ§é ã«ãªãããèªåã®é ã§èããŠèšèšããçµéšãå¿
èŠã§ãã å匷äŒã§ã¯ãããã¯ã·ã§ã³ã³ãŒãã䜿ã£ãŠãªãã¡ã¯ã¿ãªã³ã°ã®ç·Žç¿ãããŸããæ³¥èãããžãã¯ã»ã©èšèšã®æšå³ãããããã§ããäŸãã°æè ãè¯ãã³ãŒãïŒæªãã³ãŒãã§åŠã¶èšèšå
¥éã gihyo.jp ã«èšèŒã®èšèšãã¿ãŒã³ãåŠã¶å Žåããã®ãã¿ãŒã³ãé©çšã§ããããªããžãã¯ããããã¯ã·ã§ã³ã³ãŒãããæ¢ããŸããæ®æ®µãšã³ãžãã¢ãè§Šãæ
£ããŠããç®æãæãŸããã§ãã該åœããããžãã¯ãèŠã€ãã£ãããæåãåãã§å€æŽå®¹ææ§ã®é«ãæ§é ãèšèšããã³ãŒããå®è£
ããŸããããããã®ææãã¿ããªã®åã§çºè¡šããã©ããªå·¥å€«ãããããªã©ã«ã€ããŠè°è«ã質çå¿çãããã£ãŒãããã¯ãåŸãŸãã ç§ã¯æ°ç€Ÿã§ãã®ååŒ·æ¹æ³ã宿œããçµæãã©ãã§ãèšèšã¹ãã«ã®åäžãæãããŸããã广ã«åçŸæ§ããããšèªè² ããŸãããªã¹ã¹ã¡ã§ãã 4. ããã㫠以äžèª¬æããæŠç¥ã®ããšã倿Žå®¹ææ§ãåäžãéçºçç£æ§ãç¶ç¶çã«é«ããã¹ãéé²ããŠãããŸãã åŒç€Ÿã¹ã¿ã¡ã³ã¯TUNAGãäžå¿ã«å³è©äžããã®æé·ãç¶ããŠããŸãããã®æé·ãããé«ãããããç§ã«èª²ãããã責åã¯éåžžã«éèŠãªãã®ã«ãªã£ãŠãããŸãã 2023幎12ææã第1ååææ±ºç®èª¬æè³æ ãã ãã®å¢ãã§åŒç€Ÿã¹ã¿ã¡ã³ã¯ãããªãäºæ¥æ¡å€§ãç®æããæ¡çšæŽ»åãããæŽ»æ§åããŠãããŸããçŸåšåŸæ¥å¡æ°ã¯çŽ80åãä»ã®èŠæš¡ã®2åã3åã5åãšã¹ã±ãŒã«ãããŠãããŸãã ãšã³ãžãã¢çµ¶è³åéäžã§ããç§ãšäžç·ã«åããŠã¿ãããèå³ãããæ¹ã¯ããã²äžèšã«ã¢ã¯ã»ã¹ããŠã¿ãŠãã ããã herp.careers
ããã«ã¡ã¯ãæ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã§ TUNAG ã®iOSã¢ããªãšã³ãžãã¢ãããŠããéæš ( @38Punkd )ã§ãã äœæ°ã«ä»åã®èšäºããã® Tech Blog ãžã®åæçš¿ã§ãã¯ã¯ã¯ã¯ããŠããŸãã TUNAGã®iOSã¢ããªã¯ããããŸã§ãªã¢ã¯ãã£ãããã°ã©ãã³ã°ã®ææ³ãšããŠã RxSwift ãå°å
¥ããŠããŸããã ãããŠä»å¹ŽåºŠãããã¢ããªããµããŒãããOSããŒãžã§ã³ã®äžéã13.0ã«åŒãäžãããããAppleå
¬åŒã®éåæãã¬ãŒã ã¯ãŒã¯ Combine ã䜿ããããã«ãªããŸããã ã¢ããªã«å¯ŸããŠãµãŒãããŒãã£è£œã®ã©ã€ãã©ãªã§ããRxSwiftãžã®äŸå床ãäžãããã£ãããšãšãçŽç²ã«æ°ããæè¡ã詊ããŠã¿ãããšãã奜å¥å¿ãçžãŸã£ãŠãã¢ããªã«Combineãå°å
¥ããããšã詊ã¿ãŸããã å®éã«Combineãå°å
¥ããŠã¿ãææ³ãšãå°å
¥ããéã®æ³šæç¹ããäŒãã§ããã°æããŸãã SingleããFutureãžã®ç§»è¡ éä¿¡ã¯å€§å¥ãããšãçµæã®åãåããç¶ç¶ããŠç£èŠããå¿
èŠã®ãããã®ãšãçµæã®åãåããäžåããã§è¯ããã®ã®2çš®é¡ããããŸããã ä»åã¯ãCombineã®äžã§ãäžåããã®éåæåŠçãç£èŠãã Future åã䜿ã£ãŠãäžåããã®APIéä¿¡ã®çµæãååŸããå®è£
ãããŸããã ãããŸã§ã¯ãäžåããã®APIéä¿¡éšåã¯ãRxSwiftã®SingleãçšããŠä»¥äžã®ãããªã³ãŒããæžããŠããŸããã çµæãçºè¡ããåŽ SingleãçšããŠãéåæåŠçã®çµæãéç¥ã§ãããªããžã§ã¯ããè¿ãã¡ãœãããçšæããŸãã // ããŒã¿ã¬ã€ã€ãŒïŒAPIãšéä¿¡ãããïŒ class Repository { func fetchTaskList () -> Single <[ TaskEntity ]> { Single < [TaskEntity] > .create(subscribe : { observer in APIClient.request { response in observer(.success(`TaskEntityå`))) } return Disposables.create() }) } } çµæãåãåãåŽ äžèšã®Singleããsubscribeã¡ãœãããçšããŠè³Œèªããçµæãéåæã«åãåããããã«ããŸãã // ãã¡ã€ã³ã¬ã€ã€ãŒïŒããžãã¹ããžãã¯ãæ±ãïŒ class Interactor { func requestTaskList () { Repository().fetchTaskList() .subscribe( onSuccess : { taskList in // APIéä¿¡ã®çµæååŸãã taskList ãåºåããŸã } onFailure : { error in // errorãåºåããŸã }) .disposed(by : disposeBag ) } let disposeBag = DisposeBag() } ããããCombineã®FutureåãçšããŠä»¥äžã®ããã«æžããŸããã çµæãçºè¡ããåŽ FutureãçšããŠãéåæåŠçã®çµæãéç¥ã§ãããªããžã§ã¯ããè¿ãã¡ãœãããçšæããŸãã // ããŒã¿ã¬ã€ã€ãŒïŒAPIãšéä¿¡ãããïŒ class Repository { func fetchTaskList () -> Future <[ TaskEntity ], Error > { Future < [TaskEntity], Error > { [unowned self ] promise in APIClient.request .sink { completion in switch completion in case .failure( let error ) : promise (.failure(error)) case .finished : () } receiveValue : { response in promise(.success(`TaskEntityå`)) } .store( in : & cancellables) } } var cancellables = Set < AnyCancellables > () } çµæãåãåãåŽ äžèšã®Futureããsinkã¡ãœãããçšããŠè³Œèªããçµæãéåæã«åãåããããã«ããŸãã // ãã¡ã€ã³ã¬ã€ã€ãŒïŒããžãã¹ããžãã¯ãæ±ãïŒ class Interactor { func requestTaskList () { Repository().fetchTaskList() .sink { completion in switch completion in case .failure( let error ) : // errorãåºåããŸã case .finished : () } receiveValue : { taskList in // APIéä¿¡ã®çµæååŸãã taskList ãåºåããŸã } .store( in : & cancellables) } var cancellables = Set < AnyCancellables > () } Futureã¯ãéåæã®çµæãå€ã衚ãããã®åã§ãããRxSwiftã§ãã Single ãšåã圹å²ãæ
ããŸãã sink ã¡ãœããã¯ãç£èŠå¯èœãªã€ãã³ããå®éã«ç£èŠããããã®ã¡ãœããã§ãã ã€ãã³ãã®ç£èŠç¶æ³ã¯ãsinkã¡ãœããã®ãã¬ã€ãªã³ã°ã¯ããŒãžã£ã«å
¥ã£ãŠããå€(äžèšã®ã³ãŒãã§ã¯ completion ãšãã倿°åã§è¡šããŠããŸã)ãã確èªã§ããŸãã ãã®å€æ°ã¯ã failure ãš finished ã®äºã€ã®ã±ãŒã¹ãæã€enumåã§ãã ç£èŠäžã«ã€ãã³ããçºçïŒ=ãã®å Žåãã¿ã¹ã¯äžèЧã®ååŸãå®äºããïŒãããšãã¯ããŒãžã£åã®åŒæ° receiveValue ã«å€ãå
¥ã£ãŠããŸãã æåŸã« store ã¡ãœããã«ãã£ãŠãsinkã¡ãœããã® AnyCancellable åã®æ»ãå€ãcancellablesããããã£ã«ä¿åããŸãã ããããäºã§ãFutureåãã€ã³ã¹ã¿ã³ã¹çæããåŸããã€ãã³ããç£èŠã§ããä»çµã¿ãåºæ¥äžãããŸããã Combineã䜿ãäžã§æ°ãä»ããã¹ããã€ã³ãã¯2ã€ãããŸããã sink ã¡ãœããã®æ»ãå€AnyCancellableã¯ä¿æããå¿
èŠããã Future ã¯ã€ã³ã¹ã¿ã³ã¹çæçŽåŸã«ç£èŠãéå§ãã ãããã®ãã€ã³ãã«ã€ããŠã詳现ã«è§£èª¬ããŠãããŸãã sink ã¡ãœããã®æ»ãå€AnyCancellableã¯ä¿æããå¿
èŠããã sinkã¡ãœããã¯AnyCancellableãè¿åŽå€ãšããŠè¿ããŸãã func sink (receiveValue : @escaping (( Self.Output ) -> [ Void ]( https://developer.apple.com/documentation/Swift/Void )) ) -> [ AnyCancellable ] (https : //developer.apple.com/documentation/combine/anycancellable) AnyCancellableã¯ãéåæåŠçã®äžæã衚ãããã«äœ¿çšãããåã§ãã éåæåŠçãå®äºããåŸãç£èŠãç¶ããå ŽåãAnyCancellableã®ã€ã³ã¹ã¿ã³ã¹ãä¿æããå¿
èŠãªãšãã«äžæããããšãã§ããŸãã ããããAnyCancellableåã®æ»ãå€ãããããã£ãšããŠä¿åããã«æšãŠãŠããŸããšããã®ã€ã³ã¹ã¿ã³ã¹ã¯åç
§ããããããã«è§£æŸãããŠããŸããŸãã ãã®çµæãç£èŠãäžæãããŸãã AnyCancellableã®éåæãäžæããæ¹æ³ã¯ä»¥äžã®2ãã¿ãŒã³ããããŸãã AnyCancellableã®ã€ã³ã¹ã¿ã³ã¹ãç Žæ£ãããã AnyCancellableã«å¯ŸããŠã cancel ã¡ãœãããåŒã³åºãã AnyCancellableã®ã€ã³ã¹ã¿ã³ã¹ãç Žæ£ãããå Žåã«ãAnyCancellableã®éåæãäžæãããã®ã¯ãç Žæ£ãããã¿ã€ãã³ã°ã§AnyCancellableèªèº«ãcancelã¡ãœãããåŒã³åºã仿§ã«ãªã£ãŠããããã§ãã ãªã®ã§ãAnyCancellableã€ã³ã¹ã¿ã³ã¹ã«å¯ŸããŠstoreã¡ãœãããå®è¡ããŠãããããã£ãšããŠä¿åããªãå ŽåãAnyCancellableã€ã³ã¹ã¿ã³ã¹ã¯è§£æŸãããç£èŠãçµäºããŠããŸããŸãã class Interactor { // à // requestTaskListã¡ãœããã®ã¹ã³ãŒããæãããšã // sinkã¡ãœããã®æ»ãå€ã¯ããã«è§£æŸãããŠããŸããè¯ããªãäŸã§ãã func requestTaskList () { _ = Repository().fetchTaskList().sink { ... } } } (ããŸã) storeã¡ãœãããåŒã°ãªãå Žåã¯ã以äžã®ããã«ãæžããŸãã class Interactor { func requestTaskList () { cancellable = Repository().fetchTaskList().sink { ... } } var cancellable : AnyCancellables? } ãªããã®AnyCancellablesåã®ããããã£ã¯ãä¿æããŠããã¯ã©ã¹ãç Žæ£ããããšããã¡ããåæã«ç Žæ£ãããŸãããåæã«ç£èŠãçµäºããŸãã ãªã®ã§ãæç€ºçã«ç£èŠã®äžæåŠçãããã€ãã·ã£ã©ã€ã¶ã®äžã«æžãå¿
èŠã¯ãããŸããã class Repository { // Repositoryã®ã€ã³ã¹ã¿ã³ã¹ãç Žæ£ãããããcancellableãç Žæ£ãããã®ã§ã // ãã®deinitã¡ãœããã¯äžèŠã§ãã deinit { cancellable.cancel() } ... var cancellable : AnyCancellables? } Future ã¯ã€ã³ã¹ã¿ã³ã¹çæçŽåŸã«ç£èŠãéå§ãã RxSwiftã®Singleã¯ãsubscribeã¡ãœãããå®è¡ãããŸã§ãç£èŠãéå§ããŸããããã®æ§è³ªã¯ Cold Observable ãšåŒã°ããŸãã ããããFutureã¯ã€ã³ã¹ã¿ã³ã¹çæãããçŽåŸã«ç£èŠãéå§ããŸãããã®æ§è³ªã¯ Hot Observable ãšåŒã°ããŸãã SingleãšéããFutureã¯Hotã§ããããšãæèããªããšã以äžã®ããã«æå³ããªãã¿ã€ãã³ã°ã§åŠçãèµ°ã£ãŠããŸããŸãã class Repository { let taskList : Future <[ TaskEntity ], Error > = Future < [TaskEntity], Error > { in cancellable = APIClient.request.sink { ... } } var cancellable : AnyCancellables? } class Interactor { ... } äžèšã®ã³ãŒãã§ã¯ã Repository ãã€ã³ã¹ã¿ã³ã¹çæãããç¬éã«ãtaskListãååŸããAPIéä¿¡ãèµ°ã£ãŠããŸããŸãã Futureåã䜿ãéã¯ãæå³ããªãã¡ã¢ãªæ¶è²»ãé¿ããããã«ãã¹ãã¢ãããããã£ãšããŠå®çŸ©ããã®ã§ã¯ãªããã¡ãœããã®æ»ãå€ãèšç®ããããã£ãšããŠãããã®ãè¯ãããã§ãã // âªïž // fetchTaskListã¡ãœãããåŒã³åºããŠãåããŠFutureå
éšãå®è¡ãããŸãã func fetchTaskList () -> Future <[ TaskEntity ], Error > { ... } // âªïž // fetchTaskListããããã£ãåç
§ããŠåããŠãåããŠFutureå
éšãå®è¡ãããŸãã var fetchTaskList : Future <[ TaskEntity ], Error > { ... } // â³ // fetchTaskListãä¿æããã¯ã©ã¹ãã€ã³ã¹ã¿ã³ã¹çæãããç¬éã«ãFutureå
éšãå®è¡ãããŠããŸããŸãã // æå³ããªãæåã«ã€ãªããæãå®è£
ã§ãã var fetchTaskList = Future < [TaskEntity], Error > { ... } Combineã«è§ŠããŠã¿ãŠ å®éã«Combineã®æ©èœã®äžéšãå°å
¥ããŠã¿ãçµæãæžãæ¹ã¯RxSwiftãšéåžžã«äŒŒãŠããŠããã€åŠçã®æµããããäžå±€çŽæçãªã³ãŒãã«ãªã£ããšæããŸããã ãããã¯ãä¿å®æ§ã®èгç¹ããããã¢ããªã®æ¡çšæè¡ãAppleå
¬åŒã®ãã¬ãŒã ã¯ãŒã¯ã«åŸã
ã«å¯ããŠãããããšæã£ãŠããŸããããããæ©ã«ãCombineã®å°å
¥ãããæšé²ã§ããã°ãšæããŸããã åŒç€Ÿã§ã¯ããã®ããã«ããŠæ°æè¡ãç©æ¥µçã«å°å
¥æ€èšããããè¯ããããã¯ããè¿œãæ±ããŠéçºãããŠããŸãã 人ãšçµç¹ã匷ããã HR Tech SaaSãããã¯ããäœããªãããæè¡ã§ã¯ã¯ã¯ã¯ããããœãããŠã§ã¢ãšã³ãžãã¢ããå
šæè¡é åã§åéããŠããŸãã ãåŸæã®æè¡é åãåããããã²ã«ãžã¥ã¢ã«ã«ã話ãããŸãããïŒ herp.careers
ã¢ãŒããã¯ãã£å³ïŒå®äºåŸïŒ ããã«ã¡ã¯ãåœç€Ÿã ã¹ãã³ãµãŒåå ããRubyKaigi 2023 ãçµãã£ãŠ1ã¶æä»¥äžçµã¡ã6æã¯æµ·å€ã«ã³ãã¡ã¬ã³ã¹ãå€ãå¿ããæ¥ã
ãéãããŠããŸãã æè¿ã¯ãŸãTUNAGå
šè¬ãããã£ãŠããŸãã TUNAGã®ã¡ã€ã³ã¢ããªïŒRuby on RailsããŒã¹ïŒã¯ 4æã«Ruby 3.0ãžã®ã¢ããã°ã¬ãŒããã ã®ã¡ã5æååã«ã¯Ruby 3.1ãžã®ã¢ããã°ã¬ãŒããå®äºããŠããŸããïŒããã°èšäºãªãïŒãå·çæç¹ã§ã¯ãRuby 3.2ãžã®ã¢ããã°ã¬ãŒãã¯é²è¡äžãšã®åã§ãã 2019幎6æéå¬ã® åå€å±RubyäŒè°04 ã§ãã玹ä»ããéããã³ã³ããåºç€ã§åãRubyããŒã¹ãµãŒãã¹ãšã¯å¥ã«ãAWS Lambdaäžã§åãããŠããããã¯ãšã³ããµãŒãã¹ããããŸãããããã®ãµãŒãã¹ã§ã¯ãAWS Lambdaå
¬åŒæäŸruntimeã®éœåäžããããææ°çã§ãããAWSç¬èªã®ãµããŒãã«ããruby2.7 (ã³ãã¥ããã£ããåºãŠããRuby 2.7) ãå©çšããŠããŸãããïŒæ³šïŒäžéšAWS Lambda ruby2.5 runtimeãåããŠããŸãããããã¡ãã2023幎5æãŸã§ã«AWS Lambda ruby2.7 runtimeãžã®ç§»è¡ãå®äºããŠããŸããïŒ åœç€Ÿã®ãããã¯ãã§ã®AWS Lambdaã®å©çšç¶æ³ã«ã€ããŠã¯ä»¥äžãã芧ãã ãããïŒèšè¿°ã¯å·çåœæã®ãã®ã§ãããæ¢ã«ãªã¢ãŒããã¯ãã£ã³ã°ããããªã©ã«ãããä»ã®ã¢ãŒããã¯ãã£ã§çœ®ãæããããå¯èœæ§ããããŸãïŒ tech.stmn.co.jp æã
ã®ããŒã ãæè¡æ€èšããæç¹ã§ã¯ãAWS Lambda ruby2.7 runtimeã®ãµããŒãææ¥ã¯ãå°ãªããšã2023幎7æä»¥éã§ãããšçè§£ãããããæ¥ãã§Custom runtimeãå©çšããåºç€ãžã®ç§»è¡ãèŠéãããšã決å®ããŠããŸããã ã¢ãŒããã¯ãã£å³ïŒåœåïŒ ïŒæ³šïŒ Ruby 3.2ããŒã¹ã®runtimeãGAå
¬éãããŠãã6ã¶æãšå®ããããŠããããšããã®ãåœæèšè¿°ãããŠãããšæãã®ã§ãããçŸåšã®å
¬åŒããã¥ã¡ã³ãããã¯åé€ãããŠããããã§ããŸããå±¥æŽãšããŠãæè¿ deprecated æ±ããšãããŠããŸã£ã awsdocs ã調æ»ããŸããããèŠã€ããããããšãã§ããŸããã§ãããå®å
šã«èè¶³ã§ãããä»åã®èª¿æ»ã®éçšã§ãå°ã£ãã https://aws.amazon.com/blogs/aws/retiring-the-aws-documentation-on-github/ ã®å
¬åŒã®å ±åïŒRetiring the AWS Documentation on GitHub, on 17 MAY 2023, by Jeff BarrïŒã«ãããéããAWS DocumentationãGitHubäžã§ç®¡çã§ããªããªã£ãã®ã¯æ®å¿µãªéãã§ããïŒ ãããªäžãRuby 3.2 runtime now available in AWS Lambda by James Beswick | on 07 JUN 2023ãšããæå ±ãå
é±å
¥ã£ãŠããŸããã aws.amazon.com ãããçºããæç¹ã§ã¯ã远å ã®runtimeç§»è¡ã¿ã¹ã¯ã2023幎11ææ«ïŒããè©³çŽ°ãªæ¥ä»ãšããŠã¯12æ7æ¥ã§ããïŒãŸã§ã«ç©ãã§ããã°ããããããã®æž©åºŠæã§æå
ã®ä»äºã«æ»ã£ãŠããŸããã æ¬¡ã®é±ã«ãªã£ãŠãRubyKaigi 2023é¢é£ã®æèã§1ã€ã®ãã€ãŒãã瀟å
ãã£ããã«äžèšã®èšäºããªãã€ãŒããããŠããããšã«ãããæ¥éœruby3.2 runtimeç§»è¡ãæšé²ããããšã«ãªããŸãããAWS Serverless Application Model (SAM) ãå©çšããŠãããã®ã®ãå
æ¬çãªDevOpsãäžååã§ãã£ãããšããããäžæéãããªããŠã¯ãªããŸããã§ãããã2.xãã3.xãšã¡ãžã£ãŒããŒãžã§ã³ã¢ããã§ãã£ãã«ãããããã忥ãšãããããproductionãªãªãŒã¹ã«æŒãçããããšãã§ããŸããã LambdaïŒManagement ConsoleïŒ å¹æ Ruby 3.1, 3.2ãããã®æ³šç®ãã€ã³ããšããŠã¯Yet Another Ruby JITã§ããYJITãå°å
¥ãããproduction-readyã§ããããšãæããããŸããããããããã©ã«ãã§ã¯ç¡å¹ã§ãããããä»åã¯YJITãæå¹ã«ããªã圢ã§ãã¢ããããŒããªãªãŒã¹ã®ã¿ãåªå
ããŸããã ç§»è¡ããLambda Functionã¯å€éšAPIãšã®æ¥ç¶ãæãå ããå²åãå€ãã®ã§ããããããå«ãŸããªãInvocationã®DurationïŒLambdaãã©ãããã©ãŒã ã§èšæž¬ããæäŸãããå€ïŒã§ã¯10-20%ã®é«éåã芳枬ã§ããŸãããããã ãã®é«éåã¯ã³ãã¥ããã£ãªãªãŒã¹ã®Ruby 2.7 MRIâRuby 3.2 MRI (YJITãªã)ã®ã¿ã§çµéšããããšããªã次å
ã§ãããLambdaã§æŽ»çšããŠããComputeåºç€ã§å©çšããŠããCPUã¢ãŒããã¯ãã£ãææ°çã«ãªã£ãã®ãLambdaå
éšã®äœããã®æ¹åãå¯äžããŠããã®ã§ã¯ãªãããšæããŸããããŠãŒã¶ãŒäœéšãã³ã¹ãé¢çã«ã¯ãããªã£ãŠããã®ã§ããã§ããããšããæ°æã¡ã§ãããã以äžãã©ãããã©ãŒã å
éšã«è©³ãããªã£ãŠããããããªãã§ããã 10-20%ã®é«éåãå®çŸããLambda Functionã§ã¯ãæ£èŠè¡šçŸãå²ãšå€çšãããŠãããRuby 3.2ã§ã®åæ©èœã®æ¹åã«ãããã®ãããããŸããã ãŸãšã Ruby 3.2.0ããªãªãŒã¹ãããŠããçŽå幎ããæç¹ã§AWS Lambda ruby3.2 runtimeããªãªãŒã¹ãããTUNAGãããã¯ãã®äžéšã§å©çšããŠããLambda functionã§ãruby2.7âruby3.2 runtimeã®å·æ°ã宿œããŸãããç¹ã«åé¡ãèµ·ããããšãªããé床é¢ãã³ã¹ãé¢ã§è¥å¹²ã®æ¹åãèŠãããŸããã TUNAGãžã®YJITã®æ¬æ Œå°å
¥ãæ®ãã®ååã»ã©ã®ruby2.7 runtimeã®ruby3.2 runtimeå®å
šç§»è¡ãã¡ã€ã³Railsã¢ããªã±ãŒã·ã§ã³ã®Ruby 3.2ç§»è¡ãRuby 3.3ç§»è¡æºåãªã©ãããããããšãããããããã®ã§ããããšã³ãžãã¢ãå
šãè¶³ããŠããŸããã æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã¯RubyKaigi 2023ãŽãŒã«ãã¹ãã³ãµãŒã§ããRubyã䜿ã䜿ããªãã«éããã人ãšçµç¹ã匷ããã HR Tech SaaSãããã¯ããäœããªããæè¡ã§ã¯ã¯ã¯ã¯ããããœãããŠã§ã¢ãšã³ãžãã¢ãå
šæè¡é åã§åéããŠããŸãããåŸæã®æè¡é åãåãããã²ã«ãžã¥ã¢ã«ã«ã話ãããŸãããïŒ herp.careers ã¯ã¬ãžãã/ããŸã ç»åã®äžéšã«ã¯AWS Architecture Icons (Release 16-2023.04.28)ãå©çšãããŠããŸãã aws.amazon.com awsdocs/aws-lambda-developer-guide@192b0ef7 ã® doc_source/lambda-runtimes.md : github.com ãªãã仿¥ã®æã飯ã¯ã·ã³ã¬ããŒã«ããã³ã©ã€ã¹ã§ããããåçã¯ãããŸããã
ã¯ãããŸããŠãstmnã§åããŠãã@natsuokawaiãš@starmiya_miyukiã§ãã stmnã¯RubyKaigi 2023ã«ãŽãŒã«ãã¹ãã³ãµãŒãšããŠåè³ãããŠããã ããã®ã§ããšã³ãžãã¢2人ã§RubyKaigi 2023ã«ãªãã©ã€ã³ã§åå ããŠããŸããïŒ ã¹ãã³ãµãŒããŒã¹ã®æ§å ã©ã®ã»ãã·ã§ã³ãè峿·±ãã£ãã®ã§ãããæ¬ã¬ããŒãã§ã¯ç¹ã«ç€Ÿå
ã§ã話é¡ã«äžããããšã®å€ãåé¢ä¿ã®5ã€ã®ã»ãã·ã§ã³ã«ã€ããŠãŸãšããŠã¿ãŸãã Day1 Generating RBIs for dynamic mixins with Sorbet and Tapioca rubykaigi.org Slide: https://drive.google.com/file/d/1W4bmAePVOSbUVe-JUzVcGMbro1HBcWhO/view tapiocaã¯Rubyã®ãœãŒã¹ã³ãŒããèªã¿èŸŒã¿ãã¯ã©ã¹ãã¢ãžã¥ãŒã«å
ã§å®çŸ©ããã宿°ãã¡ãœããå®çŸ©ã®æ
å ±ãå
ã«åå®çŸ©ãã¡ã€ã«ãçæããgemã§ãã åºæ¬çã«ã¯ããŸãåäœããŠããããdynamic mixinsïŒã¯ã©ã¹ãã¢ãžã¥ãŒã«å®çŸ©ã®å€ã§åŒã°ãã prependãinclude ãextendïŒãããã³ãŒãã«é¢ããŠã¯ãéçãªè§£æã ãã§ã¯æ£ããåæ
å ±ãçæã§ããªããšããåé¡ããããŸããã ããã§tapiocaã§ã¯ããœãŒã¹ã³ãŒãã®ããŒãæã«å®éã«mixinãå®è¡ããæ©æ§ïŒããèªäœãdynamic mixinã§ããïŒãåããããšã«ãããmixinããã宿°ãmixinã®çš®é¡ãªã©ã®æ
å ±ãååŸã§ããããã«ãªããŸããã ã³ã¡ã³ã ã¡ã¿ããã°ã©ãã³ã°ã䜿ãããŠããã³ãŒãã®åæ
å ±ã®çæãé£ãããšãã話ã¯è²ããªãšããã§ç®ã«ãã話é¡ã§ãããããã«å¯ŸããŠåããã¡ã¿ããã°ã©ãã³ã°ã䜿ã£ãŠæ
å ±ãåçã«ååŸãããšããã®ã¯RubyããããŠé¢çœãã¢ãããŒãã ãªãšæããŸããã RBS meets LLMs - Type inference using LLM slides.com LLM(gpt-3.5-turbo)ã«å®è£
ã³ãŒãããåå®çŸ©ïŒRBSïŒãçæããŠãããããšããã話ã .nameã.buildãšããèªç¶èšèªãããã£ããname: Stringã®ãããªæšè«ãããããšã«æåããŠããŸããã äžæ¹ã§ãããŸã«RBSæ§æãããããã£ãããäžèŠãªåºåãæ··ãã£ãŠããããRBSãã¯ã©ã¹ããšã«åå²ãããŠããªãã£ãããšèª²é¡ããã£ãã®ã§ãããæçµçã«ã¯FewShotã§æš¡ç¯ãšãªãOutput Formatãå
¥åããŠããæšè«ãããããšã«ããããããã®èª²é¡ã解決ããŠããŸããã ã³ã¡ã³ã åŒç€Ÿã§ããã§ã«å®è£
ã³ãŒãããSpecã®çæã«LLMã«åãåãããè¡ã£ãŠãããšã³ãžãã¢ã¯ããã®ã§ãRBSã®çæã¿ã¹ã¯ã¯LLMãšçžæ§ãè¯ãããã ãšæããŸããã ãŸããæç€ºçã«å宣èšãããªãæ
床ãåãRubyã«ãããŠãèªåã§åæšè«ããŠãããLLMçã®çµã¿èŸŒã¿ã¯ããªãå°æ¥æ§ãããã®ã§ã¯ãªãããšæããŸãã Day2 Revisiting TypeProf - IDE support as a primary feature rubykaigi.org TypeProfã¯éçåå®çŸ©ã®ãªãã¡ãœããããªããžã§ã¯ãã®åãæšè«ããããŒã«ã§ãã ãã§ã«Rubyã«å梱ãããŠã¯ããŸãããçŸç¶ããŸã䜿ãããŠããªãããã§ãããã®åå ãšããŠããŠãŒã¶ãŒã®ããŒãºãšTypeProf v1ãåæãšããŠããããšãåã¿åã£ãŠããªãã£ãããšãæããããŸãã å
·äœçã«ã¯ãv1ã§ã¯ããã©ãŒãã³ã¹ãéèŠããŠãããããµããŒãããã³ãŒããå®å
šãªã³ãŒãã®ã¿ã察象ãšããŠããã®ã§ãããå®éã®ãŠãŒã¶ãŒã®ããŒãºã¯IDEäžã§ã®DXåäžãªã®ã§ãããã¯ãããããã¹ãã§æºããã¹ãèŠä»¶ã§ããããšãåãããŸããã ããã§ãåæãæ¹ããv2ãRuby3.3ããªãªãŒã¹ãããã§ããã2023幎æ«ãç®æããŠãªãªãŒã¹ããããšããããšã§ããã TypeProf: https://github.com/ruby/typeprof ã³ã¡ã³ã TypeProfã®ãã¢ã§ã¯IDE(VSCode)äžã§ã¡ãœããã®åãè£å®ãããŠããæ§åã確èªã§ããŸãããTypeProfã¯æç€ºçã«å宣èšããªãRubyã«ãããŠããšãŠãæåãªããŒã«ã«ãªãããã®ã§å¹Žæ«ã®é«éåãããv2ç³»ã®ãªãªãŒã¹ã楜ãã¿ã§ãã Day3 Gradual typing for Ruby: comparing RBS and RBI/Sorbet rubykaigi.org Rubyã®éçåå®çŸ©ã®ããŒã«ãšããŠRBS/SteepãRBI/Sorbetã®2ã€ååšããŠãããåè
ã¯Rubyå
¬åŒã§ãããåŸè
ã¯StripeãShopifyãšãã£ãRuby/Railsã䜿ãäŒç€Ÿã«ãã£ãŠéçºã»å©çšãããŠããã ãã®ã»ãã·ã§ã³ã§ã¯äž¡è
ã®åæ€æ»ã®å®è¡é床ã衚çŸåã®å·®ãRBSãRBIã«å€æããéã®èª²é¡ãªã©ã«ã€ããŠç޹ä»ããŠããŸããã RBI/Sorbeté«éã§ããäžæ¹ã§Rubyã®ææ³ã䜿ãã®ã§èšæ³ã«å¶çŽãå€ããRBS/Steepã¯ç¬èªã®èšèªãªã®ã§è¡šçŸåãè±ãã§ããäžæ¹ã§çŸç¶Steepã«ãã忀æ»ã¯é
ãã®ãšRubyåãã®ããŒã«ã䜿ããªãããšããã®ããã£ãããšããæ¯èŒã«ãªããŸãã ã³ã¡ã³ã ã¹ã©ã€ãã®äžã§ã¯Shopify瀟å¡ãåçããã¢ã³ã±ãŒãã®çµæããããå®éã«æ¥åã§Sorbetã䜿ã£ãŠãããšã³ãžãã¢ãã©ãæããŠããã®ããç¥ããã®ã¯è¯ãã£ãã§ããã©ã¡ãã®ãšã³ã·ã¹ãã ãã¡ãªãããšãã¡ãªããããããããããRubyã«éçåãå°å
¥ããŠããããšæããšã©ã¡ãã䜿ãã®ãè¯ãããšããã®ã¯æ©ãŸããã§ããã Let's write RBS rubykaigi.org Slide: https://speakerdeck.com/pocke/lets-write-rbs RBS3.1åŸã®rbs subtractãšrbs parseã®æ©èœã«ã€ããŠããããããªãå¿
èŠãªã®ããå®éã«ã©ã䜿ãã®ãããã¢ãéããŠè§£èª¬ãããŠããŸããã ç¹ã«rbs subtractã¯rbs prototypeã§Rubyããçæãããäžå®å
šãªRBSãæŽåœ¢ããããã«å¿
èŠãšã®ããšã§ããã ã³ã¡ã³ã å®éã®ã¢ããªã±ãŒã·ã§ã³ã³ãŒãã§RBSã®ä¿®æ£ããããŠããã®ã§éåžžã«èŠå¿ãã®ããå
容ã§ããããŸããRBS Railsãšããã©ã€ãã©ãªãéçºãããŠããã®ã§ãã¡ããæ°ã«ãªããŸããã Parsing RBS rubykaigi.org Slide: https://speakerdeck.com/soutaro/parsing-rbs RBSïŒâ RubyïŒã®ã³ãŒããæžãéã®ãšãã£ã¿æ¯æŽã®ããã«RBSã®ããŒãµãŒãã©ã®ããã«æ¹è¯ããããšãã話ã åŒæ°ãšè¿ãå€ã®åãšããŠåããã®ãäºæããŠããæã«é©åã«ãµãžã§ã¹ãã§ããªãã£ãããã¯ã©ã¹å®çŸ©ã®endãéããããŠããªããšéäžã®ã¡ãœããã®åè£ã衚瀺ãããªãã£ãããšèšã£ãåé¡ããã£ãããããŒãµãŒãæ¹è¯ããããšã«ãã解決ããã ã³ã¡ã³ã ãšãã£ã¿æ¯æŽã®ããã«éäžã§è§£æãæ¢ããŠããŸããªãããŒãµãŒãã©ãäœãããšãã話ãå®äŸã亀ããŠç¥ãããšãã§ããŠé¢çœãã£ãã§ãã ææ³ RubyKaigiã¯ååå ã§ããããã»ãã·ã§ã³å
容ã«å€§ãã«åºæ¿ãåããæ°ããªèŠç¹ãç¥èãåŸãããšãã§ããŸãããRubyèªäœã®å®è£
ã®è©±ãå€ãã£ããã®ã®ãæ®æ®µã®æ¥åã«æŽ»ãããããªè©±é¡ããã£ãã®ã§ã瀟å
ã§ãåããŠããããã§ãã ãŸããRubyãäœã£ãŠããæ¹ã
ã®æããçŽæ¥èããããTwitterãªã©ã§ç¹ãã£ãŠããæ¹ãšå®éã«ã話ãã§ããããšã³ãã¥ããã£ãšã®äº€æµãã§ãããšãŠãææçŸ©ãª3æ¥éã«ãªããŸããã ããããšãRubyKaigi æåŸã« æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã§ã¯äžç·ã«ãããã¯ããäœã£ãŠããRubyistãåéããŠããŸããRubyKaigiã«åå ããæ¹ãããã§ãªãæ¹ãããã²ã«ãžã¥ã¢ã«ã«ã話ãããŸãããïŒ
ã¯ãããŸããŠã2023幎4æããããã¹ã¿ã¡ã³ã»TUNAGãããã¯ãéçºã«ãžã§ã€ã³ããŸããã @trowems23 ã§ãã ã€ãå
æ¥Ruby 3.0ããªãªãŒã¹ãããŸããããžã§ã€ã³åæ¥ããæ°ããŠ829æ¥åã®ããšã§ããã Rubyã¯éçºçç£æ§ãé«ãã®ã§ããããã¬ã€ãã³ã°ãã§ã³ãžã®å€ãã«å¯ŸããŠã©ã€ããµã€ã¯ã«ããšãŠãçããç©æ¥µçãªã¢ããããŒããæ±ããããŸãã äžæ¹ã§ãã¹ã¿ã¡ã³äž»èŠãããã¯ãã®TUNAGã®ã³ã¢ã¢ããªã§ã®RubyããŒãžã§ã³ã¯2.2ããå§ãŸãã2.3ã2.5ãšæšç§»ããŠãæåŸã®ãã€ããŒã¢ããããŒãã¯2021幎3æã®2.7.2ã§ããïŒãã®æ¥æç¹ã§ã®Rubyææ°ããŒãžã§ã³ã¯3.0.0, 2.7.2ïŒã Ruby 2.7ã¯ãµããŒãã2023幎3æ31æ¥ã«çµäºãããšããããšããããRuby 3.0以äžãžã®ã¢ããããŒããæ©æ¥ã«æ±ããããç¶æ³ã§ããã åå ã®åæ æ¢ã«å€çš®å€æ§ãªRuby on Railsã¢ããªã±ãŒã·ã§ã³ã«ãããŠãçè
å人ã¯è€æ°ãããã¯ãã«ãããŠäœåºŠãRuby 2.xâ3.0ã宿œããçµéšããã£ãã®ã§ãè¿
éã«äœæ¥ã ãããããšãã§ããŸããããå°ãèæ¯ã«ã€ããŠãèããããšæããŸãã åœè©²ã®Ruby on Railsã¢ããªã§ã¯å€ãã®gemã䜿ã£ãŠããããšãããã2021幎æç¹ã§ã¯äŸåããŠããgemã®ã¢ããããŒããé£ãããããå幎(2021幎)äžã®Ruby 3.0ãžã®ã¢ããããŒãã¯é£ããã£ãã®ã§ã¯ãªããããšæšæž¬ãããŸãã äžæ¹ã§ãã¹ã¿ã¡ã³ã¯2022幎åãã ã¹ã¯ã©ã ããŒã ãžã®ç§»è¡ ãçµç¹ã¬ãã«ã§å®æœããããããã©ãããã©ãŒã ã§ããè¶³åãã®æŽåããããªãœãŒã¹ã¯éå®çã«ãªã£ãŠããŸããã åœæã®çµç¹éçºã«ã€ããŠã¯ã2022幎2æã«CTOã®æŸè°·ãæžããã以äžã®èšäºãã芧ãã ããã TUNAG(ããã°)ã®æè¡ãšéçºäœå¶ã®ãã¹ãŠã玹ä»ããŸãïŒ ãŽãŒã«ã®èšå® Rubyã®ææ°ããŒãžã§ã³ã¯åœæ3.2.1ã§ãããäžæ°ã«ãããç®æãæŠè¡ãåãããšãã§ããŸããããŽãŒã«ã¯ã1ç§ã§ãæ©ãã¿ã€ãã³ã°ããRuby 3.0.xã§åããŠããããšãã«ãªããŸããã1ç§ã§ãæ©ãããšããã®ãçŠãã«å€ããŠããããããªãã®ã§ããæ¬¡æã»ãã¥ãªãã£è匱æ§å¯Ÿå¿ãããããªãªãŒã¹ããããRuby 3.0.7ãã®ãªãªãŒã¹ãããããŸã§ã®éããšçœ®ãæããããšã«ããŸããã çè
ã¯Rubyã«ããŸãèå³ããªããããRuby 3.0.7ããã€åºããã®æèŠã¯èæèŠã§ããæã£ãŠããªãã£ãã®ã§ããã®ãããžã§ã¯ããå®äºãããŸã§ã®éïŒå®éã«ã¯13å¶æ¥æ¥ã§ããïŒããããã¯ãéçºéšå
ã§ã®ã³ã³ã»ã³ãµã¹ã圢æãããããšã¯ãããŸããã§ããã æé Rubyã®ããŒãžã§ã³ãRuby 2.7ç³»ã®ææ°ç (2.7.8) ã«ãã Rubyã®ããŒãžã§ã³ã3.0.6ã«èšå®ããCIãæµããŠã¿ã å¿
èŠãªgemã®ã¿ã¢ããããŒããã èªåã§æžããã³ãŒãã®ä¿®æ£ãè¡ã ã¯ãŒãã³ã°ã確èªãã Rubyã®ããŒãžã§ã³ã3.0.6ã«ãã Rubyã®ããŒãžã§ã³ãRuby 2.7ç³»ã®ææ°ç (2.7.8) ã«ãã ããã¯ç°¡åã§ããã2.7.4ã2.7.8ã«ããã ãã§ãããã®å·®åã®ãã§ã³ãžãã°ã¯å€§äœèŠããŠããŸãã Rubyã®ããŒãžã§ã³ã3.0.6ã«èšå®ããCIãæµããŠã¿ã Ruby 3.0.6ã«ããç¶æ
ã§CIãæµããŠã¿ããšãããæ³å®éãå
šãåããŸããã§ãããäŸåããgemã®ã¢ããããŒããç¶ç¶çã«å®æœããŠããªãã£ããããããã€ãã®gemãã¢ããããŒãããªããšRSpecãªã©ã®ãã¹ããéå§ãããªãç¶æ³ã§ããã å¿
èŠãªgemã®ã¿ã¢ããããŒããã å··ã«å
šãŠã®gemãã¢ããããŒããããšãããšèšŽããRubyãããã§ãã·ã§ãã«ã®æ¹ãããã£ãããããã§ããã2-3幎ã®ãã©ã³ã¯ãåããªãããåœåã®ããã·ã§ã³ãå®çŸããã®ã¯é©åã§ã¯ãããŸããã æéã¯ãããã®ã§ããã10-15åãããã«çããããšã§æ³å®å€ã®å€æŽãæå°éã«æããããšãã§ãããå¿
èŠãªgemã®ã¿ã¢ããããŒããéäžè¡ãããšã«ããŸããã èªåã§æžããã³ãŒãã®ä¿®æ£ 1ä»¶ãé€ããå
šãŠã®ä¿®æ£ã¯keyword argumentsã®ä¿®æ£ãšãªããŸãããåœç€ŸTUNAGã§å®è£
ãã6ã³ã³ããŒãã³ãã«ãããååšããŠããã®ã§ã6ã³ã³ããŒãã³ãã«å¯Ÿãã1ã³ã³ããŒãã³ã1PRãšãã圢ã§6åã®PRã«ãŸãšããããŸããã äŸå€ã ã£ã1ä»¶ã URI.escape ( encode ) ã®ä¿®æ£ã§ããã®ã§ãã·ã¹ããããã¯ã«å®æœããããšãã§ããŸãããããåŒæ°ã®åœ¢åŒã«ããç§»è¡å
ã®ã¡ãœããã®åãåããããªããŠã¯ãªããããªãŒãã¡ãŒã·ã§ã³ã¯ã§ããŸããã§ãããããã§ãåœç€Ÿ æ¥åæ¹åæšé²ãããžã§ã¯ããã¹ã¿ã©ãã ã®äžç°ã§ãGPT-4ã GitHub Copilot for Business ã®åãæŽçšããããšæã£ãã®ã§ããã該åœã³ãŒãã¯5ç®æãããªããåã¥ãã§çŽããŠããŸããŸããã ããããå§¿å¢ã¯ãããªããšæããŠããã®ã§ãã¡ãããšGitHub Copilot for Businessã«æç€ºãã§ããããã«ãªããããªãšæã£ãã®ã§ãä»å¹Žã®äžå€ã®çåðã«ã¯ãã®ããã«æžããŠãããŸãã ã¯ãŒãã³ã°ã確èªãã gemãã¢ããããŒããããç¶æ
ã§stagingã§ã®äººéã«ããæ€èšŒãçµããŠãªãªãŒã¹ã§ããããšããã£ãã®ã§ããããã®èªèã¯çãã£ãããã§ãã çŽ7幎éçºãããŠããRails補ãããã¯ãã®ã¯ãŒãã³ã°ãææ¡ããããã«ããããŒãã©ã¯ãŒãã¯ã©ãŠãéçºè
ã®æ¹ãæžãããã çŽ8幎éçºãããŠãã Rails 補ãããã¯ãã Ruby 3 ã«ããŒãžã§ã³ã¢ããããããã« keyword parameters is deprecated ããç¶²çŸ
çã«ãæ€ç¥ããæ¹æ³ ããåèã«ããŠã¯ãŒãã³ã°ãæ€ç¥ããããã«ããŸããã æé ãšããŠã¯ config/boot.rb ã«ä»¥äžãèšèŒããããšã§å¯ŸåŠããŸããã Warning [ :deprecated ] = true æ¢ã«å€ãã®gemãã¢ããããŒããããç¶æ
ã§ãã£ããããç°å¢ã«ããåºãåããããããšã¯ãªããéçºç°å¢ãå«ãå
šç°å¢ã§ã¯ãŒãã³ã°åºåããããã«ããŸããã ãªãªãŒã¹ 2021幎㮠Ruby on Rails 6.1ãžã®ã¢ããããŒãæã«å©çšããcanaryç°å¢ ã¯æè»œã«å©çšã§ããç¶æ
ã«ãªã£ãŠããŸããã§ãããæéããããŠããŸããšãããžã§ã¯ãå®äºãŸã§ã®æéãé·ããªã£ãŠããŸãïŒ=GW9é£äŒãè·šãã§ããŸãïŒããšãäºæ³ãããããããªã¹ã¯ãè©äŸ¡ããéåžžãªãªãŒã¹ã®ã¯ãŒã¯ãããŒã掻çšããããšã«ããŸããããŠãŒã¶ãŒåœ±é¿ãæå°åãã€ã€ãéåžžå¶æ¥æé垯ãéžã³ã宿œããããšã«ããŸããããã®ãããä»åã®ãªãªãŒã¹ã«ãããŠãæ·±å€ã»æ©æãåæ¥äŒæ¥ã®äœæ¥ãšã¯ãªããŸããã§ããã Ruby 3.0ããŒã¹ã®ã€ã¡ãŒãžã®ãªãªãŒã¹ã¯ æ±äº¬æ¯ç€Ÿ å
ã§ãªã¢ãŒãã§è¡ããŸãããSlack HuddleãæŽ»çšããŠãæ³å®å€ã®é害ãçºçããå Žåã«åããŠåãæ»ãã«åããŠããŸããããç¹ã«å€§ããªåé¡ã¯èµ·ããæ°æéãçµéãããããç¥æ¯ãæããã®ã¡ããªãã£ã¹ãã°ã®èŸã麻å©è±è
ãããããé£ãããšãã§ããŸããã æ±äº¬ãªãã£ã¹ãã°ã®éº»å©éºº æµ®ã圫ãã«ãªã£ãåé¡ ãã®ã¢ããããŒãäœæ¥ã®äžã§ãããã€ãã®éçºã¯ãŒã¯ãããŒã«é¢ããŠåé¡ãæµ®ã圫ããšãªããŸããã ãããŸã§ã®CIã®ãã€ãã©ã€ã³ã§ã¯å¹çãæªããéçºè
äœéšãšããŠæªãããšãåãããŸããã TUNAGã§ã¯CIåºç€ã«CircleCIãå©çšããŠããã倿Žå
容ã®ã¿ãé©åã«ãã¹ãã§ããããã«ãã€ãã©ã€ã³ã»ãžã§ããæé©åããããšæã£ãŠããŸãã ãŸããCDã«ãããŠã¯ãCDã®éäžçµéãèŠãã¥ããã©ãã§è©°ãŸã£ãŠããã®ãåããã«ããç¶æ³ããããŸããã TUNAGã®CD TUNAGã§ã¯AWS Systems Managerãèµ·ç¹ã«CodeBuildãCodeDeployãå©çšããŠãCDãã€ãã©ã€ã³ãæ§ç¯ããŠããŸãããCircleCIããCDã®ããªã¬ãŒããŠãããããAWSåŽã®CodeBuildãCodeDeployã®ç¶æ³ã®èŠéããæªããªã£ãŠããŸãã å ããŠãå³ã«ã¯æžãããŠããŸãããããšã³ãžãã¢ã®æ¿èªã®ã¯ãŒã¯ãããŒããããããæ¿èªãé
ããŠããŸããšããªãªãŒã¹ãæ»ã£ãŠããŸãããšããããŸããã ãããã¯ä»åŸã®CDé åã«ããã課é¡ã§ãã Day 2ãªãã¬ãŒã·ã§ã³ ãªãªãŒã¹ïŒCDïŒããããšã®ãéçšã«ã€ããŠãæ¹åãã¹ã課é¡ããããŸãã 2016幎ã«ãããã¯ãããªãªãŒã¹ããã®ã¡ãè€æ°ã®ã¢ãã¿ãªã³ã°ããŒã«ãå°å
¥ããŠããçµç·¯ããããã¢ãã¿ãªã³ã°ã»ãªãã¶ãŒãããªãã£ã«ãããŠéè€ã»æãæŒããçãŸããŠããŸã£ãŠããŸããã ãŸãã¯ãã®ç¶æ³ã®æŽçãè¡ããTUNAG顧客ã«é©åã«äŸ¡å€ãæäŸã§ããç¶æ
ãç¶æãã€ã€ãæ°æ©èœãªãªãŒã¹ã®ã¹ããŒãã¢ããã»ã·ã¹ãã éçšæ¥åæé©åã»ã³ã¹ãæé©åã«ç¹ããŠãããã°ãšæããŸãã TUNAGéçºçµç¹ã®ä»åŸ äžã«æãã課é¡çŸ€ããã®èšäºã§è§Šããªãã£ãå€ãã®èª²é¡ã解決ãããããã¹ã¿ã¡ã³ã§ã¯éçºçµç¹ã®åŒ·åãè¡ãªã£ãŠããŸãã Site Reliability Engineer Software Engineer, Developer Experience ãã®ä»ã®éçºç³»è·çš® æè¡ã³ãã¥ããã£æ¯æŽã®äžç°ãšããŠãã¹ã¿ã¡ã³ã¯5æã«éå¬ããã RubyKaigi 2023 ã«Gold SponsorãšããŠåå ããŸãã ãŸãã ã¹ã¿ã¡ã³note ã§GWæããããªã¬ãŒåœ¢åŒã§æ¯æ¥èšäºãå
¬éããŠããäºå®ã§ãã®ã§ããã¡ãããæåŸ
ãã ããã åè çŽ8幎éçºãããŠãã Rails 補ãããã¯ãã Ruby 3 ã«ããŒãžã§ã³ã¢ããããããã« keyword parameters is deprecated ããç¶²çŸ
çã«ãæ€ç¥ããæ¹æ³ ïŒMoney Forward Developers BlogïŒ
ã¹ã¿ã¡ã³ãšã³ãžãã¢ã®äºæ¬ã§ãã æŒæŽ©ãã§ãã«ãŒã®Webã¢ããªã±ãŒã·ã§ã³ããã«ã¹ã¿ãã¯ã«é ååããéçºããŠããŸããåŸæãªé åã¯ã€ã³ãã©å«ãããã¯ãšã³ãã§ãã æ¬èšäºã§ã¯ãå
æ2022幎12æã«ãªãªãŒã¹ãããµãŒãã¹ã æŒæŽ©ãã§ãã«ãŒ ã«ã€ããŠããããã¯ããšéçºäœå¶ã®ç޹ä»ãããŸãã æŒæŽ©ãã§ãã«ãŒã«ã€ã㊠æè¡ã«ã€ã㊠æè¡ã¹ã¿ã㯠ã¢ãŒããã¯ã㣠çµç¹ã«ã€ã㊠çµç¹äœå¶ éçºäœå¶ ãŸãšã æŒæŽ©ãã§ãã«ãŒã«ã€ããŠ æŒæŽ©ãã§ãã«ãŒã¯æ
å ±æŒæŽ©ãæªç¶ã«é²ãã»ãã¥ãªãã£ç®¡çãµãŒãã¹ã§ãã äŒæ¥ã«ãšã£ãŠã»ãã¥ãªãã£äºæ
ã®åœ±é¿ã¯ç倧ã§ãããè¿å¹Žãæ
å ±ã®æŒæŽ©äºæ
ã®ä»¶æ°ã¯å¹Žã
ãå¢å ã®åŸåã«ãããŸãã æ
å ±è³ç£ã«é¢ããã»ãã¥ãªãã£äºæ
ã«ã¯ãå€éšããã®ãµã€ããŒæ»æã®ã»ããåŸæ¥å¡ãªã©ã«ããäŒç€Ÿã®å
éšã§åŒãèµ·ãããããäžæ£è¡çºãæªæã®ãªãäžæ³šæãªã©ã«ããæ
å ±æŒæŽ©ããããŸãã æŒæŽ©ãã§ãã«ãŒã¯åŸè
ãå
éšã§åŒãèµ·ããããæ
å ±æŒæŽ©ãäºé²ã»æ€ç¥ããããã®ãµãŒãã¹ã§ãã ITéšéãååšããªãäŒæ¥ã«ãããŠã¯ãITè³ç£ã®ãªã¹ã¯ç®¡çãå§ããã«ããŠããã©ãããå§ããã°è¯ãã®ããåãããªãã£ããããŸãITè³ç£ã«åªå
é äœãã€ããŠéšåçã«ç®¡çãå§ããããšããŠããäžã®äžã®ã»ãšãã©ã®ã»ãã¥ãªãã£ããŒã«ã¯éåãªãªãŒã«ã€ã³ã¯ã³åœ¢åŒã®ãã®ãããªãã£ãããšãè²»çšé¢ãå·¥æ°é¢ã«ãããŠãå°ããå§ããããšãé£ããç¶æ³ã«ãããŸãã æŒæŽ©ãã§ãã«ãŒã¯ã¢ãžã¥ãŒã«ãšåŒã°ããæ©èœåäœã§æ§æããããµãŒãã¹ã§ããã©ã«ããŒæäœã®ç£èŠãUSBã®è±çã®æ€ç¥ãªã©ãšãã£ãæ©èœããŠãŒã¶ãŒãèªç±ã«çµã¿åãããŠå©çšããããšãã§ããŸãã ã¢ãžã¥ãŒã«ãšããã³ã³ã»ããã«ããåäŒæ¥ã®äºæ
ã«åãããŠãæ©èœã»ã³ã¹ããæé©åãããªã¹ã¯ç®¡çã宿œã§ããŸãã ãŸãã¯ã©ãŠãåã®ãµãŒãã¹ãªã®ã§ãä¿å®ã»ç®¡çã®è² æ
ãæããããããšãç¹åŸŽã§ãã ã»ãã¥ãªãã£åäžãç®çãšããããŒã«ã®å€ãããã»ãã¥ãªãã£ãITã®ãªãã©ã·ãŒãé«ããŠãŒã¶ãŒãåæãšããŠããããªã¹ã¯ç®¡çã®éå£ãšãªã£ãŠããŸãã ããã§æŒæŽ©ãã§ãã«ãŒã¯ãã»ãã¥ãªãã£ãITãåŸæãšããŠããªããŠãŒã¶ãŒã§ãç°¡åã«å©çšã§ãããã·ã³ãã«ãã远æ±ãããµãŒãã¹ãšããŠéçºãããŠããŸãã 管çç»é¢ã¯ãèªç€Ÿã®ã»ãã¥ãªãã£ç®¡çç¶æ³ãçŽæçã«çè§£ã§ããUIã«ãã¶ã€ã³ãããŠããŸãã ãŸãç£èŠå¯Ÿè±¡ã®ç«¯æ«ã«ã€ã³ã¹ããŒã«ãããšãŒãžã§ã³ãã¢ããªã±ãŒã·ã§ã³ã¯ãç
©éãã®ãªãç°¡åãªã»ããã¢ããã§åäœãéå§ããããã«ãªã£ãŠããŸãã æè¡ã«ã€ã㊠æè¡ã¹ã¿ãã¯ æŒæŽ©ãã§ãã«ãŒã®æè¡ã¹ã¿ãã¯ã¯äžå³ã®éãã§ãã æŒæŽ©ãã§ãã«ãŒã¯å€§ãã2ã€ã®ã¢ããªã±ãŒã·ã§ã³ã§æ§æãããŠããŸãã äžã€ã¯ç£èŠå¯Ÿè±¡ã®PCã«ã€ã³ã¹ããŒã«ããŠæ
å ±ãåžãäžããWindowsãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ãããäžã€ã¯åžãäžããæ
å ±ãéçŽã»é²èЧããWebã¢ããªã±ãŒã·ã§ã³ã§ãã ãã°åéã¢ããªã±ãŒã·ã§ã³ ãã°åéçšã®Windowsã¢ããªã±ãŒã·ã§ã³ã¯ã.NET 6 ã«ãã WPF(Windows Presentation Foundation) ãšããŠå®è£
ãããMVVM ãã¬ãŒã ã¯ãŒã¯ãšã㊠Prism ãå©çšããŠããŸãã ã¢ãžã¥ãŒã«ã«ãã£ãŠæ©èœãçµã¿åãããããæŒæŽ©ãã§ãã«ãŒã®Windowsã¢ããªã±ãŒã·ã§ã³ã§ã¯ãWindows ã®åçš®æ
å ±ã«ã¢ã¯ã»ã¹ããå¿
èŠããããããæ°æ§æ§ã
㪠API ãå©çšããããšãç¹åŸŽã§ããäŸãã° USBãã©ã€ãã®æ¥ç¶ç¶æ³ã«ã€ããŠã¯ WMIïŒWindows Management InfrastructureïŒ ãå©çšããWindows ãã¿ç®± ã®å®¹éååŸã«ã¯Win32 API ã® SHEmptyRecycleBin ãå©çšããŠããŸããååŸããããã°ã¯ Entity Framework ã«ãã£ãŠããŒã«ã«PCã«ä¿åããããããã¯ãŒã¯ããªã³ã©ã€ã³ã®ã¿ã€ãã³ã°ã§ãµãŒããŒã«éä¿¡ãããŸãã ãŸããæ©èœè¿œå ãé »ç¹ã«è¡ãããããšãæ³å®ãã MSIX ã§ããã±ãŒãžã³ã°ã Microsoft Store ã§é
åžããããšã§ãã¢ããªã±ãŒã·ã§ã³ã®ç°¡æã€ã³ã¹ããŒã«ãšèªåæŽæ° (ãµã€ã¬ã³ãã¢ããããŒã)ãå®çŸããŠããŸãã ãã°éçŽã»é²èЧã¢ããªã±ãŒã·ã§ã³ ãã°ã®ä¿åã»é²èЧçšã®Webã¢ããªã±ãŒã·ã§ã³ã®éçºã«ã¯ãããã¯ãšã³ããã¬ãŒã ã¯ãŒã¯ãšããŠNest.jsãããã³ããšã³ããã¬ãŒã ã¯ãŒã¯ãšããŠNext.jsã䜿çšããŠããŸããSPAæ§æãšãªã£ãŠãããããã³ããšã³ããšããã¯ãšã³ãã®éã®ã€ã³ã¿ãŒãã§ãŒã¹ã«ã¯GraphQLãæ¡çšããŸããã ã¯ã©ãŠãã¯AWSãã¡ã€ã³ãšããäžéšåºç€ãšããŠGCPããã®ä»SaaSãå©çšããŠããŸããAWSã®éçºã»ç®¡çã«ã¯AWS CDK in TypeScriptã䜿çšããŠããŸãã æŒæŽ©ãã§ãã«ãŒéçºããŒã ã¯ããŠãŒã¶ãŒã«æéã§äŸ¡å€ãå±ããããã«ãè·èœãèšèªã«ãšããããªãéçºäœå¶ãç®æããŠããŸãã ããã§ãèšèªã®éãã«ããããŒãã«ããªãããããããã³ããšã³ãããã€ã³ãã©ãŸã§ãã«TypeScriptã§éçºã§ããããã«ããŸããã ã¢ãŒããã¯ãã£ æŒæŽ©ãã§ãã«ãŒã®ã¢ãŒããã¯ãã£ã®æŠèŠã¯ä»¥äžã«ãªããŸãã ã¢ãŒããã¯ãã£ã¯æ§æã¢ããªã±ãŒã·ã§ã³ãšåæ§ã«ã倧ããïŒã€ã«åããããšãã§ããŸãã äžã€ã¯ãé¡§å®¢äŒæ¥ã®ç€Ÿå¡ã®PCã®ç¶æ
ãç£èŠããæäœãã°ãªã©ã®æ
å ±ãåžãäžãããããåŒç€Ÿã¹ãã¬ãŒãžã«èç©ãããã°åéã¢ãŒããã¯ãã£ã§ãã ããäžã€ã¯ãèç©ãããã°æ
å ±ã管çè
ãé²èŠ§ã»æ€çŽ¢ãã管çç»é¢ã¢ãŒããã¯ãã£ã§ãã ãã°åéã¢ãŒããã¯ãã£ é¡§å®¢äŒæ¥ã®ç€Ÿå¡ã®PCäžã§ã¯ç£èŠãšãŒãžã§ã³ããšããŠWindowsãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ã皌åããŠããããŠãŒã¶ãŒã®æäœãã¹ã±ãžã¥ãŒã©ãããªã¬ãŒãšããŠæ
å ±ãåéããŸã åéããŒã¿ã¯äžå®éããšã«AWSäžã«æ§ç¯ããããã°åéãšã³ããã€ã³ãã«éä¿¡ãããŸãã åä¿¡ãããã°ã¯AWS Lambdaçµç±ã§äžåºŠAmazon SQSã«ãã¥ãŒã€ã³ã°ãããããã«åŸæ®µã«äœçœ®ãããã°åŠçãµãŒããŒããAmazon SQSã«å¯ŸããŠããŒãªã³ã°ããããšã§é ã«åŠçãããŸãã ãã°åŠçãµãŒããŒã¯Amazon ECS(Fargate)ã«ã³ã³ãããšããŠãããã€ãããŠããããã°çš®å¥ããšã®ä»åãã®ä»ãç£èŠå¯Ÿè±¡ãŠãŒã¶ãŒã®äžå¯©ãªè¡åãã°ãæ€ç¥ããŠã¢ã©ãŒããçºå ±ããŸãã ãã¥ãŒã€ã³ã°ã«ããããã°åä¿¡ãšãã°åŠçãéåæã«å®è¡ããããšã§ãç£èŠå¯Ÿè±¡ã®PCã®è² è·ã®äžæãåŠçãµãŒããŒã®è² è·å€åãæå¶ããŠããŸãã ãã°ã¯Amazon S3ã«èç©ãããç£èŠå¯Ÿè±¡ã®PCã®ãªã³ã©ã€ã³ç¶æ
ãã¢ã©ãŒããªã©ã®æ
å ±ã¯Amazon RDSã«ä¿åãããŸãã 管çç»é¢ã¢ãŒããã¯ã㣠䞻ã«é¡§å®¢äŒæ¥ã®ç®¡çè
ãå©çšãã管çç»é¢ã¢ããªã±ãŒã·ã§ã³ã®ããã®ã¢ãŒããã¯ãã£ã§ãã ãã¡ãã¯å
çšã®ãã°åéã¢ãŒããã¯ãã£ãšæ¯èŒããŠãã·ã³ãã«ãªæ§æã§ãã Webã¢ããªã±ãŒã·ã§ã³èªäœã¯åè¿°ã®éããSPAæ§æãšãªã£ãŠãããããã³ããšã³ãã¯Next.jsãšçžæ§ã®è¯ãVercelã«ãããã¯ãšã³ãã¯Amazon ECSäžã«ãããã€ãããŠããŸãã Amazon S3äžã®ãã°ããŒã¿ã¯AWS GlueãçšããŠããŒãã«å®çŸ©ãããŠãããWebã¢ããªã±ãŒã·ã§ã³ããã¯Amazon Athenaãçµç±ããããšã§æ€çŽ¢ã»ååŸãè¡ãããŸãã ãŸããæŒæŽ©ãã§ãã«ãŒã¯ãã«ãããã³ãæ¹åŒã®ãµãŒãã¹ã§ãã ãã«ãããã³ãã¯åãDBããµãŒããŒãè€æ°ã®ãŠãŒã¶ãŒ(äŒæ¥ãªã©)ãå
±çšããæ¹åŒãæãããµãŒãã¹ããã³ãå士ã®ããŒã¿åé¢ãå¿
é ã§ãã ããŒã¿ããŒã¹ã«PostgreSQLäºæã®Amazon Auroraãæ¡çšããPostgreSQLã® RLS(Row Level Security) ãæŽ»çšããããšã§ããã³ãåé¢ãè¡ã£ãŠããŸãã ã¢ããªã±ãŒã·ã§ã³ã¬ã€ã€ãŒã§ã¯ãªããããäœã¬ã€ã€ãŒã®æ©èœã«ãã£ãŠããã³ãåé¢ãå®çŸããããšã§ãããã³ãIDã«ããçµã蟌ã¿ã®whereæ¡ä»¶ãæžãå¿ããããšãã£ãæ
å ±ã®æŒæŽ©ãªã¹ã¯ãäœæžããããšãã§ããŸãã ãã®ä» èªèšŒæ©èœãæ±ºæžæ©èœãªã©ããããã¯ãã®ã³ã¢ããªã¥ãŒã§ã¯ãªãããäºæ¥äžã¯ãªãã£ã«ã«ãªã·ã¹ãã ã«ã€ããŠã¯ãSaaSãå©çšããããšã§ãéçºã»éçšã³ã¹ãã®äœæžããã³å質ã®åäžã«åªããŠããŸãã ãŸãCI/CDãã€ãã©ã€ã³ãšããŠãCircleCIã«ããããã¹ãå®è¡åŸãAWSäžã§ã³ã³ãããã«ããåçš®ECSã¿ã¹ã¯ã®æŽæ°ãšãã£ãäžé£ã®åŠçãèªååããŠããŸãã çµç¹ã«ã€ã㊠çµç¹äœå¶ 次ã®ãããªäœå¶ã§éçºããŠããŸãã 管çç»é¢ãªã©Webã¢ããªã±ãŒã·ã§ã³å
šè¬ã®éçº 2å Windowsã¢ããªã±ãŒã·ã§ã³ã®éçº 1å ãã¶ã€ã㌠1å Webã¢ããªã±ãŒã·ã§ã³ã®éçºæ
åœè
ã¯ããã«ã¹ã¿ãã¯ã«éçºããããšã§ããã³ããšã³ããããã¯ãšã³ããšãã£ãè·èœã«å·Šå³ããããäºæ¥äžã®åªå
床ã«åŸã£ãŠæ¬¡ã®éçºã¢ã€ãã ãéžã¶ããšãå¯èœã§ãã ãŸãããŒã±ã»å¶æ¥æ
åœã®ã¡ã³ããŒ1åãå«ããäºæ¥æšé²ããŒã å
šäœãšããŠã5åã®å°æ°ç²Ÿéã§ãããããžãã¹ãµã€ãã®ã¡ã³ããŒãšå¯ã«ã³ãã¥ãã±ãŒã·ã§ã³ãåããªããäºæ¥ãé²ããŠããŸãã éçºäœå¶ 1ããŒã ã®ã¹ã¯ã©ã äœå¶ã§éçºãããŠããŸãã æ¥ã
ã®é²æå
±æã®å Žã§ãããã€ãªãŒã¹ã¯ã©ã ã«ã¯ãããžãã¹ãµã€ãã®ã¡ã³ããŒãåå ããŠããæ¥ã
ãå
±éã®KPIãšçŸåšå€ã確èªããŠããŸãã 売ãäžãããŠãŒã¶ãŒæ°ãªã©ãå
±éã®ç®æšå€ãšããŠè¿œãããšã§ãåã屿©æãæã¡ãåãéæã®åã³ãå
±æããããšãã§ããŸãã 顧客ã®å£°ãçŽã«åããŠããã¡ã³ããŒããåžžã«ãã£ãŒãããã¯ãåããããšã«ããªãããæ¬åœã«é¡§å®¢ã«ãšã£ãŠäŸ¡å€ã«ç¹ããã®ããåžžã«åãåãç¶ããŠããŸãã æŒæŽ©ãã§ãã«ãŒäºæ¥ã«é¢ããããšã§åŸããããå°æ°ç²ŸéããŒã ããã®è²Žéãªçµéšã®äžã€ã«ãªã£ãŠããŸãã ãŸãšã æŒæŽ©ãã§ãã«ãŒã¯ã管ç察象ã®PCã«ã€ã³ã¹ããŒã«ããã.NET補ã®Windowsã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠããã°æ
å ±ãåéããŠããŸãã åéãããã°ã¯AWSäžã®ã¹ãã¬ãŒãžã«éçŽãããSPAæ§æã®Webã¢ããªã±ãŒã·ã§ã³ã§é²èЧãå¯èœã§ãã ãã®Webã¢ããªã±ãŒã·ã§ã³ã¯ããŠãŒã¶ãŒãžã®äŸ¡å€æäŸã®ã¹ããŒãåäžã®ããã«ããã«TypeScriptïŒã¹ã¯ã©ã äœå¶ã§éçºãé²ããŠããŸãã åŒç€Ÿã¹ã¿ã¡ã³ã§ã¯ãä»åŸããã«å éããŠãŠãŒã¶ãŒã«äŸ¡å€æäŸããããã«ãå
±ã«æŒæŽ©ãã§ãã«ãŒã®éçºã«æºãã仲éãåéããŠããŸãã æŒæŽ©ãã§ãã«ãŒã®æè¡ã¹ã¿ãã¯ãéçºäœå¶ã«èå³ãæã£ãŠããã ããŸãããããã²äžèšã®ããŒãžããæ¡çšãšã³ããªãŒããã ãããšå¹žãã§ãã Webãšã³ãžãã¢(Forkwell) Windowsãšã³ãžãã¢(Forkwell) Windowsãšã³ãžãã¢(Wantedly)
2023幎1æ11æ¥(æ°Ž)ã1æ13æ¥(é)ã«éå¬ããããã¹ã¯ã©ã ã®åœå
æå€§ã®ã€ãã³ãã§ããRegional Scrum Gathering Tokyo 2023(以äž: RSGT)ã«ã¹ãã³ãµãŒãšããŠåå ããŠããã®ã§ãã®å ±åã§ãã 2023.scrumgatheringtokyo.org ä»åã¯CTOïŒãšã³ãžãã¢å
Œã¹ã¯ã©ã ãã¹ã¿ãŒÃ3人ã®4人ã§åå ããŠããŸããã äŒå Žã®é°å²æ° äŒå Žã«å
¥ããšã¹ãã³ãµãŒããŒã¹ãåºå±ããŠãããšãªã¢ãããã®ã§ãããããŒã¹ã®åšããã»ãã·ã§ã³äŒå Žã®å€ãªã©ãäŒå Žã®è³ããšããã§è©±ãåããããŠããã®ãå°è±¡çã§ããã ååå ã ãšå
¥å Žãã¹ã«"First Timer"ãšããã·ãŒã«ãä»ããããã®ã§ããããããåããŠãªãã§ãããããšäŒè©±ãåºããããšãå€ãã§ãããã»ãã·ã§ã³äžã§ããããã«ã€ããŠåšãã®äººãšè©±ãåã£ãŠã¿ãŸãããããšããæ©äŒããããååå ã§ç¥ãåããå°ãªããŠã話ããããç°å¢ã«ãªã£ãŠãããšæããŸãã ããšãã©ã³ãã®ããçŒãåŒåœã倧人æ°ã§ããã«ãªããªããŸãã ã¹ãã³ãµãŒæŽ»åå ±å ã¹ãã³ãµãŒã»ãã·ã§ã³æ ã«ãŠãCTOæŸè°·ããã¹ã¿ã¡ã³ã®LeSSã®å°å
¥ãš äºæ¥éšå
šäœãå·»ã蟌ãã ã¢ãŠãã«ã æåãžã®éã®ãããšããã¿ã€ãã«ã§çºè¡šãããŸããã ã¹ã¿ã¡ã³ãšããŠã®åãçµã¿ãçºä¿¡ã§ããã»ããLeSSãå®è·µããŠããæ¹ãšã話ã§ããããå®éã«TUNAGã䜿ã£ãŠãã ãã£ãŠãããŠãŒã¶ãŒã®å£°ãèããããšè¯ãæ©äŒã«ãªããŸããã RSGT2023 ã¹ã¿ã¡ã³ã¹ãã³ãµãŒã»ãã·ã§ã³ ã¹ã©ã€ãã¯ãã¡ãâ ããŒã¹ã®åºå±ãããŸãã ã¹ã¿ã¡ã³ã¹ãã³ãµãŒããŒã¹ ïŒããŒãããã°ãå
¬åŒã°ããºãšãã¶ã£ãŠããŸã£ãã®ã¯åçç¹ð£ïŒ åå ããææ³ æ²³äº OSTïŒOpen Space TechnologyïŒ ã匷çã«èšæ¶ã«æ®ã£ãŠããŸãã æåã«åå è
ã話ãããããŒããçã®åã§çºè¡šããèå³ãæã£ãä»ã®åå è
ãããããéãŸã£ãŠãã£ã¹ã«ãã·ã§ã³ãããããšããã®ãç¹°ãè¿ãã»ãã·ã§ã³ã§ããã è²ããªãã£ã¹ã«ãã·ã§ã³ããµããµããšæž¡ãæ©ããŠãŸããããéäžããã¯ããã¶ã€ããŒãã¹ã¯ã©ã ãšã©ãé¢ããã®ãããšããããŒãã®ããŒãã«ã§ãã£ãããšè°è«ã«åå ããŠãåå è
ã®æ¹ã
ãšäº€æµã§ããã®ãè¯ãã£ãã§ãã å察é¢ã®äººãå«ããŠæ¬¡ã
ã«äŒè©±ãçãŸããå Žãç®ã®åœããã«ããŠãèªç€Ÿã§ããããªæŽ»çºãªå ŽãäœããããªãšæããŸããã ç¥å°Ÿ ã¹ã¯ã©ã ãã¹ã¿ãŒå
Œãšã³ãžãã¢ãšããŠTUNAGã®éçºãããŠããç¥å°Ÿã§ãã RSGTã«åå ããŠäžçªæããããšã¯ãã¢ãžã£ã€ã«ã«é¢ããã¿ãªããããšãŠãæãããšããããšã§ãã æ®æ®µããã¹ã¯ã©ã ãã¹ã¿ãŒãšããŠçµç¹ãããŒã ã®ããã«æŽ»åãããŠããæ¹ãå€ãããšããã£ãŠãã¯ãŒã¯ã·ã§ããã«åå ããéã¯ã¹ã¯ã©ã ã®çµéšãæµ
ãèªåã®è©±ããããããïŒãããïŒããããããšæ¬åœã«ãããŸãããïŒããšãã£ãæãã§ãšãŠã芪身ã«èããŠãããæ¹ãæ²¢å±±ããã£ããããŸããã ãŸããã»ãã·ã§ã³ã®æéããšãŠãææçŸ©ãªãã®ã«ãªã£ãã®ã§ãããã§åŸãçµéšãäŒç€Ÿã«æã¡åž°ã£ãŠèªããŒã ã ãã§ãªãä»ããŒã ã«ãéå
ããŸãã æ¥å¹Žã®RSGT2024ãåå ããããšæãã®ã§ããã®èšäºãèªãã§ãã ãã£ãæ¹ãšããäŒãã§ããã®ã楜ãã¿ã«ããŠããŸãã æŸ€ç° TUNAGãããã¯ãéšéã®ã¢ãã€ã«ã¢ããªGã§ã¹ã¯ã©ã ãã¹ã¿ãŒãããŠããã«ãŒã( @khaki_ngy )ã§ãã ä»åãåããŠã®RSGTãžã®åå ã«ãªããŸããã æšå¹Žã®10æã«ãã¡ãšã³ãžãã¢ããããŒã ã®ã¹ã¯ã©ã ãã¹ã¿ãŒãšãªãããããªèªåãåå ããŠå€§äžå€«ãªã®ã ãããïŒãšã¯ããã¯äžå®ãæããŠããŸããã ãã ä»ååå ããŠã¿ãããšã§ãåå è
ã®å€ããåããããªåé¡ã§æ©ã¿è¡åãããŠããããšãç¥ãããšãã§ããŸããã ãããŠãèªåèªèº«ãã¹ã¯ã©ã ãã¹ã¿ãŒãšããŠã®åœ¹å²ãä»ã®çµç¹ã§çºæ®ããŠãããããèªåãäžæ©é²ãã§ããããšããåæ°ãããããŸããã ãŸãRGSTã¯ã¹ã¯ã©ã ã«é¢ãã ã«ã³ãã¡ã¬ã³ã¹ ã§ã¯ãããŸããããã以äžã« ã®ã£ã¶ãªã³ã° ã§ããããšã宿ããŸããã ã»ãã·ã§ã³ã¯ãã¡ããã§ãããã¯ãŒã¯ã·ã§ãããã€ãã³ãã®åéãçµäºåŸã§ã®åå è
å士ã®äŒè©±ãéåžžã«å€§åã«ãããŠãããå€ãã®åå è
ã®æ¹ãšã話ãããããšãã§ããŸããã ä»ååå ããŠåŸãããåŠã³ãè¡åã«æŽ»ãããŠãæ¥å¹Žåå ããéã«ã¯ãã®å·®åãå€åã«ã€ããŠåå è
ã®æ¹ãšã話ãã§ããããã«ãªããããšæããŸããã ãŸãšã ä»åã®åå ã§åŸãããç¥èŠãåèªããŒã ã«æã¡åž°ããæ¥ã
ã®éçºã«æŽ»ãããŠãããŸãã æåŸã«ãã¹ã¿ã¡ã³ã§ã¯äžç·ã«ãããã¯ããäœã£ãŠãã仲éãåéããŠããŸãã ã¢ãžã£ã€ã«ãªéçºããã£ãŠããããæ¹ããã²ã話ã ãã§ãã§ãããå¬ããã®ã§å¿åãåŸ
ã¡ããŠãããŸãïŒ
ããã«ã¡ã¯ïŒæ ªåŒäŒç€Ÿã¹ã¿ã¡ã³/TUNAGäºæ¥éšãããã¯ãéçºéšã®æå¶/西å·/è¥åã§ãã åŒç€Ÿã®ãããã¯ãéšã§ã¯2022幎ãã å€§èŠæš¡ã¹ã¯ã©ã LeSS (以äž: LeSS)ãå°å
¥ããŠããŸãã ãã®äžã§ç§ãã¡3人ã¯ã ããŒã ãããã¯ããªãŒã㌠(以äžïŒããŒã POãšåŒã¶)ãšããéåžžã§ã¯LeSSã«å®çŸ©ãããŠããªã圹å²ãæ
ã£ãŠæ§ã
ãªããšã«ãã£ã¬ã³ãžããŠããŸããã ä»åã®ããã°ã§ã¯ãå®éã«ããŒã POãšããŠã©ã®ããã«æŽ»åãããŠããã®ãã玹ä»ããªããã ããŒã POãã¹ã¯ã©ã ã«ããã¡ãªãããèŠåŽããç¹ ãæžããŠãããããšæããŸãã LeSSãšã¯ åæãšããŠãLeSSãšã¯äœãã玹ä»ããŸãã (åŒçšå
ïŒå€§èŠæš¡ã¹ã¯ã©ã Large-Scale Scrum(LeSS) ã¢ãžã£ã€ã«ãšã¹ã¯ã©ã ãå€§èŠæš¡ã«å®è£
ããæ¹æ³) LeSSã¯ãïŒã€ã®ãããã¯ããè€æ°ããŒã ã§ååããããã«èããããã¹ã¯ã©ã ã§ãã LeSSã¯ã¹ã¯ã©ã ã®åçã»ååãç®çãèŠçŽ ãæŽç·Žãããç¶æ
ãå€§èŠæš¡ãªç¶æ³ã«ã§ããã ãã·ã³ãã«ã«é©çšãããã®ã§ãã åºæ¬çã«LeSSã§å®çŸ©ãããŠãã圹å²ã¯ä»¥äžïŒã€ã§ãã ãããã¯ããªãŒããŒ(1人) ã¹ã¯ã©ã ãã¹ã¿ãŒ(è€æ°äºº) ããŒã (è€æ°) ããŒã 代衚è
äžèšã®éããLeSSã«ãããPOã¯1人ã ãã§ããã®POãåããŒã ã«ä»äºãäžããããšãã§ããå¯äžã®åœ¹å²ã ãšå®çŸ©ãããŠããŸãã (åŒçšå
ïŒå€§èŠæš¡ã¹ã¯ã©ã Large-Scale Scrum(LeSS) ã¢ãžã£ã€ã«ãšã¹ã¯ã©ã ãå€§èŠæš¡ã«å®è£
ããæ¹æ³) ãããã¯ããªãŒããŒã¯ïŒäººã§ã顧客ã«ãšã£ãŠçŽ æŽããããããã¯ãã®ããžã§ã³ã«è²¬ä»»ããã£ãŠããã®åœ±é¿ïŒROIãªã©ïŒãæé©åããŸãããããã¯ããªãŒããŒãšããŠãããªãã¯ãããã¯ãããã¯ãã°ãç¶ç¶çã«è²ãŠãåŠç¿ããã³å€åã«å¯Ÿããé©å¿ã«ããšã¥ããŠã¢ã€ãã ã远å ãåé€ãæåªå
é äœä»ãïŒäžŠã³æ¿ãïŒããŸãããŸããäžäœãããžã¡ã³ããããŒã ã顧客ã«å¯ŸããŠããããã¯ãããã¯ãã°ãèŠããç¶æ
ã«ããŠããããšã§ãéææ§ãä¿ã¡ãŸããããªãã¯ã¢ã€ãã ãæç¢ºã«ãªãããã«ãããŒã ã顧客ãšååããŸããæ°ããã¹ããªã³ãã«æç€ºããã¢ã€ãã ã¯ããããã¯ããªãŒããŒãé©å¿çã«æ±ºããŸãããã©ã®ãããéžæãããã¯ããŒã ãæ±ºããŸãããããŠããããã¯ããªãŒããŒã ããããŒã ã«ä»äºãäŸé Œããããšãã§ããŸãã åŒç€Ÿã§ãã¹ã¯ã©ã å°å
¥çŽåŸã¯ãäžèš4ã€ã®ããŒã«ã§ã¹ã¯ã©ã ãåããŠããŸããã ã¹ã¿ã¡ã³ã§ã®LeSSã®çŽ¹ä» æ¬æ¥ã®LeSSã®äœå¶ãèžãŸããäžã§ãåŒç€Ÿã®LeSSã®äœå¶ãã玹ä»ããŸãã åŒç€Ÿã®LeSSã¯ãåããŒã ãã¡ã³ããŒã®æè¡é åã§ã¯ãªãè·èœã§æšªæããã以äžã®ããã«ç·šæãããŠããŸãããŸãåããŒã ã«ã¯ããããã¯ããªãŒããŒã®åœ¹å²ãç§»è²ããããããŒã POãã1人é
眮ãããŠããŸãã åé ã§è¿°ã¹ãéããããŒã POã¯LeSSã§ã¯å®çŸ©ãããŠããªããããã¹ã¯ã©ã äœå¶ã«ç§»è¡ããçŽåŸã«ã¯ãªã圹å²ã§ããããä»ã§ã¯åºæ¬çã«åããŒã ã«1人(éçºè
ãšå
Œä»»)é
眮ããããšãåæãšããŠã以äžã®ãããªçµç¹äœå¶ãç®æããŠããŸãã 以éããããŒã POå¶ãå°å
¥ã®èæ¯ãã¹ã¯ã©ã ã§ã®å®äœéšãã玹ä»ããŸãã ãããã¯ãéçºéšã®çµç¹æ§æïŒâ»äžéšç°¡ç¥åããŠããŸãïŒ ãããŒã POå¶ãå°å
¥ã®èæ¯ ãããŒã POå¶ãå°å
¥ã®ç®çã¯äž»ã«ä»¥äžã®2ç¹ã§ããã â POã®ããã«ããã¯åã®é²æ¢ â¡ããŒã ã®ãæææ±ºå®æ©èœãã匷ããèªå·±çµç¹åãäžå±€æ·±ãã ãããŒã POå¶ãå°å
¥åã¯ãåºæ¬çã«ã¯åããŒã ã®ã¹ã¯ã©ã 掻åã«ãããŠãåå
¥æ¡ä»¶ãè©³çŽ°ä»æ§ãéœåºŠPOã«ç¢ºèªãããŸãååžã®äžã§ããã¯ãã°ã¢ã€ãã ãäœæããŠããŸãããã ãã®çµæãããŒã ã®æææ±ºå®ã«é¢ããŠPOãžã®äŸå床ãé«ããªããåŸ
ã¡ã®ããŒã ããçºçããPOãããã«ããã¯ã«ãªãããšãå¢ããŠããŸããŸããã ãã®ããã«ããã¯ãè§£æ¶ããããã«ãããŒã ã®æææ±ºå®ãçå
ããŠãã圹å²ãšããŠãããŒã POå¶ããå°å
¥ããããšã決ããŸããã å
ã
ã¯1éçºè
ã ã£ãäžã§ããŒã POãšå
Œä»»ã«ãªã£ããããèŠåŽããç¹ãéåžžã«å€ãã£ãã§ãããã¹ã¯ã©ã ã«ãããæ§ã
ãªã€ãã³ãã§ããŒã ãèªç«çã«åããå Žé¢ãå¢ãããšæããŠããŸãã ã¹ã¯ã©ã ã®äžã§ã®åã åŒç€Ÿã®ã¹ã¯ã©ã ã§ã¯ãåºæ¬çã«ä»¥äžã¹ã±ãžã¥ãŒã«ã§æŽ»åãè¡ã£ãŠããŸãã ãã®äžã§ãå®éã«ããŒã POãšããŠã©ã®ãããªåããããŠããã®ãã玹ä»ããŸãã ã1é±éã¹ããªã³ãã®ã¹ã±ãžã¥ãŒã«ã ææ ã¹ããªã³ãã¬ãã¥ãŒ(15:00 ~ 16:00) ã¹ããªã³ãã¬ããã¹ãã¯ãã£ã(16:00 ~ 17:00) ã¹ããªã³ããã©ã³ãã³ã°1(17:00 ~ 17:30) ã¹ããªã³ããã©ã³ãã³ã°2(17:30 ~ 18:30) ç«æ ã¹ã¯ã©ã ãã¹ã¿ãŒäŒè°(11:00~12:00) ãªãŒããŒãªãŒã«ãªãã¡ã€ã³ã¡ã³ã(16:00 ~ 17:00) æ°Žæ (ããŒã å
)ãªãã¡ã€ã³ã¡ã³ã æšæ POäŒè°(17:30 ~ 18:00) ã¹ããªã³ããã©ã³ãã³ã° ã¹ããªã³ããã©ã³ãã³ã°ã§ã¯äž»ã«ãèªããŒã ã®ã¹ããªã³ããŽãŒã«ã®æ±ºå®ãšããŒã éã§ã®ã¢ã€ãã ã®èª¿æŽãäž»å°ããŠè¡ã£ãŠããŸãã éçºéšå
šäœã®ã¹ããªã³ããŽãŒã«ã«é¢ããŠPOããå
±æããã£ãåŸãåããŒã POãäžå¿ã«ãŽãŒã«éæã«åããŠã©ã®ããã«1é±é掻åããŠããã®ãè°è«ãšæ±ºå®ãããŸãã ã¹ããªã³ããŽãŒã«ã«çŽæ¥é¢äžããªãã¢ã€ãã (åŒç€Ÿã§ã¯SREé¢é£ãèšæã®é¡§å®¢å¯Ÿå¿ãã«ãŒãã£ã³æ¥åãªã©)ãããããŸãåããŒã ã®ããã·ãã£ãéãã®ã§ãèªããŒã ã®ç¶æ³ãšå
šäœã®åªå
é äœã®äž¡æ¹ãèæ
®ããŠæææ±ºå®ãè¡ã£ãŠããŸãã 以åã®ã¹ããªã³ããã©ãã³ã°ã§ã¯ãåããŒã æ¯ã«çºèšããã¡ã³ããŒãå
容ã«åãããã£ããããã¿ã€ã ããã¯ã¹å
ã«ã¹ããªã³ããŽãŒã«ã決ããããšã«éåžžã«èŠåŽããŠããŸãããã ä»ã§ã¯æææ±ºå®ããªãŒãããããŒã POãšPOãäžå¿ã«åªå
é äœã«ãã©ãŒã«ã¹ããè°è«ããããšã§ã¹ã ãŒãºã«æ±ºå®ã§ããããã«ãªã£ãŠããŸããã ãªãŒããŒãªãŒã«ãªãã¡ã€ã³ã¡ã³ã ãªãŒããŒãªãŒã«ãªãã¡ã€ã³ã¡ã³ãã§ã¯ãæ°ã¶æå
ãèŠæ®ããåªå
é äœä»ããšãªãã¡ã€ã³ã¡ã³ãã®æ
åœããŒã ã®å²ãæ¯ãã«ã€ããŠè°è«ããŠããŸãã 以äžã®ããã«ãªãã¡ã€ã¡ã³ãã®æ
åœãæ¹æ³ã«é¢ããŠã¯ãããŒã ãæææ±ºå®ãè¡ãããšãæšå¥šãããŠããŸãã (åŒçšå
ïŒå€§èŠæš¡ã¹ã¯ã©ã Large-Scale Scrum(LeSS) ã¢ãžã£ã€ã«ãšã¹ã¯ã©ã ãå€§èŠæš¡ã«å®è£
ããæ¹æ³) ãªãŒããŒãªãŒã«PBRã§ã¯ããã詳现ãªãªãã¡ã€ã³ã¡ã³ãããè€æ°ããŒã PBRãã§è¡ããããåäžããŒã PBRãã§è¡ãããæ±ºãããããã¯POã§ã¯ãªãããŒã ã«æ±ºããŠãããããšã§ãèªå·±çµç¹åãä¿ããPOã®äœæ¥ãæžãããŸãã 以åã®ãªãŒããªãŒã«ãªãã¡ã€ã¡ã³ãã¯ãåºæ¬çã«POããããžãã¹äžã®åªå
é äœã«ã€ããŠå
±æãåããäžã§ãã¢ãµã€ã³ããŒã ããªããšãªã決ãŸã£ãŠããããŒã ãæææ±ºå®ãè¡ãããšãå°ãªãç¶æ
ã§ããã ãããŒã POå¶ãå°å
¥åŸããŒã ã®èªå·±çµç¹åãå°ããã€é²ã¿ãPOããã®å
±æå
容以å€ã«ãããŒã ããéçºã«é¢ããèŠæ(ex.æè¡çè² åµã®è§£æ¶ãªã©)ãããã ã¢ããã§åºãããšãå¢ããŸããã ä»ã§ã¯ããããå«ãå
šãŠã®åªå
é äœãæ€èšããäžã§ãåããŒã ããªãã¡ã€ã¡ã³ã察象ã®ã¢ã€ãã ã«çæã§ããããªã¿ã€ãã³ã°ãå
±æããæ
åœããå¯èœæ§ãé«ãããŒã ããªãã¡ã€ã³ã¡ã³ããè¡ããããã«ããŒã éã§èª¿æŽããŠããŸãã åæã«ãPOããã¯éçºã®WHY(ãªãä»å¿
èŠãªã®ããããã¿ã€ãºãææ¥)ãšWHAT(ãŠãŒã¹ã±ãŒã¹ãã¹ããŒãªãŒãèŠä»¶)ã«ã€ããŠå
±æãåããåŸã®ããŒã å
ã®ãªãã¡ã€ã¡ã³ãã§æŽ»ãããŠããŸãã ãªãã¡ã€ã³ã¡ã³ã ãªãã¡ã€ã³ã¡ã³ãã®åã«ããªãŒããŒãªãŒã«ãªã©ã§å
±æãåããå
容ãããšã«ãããŒã POãåå
¥æ¡ä»¶ãæèšããŠããã¯ãã°ã¢ã€ãã ãäœæããŠããŸãã èŠç©ããæã¯ããŒã POããã¡ã·ãªããŒã·ã§ã³ãè¡ããªãããã€ã³ããç®åºããŠããŸãã éçºè
ã®çåç¹ã«å¯ŸããŠã¯ããªãŒããŒãªãŒã«ãªãã¡ã€ã³ã¡ã³ãçã§å
±æãåããæ
å ±ãå
ã«ããŒã POãè§£æ¶ããããšã§ãããŒã ç¬åã§ã¢ã€ãã äœæã§ããããšãå¢ããŸããã ãŸã ãŸã æ¹åç¹ã¯ãããŸããã以åãšæ¯ã¹ããšPOãä»ããæææ±ºå®ãå°ãªããªããããŒã ãäž»äœçã«åå
¥æ¡ä»¶ãè©³çŽ°ä»æ§ã«é¢ããŠæææ±ºå®ã§ããããã«ãªããŸããã ãŸãã以åã¯HOW(ã©ã®ããã«å®è£
ãããã)ã«æèãåããã¡ã§ããããæææ±ºå®ã®åæ°ã責任ãå¢ããããšã§ãããŒã å
šäœãšããŠãããã¯ãã®WHYãWHATã«ãã©ãŒã«ã¹ããè°è«ã掻çºã«ãªããéçºãžã®åãåãæ¹ãå€ããå§ããŠããŸãã ããŒã POãéçºè
ãšå
Œä»»ãªã®ã§ãæè¡çã«å°éæ§ãé«ãã¢ã€ãã ã«é¢ããŠãæææ±ºå®ãã¹ã ãŒãºã«è¡ããå Žé¢ãå¢ããããšãã¡ãªããã®1ã€ã§ããã POäŒè° POäŒè°ã¯åŒç€Ÿãç¬èªã§è¡ã£ãŠããã¹ã¯ã©ã ã®ã€ãã³ãã§ãã POãšåããŒã POãåå è
ã§ãããŒã POãåããããããããã«æ
å ±ãåæããå ŽãšããŠéå¬ãå§ããŸããã å
·äœçã«ã¯ãçŽè¿æ°ã¹ããªã³ãã®èšç»ãã¹ããªã³ãã¬ãã¥ãŒã®èšèšã«ã€ããŠè©±ããŠããŸãã çŽè¿æ°ã¹ããªã³ãã®èšç»ã«é¢ããŠã¯åããŒã ã®æ
å ±ãææ¡ããããã«å§ããŸããã ã¹ããªã³ããã©ã³ãã³ã°ã®å Žã§1é±éæ¯ã®åãã¯ããããŸãããæ¯èŒçé·ããããžã§ã¯ãã«ã¢ãµã€ã³ããããšããããžã§ã¯ãã®çµäºææãèŠãã¥ãããåããŒã ãäžæçã«ã©ã®ããã«é£æºããŠããã¹ããªã®ãææ¡ãèŸãã£ãããã§ãã ã¹ããªã³ãã¬ãã¥ãŒã®èšèšã«é¢ããŠã¯ãã¹ããªã³ãã®ç¶æ³ãå
±æãã€ã€æ¬¡ã®ã¹ããªã³ãã¬ãã¥ãŒã§ã©ã®ãããªãã¢ãè¡ãã®ãäºåã«ããåãããè¡ã£ãŠããŸãã ãã¢ã®æéãéãããŠããã®ã§ãåããŒã ã䜿çšããæéãåªå
é äœã«ã€ããŠè°è«ããŸãã ãŸãã瀟å
ã®ã©ã®ã¹ããŒã¯ãã«ããŒ(å¶æ¥éšãã«ã¹ã¿ããŒãµã¯ã»ã¹éšã®ã¡ã³ããŒ)ããã¢ã«æåŸ
ããã®ããæ±ºããŠããŸããçµæãšããŠãã¹ããªã³ãã¬ãã¥ãŒã§æçãªãã£ãŒãããã¯ãè²°ããå Žé¢ãåŸã
ã«å¢ããŠããŸããã æè¿ã§ã¯ãPOäž»å°ã§ããŒã POã®ã¬ããã¹ãã¯ãã£ããå§ããŸããã æ®æ®µã®ã¬ããã¹ãã¯ãã£ãã¯éçºè
ãšããŠåå ããŠããããããªããªãæ¯ãè¿ããããæ©äŒããããŸããã§ãããããã®æ¯ãè¿ããéããŠéçºéšå
šäœãšããŠPOã¹ãã«ã®åäžãå³ã£ãŠããŸãã 以äžãã¹ã¯ã©ã ã§ã®æŽ»åã®ç޹ä»ã«ãªããŸãã ãã®ä»ã«ãæ¯èŒç倧ããã®ãããžã§ã¯ãã«ã¢ãµã€ã³ãããŠããæã¯ããªãªãŒã¹ã¹ã±ãžã¥ãŒã«ãããžã¡ã³ã/ãQAé
ç®ã®äœæãªã©ãè¡ã£ãŠããŸãã ããŒã POãçµéšããŠæããããš è¯ãã£ãããšãšããŠã¯ãããŒã å
ã§æææ±ºå®ãå®çµã§ããããšãå¢ãããŒã ãšããŠè¿
éã«éçºãè¡ããããã«ãªã£ãããšããããŒã POã ãã§ãªãéçºã¡ã³ããŒãèªåãã¡ã§ãããã¯ããäœãæèãé«ãŸã£ãããšãæããããŸãã å ããŠãããã¯ãã®éçºæ¹æ³ãããããã®å段ã«ããWHYãWHATã«æèãåãããã«ãªãããããããã¯ãã®æäŸäŸ¡å€ã«ãã ãããæã€ã¡ã³ããŒãå¢ãããšæããŠããŸãã å®éã«çŽè¿ã§ã¯ããããã¯ãã®KPIã«éçºéšå
šäœã§ãã©ãŒã«ã¹ããããã«ãããŒã POãäž»äœãšãªãéçºã®KPIãå¯èŠåããããã·ã¥ããŒããäœæãããããžã§ã¯ããå§ããŸããã ãã®ãããªéçºã®ææãå¯èŠåããåãã¯ãããŒã ã¡ã³ããŒã®é¢å¿ãé«ããããä»åŸã®ã¹ã¯ã©ã 掻åã«ãããŠããæ³šåããŠãããããã€ã³ãã®1ã€ã§ãã äžæ¹ã§ãéçºè
ãšå
Œä»»ãªã®ã§éçºãšã®æéé
åã誀ããšããŒã POã®æ¥åã«ååãªæéãå²ãããããŒã ã®åããåæ»ãããŠããŸãããšããããŸããã ç¹ã«ããã¯ãã°ã¢ã€ãã ã®åå
¥æ¡ä»¶ãã¹ããŒãªãŒãæç¢ºã«ãªã£ãŠããªããšããªãã¡ã€ã¡ã³ãã§æéãæŒããŠããŸãã®ã§ãããã¯ãã°ã¢ã€ãã äœæã®æéã確ä¿ããå¿
èŠããããŸãããã¹ããªã³ãäžã«éçºãšã®ãã©ã³ã¹ã調æŽããããšã«é£ãããæããŠããŸãã ãŸãããããžã§ã¯ããããžã¡ã³ãã®ã¹ãã«ãäžè¶³ããŠãããšãã倧ããªèª²é¡ãããã®ã§ãä»åŸã¯ãã¡ã·ãªããŒã·ã§ã³ã仿§ã®æææ±ºå®ã«é¢ããŠPOããã¹ãã«ãåŠãã ããã¹ããŒã¯ãã«ããŒãšã®é£æºã匷ããããã«ç€Ÿå
ã®é£æºãããŒãæŽããŠãããããšæã£ãŠããŸãã ãããã« å®éã«ããŒã POãšãã圹å²ãçµéšããŠã¿ãŠãæææ±ºå®ã®ææ³ãéçºãšã®ãã©ã³ã¹ã®åãæ¹ã«ä»ã§ãé£ãããæããŠããŸãã äžæ¹ã§ããŒã å
ã§æææ±ºå®ãå®çµã§ããããšãå¢ããåœåã®ç®çã§ãã£ãPOã®ããã«ããã¯ãè§£æ¶ã§ããããšã§ãããŒã ãšããŠè¿
éã«éçºã§ãããšããã¡ãªããããããŸããã ä»åŸã¯ããããŒã ã®èªå·±çµç¹åãé²ããŠããããã«ããããŸã§POãæ
ã£ãŠãã圹å²ãå·»ãåã ããã«ããŒã POã®æŽ»èºã®å¹
ãåºããŠãããããšæã£ãŠããŸãã æåŸãŸã§èªãã§ããã ããããããšãããããŸããã Lessã«ãããããŒã ã®ããæ¹ãšããŠãå°ãã§ãåèã«ãªãã°å¹žãã§ããã æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã¯2023幎1æã«æ±äº¬ã«æ°ãã«éçºæ ç¹ãèšç«ããããšã«ãªããç«ã¡äžãã¡ã³ããŒãåéããŠããŸãïŒå¹
åºãããžã·ã§ã³ã§åéããŠããŸãã®ã§ããèå³ããæ¹ã¯ãæ°è»œã«ãå¿åãã ããïŒ æ±äº¬ãžéçºã®æ ç¹æ¡å€§ïŒæ¥æé·ããå€§èŠæš¡SaaSãããã¯ãã®ãšã³ãžãã¢åéïŒ ãŸã ã¹ã¿ã¡ã³ Engineering Handbook ãšããŠãã¹ã¿ã¡ã³ã®éçºäœå¶ã«ã€ããŠäœç³»çã«ãŸãšããããããŒãžãå
¬éããŠããŸãã®ã§ããã¡ããæ¯éã芧ãã ããã
ç®æ¬¡ ã¯ããã« ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãšã¯ react-content-loaderã«ããå®è£
ããªã»ããã䜿çšããæ¹æ³ Create React Content Loaderã§ç¬èªã®ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæã䜿çšããæ¹æ³ ãããã« ã¯ããã« ã¯ãããŸããŠãæ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã®ç¥å°Ÿã§ãã æ®æ®µã¯ã¹ã¯ã©ã ãã¹ã¿ãŒå
Œãšã³ãžãã¢ãšããŠåŒç€Ÿãéå¶ããŠãããšã³ã²ãŒãžã¡ã³ããã©ãããã©ãŒã TUNAG ãéçºããŠããŸãã 2022幎10ææ«ã«TUNAGå
ã®ãã£ããã«ãã¿ã¹ã¯ç®¡çãæ©èœã远å ãªãªãŒã¹ããã¿ã¹ã¯äžèЧã®ããŒãã£ã³ã°UIãšããŠTUNAGã§åããŠã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãå°å
¥ããŸããã ããã§ä»åã¯ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãUXã«ããããã¡ãªãããå®è£
æ¹æ³ãªã©ã玹ä»ããããšæããŸãã ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãšã¯ ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãšã¯ãäžã®ç»åã®ããã«ããŒãã£ã³ã°äžã«è¡šç€ºããã骚çµã¿ã®ãããªãã¶ã€ã³ã®ããšã§ãã äŸ) youtube ã¹ãããŒãã€ã³ãžã±ãŒã¿ãšãã£ãããŒãã£ã³ã°UIãšæ¯èŒããŠããŠãŒã¶ãŒãããŒãã£ã³ã°å®äºåŸã®ã³ã³ãã³ããäºæž¬ã§ãããšããã¡ãªããããããŸãã ãã®çµæããŠãŒã¶ãŒã¯ã¹ãããŒãã€ã³ãžã±ãŒã¿ãããå€ãã®æ
å ±ãåŸãããšãã§ãããããçµæãšããŠäœææéãçããªããšèšãããŠããŸãã ãŸããã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãšããŒãã£ã³ã°å®äºåŸã®ã³ã³ãã³ãã®ãµã€ãºã衚瀺äœçœ®ãå¯èœãªéãè¿ã¥ããããšã§GoogleãWebãµã€ãã®å¥å
šæ§ãç€ºãææšãšããŠå®çŸ©ããŠããCore Web Vitalsã®äžã€ã® CLS ã®åäžã«ãç¹ãããSEOã«ã广ããããŸãã react-content-loaderã«ããå®è£
ä»å㯠react-content-loader ã䜿ã£ãŠã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãå®è£
ããŸãããå
·äœçãªå®è£
æ¹æ³ã説æããåã«react-content-loaderãæ¡çšããçç±ãç°¡åã«è©±ããããšæããŸãã cssã§å®è£
ããããšãå¯èœã§ããããäžèšã®çç±ããreact-content-loaderãæ¡çšããŸããã æ¬æ Œçã«TUNAGå
šäœã§å°å
¥ããåã«æ°æ©èœã®äžéšã§ã³ã¹ãäœã詊ãããã£ããã ãã£ããã®ã¿ã¹ã¯äžèЧã¯åºå®å¹
ã®ãã Create React Content Loader ã䜿çšããããšã§ãç°¡åã« ã¬ã€ã¢ãŠãã·ãã ããªãã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãå®è£
ããããšãã§ãããã(Create React Content Loaderã®äœ¿ç𿹿³ã«ã€ããŠã¯åŸè¿°ããŸã) Create React Content Loader ã䜿çšããããšã§ç°¡åã«ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãå®è£
ããããšãå¯èœã«ãªãã³ã¹ããããŒãã«ãäœããšèãããã ã©ã€ãã©ãªãéåžžã«è»œéã§ãããã ããããã¯ãå
·äœçãªå®è£
æ¹æ³ãèŠãŠãããããšæããŸãã react-content-loaderã¯ã以äžã®2çš®é¡ã®æ¹æ³ã§ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãå®è£
ã§ããŸãã 1. ããªã»ããã䜿çšããæ¹æ³ ããã©ã«ãã§FacebookãInstagramã§äœ¿ãããŠãããã®ãšåããã¶ã€ã³ã®ãã®ãçšæãããŠããŸããããããããã±ãŒãžããimportããã ãã§ç°¡åã«ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ã衚瀺ããããšãã§ããŸãã import React from "react" ; import { Facebook } from "react-content-loader" ; export const MyFacebookLoader = () => < Facebook / >; äŸ ) Facebookã®ããªã»ãã ãã®ä»ã«ãããªã»ãããããã€ãçšæãããŠããã®ã§ãæ°ã«ãªãæ¹ã¯ ãã¡ã ãã芧ãã ããã ãã ãããã®ããªã»ããããã®ãŸãŸäœ¿ã£ãŠããããŒãã£ã³ã°å®äºåŸã«è¡šç€ºãããã³ã³ãã³ããšã¯èŠãç®ãç°ãªãããšãå€ããšæããŸãã ã¹ã±ã«ãã³ã®äžèº«ãã³ã³ãã³ããšã¯ç°ãªã£ãŠããŠããµã€ãºãåãã§ããã°UXãCLSãåäžãããããšãã§ããŸãããå®éã®ã³ã³ãã³ããšåãã«ããããšã§ããUXåäžã誀ã¿ãããé²ãããšã«ç¹ãããŸãã ãã®ãããreact-content-loaderã¯æ¬¡ã®æ¹æ³ã§ç¬èªã®ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæããããšãã§ããŸããTUNAGã§ãæ¬¡ã®æ¹æ³ã䜿çšããŸããã 2. Create React Content Loaderã§ç¬èªã®ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæã䜿çšããæ¹æ³ react-content-loaderã«ã¯ Create React Content Loader ãšããããŒã«ããããç»é¢å³åŽã§ãã¶ã€ã³ãäœæãããšãç»é¢å·ŠåŽã®ã³ãŒãã«åæ ãããã®ã§ãããã䜿çšãããšç°¡åã«ç¬èªã®ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæããããšãã§ããŸãã Create React Content Loader å®éã«ã¯ä»¥äžã®æé ã§è¡ããŸããã Figmaããã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæãããã³ã³ãã³ãã®ç»åãä¿å Create React Content Loaderå³åŽã®ããã¡ã€ã«ãéžæãã«1ã§ä¿åããç»åãã¢ããããŒã èæ¯ã«è¡šç€ºãããã³ã³ãã³ãã®ç»åã«åãããŠã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæ å·ŠåŽã®ãCopy to clipboardãã§ã³ãŒããã³ããŒããReactã®ã³ã³ããŒãã³ãã«è²Œãä»ããããŒãã£ã³ã°UIãšããŠåŒã³åºãã æé ãã²ãšã€ã²ãšã€èŠãŠãããŸãã ïŒ. Figmaããã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæãããã³ã³ãã³ãã®ç»åãä¿å TUNAGã¯ãã¶ã€ã³äœæã«Figmaã䜿çšããŠããã®ã§ãFigmaäžã§ãã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæãããã³ã³ãã³ããéžæããšã¯ã¹ããŒãããŠä¿åããŸãã ããã§ä¿åããç»åã¯ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæããéã«ãµã€ãº(width, height)ãªã©ãåèãšããããã¹ã¯ãªãŒã³ã·ã§ããã§ã¯ãªãå®éã«è¡šç€ºããããµã€ãºã®ç»åãä¿åããŠãã ããã ïŒ. Create React Content Loaderå³åŽã®ããã¡ã€ã«ãéžæãã«1ã§ä¿åããç»åãã¢ããããŒã ïŒ. èæ¯ã«è¡šç€ºãããã³ã³ãã³ãã®ç»åã«åãããŠã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãäœæ ïŒ. å·ŠåŽã®ãCopy to clipboardãã§ã³ãŒããã³ããŒããReactã®ã³ã³ããŒãã³ãã«è²Œãä»ããããŒãã£ã³ã°UIãšããŠåŒã³åºã( SkeltonTaskItem ãšããŠã³ã³ããŒãã³ããäœæ) import React from 'react' import ContentLoader from 'react-content-loader' export const SkeletonTaskItem = () => ( < ContentLoader speed = { 2 } // ã°ã©ããŒã·ã§ã³ã®ã¹ããŒã width = { 320 } height = { 98 } viewBox = '0 0 320 98' backgroundColor = '#F2F6F9' // ã¹ã±ã«ãã³ã®èæ¯è² foregroundColor = '#E1E8EE' // ã°ã©ããŒã·ã§ã³ã®è² > < rect x = "248" y = "25" rx = "0" ry = "0" width = "5" height = "0" / > < rect x = "244" y = "28" rx = "0" ry = "0" width = "3" height = "2" / > < rect x = "215" y = "24" rx = "0" ry = "0" width = "1" height = "0" / > < rect x = "16" y = "16" rx = "0" ry = "0" width = "24" height = "24" / > < rect x = "56" y = "21" rx = "4" ry = "4" width = "210" height = "11" / > < rect x = "56" y = "48" rx = "4" ry = "4" width = "136" height = "8" / > < rect x = "55" y = "73" rx = "4" ry = "4" width = "158" height = "8" / > < rect x = "146" y = "23" rx = "0" ry = "0" width = "0" height = "1" / > < /ContentLoader > ) ã¿ã¹ã¯äžèЧã®ããŒãã£ã³ã°UIãšããŠäœ¿çšãããã£ãã®ã§ SkeltonTaskItem ãè€æ°ååŒã³ã ãäžäžã« border ãåœãŠãŠè¡šç€ºããŠããŸãã ãããã« ä»åã¯ãã£ããã®äžéšã«ã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ãå°å
¥ããŸãããããããã¯ã¿ã€ã ã©ã€ã³ãå¶åºŠãšãã£ãä»ã®æ©èœã«ãå°å
¥ããŠããããšã§ãTUNAGå
šäœã®ãŠãŒã¶ãŒäœéšã®åäžã«ç¹ããŠãããããšæããŸãã ããã¯ãšã³ããããã³ããšã³ãã®ããã©ãŒãã³ã¹æ¹åã§å®éã®åŸ
ã¡æéãçãããããšã倧äºã§ãããã¹ã±ã«ãã³ã¹ã¯ãªãŒã³ã®ããã«å®éã®åŸ
ã¡æéãããçãæããŠãããããããªãŠãŒã¶ãŒäœéšã®æ¹åãç©æ¥µçã«ããŠãããããšæããŸãã æåŸãŸã§èªãã§ããã ããããããšãããããŸããã ãã®èšäºãå°ãã§ãçæ§ã®åèã«ãªãã°å¹žãã§ãã æ ªåŒäŒç€Ÿã¹ã¿ã¡ã³ã¯2023幎1æã«æ±äº¬ã«æ°ãã«éçºæ ç¹ãèšç«ããããšãšãªããç«ã¡äžãã¡ã³ããŒãåéããŸãïŒå¹
åºãããžã·ã§ã³ã§åéããŠããŸãã®ã§ããèå³ããæ¹ã¯ãæ°è»œã«ãå¿åãã ããïŒ æ±äº¬ãžéçºã®æ ç¹æ¡å€§ïŒæ¥æé·ããå€§èŠæš¡SaaSãããã¯ãã®ãšã³ãžãã¢åéïŒ www.wantedly.com ãŸã ã¹ã¿ã¡ã³ Engineering Handbook ãšããŠãã¹ã¿ã¡ã³ã®éçºäœå¶ã«ã€ããŠäœç³»çã«ãŸãšããããããŒãžãå
¬éããŠããŸãã®ã§ããã¡ããæ¯éã芧ãã ããã engineering-handbook.stmn.co.jp