Features Flag

Hãy tưởng tượng, team của bạn đang cần xử lý 1 tình huống như thế này:


Tình huống: Application của công ty đang chạy ổn định, nhưng người dùng phàn nàn UI quá rắc rối, do đó chúng ta phải re-design lại 1 số trang

Sau khi đã có design mới, quá trình implement các trang này khá lâu. Để PM và QA có thể test được, ta phải implement các trang này, kết nối với data thật hoặc data ở môi trường Staging.

Yêu cầu: Sau khi PM xác nhận, QA đã test xong, ta sẽ cho 1 số beta user dùng thử UI mới trước, còn lại vẫn dùng UI cũ. Sau một thời gian, ta sẽ cho toàn bộ người dùng sử dụng UI mới

Trong quá trình implement các trang này, ta vẫn phải bảo trì, sửa đổi và nâng cấp application cũ.

Redesign hệ thống luôn luôn là chuyện đau đầu

Một trong những cách đơn giản nhất là tạo 1 branch riêng để implement việc re-design này. Sau đó, khi implement xong thì ta có thể merge vào branch chính.

Tuy nhiên, với những thay đổi lớn như vậy, việc merge code/setup về lâu dài sẽ khá phức tạp. Ta cũng khó mà cho beta user dùng thử design mới, vì họ không thể vào môi trường staging.

Do vậy, ta có 1 cách hay và hiệu quả hơn nhiều, đó là dùng feature flag.

Feature Flag là cái chi chi?

Nói đơn giản, Feature Flag là 1 kĩ thuật cho phép developer thay đổi cách hoạt động của ứng dụng, mà không cần phải sửa code (ngạc nhiên chưa).

Nghe cao siêu như vậy chứ kĩ thuật này không hề phức tạp chút nào. Ta sẽ sử dụng một biến, xem nó như cờ (flag) để quyết định luồng chạy của ứng dụng.

Code ở đây cũng khá đơn giản thôi, dựa vào giá trị SHOW_NEW_UI là true hay false mà ta sẽ hiển thị UI cũ hay UI mới!

function showPages() {
  // ... Show UI cũ
}

function showPagesV2() {
  // Show UI mới, đang code
}


// Code cũ, trước khi dùng feature flag
function showUI() {
  showPages() // Show UI cũ
}

// Code mới, sau khi có feature flag
function showUI() {
  // Feature flag tên SHOW_NEW_UI, lưu vào variable
  const SHOW_NEW_UI = true;

  if (SHOW_NEW_UI) {
     showPagesV2()
  } else {
     showPages() // Show UI cũ
  }
}

Tới đây hẳn bạn đọc sẽ thắc mắc: Ủa nếu vậy muốn thay đổi hoạt động của ứng dụng, ta cũng phải sửa code để thay đổi biến SHOW_NEW_UI sang false hoặc true mà? Để làm được chuyện đó, chúng ta sẽ không lưu giá trị của feature flag SHOW_NEW_UI trong code, mà lưu ở … chỗ khác cơ!

Lưu trữ feature flag ở đâu?

Feature flag được dùng để thay đổi cách hoạt động của một chương trình. Do vậy, để có thể dùng feature-flag hiệu quả, ta phải tìm cách thay đổi giá trị của Flag đó, mà không cần thay đổi code.

Do vậy, feature flag thường được lưu trữ như sau:

  • Lưu trữ trong code, mỗi khi sửa phải deploy lại code
  • Lưu trữ trong configuration file (web.config trong C#, .env trong NodeJS) hoặc biến môi trường. Khi cần sửa chỉ cần sửa config và chạy lại
  • Lưu trữ trong 1 số service bên ngoài, developer/PM có thể vào và bật/tắt flag này
Ngày xưa công ty mình dùng launchdarkly, PM hoặc dev chính có quyền vào thay đổi flag

Lúc này, feature flag có thể được dùng như sau:

function showUI() {
  // Dùng hàm isFlagEnable để lấy giá trị flag, thay vì hardcode
  const SHOW_NEW_UI = isFlagEnable('show-new-ui');

  if (SHOW_NEW_UI) {
     showPagesV2()
  } else {
     showPages() // Show UI cũ
  }
}

isFlagEnable(flagName) {
  // Lấy giá trị flag từ config hoặc biến môi trường
  const flagEnable = Env[flagName] || Config[flagName]; 
  // Lấy giá trị flag từ 1 service nào đó
  flagEnable = flagService.getFlag(flagName) 
  
  return flagEnable
}

Ứng dụng của Feature Flag

Các bạn thấy không, Feature Flag chỉ là 1 kĩ thuật đơn giản, nhưng ta có thể làm được khá nhiều hay ho với nó:

  • Code chưa hoàn chỉnh ta cũng có thể deploy được, chỉ cần set feature flag thành false là code đó sẽ không chạy
  • Set feature flag khác nhau ở mỗi môi trường khác nhau. Ví dụ flag đó là true ở môi trường test và stage,  cho PM và QA có thể tha hồ test, không ảnh hưởng đến môi trường production.
  • Khi gắn feature flag, ta nên truyền thêm context và thông tin người dùng. Do vậy, ta có thể show tính năng mới cho beta user, cho 1 số người dùng được chỉ định.
isFlagEnable(flagName) {
  // Lấy tên, email của người dùng hiện tại
  const currentUser = userService.getCurrentUser(); 
  
  // Kiểm tra xem người dùng hiện tại
  // có được dùng chức năng có tên "flagName" không
  const flagEnable = flagService.getFlag(flagName, currentUser) 
  
  return flagEnable
}
Với feature flag, ta có thể roll out dần tính năng cho người dùng

Một số kinh nghiệm khi dùng feature-flag

Ngoài ra, mình còn 1 số kinh nghiệm nho nhỏ khi dùng feature flag

  • Đặt tên flag dễ hiểu: Tên flag cũng như tên biến vậy, các bạn nên viết rõ ràng flag này dùng cho chức năng gì, chứ đừng ghi “flagA”, “flagB” sau này kiểm tra lại mệt lắm đấy
  • Gắn vô nhớ gỡ: Khi thêm 1 flag vào code, các bạn nên tạo ticket/note lại để gỡ flag đó ra khỏi code sau này. Ví dụ các bạn đã code xong chức năng mới, thay vì để flag đó true hoài thì hãy … xoá luôn flag đó, sửa lại code là được
  • Hạn chế độ phức tạp: Đôi khi, flow của ứng dụng sẽ khá phức tạp. Nếu dùng Feature Flag, bạn sẽ thêm if/else vào nên càng phức tạp hơn. Để hạn chế, bạn nên code chức năng mới trong hàm/mobile mới, sau đó dùng flag để show/UI những UI gọi code mới đó
  • Cho phép PM/QA sửa feature-flag: Một số tool quản lý feature-flag có kèm theo dashboard, phân quyền, cho phép ta phân quyền những người được đổi flag. Theo kinh nghiệm của mình cứ cho PM/QA và đổi flag khi cần để họ test. Nếu ổn thì PM cũng có thể bật flag trên Production để relase 1 tính năng luôn.

 

Nguồn: Tôi đi code dạo

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất /  Thay đổi )

Google photo

Bạn đang bình luận bằng tài khoản Google Đăng xuất /  Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất /  Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất /  Thay đổi )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.