æ¨å¹´ã®6æã«å ¥ç¤¾ãã Web Engineer ã® @ravelll ã§ãã令å2å¹´ã«ãªãã¾ããããã©ãã§ããï¼
ä»åã¯ç§ã以åæå±ãã¦ããæ°è¦äºæ¥éçºãæ ããã¼ã 㧠Feature Management ã«å©ç¨ãã LaunchDarkly ã®ç´¹ä»ã¨å©ç¨äºä¾ã«ã¤ãã¦æ¸ããã¨æãã¾ãã
LaunchDarkly ã¨ã¯
LaunchDarkly 社ãéå¶ãã Feature Management Platform ã§ãã
LaunchDarkly ãå©ç¨ãããã¨ã§ã«ããªã¢ãªãªã¼ã¹ã A/B ãã¹ããªã©ãå®ç¾ãã Feature Toggles*1 ã®ä»çµã¿ã容æã«ã½ããã¦ã§ã¢ã¸çµã¿è¾¼ããã¨ãã§ãã¾ãã
å°å ¥ããéã®ã³ã¼ãã¯ãä¾ãã°ä»¥ä¸ã®ããã«ãªãã¾ãã
if ld_client.variation("enable-something-updated", { key: user.id } , false) do_something_updated else do_something end
ãã㯠LaunchDarkly ã«è¨å®ãã Feature Flag ã®ãã¡ "enable-something-updated" ã¨ããååã®ãã®ãåç §ããè©ä¾¡ããã³ã³ããã¹ãã¨ãªãã¦ã¼ã¶ã¼ãèå¥ãããã®ã¯ user.id ãFlag ã®ããã©ã«ãå¤ã¯ falseãã¨ãããã¨ã表ãã¦ãã¾ãããã® Flag ã®å¤ã Web ä¸ã®ã³ã³ã½ã¼ã«ããå¤æ´ãããã¨ãã§ãã¾ãã
æ´ã«ãFlag ã®å¤ã¯æ§ã
ãªæ¡ä»¶ãå
ã«åºãåãããã¨ãã§ãã¾ãããã®æ¡ä»¶ã«ã¯ãã¾ã #variation
ã®ç¬¬2å¼æ°ã«æ¸¡ããå±æ§ãå©ç¨ãããã¨ãã§ããä¸è´ãæ£è¦è¡¨ç¾ãããã大å°é¢ä¿ãªã©ã®æ¡ä»¶ä»ãããããã¨ãã§ãã¾ããã¾ãå
¨ä½ã® 30% ã®ã¦ã¼ã¶ã¼ã¸ true ãè¿ããã¨ãã£ãæ¡ä»¶ä»ããå¯è½ã§ãã
Flag ã®å¤ã¯å¿ ããã boolean ã§ããå¿ è¦ã¯ãªããString ã JSON (!) ãªã©ã® type ãé¸æå¯è½ã§ãå¤ã3ã¤ä»¥ä¸ãåºãåãããã¨ãã§ãã¾ãããã ãã1ã¤ã® Flag ã§è¤æ°ã® type ã®å¤ãåºãåãããã¨ã¯ã§ãã¾ããã
å©ç¨ã§ããç°å¢ã«ã¤ãã¦ã¯ã21ã®è¨èªããã©ãããã©ã¼ã ï¼å ¬å¼ãã¼ã¸æ å ±ï¼ã«å¤§ã㦠SDK ãç¨æããã¦ãã*2ãWeb ã¢ããªã±ã¼ã·ã§ã³ã«éããå¤ãã®ã½ããã¦ã§ã¢ããå©ç¨ãããã¨ãã§ããã§ãããã
ãã詳ããæ©è½ã®èª¬æã¯å ¬å¼ã®ããã¥ã¡ã³ãã«è²ãã¨ãã¦ãå©ç¨äºä¾ã®è©±ã«ç§»ãã¾ãã
Quipper ã§ã®å©ç¨äºä¾
ä»åã¯ããã Microservices ç°å¢ã«ãããããã¯ãã§èªè¨¼ãè¡ãããã¯ã¨ã³ããµã¼ãã¹ã移è¡ããéã®å©ç¨äºä¾ãç´¹ä»ãã¾ãã
"Web ãµã¼ãã¹" ã®ãããªãããã "ãµã¼ãã¹" 㨠Microservices ã®æèã«ããã "ãµã¼ãã¹" ãæ··å¨ããã¨ãããããã®ã§ã以éã§ã¯æ¬¡ã®ããã«æ¸ãåãã¾ãã
- Service: Microservices ã®æèã«ããã Service
- ãããã¯ã: "ã¯ã¦ãªããã°" ã "ã¹ã¿ãã£ãµããª" ãªã©ããããã Web ãµã¼ãã¹
èæ¯
å½ææå±ãã¦ãããã¼ã ã®ãããã¯ãã¯ã以ä¸ã®ãã㪠Microservices ã§æ§æããã¦ãã¾ããã
å³ãããåããéããèªè¨¼ã«ã¤ãã¦ã¯ä»¥åããåå¨ãã¦ããä»ã®ãããã¯ããææãã Service ãå©ç¨ãã¦è¡ã£ã¦ãã¾ãããããã«ãããä»ã®ãããã¯ãã¨ã®ä¾åãçã¾ããã¦ã¼ã¶ã¼ã«é¢ããæ©è½éçºãç§ãã¡ãã¼ã ã®è¦æ±ã«å¿ãã¦æè»ã«è¡ããã¨ãé£ãããªã£ã¦ãã¾ãããã¾ãä¾åå ã®ãããã¯ãã«ç¨¼ååæ¢ãä¼´ãã¡ã³ããã³ã¹ãè¡ããã¨ãããã°ç§ãã¡ã®ãããã¯ããå·»ãè¾¼ã¾ãã¦ãã¾ãã¨ããåé¡ãããã¾ããã
ãããã®åé¡ã解æ¶ãããããç§ãã¡ã®ãã¼ã ã§ç¬èªã«ã¦ã¼ã¶ã¼ã«é¢ããå¦çã責åã¨ãã Service ï¼ä»¥éãã® Service ã Users Service ã¨å¼ã³ã¾ãï¼ãéçºãããããç¨ãã¦èªè¨¼ãè¡ãããã« Service ã®ç§»è¡ãè¡ããã¨ã¨ãã¾ããã
ä¸ã®å³ã¯ç§»è¡å¾ã®ã¢ã¼ããã¯ãã£ã®ã¤ã¡ã¼ã¸ã§ãã
移è¡ãã¼ã«ã®æ¤è¨
人éããã£ãã¨ã³ããããç©ã¿å¹¾ææ¥ãã¤ãã« Users Service ã¯å®æãã¾ããã
ãã¦ãåé¡ã¯ã©ã®ããã«èªè¨¼ã®çµè·¯ã Users Service ã使ãããã«åãæ¿ããããã¨ãããã¨ã§ãã
ããã§ã®è¦æ±ã»å¶éã¨ãã¦ã¯ä»¥ä¸ã®ãããªäºæãããã¾ããã
- ãããã¯ã㯠24/365 ã§ã¦ã¼ã¶ã¼ã«ä½¿ããããã®ã§ã¯ãªãããã¦ã¼ã¶ã¼ã®å©ç¨ä¸ã«åé¡ãçºçãããã¨ã¯æ¥µåé¿ãããããã®ãããUsers Service ã¸ã®ç§»è¡æéä¸ã«ä½ãåé¡ãèµ·ããéã«ãã°ããæ§çµè·¯ã«æ»ããããã«ããã
- ã¦ã¼ã¶ã¼ããããã¯ããå©ç¨ããæé帯ã«éçºè å ¨å¡ããªãã£ã¹ã«å± ãªãå¯è½æ§ããããããæ§ç°å¢ã¸ã®åãæ¿ãã¯ã³ã¼ãã®ãããã¤ã社å åãã®ç®¡çãã¼ã«ã使ããã«è¡ããã
- çµè·¯ãåãæ¿ããããã®ä»çµã¿ãèªåãã¡ã§ã¼ãããä½ãã¡ã³ããã³ã¹ãã¦ãããã¨ã¯éçºãªã½ã¼ã¹ã®é¢ããé¿ããã
- ååã® @ujihisa 謹製㮠Ruby ç¨ Darklaunch ã¢ã¸ã¥ã¼ã«*3ã¯ããããããã«ä¾åãã社å ã©ã¤ãã©ãª gem ãããããå¿ è¦ã¨ããã¤ã³ãã©ãªã©ã®çç±ããå©ç¨ããªã*4
ããããè¸ã¾ãã¦ããã¤ãã® Feature Toggles ãå®ç¾ãããããã¯ããæ¤è¨ãã¾ããããå°æ¥çã«ã¦ã¼ã¶ã¼ã®å±æ§ã«å¿ããç´°ã㪠Feature Management ãè¡ãããã¨ããè¦æ±ãæºãããã¨ãå¾æ¼ãããLaunchDarkly ãæ¡ç¨ãããã¨ã¨ãªãã¾ããã
LaunchDarkly ã®å°å ¥
ããã¨æ±ºã¾ãã°æ©éå°å ¥ã§ãã
å°å ¥å¯¾è±¡ã®ã¢ããªã±ã¼ã·ã§ã³ã¯ Ruby on Rails 製ã®ã¢ããªã±ã¼ã·ã§ã³ã§ãHTTP Server ã«ã¯ Unicorn ãå©ç¨ãã¦ãã¾ãããå ¬å¼ããã¥ã¡ã³ãã«æ¸ããã¦ãã¾ãããruby ã® SDK ãã LaunchDarkly ã¸ã®ã³ãã¯ã·ã§ã³ã¯ Unicorn ã®å worker ãã¨ã«å¼µããã¨ãå¼·ãæ¨å¥¨ããã¦ãã¾ãã
ã¨ããããCI ãªã©ä¸é¨ã®ç°å¢ã§ã¯ Unicorn ã¯å©ç¨ãããªããããUnicorn ã®è¨å®ãã¡ã¤ã«å ã§å®ç¾©ãã client ãç´ æ´ã«å©ç¨ããã¨å®è¡æããã¹ãæã« client ãåç §ã§ããã¨ã©ã¼ã¨ãªã£ã¦ãã¾ããã¨ãåããã¾ããã
ãã®åé¡ã«ã¯ãclient ãåå¨ããªãå ´å㯠Flag ã®å¤ãè¦ãã« false ãè¿ãå¦çãæãã èã wrapper module ãä½æã使ããã¨ã§å¯¾å¿ãã¾ããã
module FeatureTogglable def launch_darkly_variation_for(key:, user:) if Rails.configuration.respond_to?(:ld_client) Rails.configuration.ld_client.variation(key, user, false) else false end end end
Service ã®ç§»è¡
移è¡ã¯ä»¥ä¸ã®æé ã§è¡ãã¾ããã
- ããã¾ã§ã®èªè¨¼å¦çã«å ããUsers Service ãå©ç¨ããèªè¨¼å¦çãæ¸ãããã®éãå¦çã®çµè·¯ã LaunchDarkly ã§åãæ¿ããããããã«ãã
- 両æ¹ã®å¦ççµè·¯ã§æå¾ éãã®åä½ããããã¨ãéçºç¨ã®ç°å¢ã§ç¢ºèªãã
- ããã¾ã§ã®èªè¨¼å¦çãå©ç¨ãããããã« Flag ã®å¤ãè¨å®ããã³ã¼ããæ¬çªç°å¢ã«ãããã¤ãã
- ã¦ã¼ã¶ã¼ãå©ç¨ãã¦ããªãæé帯㫠Flag ãå¤ãå¤æ´ããUsers Service ãå©ç¨ããå¦ççµè·¯ã§æå¾ ããåä½ããããã¨ã確èªãã
- ã¦ã¼ã¶ã¼ã« Users Service çµç±ã®èªè¨¼ãå©ç¨ãã¦ããããåé¡ãèµ·ããªããã¨ãè¦å®ããä¸ãä¸åé¡ãèµ·ãããããã« Flag ãæ´æ°ãã¦ããã¾ã§ã®èªè¨¼å¦çã®çµè·¯ã«æ»ã
çµæãçµè·¯ãæ»ããã¨ããªããç¡äºã« Service ã移è¡ãããã¨ãã§ãã¾ããð
ä»ã«ãã¦æãã¨ãUsers Service å´ã§åé¡ãçºçããã Flag ã®å¤ã LaunchDarkly ã® API ããæ´æ°ãã¦å¦ççµè·¯ãæ»ããããªä»çµã¿ãå ¥ãã¦ããã°ããç¤ç³ã§ãããã
ã¡ãªã¿ã«ãå ¨ã¦ã¼ã¶ã¼ã§ã¯ãªãã¹ã¿ããç¨ã®ã¢ã«ã¦ã³ãã ãã対象㫠Flag ã®å¤ãæ´æ°ããã°æé帯ãåããå®å ¨ã«ç¢ºèªãã§ããã®ã§ã¯ï¼ã¨æãããããããã¾ããããFeature Toggle ãããç®æããã°ã¤ã³ãããæåã«ããããã«ã¦ã¼ã¶ã¼ãä¸æã«èå¥ããæ å ±ãéä¿¡ãããã¨ãã§ããå ¨ã¦ã¼ã¶ã¼ã対象ã¨ããããããã¾ããã§ããã
ã¾ã¨ã
ä»å㯠Feature Management Platform ã§ãã LaunchDarkly ã«ã¤ãã¦ããã®ç°¡åãªæ¦è¦ã¨ Quipper ã§ã®å©ç¨äºä¾ãç´¹ä»ãã¾ããã
ç¾å¨ã¯åã以åã«æå±ãã¦ãããã¼ã ã®æ ãè¶ ãã¦å¥ã®ãã¼ã ã§ãå°å ¥ãé²ãã§ããã¨ããã§ãä»å¾ã®å±éã«ã¯ã¯ã¯ã¯ãã¦ããã¨ããã§ãã
LaunchDarkly ãåãããä»ã®ç¾å ´ã§ã® Feature Management ã®äºä¾ããã²ç¥ãããã¨æã£ã¦ããã®ã§ãå社ç¥è¦ããæã¡ã®ããã¯ã³ã½ãã¨ï¼ãã¡ããå ¬ç¶ã¨ã§ãï¼ï¼å ±æãã¦ããã ããã¨å¬ããã§ãã
ã¤ãã³ãã®ãæ¡å
2020å¹´2æ5æ¥(æ°´)ã«ãã¹ã¿ãã£ãµããª/Quipper Product Meetup #4 ãéå¬ãã¾ãï¼ ä»åã®ãã¼ãã¯ã¢ãã¤ã«éçºã§ã以ä¸ï¼ã¤ã®ã»ãã·ã§ã³ããå±ãããäºå®ã§ãã
- ã¹ã¿ãã£ãµããªENGLISH ã¢ãã¤ã«ãã¼ã ã®æè¡æ¦ç¥
- ã¹ã¿ãã£ãµããªENGLISHã®ä»ã¨æ»ãã®éçº~MotionLayoutå ¥ãã¦ã¿ã~
- iOS app meets GraphQL
- Baby steps to improve architecture in Study Sapuri Android
çæ§ã®ãåå ããå¾ ã¡ãã¦ããã¾ãã ãç³ãè¾¼ã¿ã¯ä»¥ä¸ãããé¡ããããã¾ãï¼
ããã§ã¯ï¼
*1:Feature Toggles ã«ã¤ãã¦ã¯ Pete Hodgson æ°ãæ¸ãããè¨äºãèªãã¨å¤§æ ãã¤ãããã§ããã https://martinfowler.com/articles/feature-toggles.html
*2:github.com/launchdarkly ãè¦ãã¨å ¬å¼ãã¼ã¸ã®ãªã¹ãã«ãªãè¨èªã»ãã©ãããã©ã¼ã ã® SDK ããµã³ãã«ã³ã¼ããããã¾ãã
*3:ã¦ã¼ã¶ã¼ã® ID ãªã©ãæ¡ä»¶ã« boolean ãåºãåããã·ã³ãã«ãª Feature Toggles ãå®ç¾ã§ãããã¼ã«ã社å ã§ããã¼ã«å©ç¨ãã¦ããã
*4:ãããæ¡å¼µãã¦ä¸è¬åããæ¹æ³ãããã¾ãããããã®ç¤¾å ã©ã¤ãã©ãªã¯ããã¾ã§æåæãæ¯ããå®ç¨çãªè©¦ä½åã¨ããä½ç½®ã¥ãã§ãæ±ç¨ãããã¯ããå©ç¨ãã¦è§£æ±ºããæ¹åã«åããããã¨ããææãããã¾ããã