Việc xây dựng và phát triển phần mềm là một hành trình dài. Một mặt cần đáp ứng nhu cầu của người dùng, mặt khác thì cần phải thích nghi với những thay đổi liên tục về mặt kỹ thuật nhằm nâng cao chất lượng sản phẩm.
Sơ lược về Garoon
Garoon là một trong những sản phẩm mà Cybozu Việt Nam đang phát triển và là sản phẩm đứng đầu thị trường Nhật Bản, giúp cho các công ty, doanh nghiệp quản lí công việc một cách dễ dàng hơn theo hướng teamwork. Với dòng sản phẩm groupware (collaborative software) của Cybozu - Garoon đã có lịch sử phát triển hơn 15 năm, không ngừng nâng cấp tính năng cũng như cải thiện kỹ thuật, sản phẩm Garoon hiện được sử dụng bởi hàng triệu user trên thế giới.
Trong bài viết này, chúng ta sẽ cùng tìm hiểu về sự phát triển của Garoon để hiểu hơn về những vấn đề gặp phải cũng như những thách thức khi cải thiện hệ thống Front-end.
Để cải tiến và giải quyết những vấn đề tồn đọng sẽ phải tốn nhiều thời gian, công sức cũng như gặp nhiều khó khăn thách thức, nhưng chúng tôi quyết định sẽ thực hiện việc cải tiến.
- Mục đích quan trọng nhất của sự cải tiến là để có thể tăng khả năng mở rộng của sản phẩm và duy trì được sự ổn định lâu dài.
- Ngoài ra, việc cải tiến cũng nhằm giúp cho thế hệ hiện tại cũng như sau này dễ tiếp cận với project Garoon hơn so với việc sử dụng những công nghệ cũ.
Tính phức tạp
Garoon là một product tích hợp hơn 30 application phục vụ cho công việc và mang tính teamwork mạnh mẽ, có thể sử dụng cho môi trường đa dạng nguồn user cũng như đa dạng ngành nghề khác nhau như: sản xuất, cửa hàng, dịch vụ và công nghệ thông tin. Ví dụ như bạn có thể sử dụng Garoon Scheduler để đặt lịch làm việc, book phòng cho nhóm hoặc có thể xem các thông báo mới, tổng hợp thông tin từ các ứng dụng của Garoon thông qua app Portal.
Trải qua quá trình nhiều năm phát triển, bên cạnh những mặt tốt của sản phẩm, một mặt khác khó tránh khỏi là những "di sản" kế thừa từ các thế hệ phát triển. Có thể kế đến như sự phức tạp của codebase, các dependency/thư viện lỗi thời, legacy code, v.v...
Độ phức tạp của source code là một trong các yếu tố gây ảnh hưởng đến quá trình phát triển cũng như bảo trì sản phẩm. Tính phức tạp có thể từ logic của nghiệp vụ, từ kiến trúc (cách tổ chức code) của source code, từ các kỹ thuật / thư viện mà chúng được đưa vào sử dụng trong sản phẩm.
Một ví dụ điển hình cho tính phức tạp trong source code Garoon là nó bao gồm nhiều kỹ thuật front-end khác nhau từ ES5, ES6, TypeScript, React, v.v... với số lượng line-of-code hơn 12.000.
Inline JavaScript
<html>
<button onclick=“handleSubmit();”>Submit</button>
<script>
function handleSubmit() {
// code here
}
</script>
</html>
Trên đây là 1 ví dụ về code inline JS, hiểu một cách đơn giản thì inline JS là bạn viết code JavaScript trộn lẫn với HTML. Việc chứa code inline như vậy khiến lập trình viên khó có thể hiểu được toàn luồng hoạt động của một tính năng nào đó. Chẳng hạn như trên một màn hình có nhiều chức năng với xử lý UI phức tạp liên quan đến nhiều thành phần trên màn hình. Việc đặt code inline phân rã trong các file HTML template không được tổ chức dưới dạng component có thể làm cho developer không biết bắt đầu đọc source code xử lý của màn hình đó từ đâu.
Ngoài ra chúng ta không thể debug hay viết unit test cho code inline. Nếu trong tương lai phần code này được chỉnh sửa để đám ứng thêm chức năng mới có khả năng gây bug tiềm ẩn (degrade) cho chức năng hiện có. Developer tự thực hiện manual test trong lúc phát triển có khả năng "quên" không cover hết các trường hợp của nghiệp vụ phức tạp.
Các thư viện lỗi thời (outdated)
Việc trải qua một thời gian phát triển lâu như vậy dẫn đến có rất nhiều thư viện được sử dụng trong Garoon. Và dĩ nhiên công nghệ đang thay đổi hằng ngày, hôm nay thư viện này là hot trend thì ngày mai đã có thêm thư viện mới ra đời. Một số thư viện đã outdated vẫn đang được sử dụng trong Garoon như Yahoo UI, jQuery Mobile, Smarty 2, v.v...
Đối với những thư viện lỗi thời thì thường sẽ không được bảo trì và fix bug thường xuyên nữa do đó sẽ có khả năng xuất hiện các lỗ hổng bảo mật tiềm ẩn bên trong. Ngoài ra những developer thế hệ sau không quen thuộc với các thư việc "cổ" nên có thể dẫn đến giảm hiệu suất phát triển sản phẩm.
Do đó hiện nay đội ngũ phát triển Garoon đã và đang nỗ lực dần dần loại bỏ những thư viện lỗi thời này ra khỏi sản phẩm.
Legacy code
“Legacy Code is the code you need to change and you struggle to understand.” - Working Effectively With Legacy Code – page 17
Bạn có thể hiểu một cách nôm na Legacy code là những phần code mà mình cần thay đổi và bạn phải "vật lộn" với nó thì mới có thể hiểu được chúng. Legacy code thực ra không xa lạ gì đối lập trình viên. Để hình dung dễ hơn về nó thì chúng ta sẽ đi qua một số trường hợp đơn giản mà chúng ta gặp hằng ngày nhưng nhiều lúc không nhận ra đó là Legacy code.
Mình ví dụ một vài trường hợp:
Thứ nhất là đặt tên biến, hàm khá khó hiểu. Đối với những trường hợp như vậy thì lập trình viên phải tốn thời gian để đi đọc hết toàn bộ code của hàm đó mới hình dung được chức năng của nó. Thay vào đó khi đặt một tên biến/hàm có ý nghĩa thì chính nó đã phản ảnh được nghiệp vụ. Chưa kể đến việc nếu tên biến/hàm được đặt cách tuỳ tiện có khi sẽ dẫn đến một cách hiểu sai cho những người đi sau sẽ phát triển nó.
Thứ hai là code của một hàm/file rất dài trong đó bao hàm rất nhiều xử lý con, vì source code dài nên khá khó để hiểu bao quát các xử lý của nó, những trường hợp như thế này thì thường chúng ta phải đọc hết toàn bộ thì mới hình dung ra được.
Thứ ba là code một cách "cồng kềnh". Chưa tận dụng những tính năng mới của ngôn ngữ lập trình hỗ trợ, legacy code vẫn xử lý logic bằng rất nhiều dòng code. Ví dụ trong JavaScript sử dụng các hàm có sẵn được cung cấp để thao tác với mảng như find, filter, map, v.v… thay vì truy cập mảng dùng vòng lặp for theo kiểu truyền thống.
Nhận thấy Legacy code là một điều khó tránh khỏi, trên đây chỉ là vài trường hợp thường gặp. Để có thể "sống chung" và cải thiện Legacy code như thế nào, hẹn các bạn trong các bài viết tiếp theo mình sẽ phân tích sâu hơn.
Những thách thức khi thực hiện cải tiến
Đối với đội ngũ phát triển Garoon tại Cybozu sẽ phải đối mặt với những thách thức gì để giải quyết những vấn đề trên? Thay đổi cải tiến source code là một việc khó khăn, trong đó có 3 tiêu chí mà Garoon developer Việt Nam đặt ra
- Làm sao để dev team nắm bắt tận dụng công nghệ mới để phát triển nhanh
- Làm sao để source code (legacy code) dễ hiểu hơn
- Làm sao để tăng cường chất lượng, phát hiện bug sớm trong quá trình viết code
Quy trình phát triển
- Làm sao để dev team nắm bắt tận dụng công nghệ mới để phát triển nhanh
Để trả lời cho câu hỏi này, chúng ta sẽ khái quát về quy trình phát triển sản phẩm ở team Cybozu Garoon một chút nhé. Hiện tại ở team đang vận hành theo quy trình Scrum.
Scrum là một framework về quy trình và quản lý giúp giải quyết các vấn đề phức tạp, nhưng vẫn đảm bảo tính hiệu quả, sáng tạo và sản phẩm được tạo ra phải đạt được giá trị cao nhất. Quy trình này được sử dụng khá phổ biến nên mọi người có thể dễ dàng tìm hiểu thông tin liên quan đến Scrum. Bài viết này chỉ để cập tới một phần nhỏ trong Scrum đó là Scrum team để mọi người có thể hình dung rõ hơn về vấn đề thách thức để cài tiến Garoon Front-end nhé.
Hiểu một cách đơn giản thì trong Scrum có các role như PO (product owner), Dev team, SM (scrum master), mỗi scrum team bao gồm Developer, QA/QC/Tester và SM.
Trong Garoon team bao gồm nhiều scrum team, trong từng sprint các Scrum team sẽ pick (chọn) những product backlog để implement. Và theo định hướng của Garoon team thì sẽ không chỉ có một team chuyên biệt nào đó thực hiện được task về công nghệ mới (hay một kỹ thuật chuyên biệt, như frontend) mà là tất cả các scrum team đều có thể phát triển được.
Áp dụng công nghệ mới
Thách thức đầu tiên đối với dev team trong quá trình cải tiến đó chính là việc tìm hiểu và áp dụng những công nghệ mới.
Mỗi Scrum team có nhiều thành viên và mỗi thành viên lại có kinh nghiệm, thế mạnh khác nhau dẫn đến kĩ năng và khả năng không đồng đều nên việc để tất cả các thành viên có thể cùng làm được công việc cải tiến/ thay thế bằng những công nghệ mới sẽ cần một thời gian nhất định. Hơn nữa mô hình Scrum, phát triển dự án một cách liên tục, cần đảm bảo tiến độ release của sản phẩm.
Với bối cảnh như vậy Garoon team đã áp dụng một hình thức thành lập một team trong thời gian ngắn hạn, chúng tôi gọi là Tiger, team tiên phong - nơi hội tụ các thành viên từ các scrum team gồm các bạn có kinh nghiệm đã từng tiếp cận công nghệ cần làm hoặc đơn giản có cùng mong muốn thực hiện việc cải tiến một phần nào đó của sản phẩm.
Các thành viên trong team Tiger sẽ tạm thời rời Scrum team để cùng làm việc với nhau trong 1 khoảng thời gian nào đó(ví dụ như nửa tháng, 1 tháng, v.v...). Trong thời gian này có các thành phiên sẽ chủ động phân chia nhiệm vụ research và chia sẻ lại kết quả để mọi người cùng xem xét, góp ý kiến và đưa ra kết luận giải pháp. Tại Cybozu, chúng tôi cũng thường xuyên áp dụng hình thức mob programming để cùng code với nhau.
Mob-programming là một hình thức làm việc nhóm - mọi người code với nhau trên cùng một máy tính. Trong đó có: "Navigator" những người phụ trách hướng dẫn đưa ra ý tưởng giải pháp cho cách thực hiện code. "driver" người thực hiện chuyển ý tưởng của các "Navigator" thành code.
Sau khi hoàn thành nhiệm vụ, các thành viên trở về Scrum team và chia sẻ lại, hỗ trợ cho những thành viên trong Scrum team để mọi người có thể sử dụng công nghệ mới đó. Mục đích là không chỉ người đi tiên phong làm được task mà là tất cả các thành viên đều có thể tự thực hiện được.
Tới thời điểm hiện nay thì hình thức này đã và đang mang lại hiệu quả nhất định cho bộ phận phát triển Garoon. Thông qua đó, kỹ năng của các thành viên trong team cũng dẫn được cải thiện, giúp dần thu hẹp sự chênh lệch kỹ năng giữa các thành viên trong team.
Những vấn đề khác
Làm sao để source code dễ hiểu hơn (legacy code) Làm sao để tăng cường chất lượng, phát hiện bug sớm trong quá trình viết code
Để giải quyết 2 vấn đề trên, chúng ta có thể áp dụng Code refactoring và unit testing.
Trong khuôn khổ của bài viết này thì mình xin để lại 2 từ khóa trên cho các bạn tham khảo, trong các viết tiếp theo mình sẽ tiếp tục chia sẻ và phân tích chi tiết hơn. Hẹn các bạn trong các bài viết tiếp theo của mình nhé!