IT Staff

Blog về chuyên ngành IT

Những bài học từ một dự án phần mềm

leave a comment »

/*
*
* Nguồn: Blog Châu Hồng Lĩnh ~ Project N

*
*/

https://sites.google.com/site/quanlyduanphanmem/_/rsrc/1220028860905/config/app/images/customLogo/customLogo.gif?revision=1

Đây là một câu chuyện có thật về một dự án phần mềm trải qua 4 năm và tiêu tốn 35 triệu USD mà không đem lại kết quả nào, và có kế hoạch kéo dài thêm ít nhất là 4 năm nữa.

Dự án này diễn ra tại một công ty sản xuất dụng cụ thể thao vào hàng đầu trên thế giới, doanh thu khoảng hơn chục tỷ USD một năm, có trụ sở tại Tây Bắc Mỹ, tạm gọi là công ty N.

Trên phương diện là một study case, đây là một dự án khá độc đáo, và có thể dùng làm bài học điển hình về nhiều khía cạnh khác nhau của một dự án phần mềm, nhất là dành cho các doanh nghiệp sản xuất, dịch vụ đang có ý định ứng dụng công nghệ thông tin vào quy trình sản xuất và hoạt động của mình. Bài viết này hướng tới các đối tượng là Giám đốc Công nghệ Thông tin của doanh nghiệp (CIO – Chief Information Technology Officer), Quản trị Dự án (Project Manager) và Kiến trúc sư phần mềm (Software Architect), và sẽ phân tích qua các khía cạnh sau đây của dự án: Quy trình Quản lý (Management Process), Quy trình phát triển phần mềm (Software Development Process)  và Kiến trúc phần mềm (Software Architecture).

I. Giới thiệu tổng quát về dự án và tổ chức nhân sự

Dự án này là một dự án xây dựng một hệ thống enterprise software nhằm mục đích phối hợp (collaborate) hoạt động giữa các bộ phận trong hệ thống sản xuất giày dép (Footwear Production) của công ty N trên khắp thế giới, bao gồm:

–          Hệ thống quản lý tài liệu Thiết kế giày dép  (Footwear production documents), bao gồm tài liệu, bản vẽ mẫu giày dép, tài liệu về nguyên vật liệu, màu sắc, công nghệ …

–          Hệ thống quản lý dự án sản xuất (Project Management) để quản lý các dự án cho từng mẫu giày dép, từ thiết kế qua tới thử nghiệm, sản xuất, tiêu thụ …

–          Hệ thống phối hợp hoạt động giữa các bộ phận khác nhau của công ty N, từ Bộ phận Thiết kế mẫu sản phẩm ở Bắc Mỹ đến các Nhà máy sản xuất giày dép đặt tại châu Á và các Nhà cung cấp nguyên vật liệu trên khắp thế giới, bao gồm việc lưu chuyển và quản lý một cách tự động việc đưa mẫu thiết kế từ Bắc Mỹ đến sản xuất thử nghiệm tại châu Á, đến việc thử nghiệm, thu thập thông tin về sản phẩm mẫu, cải tiến, sản xuất chính thức và tiêu thụ,  tự động theo dõi hệ thống lưu chuyển nguyên vật liệu và vận tải sản phẩm.

Trước đây, công ty đã có thời kỳ sử dụng mainframe computer và COBOL, sau đó tới thời kỳ sử dụng Power Builder và SAP để quản lý một số phần rất nhỏ trong quy trình sản xuất. Hiện nay, công ty muốn xây dựng một hệ thống hoàn chỉnh, toàn diện với những công nghệ mới hiện nay.

Công nghệ được sử dụng trong dự án là J2EE và Oracle database. Application Server là Apache Webserver kết nối với Tomcat servlet engine. Dự án này không phải được xây dựng hoàn toàn từ đầu (build from scratch), mà dựa trên một enterprise platform khá nổi tiếng trong loại phần mềm PDM/PLM (Product Data Management/Product Lifecycle Management) và Enterprise Collaboration Software, có tên là Windchill. Windchill là một sản phẩm J2EE của công ty PTC (Parametric Technology Corp.), trụ sở chính tại bang Massachusetts, Mỹ [1]. Đây là một phần mềm nền tảng (platform), cung cấp toàn bộ cơ sở hạ tầng và các chức năng căn bản cho  một hệ thống enterprise software.

Các công ty sản xuất có nhu cầu xây dựng B2B enterprise software để phối hợp hoạt động giữa các bộ phận khác nhau trong công ty, hoặc với các công ty khác, với các nhà cung cấp và khách hàng thường sẽ ít khi xây dựng từ đầu, mà sẽ mua Windchill (hoặc các sản phẩm tương tự, ví dụ như Matrix One, EDS, SAP, People Soft, IBM Dassault …) về, cải biến và cài đặt thêm (customization) trên platform có sẵn để phù hợp với đặc điểm riêng của doanh nghiệp, và đưa vào sử dụng. Hiện có khoảng hơn 3000 công ty sản xuất lớn trên thế giới đang sử dụng Windchill để điều hành hoạt động của toàn bộ doanh nghiệp, trong đó có nhiều tên tuổi đáng kể như NASA, Boeing, Airbus, Lockheed Martin, Rolls Royce, DaimlerChrysler, Ferrari, Toyota, Bose …  Mỗi dự án triển khai Windchill cho một doanh nghiệp kéo dài vào khoảng từ 6 tháng đến 2 năm (Một thời gian tương đối ngắn cho việc triển khai Enterprise Software, bao gồm cài đặt hệ thống, cải biến và cài đặt thêm, performance tuning, administrator training, user training, chạy thử nghiệm và chạy chính thức).[2]

Từ 4 năm nay, Công ty sản xuất hàng thể thao N cố gắng dử dụng Windchill làm nền cho hệ thống enterprise software của mình, và đã chi hơn 35 triệu USD cùng nhiều nhân tài vật lực vào dự án này..

Bộ phận Sản xuất giày dép (Footwear Production) của công ty N có bộ phận IT riêng của mình, nhưng để triển khai dự án, công ty thuê các chuyên gia tư vấn về Công nghệ thông tin để tiến hành. Đây là cách làm việc rất phổ biến ở Mỹ, vì việc phát triển phần mềm hoặc cài đặt các hệ thống mới chỉ mang tính chất thời vụ, nhưng lại đòi hỏi trình độ chuyên môn cao. Mặt khác, khi hệ thống đã hoàn thành, thì việc vận hành và bảo trì chỉ đòi hỏi trình độ chuyên môn tương đối thấp. Vì thế các công ty sản xuất và dịch vụ chỉ duy trì một đội ngũ IT với trình độ vừa phải, lương thấp để bảo trì và vận hành hệ thống, và khi có nhu cầu làm mới, thì sẽ thuê chuyên viên tư vấn với giá cao, nhưng chỉ trong thời gian thực hiện dự án. Cách làm này giúp cho công ty tiết kiệm chi phí hoạt động, và bảo đảm tính chuyên môn hóa cao (Giả sử là công ty thuê được chuyên gia tư vấn tốt, và tổ chức làm việc theo nhóm một cách có hiệu quả).

Trong quản lý dự án, công ty N sử dụng một Quản trị dự án (Project Manager) là nhân viên chính thức của N (Permannent full time employee). Các nhân viên trong Dự án được chia làm ba nhóm chính là Nhóm Chuyên gia sản xuất giày dép (Domain expert – Trong trường hợp này, domain là footwear production, và nhóm còn gọi là Footwear Expert), Nhóm Phân tích Hệ thống kinh doanh (Business System Analyst) và Nhóm Chuyên gia phần mềm (Application Engineer).

Nhóm Chuyên gia sản xuất giày dép là những nhân viên chính thức của công ty N, công việc hàng ngày là thiết kế mẫu giày dép, giao dịch với các nhà máy ở châu Á và công ty cung cấp nguyên vật liệu trên khắp thế giới, là những người sẽ cung cấp thông tin về quy trình, phương pháp và logic làm việc của công việc footwear production cho Dự án.

Nhóm Chuyên gia Phần mềm (Application Engineer) có nhiệm vụ dựa trên những thông tin về quy trình, phương pháp và logic làm việc để xây dựng phần mềm tự động hóa những công việc đó. Trong nhóm này, các vị trí Senior đều là các chuyên viên tư vấn, và ở những vị trí lập trình, có xen lẫn những nhân viên tư vấn có kinh nghiệm và nhân viên chính thức của N.

Trong những dự án phức tạp, đòi hỏi có sự giao tiếp chặt chẽ, chính xác giữa nhóm cung cấp thông tin về sản xuất, dịch vụ với nhóm làm ra phần mềm, thường sẽ có một nhóm trung gian gọi là Nhóm Phân tích Hệ thống sản xuất (Business System Analyst), đóng vai trò trao đổi thông tin giữa Nhóm Domain Expert và Nhóm Application Engineer. Trong Công nghệ Phần mềm, thông thường những chuyên gia sản xuất, dịch vụ và những Chuyên gia Phần mềm nhìn công việc và hệ thống từ những góc nhìn khác nhau, và sử dụng những thứ ngôn ngữ khác nhau để mô tả về hệ thống. Do đó, những chuyên gia trong nhóm  Phân tích Hệ thống sản xuất phải vừa có kiến thức về sản xuất lẫn kiến thức về làm phần mềm (về độ am hiểu chuyên môn sâu thì không cần thiết phải như các nhóm Chuyên gia Sản xuất và Chuyên gia Phần mềm, nhưng phải am hiểu các khái niệm cơ bản và thuật ngữ) để có thể làm trung gian giữa hai nhóm. Trong nhóm Phân tích Hệ thống sản xuất  có cả chuyên viên tư vấn lẫn nhân viên chính thức của công ty N.

Điểm yếu nhất trong ba nhóm của công ty N là Nhóm Phân tích Hệ thống sản xuất. Nhóm này (hoàn toàn trái ngược với yêu cầu) không có một khái niệm gì cả về sản xuất giày lẫn về sản xuất phần mềm. Điều này làm nảy sinh ra tình trạng hoạt động không hiệu quả trong quy trình quản lý và quy trình làm phần mềm.

II. Những điểm yếu trong quy trình quản lý(Management Process)

Công ty N không có một phương pháp chuẩn (methodology) nào trong việc quản lý dự án phần mềm. Dựa trên quá trình thu thập thông tin, chưa xây dựng thành Use Case, chưa qua phân tích và làm specification, mới chỉ dựa trên một vài mục đích, nhận định, công ty đã đưa ra một số giới hạn về thời gian, nhân lực, ngân sách, mà không có căn cứ cụ thể.

Về mặt quản lý, công ty hoàn toàn không có phương pháp cụ thể về việc phân chia trách nhiệm, quyền hạn giữa các nhóm và các thành viên trong các nhóm. Điều này dẫn đến tình trạng có những lúc công việc bị ách tắc hoặc sai lệch, nhưng không tìm được nguyên nhân chính một cách kịp thời, và không quy được trách nhiệm cho đối tượng nào cần phải sửa chữa hoặc có hình thức xử lý.

Công ty cũng hoàn toàn không có một hệ thống hợp lý để theo dõi quá trình làm việc, theo dõi về ngân sách và tiến độ để có thể điều chỉnh cho phù hợp. Điều này dẫn đến các giai đoạn của dự án thường xuyên bị chậm dead line và vượt quá ngân sách dự tính.

Do không có Phương pháp chính thức (formal methodology) để đánh giá về khả năng, trình độ cũng như tốc độ làm việc của từng nhóm và từng nhân viên trong dự án, và do không có đủ trình độ về Chuyên môn Sản xuất giày dép và Chuyên môn về Công nghệ Phần mềm để có thể nhận định được về năng lực và kết quả làm việc thực sự của nhân viên, nên Quản trị Dự án (Project Manager) và Ban Lãnh đạo Dự án thu thập thông tin bằng cách nói chuyện với nhân viên này trong dự án để tìm hiểu về nhân viên kia, họp với nhóm này để lấy thông tin về nhóm kia trong dự án, và dẫn đến những đánh giá chủ quan, cảm tính và thường không chính xác. Sự đời ở đâu cũng thế, những kẻ nói giỏi và những kẻ hay nói thường là làm ăn không ra gì, và thông tin thường là sai lệch. Vì thế Ban Lãnh đạo Dự án hoàn toàn không có một nhận thức chính xác về trình độ nhân viên, tiến trình của dự án, và không nắm bắt được chi tiết những gì đang thực sự xảy ra trong dự án.

Công ty N thực hiện khâu tổ chức thực hiện dự án một cách hết sức máy móc. Hàng tuần, có những cuộc họp cố định vào thứ hai để báo cáo tiến độ công việc, vào thứ ba để xem xét thiết kế phần mềm và thứ năm để trao đổi thông tin giữa các nhóm Chuyên gia Sản xuất, Chuyên gia Phân tích Hệ thống Sản xuất và Chuyên gia Phần mềm. Ngoài ra còn rất nhiều cuộc họp phụ khác. Một tuần làm việc có 40 tiếng, đã có một vài lần tôi phải tham gia họp 30 tiếng một tuần, và có một vài ngày tôi phải ngồi 6 tiếng trong phòng họp.

Mặc dù có cuộc họp để báo cáo tiến độ công việc, nhưng vì thiếu một phương pháp tốt để theo dõi, phân tích, đánh giá tình hình và phân chia trách nhiệm, nên những cuộc họp này chỉ giúp cho Quản trị Dự án nhận ra những gì đã làm được, những gì còn lâu mới xong, mà không biết tại sao, có cách nào làm nhanh hơn không, đâu là vị trí khó khăn tại thời điểm này của dự án …

Cuộc họp về xem xét thiết kế phần mềm cũng không có tác dụng gì bổ ích mấy, vì công ty N đã tốn 4 năm và chi phí hơn 35 triệu USD để xây dựng một hệ thống phần mềm có nhiều vấn đề về mặt thiết kế (tôi sẽ phân tích kỹ hơn trong phần liên quan tới Kiến trúc phần mềm). Đại khái cũng như trong xây dựng, khi người ta đã vẽ ra một thiết kế có vấn đề và xây nên một vài phần móng có vấn đề, thì việc xây thêm và gia cố cũng khó mà dẫn đến một kiến trúc gì thực sự tốt và có giá trị sử dụng được. Vì thế, các cuộc họp này chỉ nhằm đưa ra những giải pháp chắp vá, tạm thời để tạo ra những chức năng có liệt kê trong danh sách mục đích xây dựng phần mềm.

Nhưng những cuộc họp về trao đổi thông tin giữa các nhóm làm việc mới thực sự là thảm họa. Có một quy định hết sức máy móc là Nhóm Chuyên gia Sản xuất chỉ được nói chuyện với Nhóm Phân tích Hệ thống sản xuất, rồi nhóm này sẽ đi nói lại với Nhóm Chuyên gia Phần mềm. Nhóm Chuyên gia Phần mềm cần hỏi thông tin gì, cũng chỉ được phép nói chuyện với Nhóm Chuyên gia Phân tích, rồi nhóm này sẽ đi hỏi Nhóm Chuyên gia Sản xuất và truyền đạt lại.

Trong khi đó, như đã nói, Nhóm Chuyên gia Phân tích lại bao gồm những người không có khái niệm gì về cả Sản xuất giày lẫn Sản xuất Phần mềm, nên Nhóm Phân tích chỉ đóng vai trò như Nhóm đưa tin giữa hai nhóm Chuyên gia Sản xuất và Chuyên gia Phần mềm. Hơn nữa, do không có trình độ chuyên môn, nên nhóm Phân tích không đọc được Use Case Diagram để trao đổi với nhóm Phần mềm, mà cũng không biết các thuật ngữ như size-range, color-bucket … để nói chuyện với nhóm Sản xuất. Như vậy, hoàn toàn không có một thứ ngôn ngữ chính xác để trao đổi về mặt phân tích yêu cầu, thu thập thông tin và thiết kế hệ thống cho toàn bộ dự án.  Ngoài ra, cách tổ chức trao đổi thông tin cũng kỳ quặc: Trong thứ năm của một tuần, Nhóm Phần mềm họp với Nhóm Phân tích, bàn đi bàn lại một hồi, rút ra là có một số vấn đề sau đây chúng ta chưa biết. Nhóm Phân tích sẽ đem vấn đề đó đi hỏi nhóm Sản xuất vào cuộc họp thứ năm tuần kế tiếp. Và trong cuộc họp ngày thứ năm của tuần tiếp sau nữa, Nhóm Phân tích sẽ đem câu trả lời về cho Nhóm Phần mềm. Như vậy là mất 3 tuần cho một câu hỏi và trả lời, và việc này diễn ra trong 4 năm nay, mặc dù đi bộ từ khu nhà của Nhóm Phần mềm xuống Nhóm Sản xuất mất đúng 3 phút, và tất cả các nhân viên trong dự án đều có điện thoại và e-mail. Đó là chưa kể đến sự thiếu hiểu biết chuyên môn của Nhóm Phân tích dẫn đến việc trình bày sai, thiếu phương pháp ghi chép tài liệu (documentation methodology), nên có những vấn đề phải hỏi đi hỏi lại.

Có hai trường hợp điển hình. Một lần có một chuyên gia phần mềm hỏi “Trong thiết kế mẫu, người ta quản lý cỡ giày như thế nào, theo giá trị chính xác (exact size, nghĩa là từng con số 5,6,7,8,9 ..), hay theo khoảng cỡ (size-range, tức là 5-7, 8-10 , 11-12 …). Sau vài tuần trao đổi đi, trao đổi lại, Nhóm Phân tích không đưa ra được câu trả lời cụ thể. Chuyên gia phần mềm đành phải làm một câu hỏi có nhiều chọn lựa (multi-choice question), gồm có a) Quản lý theo giá trị chính xác, b) Quản lý theo khoảng cỡ, c) Quản lý theo kiểu khác, đề nghị viết rõ, rồi đưa cho Nhóm Phân tích đi hỏi Nhóm Sản xuất, đề nghị khoanh vào a hoặc b hoặc c, thì mới có câu trả lời là a).

Nếu không có quy định quá máy móc là Nhóm Phần mềm không được giao tiếp với Nhóm Sản xuất , hoặc nếu Nhóm Phân tích biết chuyên môn cơ bản và biết sử dụng thuật ngữ, thì tình trạng không đến nỗi thế.

Trường hợp thứ hai là có lần có chuyên gia phần mềm hỏi: “Về mặt quản lý vận tải, trong một lần gửi hàng, có thể có hàng hóa của nhiều đơn đặt hàng được gửi cùng một chuyến hay không?”.

Trước đây công ty N không có hệ thống theo dõi vận tải, mọi giao dịch được làm bằng giấy tờ. Thay vì đi hỏi trực tiếp những người từ trước đến nay vẫn theo dõi việc vận tải bằng sổ sách, Ban Quản trị Dự án họp nhau đoán già đoán non, và cho rằng việc theo dõi nhiều đơn đặt hàng khác nhau trong một chuyến vận tải là quá khó (?), nên cho rằng phần mềm chỉ cần theo dõi mỗi chuyến vận tải là một đơn đặt hàng thôi, bất chấp ý kiến của Nhóm Phần mềm là về mặt công nghệ không có gì khó, và ý kiến của Nhóm Sản xuất là trước nay vẫn có nhiều trường hợp một chuyến hàng chứa nhiều đơn đặt hàng. Sau khi Nhóm Phần mềm cài đặt xong Hệ thống theo dõi Đơn đặt hàng và Vận tải, công ty N cử một nhóm 3 người sang châu Á để đưa cho các nhà máy ở châu Á sử dụng thử và thu thập ý kiến phản hồi, thì mới nhận ra là phải làm hệ thống theo dõi nhiều đơn đặt hàng khác nhau trong một chuyến vận tải. Kết quả là toàn bộ công việc trong hai tháng trời phải bỏ đi hoàn toàn, làm lại từ đầu.

Một hiện tượng khác điển hình cho sự thiếu cả Kiến thức lý thuyết lẫn Kinh nghiệm thực tế trong Quản lý Dự án phần mềm của Ban Lãnh đạo Dự án là mỗi khi dự án chậm so với thời hạn, Ban Lãnh đạo Dự án lại thuê thêm lập trình viên vào, nhằm cứu vãn tiến độ công việc. Bất kỳ một nhân viên quản trị dự án phần mềm nào khi mới tập tọng vào nghề cũng phải nghe qua định luật Brooks [3]: “Thêm người vào một Dự án phần mềm bị chậm thì chỉ làm cho nó chậm hơn.” Định luật này được Brooks chứng minh bằng mô hình toán học một cách chính xác, và đã được kiểm nghiệm qua rất nhiều dự án phần mềm trong thực tế.

III. Những điểm yếu trong quy trình phát triển phần mềm (Software Development Process)

Công ty N sử dụng một Quy trình Phát triển phần mềm chuẩn trong Công nghệ Phần mềm là Rational Unified Process (RUP). Hiện tại, trong ngành Công nghệ Phần mềm, đại đa số các Dự án Phần mềm lớn và phức tạp đều sử dụng RUP làm Quy trình Phát triển phần mềm.

Quy trình này gồm có 4 giai đoạn: Khởi đầu (Inception), Dự thảo chi tiết (Elaboration), Thực hiện xây dựng (Construction), Chuyển giao (Transition).

Trình bày chi tiết về Rational Unified Process hoàn toàn không nằm trong khuôn khổ của bài viết này.

Nhưng một quy trình tốt không bảo đảm cho sự thành công của một dự án phần mềm. Phương pháp tiến hành các bước trong các giai đoạn của một dự án là một yếu tố hết sức quan trọng. Trong toàn bộ ba giai đoạn đầu của dự án, công ty N đều phạm phải các sai lầm hết sức cơ bản. Giai đoạn bốn (Transition) chưa bao giờ có, vì chưa bao giờ có sản phẩm chính thức đưa vào sử dụng, nên chưa có sai lầm. Suốt 4 năm từ lúc bắt đầu Dự án cho đến nay, sau khi tiêu tốn hơn 35 triệu USD, công ty N mới đưa ra được một vài kết quả thử nghiệm:

–          Hệ thống Quản lý Vật liệu (Material Management). Nghe tên thì như vậy, nhưng thực chất đây là một hệ thống cho phép ghi đối tượng về vật liệu vào database, thêm, xóa, sửa, tìm kiếm …, nghĩa là các chức năng thông thường của một chương trình quản lý cơ bản bất kỳ cái gì.

–          Hệ thống Quản lý màu sắc (Color Management) : Đây là một hệ thống cho phép thêm, xóa, sửa, tìm kiếm màu sắc trong database.

–          Hệ thống quản lý Dự án (Project Management), thực ra chỉ là một hệ thống tạo thêm, xóa, sửa, tìm kiếm tài liệu cho các dự án, chứ không có quản lý tiến trình (workflow management) và  theo dõi tiến độ dự án (project progress tracking),đang trong giai đoạn chạy thử nghiệm và có đầy lỗi.

Giai đoạn Khởi đầu (Inception) : Đây là giai đoạn dùng để thu thập thông tin, nhằm đặt ra mục đích và tầm mức của Dự án Phần mềm. Thay vì thu thập trực tiếp thông tin trong thực thế thiết kế và sản xuất giày để xây dựng tầm mức và mục đích, công ty N đã chọn cách thu thập chức năng và mục đích cho chương trình bằng cách sao chép lại toàn bộ chức năng và mục đích của hệ thống phần mềm cũ  (legacy system) chạy trên mainframe, hệ thống cũ làm bằng Power Builder và SAP. Đây là một sai lầm hết sức ấu trĩ, vì các legacy system kể trên được xây dựng cách đây hàng chục năm, dựa trên công nghệ hết sức lạc hậu, không thông qua các quy trình thiết kế và phân tích chuẩn cho các hệ thống Hướng đối tượng (Object Oriented), vì thời đó chưa có công nghệ này. Hơn nữa, quy trình thiết kế và sản xuất giày dép và việc trao đổi thông tin hiện nay đã khác xa so với quy trình  hàng chục năm trước, công nghệ sản xuất, phương tiện sản xuất, phương tiện thông tin liên lạc giữa các chi nhánh và quy trình sản xuất đã hoàn toàn thay đổi. Chính vì thế, quyết định về việc xây dựng một hệ thống phần mềm với công nghệ mới để sao chép hoàn toàn chức năng và hoạt động của hệ thống phần mềm cũ đang sẵn có, với rất ít bổ sung, là rất phi lý, thiếu thực tế, và xét cho cùng, nếu vậy thì cứ việc giữ nguyên hệ thống cũ để sử dụng thì còn có giá trị thực tiễn và kinh tế cao hơn.

Giai đoạn Dự thảo chi tiết (Elaboration): Trong giai đoạn này, các thông tin thu thập được ở giai đoạn Khởi đầu (Inception) sẽ được đánh giá và phân tích chi tiết, nhằm xác định cụ thể, chính thức về tầm mức của dự án (project’s scope) , các yêu cầu của dự án (project’s requirement), các điều kiện để dự án được coi là hoàn thành (project’s acceptance criteria), các tính năng của dự án (project’s feature) và những tính năng nào là quan trọng (critical criteria), xác định những mạo hiểm có thể xảy ra (potential risk), xác định chi tiết về thực tế sản xuất (business specification) để dẫn tới xây dựng chi tiết về thiết kế phần mềm (design specification) và xây dựng dự thảo cho kiến trúc phần mềm (software architecture). Những công việc hỗ trợ như thiết lập mạng (network), mua bán phần cứng (hardware), phần mềm (software), chuẩn bị quy trình, công cụ cũng được thực hiện trong giai đoạn này.

Một trong những sai lầm căn bản nhất của giai đoạn cụ thể hóa dự án này là Ban Lãnh đạo Dự án đã đánh giá sai thời gian và khối lượng công việc trong việc chuyển đổi database từ các hệ thống cũ (legacy system) dùng mainframe, Power Builder và SAP sang Oracle database của Windchill.

Không hiểu căn cứ vào đâu, dựa trên những tiêu chí nào, vào những phân tích ra sao, mà Ban Lãnh đạo Dự án xác định rằng để chuyển đổi database từ hệ thống cũ sang Windchill’s Oracle database phải tốn ít nhất là 5 năm. Điều này chứng tỏ Ban Lãnh đạo Dự án không có bất kỳ một khái niệm gì về database migration.

Hệ thống cũ chạy Power Builder và SAP cũng dùng Oracle database, nghĩa là hoàn toàn có thể được truy cập từ chương trình Java. Có những dữ liệu được lưu trong những khu vực lưu trữ riêng của Power Builder App và SAP, nhưng đều có những công cụ kết nối (adapter), do đó có thể đọc được từ chương trình Java.

Như vậy công việc chuyển đổi database từ legacy system sang Windchill bao gồm những phần việc sau:

–          Xác định database schema và data format của legacy system.

–          Xây dựng database schema cho hệ thống mới trong Windchill’s Oracle database.

–          Viết một chương trình đọc database từ legacy system và ghi vào Windchill’s database.

Đây là một công việc rất cơ bản, hầu như là lặp đi lặp lại cho tất cả các dự án có chuyển đổi database (database migration). Bất kỳ một Kiến trúc sư Phần mềm (Software Achitect) có kinh nghiệm nào cùng với một nhóm lập trình viên trình độ trung bình có thể hoàn thành những Dự án database migration trong khoảng 6 tháng đến 1 năm. Rất nhiều dự án database migration ở những nhà máy sản xuất máy bay chiến đấu, tàu ngầm hạt nhân, ô tô đua … ( là những thứ phức tạp hơn một chiếc giày rất nhiều) được thực hiện với thời gian còn ngắn hơn thế.

Chính vì nhận định sai về thời gian chuyển đổi database, nên Ban Lãnh đạo Dự án đã đề ra một mục đích và tầm mức hết sức kỳ quặc cho dự án.

Dự án sẽ được xây dựng như là một chương trình sử dụng Java, J2EE trên nền Windchill để cung cấp giao diện mới và database mới cho một Hệ thống quản lý sản xuất giày có chức năng giống hệt như Hệ thống cũ viết bằng Power Builder, với một vài chức năng mới không đáng kể, ví dụ như theo dõi Vận tải và Đơn đặt hàng. Phần phối hợp chức năng hoạt động giữa các bộ phận, tạo ra một vài loại đối tượng nhất định, vẫn dùng Hệ thống cũ viết bằng Power Builder và SAP, rồi gửi dữ liệu qua Windchill. Dần dần, sau một thời gian chạy thử vào khoảng 7 đến 10 năm, một hệ thống mới được xây dựng dựa trên Windchill sẽ được đưa vào thay thế hoàn toàn hệ thống cũ.

Sự sai lầm của nhận định về mục đích và tầm mức này là: Windchill đã có sẵn toàn bộ các chức năng để phối hợp hoạt động sản xuất và kinh doanh giữa các bộ phận khác nhau (vì thế nên nó mới được gọi là PDM/PLM và Collaborative enterprise software). Quyết định chỉ dùng Windchill để làm giao diện và lưu trữ dữ liệu, trong khi đó vẫn dùng hệ thống cũ để phối hợp hoạt động (mặc dù công nghệ của hệ thống cũ đã lạc hậu, lỗi thời và không có đủ chức năng) là một quyết định không thể hiểu nổi.

Hơn nữa, theo tiến trình phát triển của công nghệ hiện nay, trong khoảng 7 đến 10 năm nữa, công nghệ đã hoàn toàn thay đổi, những Hệ thống được xây dựng dựa trên J2EE hiện tại sẽ trở nên lỗi thời. Chả lẽ lúc đó lại tiến hành xây dựng một hệ thống mới, trong lúc việc chuyển đổi chức năng, dữ liệu giữa Hệ thống Power Builder + SAP với Hệ thống Windchill hiện nay chưa xong, và sử dụng song song cả 3 hệ thống cho tới 7 hay 10 năm tiếp sau đó nữa?

Những nhận định và kế hoạch nói trên chứng tỏ Ban Lãnh đạo Dự án thiếu thực tế về mặt Sản xuất và không có khái niệm gì về Quản lý và Tiến hành Dự án Phần mềm.

Khâu chuẩn bị vật chất và công cụ cho dự án cũng được tiến hành rất kém. Mạng máy tính của công ty N vào năm 1999 đã bị hacker tấn công một lần, tai tiếng khá lớn, nên công ty trở nên quá đa nghi về an ninh mạng (network security), và do thiếu khả năng, nên đã cài đặt quá nhiều công cụ security tự động lên mạng và các máy tính cá nhân, làm cho mạng máy tính trở nên chậm và kém ổn định. Rất nhiều lập trình viên trong một ngày đẹp trời tự nhiên thấy máy tính của mình bị loại khỏi domain của N network, và phải gọi quản trị mạng để kết nối trở lại. Máy tính được dùng trong hệ thống được mua của một hãng khá danh tiếng, nhưng có lẽ là loại rẻ, dùng cho gia đình, chưa qua test để dùng trong công nghiệp, nên có rất nhiều máy tính bị hỏng, nguy hiểm nhất là hỏng đĩa cứng, và mất toàn bộ dữ liệu.

Về môi trường phát triển phần mềm (software development environment), công ty sử dụng khá nhiều công cụ chuẩn (standard tool) được sử dụng rộng rãi trong Công nghệ Phần mềm ở nhiều công ty khác, nhưng đáng tiếc là lại sử dụng sai, nên phát sinh rất nhiều sự cố trong quá trình phát triển phần mềm. Một ví dụ điển hình là để kiểm soát mã nguồn (source code control) và chia sẻ làm việc theo nhóm, công ty sử dụng ClearCase, một công cụ quản lý mã nguồn rất mạnh của công ty Rational Software. Nhưng đáng tiếc là công ty không thuê đúng chuyên gia cài đặt và định cấu hình ClearCase có đủ trình độ, nên việc quản lý mã nguồn của dự án luôn luôn gặp trục trặc, chương trình không dịch được, hoặc ClearCase view không thể update được là chuyện bình thường. Chương trình dùng để viết Java code trong Dự án là Eclipse, một opensource IDE rất phổ biến, có nhiều chức năng và công cụ rất mạnh, nhưng do mã nguồn của dự án và từng project được tổ chức trên File System quá phức tạp, nên việc setup Eclipse Project để viết và chạy chương trình đòi hỏi phải qua rất nhiều bước phức tap, và không có chuẩn hóa. Quá trình tạo mẫu đối tượng (object modeling), phát sinh mã nguồn Java cho đối tượng (Java source code generation) và phát sinh lệnh SQL để tạo table trong database (SQL generation) được thực hiện bằng UML diagram trong Rational Rose. Nhưng do không biết cách cài đặt (setup) và định cấu hình (configure), nên mỗi lần thay đổi mô hình (model), các lập trình viên lại trải qua một thời gian dài đau khổ trước khi database hoạt động và chương trình chạy trở lại. Có nhiều lập trình viên đến công ty chơi cả tuần vì máy tính hỏng, không có gì để làm, và cũng không có máy tính để thay thế. Hiện nay, công ty đang thuê một vài nhân viên tư vấn để chuyên nghiên cứu về việc cài đặt môi trường phát triển (setup development enviroment), nhưng tình hình cải biến một cách chậm chạp, mặc dù project đã tiến hành được 4 năm.

Giai đoạn Thực hiện xây dựng (Construction):

Trong giai đoạn này, sai lầm có tính chất quyết định chính là sai lầm về Kiến trúc phần mềm (Software Architecture). Những sai lầm này sẽ được phân tích chi tiết trong phần Những điểm yếu trong Kiến trúc Phần mềm.

Trong phần này, tôi tập trung phân tích những sai lầm của việc cài đặt phần mềm, nhưng không liên quan đến kiến trúc.

Ban Lãnh đạo Dự án của công ty N chọn quy trình phát triển phần mềm theo mô hình Iterative Development, là một mô hình rất phổ biến trong phát triển phần mềm hiện nay. Nhưng Ban Lãnh đạo Dự án đã hiểu sai toàn bộ ý nghĩa của Iterative Development.

Iterative Development chia quá trình xây dựng phần mềm làm nhiều khoảng thời gian nhỏ gọi là iteration. Trong từng iteration đó, có đủ cả bốn giai đoạn của RUP là Khởi đầu (Inception), Dự thảo chi tiết (Elaboration), Thực hiện xây dựng (Construction) và Chuyển giao (Transition). Toàn bộ Hệ thống phần mềm sẽ được chia nhỏ thành từng chức năng hoặc nhóm chức năng, đủ để thực hiện trong thời gian của một iteration. Trong khoảng thời gian của một iteration, chức năng (hoặc nhóm chức năng) phải hoàn thành sẽ được đưa qua đủ 4 giai đoạn kể trên, và phân tích, thiết kế cho thành phần phần mềm này của Hệ thống có thể được phát triển, thay đổi hoặc đánh giá lại, và kết quả là khi kết thúc mỗi iteration, sẽ có thêm một phần của Dự án được hoàn thành. Trải qua nhiều iteration, cả hệ thống phần mềm sẽ được hoàn thành. Phát triển theo mô hình Iterative Development như thế sẽ cho phép bổ sung thêm thông tin thực tế, thay đổi thiết kế và chỉnh sửa việc cài đặt chức năng cho từng chức năng hoặc nhóm chức năng,  mà không làm ảnh hưởng hoặc ảnh hưởng rất ít đến tiến trình của toàn bộ Dự án và các phần khác của Hệ thống.

Nhưng các iteration trong Dự án của công ty N được thực hiện như sau: Cả hệ thống được chia làm nhiều chức năng (hoặc nhóm chức năng) nhỏ. Sau đó, mặc dù việc phân tích mới chỉ qua loa đại khái, chưa có đủ thông tin đã bắt tay ngay vào việc thiết kế và lập trình. Sau khi hoàn thành việc lập trình cho chức năng (hoặc nhóm chức năng) này, bỗng nhiên quá trình thu thập thông tin, phân tích có thêm thông tin, thiết kế thay đổi, thế là lại vứt bỏ toàn bộ từ mô hình đối tượng (object model), Java code cho đến database schema, viết lại từ đầu trong một iteration mới. Kết quả là trải qua nhiều iteration, sẽ có một phần của Dự án được hoàn thành, và thời hạn của Dự án (dead line) thường xuyên bị thay đổi, dời chậm lại. Ban Lãnh đạo Dự án thường nhắc đi nhắc lại mỗi khi bắt đầu một iteration mới là “Chúng ta lùi hai bước để tiến lên ba bước”, nhưng trên thực tế là lùi hai bước và chỉ tiến lên đúng hai bước (vì kết thúc iteration mới, cũng chỉ có chức năng trong iteration cũ được cài đặt lại mà thôi), và quá trình này diễn ra lặp đi lặp lại rất nhiều lần.

Hiện tượng trên xảy ra vì Ban Lãnh đạo Dự án không hiểu ý nghĩa và cách vận dụng của Iterative Development, đồng thời Kiến trúc sư Phần mềm (Software Architect) của Dự án không có tầm nhìn đủ xa và không có đủ kỹ năng để thiết kế mẫu đối tượng (object model) và sử dụng mẫu thiết kế (Design Pattern) một cách tổng quát (generic) và linh hoạt (flexible), để mỗi khi có thay đổi về yêu cầu và thay đổi thông tin, thì không ảnh hưởng đến kiến trúc của hệ thống hoặc ảnh hưởng rất ít.  Kiến trúc Hệ thống của công ty N không đạt được tính ổn định, linh hoạt, dễ bảo trì và dễ sử dụng, vì những người thiết kế Hệ thống và Ban Lãnh đạo Dự án đơn thuần chỉ có giải pháp tức thời cho những thông tin trước mắt, không có hoạch định (planning) và tầm nhìn (vision) cho sự thay đổi, mở rộng và phát triển.

Một sai lầm khác không thể hiểu nổi của Ban Lãnh đạo Dự án là thứ tự thực hiện cài đặt phần mềm. Thông thường, các thông tin thực tế trong sản xuất và dịch vụ sẽ được thu thập, phân tích, đánh giá, hệ thống hóa và được viết lại dưới dạng Use Case và vẽ ra Use Case Diagram. Sau khi Use Case và Use Case Diagram được đánh giá là đủ tốt và chính xác vào một thời điểm nhất định của dự án, các  lập trình viên sẽ tạo ra các chức năng của chương trình dựa trên Use Case và Use Case Diagram. Trong Dự án của công ty N, các thực tế sản xuất, thông tin thực tế được Nhóm Sản xuất nói cho Nhóm Phân tích, và Nhóm Phân tích nói lại cho Nhóm Phần mềm, thông qua các tài liệu viết bằng tiếng Anh, nhưng không có độ chính xác về thuật ngữ, và các biểu đồ được vẽ một cách tùy tiện với những hình khối tùy tiện, không có cú pháp (syntax) và ngữ nghĩa (semantic) nào chặt chẽ, và cũng không có một Phương pháp Chính thức (formal methodology) nào cho việc trao đổi, ghi nhận và trình bày thông tin. Nhóm Phần mềm sẽ căn cứ vào những tài liệu này vừa làm, vừa đoán, vừa hỏi, vừa đi họp, sau đó, qua rất nhiều iteration như đã trình bày ở trên, sẽ làm ra một chức năng (hoặc nhóm chức năng) tạm chấp nhận được. Trong thời gian Nhóm Phần mềm làm lập trình qua nhiều iteration, thì Nhóm Phân tích sẽ đi hỏi han cả Nhóm Sản xuất lẫn Nhóm Lập trình để xem thông tin thực tế, yêu cầu và phân tích như thế nào, được lập trình ra sao, sau đó bắt đầu viết Use Case bằng tiếng Anh thông thường và vẽ biểu đồ bằng Visio một cách tùy tiện, sử dụng mũi tên, hình khối và tạo bóng thẩm mỹ một cách bừa bãi chứ không sử dụng UML. Kết quả là mỗi khi Nhóm Phần mềm hoàn thành một iteration Lập trình, thì Nhóm Phân tích cũng cho ra một version của Use Case document nói chung chả ai thèm đọc và chả giúp ích gì cho ai. Có bao nhiêu iteration để lập trình một chức năng thì cũng có bấy nhiêu version của Use Case document, nhưng Use Case được viết ra sau khi đã lập trình xong, không có cú pháp (syntax) và ngữ nghĩa (semantic) chính xác, thì cũng chả có tác dụng gì ngoài việc làm tốn giấy, tốn mực máy in và tốn chỗ lưu trữ trong tủ.

Trong quá trình lập trình cụ thể , do Ban Lãnh đạo Dự án và đội ngũ Kiến trúc sư của Dự án quá kém về chuyên môn, nên xảy ra nhiều chuyện hết sức vô lý và làm chậm đáng kể tiến độ lập trình.

Một ví dụ điển hình là có trường hợp, một lập trình viên cho server code báo cáo là các đối tượng của anh ta làm việc hoàn toàn chính xác với Unit Test (sử dụng JUnit) và với client sử dụng Struts framework, nhưng thông tin không được hiển thị chính xác trên Swing GUI, trong khi cả JUnit, Struts client và Swing client đều sử dụng server code này theo cùng một cách, gọi cùng một tập các hàm API và dùng cùng một lớp trung gian (middleware). Qua rất nhiều tuần, Ban Lãnh đạo Dự án cứ nhất quyết đòi lập trình viên này xem xét tại sao server code của mình không hoạt động tốt với Swing GUI. Điều này chứng tỏ sự dốt nát toàn diện của Ban Lãnh đạo Dự án và Kiến trúc sư phần mềm (Software Architect) về Lập trình Hướng đối tượng căn bản. Một thành phần phần mềm (software component) hoạt động tốt đối với Unit Test chính là điều chứng tỏ là thành phần này được lập trình đúng theo Chỉ định thiết kế (Design Specification), và thỏa mãn yêu cầu (Requirement). Một bằng chứng khác về sự hoạt động tốt của server code là thành phần này làm việc chính xác với Struts client. Không hiểu do thiếu hiểu biết về lập trình hay vì lý do gì khác, mà Ban Lãnh đạo và Kến trúc sư phần mềm cứ nhất quyết đòi tìm nguyên nhân không hoạt động trong server code chứ không phải trong Swing GUI code.

IV. Những điểm yếu trong Kiến trúc phần mềm (Software Architecture)

Hệ thống phần mềm của công ty N được xây dựng trên nền tảng của Windchill, và sau một thời gian dài nghiên cứu, Ban Quản trị Dự án đã xây dựng nên một sơ đồ kiến trúc như sau:

Đây là một kiến trúc phần mềm nhiều lớp tiêu biểu (a typical muti-layer software architecture). Thực ra thì không cần phải là một kiến trúc sư phần mềm giàu kinh nghiệm mới có thể vẽ được sơ đồ như trên, mà chỉ cần lật một quyển sách Nhập môn Kiến trúc Phần mềm bất kỳ nào cũng có thể thấy những sơ đồ đơn giản kiểu này, thay tên và các mũi tên thích hợp là xong.

Việc thiết kế cụ thể và cài đặt cho từng lớp (layer) cũng như tổ chức giao tiếp giữa các lớp mới là việc quan trọng.

Trong Dự án này, toàn bộ tất cả các dịch vụ cho các phần từ Application Layer, Server Layer cho đến Data Layer đã được cài đặt sẵn trong Windchill foundation. Trong Kiến trúc (Architecture) và cài đặt (Implementation) của Windchill foundation đã có cung cấp toàn bộ những thành phần (component) được liệt kê trong sơ đồ như Service Management, Business Services, System Services, Task Delegate, Windchill Adapter Webject, Command Beans, Command Delegate, Info* Engine, Business Object Model, Naming Service, Directory Server , Persistence layer …

Phần cải biến và thêm chức năng chỉ xảy ra trong phần Client Layer và phần xây dựng mô hình cho các đối tượng kinh doanh (Business Object Modelling).

Thực ra trong sơ đồ của phần Server Layer và Data Layer có hai điểm sai rất căn bản, do Kiến trúc sư Phần mềm (Software Architect) và Lãnh đạo kỹ thuật của Dự án (Technical Lead) trong thời kỳ trước khi tôi tham gia dự án không hiểu rõ về cấu trúc của Windchill, đoán mò và chép sách Nhập môn Thiết kế phần mềm một cách bừa bãi.Thứ nhất là trong Windchill không có cái gọi là Modelled Attributes (Các thuộc tính được mô hình hóa), vì tất cả các Business Object đều được mô hình hóa (model) như là những Java Object, và được sử dụng trong tất cả các lớp (layer) từ Windchill Service đến Presentation. IBA (International Business Attribute) cũng không phải là một component của kiến trúc phần mềm, mà chỉ là một hệ thống công cụ để chuyển đổi giữa các hệ thống đo lường Anh-Mỹ và Quốc tế. Do đó, sẽ không có cái gọi là Modelled Attributes và IBA nằm giữa Command Delegate và Windchill Services. Thứ hai là giữa lớp Windchill Services và Oracle Database còn có một lớp nữa là Persistence Layer, làm nhiệm vụ chuyển đổi giữa Java object và Relational Database (Object-Relational Mapping – ORM), đồng thời đóng vai trò tìm kiếm (query) và thao tác (manipulate)  database.

Sai lầm căn bản ngay từ xuất phát điểm của dự án là không sử dụng hết các chức năng sẵn có của Windchill. Hệ thống Windchill đã cung cấp toàn bộ những tính năng cần thiết của một hệ thống PDM/PLM Enterprise Software bao gồm các chức năng cơ bản như Persistence Management, Document Magement, Project Management, LifeCycle Management, Workflow Management, CAD/CAM management, Document and Part versioning, Data Transprotation, Distributed Data Management, Data Replication, Enterprise Security, Access Control, Enterprise Resource Management and Planning … dưới dạng các dịch vụ (service) và framework có thể mở rộng được.

Nhưng Dự án triển khai Windchill ở công ty N chỉ sử dụng một phần rất giới hạn các chức năng của Windchill:

–          Chức năng mô hình hóa các đối tượng (object modelling), mô hình hóa các dịch vụ (service modelling), phát sinh mã chương trình Java từ mô hình (Java code generation from model) và  phát sinh SQL DML (SQL Data Manipulation Language) từ mô hình (SQL DML generation from model), sử dụng Rational Rose.

–          Sử dụng PersistenceLayer chỉ để ghi object vào database, đọc object từ database và xóa object trong database. Không sử dụng được chức năng database query và database manipulation.

–          Sử dụng một phần nhỏ của LifeCycle Management để đổi trạng thái (State) của object trong database.

–          Sử dụng RMI server của Windchill để làm giao tiếp RMI giữa client và server.

–          Sử dụng Windchill configuration cho Apache Webserver, Tomcat và Aphelion LDAP server để dùng một phần nhỏ của Directory Service và Authentication.

Như vậy, các chức năng chính của một enterprise software trong Windchill như object versioning, data transportation, workflow management, built-in business object , advanced query capabilities, data replication, security và access control hoàn toàn không được sử dụng.

Do thiếu hiểu biết về kiến trúc và các chức năng của Windchill, nên khi cần có những chức năng rất sơ đẳng và cơ bản, Nhóm Phần mềm của Dự án phải làm mới từ đầu, phát minh lại rất nhiều bánh xe, và do thiếu hiểu biết, nên những thành phần (component) mới làm việc không được tốt với Windchill foundation, và nhiều thành phần có tốc độ thi hành chậm (slow performance).

Một  ví dụ  điển hình về phát minh lại bánh xe trong dự án là N Search Framework. Windchill Foundation cung cấp một Persistence Layer rất hoàn chỉnh, với toàn bộ các chức năng về database query và database manipulation từ cơ bản đến nâng cao, bao gồm hết toàn bộ các chức năng của SQL’92 và phần mở rộng của Oracle SQL, phiên bản 8i và 9i. Nhưng do hoàn toàn không biết cách sử dụng, Kiến trúc sư Phần mềm (Software Architect) và Ban Lãnh đạo Dự án quyết định xây dựng một cái gọi là N Search Framework, chỉ dùng để tìm kiếm các đối tượng trong database. Từ khi N Search Framework ra đời, mỗi khi cần tìm kiếm mỗi đối tượng trong database, thay vì viết code mất khoảng 5 phút sử dụng Persistence Layer, các lập trình viên phải dùng Rational Rose để tạo mẫu (model) cho 4 loại đối tượng khác nhau, viết 2 lớp đối tượng Search Criteria và Search Result cho client side và viết code cho 4 lớp đối tượng Java ở server side, cập nhật (update) 2 file cấu hình XML (XML configuration),  mất ít nhất 1 ngày làm việc (8 tiếng). Việc tìm kiếm đối tượng trong database trở nên phức tạp đến nỗi mỗi khi có một kiểu đối tượng mới, thì phải dành hẳn một lập trình viên làm việc mất mấy ngày để viết code cho việc ghi đối tượng vào database và tìm kiếm đối tượng.

Ngoài ra, hệ thống software của N hoàn toàn không có security và access control, bất kỳ ai sau khi đã qua basic authentication với Webserver có thể thực hiện tất cả mọi lệnh với tất cả các đối tượng trong hệ thống.

Không chỉ thiếu hiểu biết về enterprise software và Windchill, Kiến trúc sư phần mềm (Software Architect) và Ban lãnh đạo Kỹ thuật của Dự án tỏ ra thiếu hiểu biết toàn diện về Phân tích/Thiết kế Hướng đối tượng (Object Oriented Analysis/Design – OOA/OOD) và Lập trình Hướng đối tượng (Object Oriented Programming – OOP).

Về mặt phân tích (Analysis), tất cả những thực thể (entity) tham gia vào quá trình sản xuất trong User Story đều được tạo ra một object tương ứng trong Hệ thống Phần mềm. Điều này là một sai lầm rất sơ đẳng của những học sinh mới học lập trình, vì không phải tất cả các thực thể được kể trong quy trình sản xuất đều là đối tượng trong phần mềm, mà chỉ có một số nhất định là các đối tượng chính (business object), một số là các mối quan hệ giữa các đối tượng (object relationships) và một số chỉ là các thuộc tính của các đối tượng (attributes of objects). Tất nhiên, trong Object Oriented Analysis/Design cũng tương tự như trong Kiến trúc Xây dựng, không có câu trả lời tuyệt đối đúng, mà chỉ có câu trả lời tốt hơn, và nằm trên ranh giới của nghệ thuật (Art) nhiều hơn là nằm trên ranh giới của Kỹ thuật (Engineering). Nhưng trong thu thập thông tin sản xuất, dịch vụ, có thực thể (entity) nào đều quy cả ra là object trong hệ thống phần mềm thì là một sai lầm ấu trĩ không thể tha thứ được.

Sau vài năm, sau khi có khái niệm về mối quan hệ giữa các đối tượng (object relationships) và mối liên kết giữa các đối tượng (object-to-object link), Kiến trúc sư Phần mềm lại tỏ ra hăng hái trong việc tạo ra object-to-object link đến nỗi có nhiều business object được tạo mẫu (model) trong hệ thống như là các link.

Một sai lầm khác trong phân tích (OOA) là không xác định được Tính Tối thiểu Và Đủ trong xây dựng đối tượng. Một ví dụ về Tính Tối thiểu và Đủ: Giả sử trong một Hệ thống theo dõi Chuyên môn, có một lớp đối tượng là Programmer, thì những thuộc tính mà hệ thống cần phải biết về một Lập trình viên là Tên, Bằng cấp, Trình độ Lập trình, Những kỹ năng chuyên môn, Khả năng đặc biệt, Số năm kinh nghiệm, Quá trình làm việc (Tùy theo hệ thống theo dõi Chuyên môn, có thể có một vài thuộc tính nữa, nhưng với mục đích ví dụ, tôi giới hạn ở các thuộc tính đề cập ở trên). Tất nhiên, ông lập trình viên A có thể khác ông lập trình viên B ở chỗ ông thì béo, ông thì gầy, ông này là người Ấn Độ còn ông kia là người Mỹ, ông thì lái xe màu đỏ, ông thì lái xe màu xanh … Nhưng những thuộc tính như Béo-Gầy, Ấn Độ – Mỹ – Xe màu đỏ – Xe màu xanh … không phải là những thuộc tính tiêu biểu cho việc theo dõi Chuyên môn , nên không được lưu trữ trong lớp Programmer (Nhưng để mục đích theo dõi cá nhân, có thể được lưu trữ trong lớp đối tượng Employee, nếu có). Như vậy, tập các thuộc tính Tối thiểu và Đủ cho lớp Programmer là (Tên, Bằng cấp, Trình độ Lập trình, Những kỹ năng chuyên môn, Khả năng đặc biệt, Số năm kinh nghiệm, Quá trình làm việc ). Nhưng do không xác định được tính Tối thiểu và Đủ, nên các đối tượng trong dự án N thường có những thuộc tính chồng chéo, có trong nhiều lớp đối tượng có quan hệ với nhau, tham khảo lòng vòng giữa các đối tượng, và có nhiều thuộc tính đặt sai vị trí. Ví dụ về thuộc tính đặt sai vị trí:  trong ví dụ ngoài lề ở trên, thuộc tính về quốc tịch không đặt trong lớp Employee, mà đặt trong lớp Programmer.

Một sai lầm thô thiển khác là không phân biệt được lớp đối tượng (object class) và một thể hiện của đối tượng (object instance). Ví dụ khi ta nói đến xe ô tô, tức là ta nói đến một lớp (class) các xe ô tô nói chung, và khi ta nói đến chiếc ô tô BMW có biển đăng ký XYZ 123, tức là ta nói đến một chiếc xe chính xác và cụ thể, là thể hiện (instance) của lớp đối tượng ô tô. Chính vì không phân biệt được các khái niệm class và instance, trong Hệ thống Phần mềm của công ty N có những trường hợp đặc biệt ấu trĩ như

–          Trong hệ thống có các lớp đối tượng (class) And, lớp đối tượng Or, lớp đối tượng Xor, lớp đối tượng Not, có các thuộc tính giống hệt nhau. Đúng ra, tất cả các vật thể (entity) And, Or, Xor, Not kể trên đều thuộc về một lớp đối tượng (class) gọi là Toán tử (Operator), và chúng chỉ là những thể hiện (instance) có tên khác nhau là And, Or, Xor, Not.

–          Trong hệ thống có những lớp đối tượng như Mũi giày, Đế giày, Dây giày, Thân giày … Đúng ra tất cả những vật thể (entity) kể trên đều thuộc về một lớp đối tượng gọi là Chi tiết Giày (ShoePart) và có các tên gọi khác nhau.

Một chiếc máy bay có hàng chục triệu chi tiết khác nhau, và nếu Hệ thống Phần mềm cho Sản xuất máy bay ở Boeing, Airbus hay Lockheed Martin được cài đặt theo phân tích và thiết kế như ở công ty N, thì Hệ thống phải có hàng chục triệu kiểu đối tượng (object type), và chỉ để viết code cơ bản cho các đối tượng cũng phải mất vài nghìn năm, chưa nói đến chuyện viết code cho cả hệ thống.

Công nghệ Hướng đối tượng (Object Oriented Technology) có ưu điểm là có công cụ để xây dựng được các thành phần (component)  có tính sử dụng lại (reuse) cao, dễ bảo trì (easy to maintain), dễ phát triển, mở rộng (easy to extend). Nhưng tính sử dụng lại (reuse), dễ bảo trì (easy to maintain) và dễ phát triển, mở rộng (easy to extend) của các thành phần không phải tự nhiên mà có, mà phải thông qua một quá trình phân tích kỹ lưỡng, và phải được thiết kế một cách hợp lý, có tính toán sâu sắc và tầm nhìn xa. Điều này phụ thuộc vào quy trình, phương pháp làm việc và trình độ của Kiến trúc sư phần mềm, chứ không phải là điều sẵn có của Công nghệ Hướng đối tượng.

Có vẻ như Kiến trúc sư phần mềm (Software Architect) và Lãnh đạo Kỹ thuật trong dự án của công ty N chỉ biết đến những từ ngữ reuse, extensible qua sách Nhập môn Lập trình, chứ không có kiến thức thực tế, nên mặc dù các thuật ngữ được sử dụng vung vít trong các tài liệu thiết kế và trong các cuộc họp, nhưng hầu như không có thành phần nào trong hệ thống có thể sử dụng lại được, hoặc dễ dàng mở rộng.

Một ví dụ điển hình là khi thiết kế một kiểu đối tượng (object type) để quản lý Vận tải cho Đơn đặt hàng, Ban Lãnh đạo Dự án quyết định là để cho kiểu đối tượng ShipmentInfo có thể sử dụng được (reuse) cho việc quản lý gửi hàng cho nhiều loại đối tượng khác nhau, không chỉ riêng cho Đơn đặt hàng, trong đối tượng ShipmentInfo sẽ không có thông tin gì về Đơn đặt hàng trong đó.

Thế nhưng ShipmentInfo là đối tượng để quản lý Vận tải, tức là phải có nội dung về hàng hóa được giửi trong chuyến gửi hàng đó. Thông tin về gửi hàng mà không nói lên cái gì được gửi thì sẽ được sử dụng vào đâu? Sau một thời gian họp hành khá lâu, Ban Lãnh đạo Dự án mới nhận ra điều hiển nhiên này. Thay vì dùng một kiểu giao diện tổng quát (generic interface) gọi là ShipmentContent để chứa thông tin về nội dung được gửi trong ShipmentInfo, và cài đặt những đối tượng cụ thể được gửi trong Hóa đơn Vận tải như Đơn đặt hàng, Mẫu tiếp thị , Hàng bán Chính thức như là một implementation của interface ShipmentContent, do đó ShipmentInfo có thể sử dụng lại để quản lý Vận tải cho tất cả các lớp đối tượng có cài đặt (implement) ShipmentContent interface,   thì Kiến trúc sư phần mềm và Ban Lãnh đạo quyết định dùng rất nhiều liên kết (link) lòng vòng để diễn tả thông tin và các mối quan hệ giữa một Hóa đơn Vận tải, Hàng được gửi và Địa chỉ gửi hàng, làm tăng đáng kể độ phức tạp của các thao tác căn bản, lẽ ra phải rất đơn giản như ghi Hóa đơn và Đơn đặt hàng vào database và đọc Hóa đơn và Đơn đặt hàng từ database. Và cuối cùng, thực ra do mối liên kết thông qua các link còn phức tạp và có mối ràng buộc cao hơn, nên đối tượng ShipmentInfo cũng chẳng reuse được vào đâu.

Việc thiết kế các kiểu đối tượng một cách bừa bãi, mỗi kiểu đối tượng tương ứng với một thực thể trong thực tế, không có phân loại các đối tượng có cùng nhóm chức năng, cùng có giao diện chung, làm cho mỗi kiểu đối tượng chỉ dùng được cho một trường hợp cụ thể trong Hệ thống, không có tính sử dụng lại (reuse), và mỗi lần cần mở rộng, bổ sung chức năng thì chỉ có mỗi cách mở file Java code ra viết lại.

Trong Thiết kế Hướng đối tượng (OOD), Kiến trúc sư Phần mềm (Software Architect) và Ban Lãnh đạo Dự án tỏ ra có một sự hiểu biết rất nông cạn và ấu trĩ. Số lượng các Mẫu thiết kế (Design Pattern) được áp dụng vào dự án rất hạn chế, và thường là áp dụng sai, mặc dù với yêu cầu và đặc điểm của dự án, thiết kế hệ thống hoàn toàn rơi vào đại đa số các trường hợp điển hình để áp dụng Mẫu thiết kế cơ bản (Basic Design Pattern) và Mẫu thiết kế J2EE (J2EE Design Pattern).

Có duy nhất hai trường hợp áp dụng được Design Pattern một cách tương đối là Business Delegate và Singleton Design Pattern, nhưng đó là do có ví dụ sẵn trong Windchill foundation [4]. Trong Windchill foundation còn có nhiều ví dụ khác về áp dụng Design Pattern, nhưng do thiếu kiến thức về Windchill và không đọc Windchill document cũng như Windchill code, nên thiết kế của Dự án không áp dụng được gì.

Trong khi đó, những ví dụ về áp dụng sai Design Pattern thì nhiều không kể xiết. Sai lầm cơ bản đầu tiên phải kể đến là áp dụng sai MVC Design Pattern [5], một design pattern rất căn bản mà bất kỳ ai học nhập môn Lập trình Hướng đối tượng cũng phải biết. Mục đích chính của MVC Design Pattern là nhằm để tách biệt dữ liệu (data) và phần hiển thị dữ liệu (view). Như vậy, trong đối tượng lưu trữ dữ liệu sẽ không có logic về mặt hiển thị (presentation logic), và các đối tượng hiển thị dữ liệu (view) chủ yếu là sử dụng các getters của đối tượng dữ liệu (model) để lấy thông tin cần hiển thị. Trong khi đó, trong Dự án, các đối tượng tạm gọi là Client Object lại có chứa các chức năng về hiển thị, như việc notify các GUI component về việc thay đổi giá trị và một vài chức năng khác, do đó, các đối tượng View và Model bị phụ thuộc rất chặt chẽ vào nhau.

Do sử dụng sai MVC Design Pattern, chèn logic hiển thị vào đối tượng mang dữ liệu, nên các đối tượng mang dữ liệu để hiển thị khác với business object được tạo ra và lưu trữ trong database. Như vậy, trong hệ thống có hai loại đối tượng để biểu diễn cho cùng một dữ liệu là Client Object và Business Object (ví dụ, để biểu diễn mẫu giày, ta có ClientShoe và BusinessShoe, ClientShoe được sử dụng ở client side và BusinessShoe được sử dụng ở server side).

Do đó, khi cần hiện thông tin về business object (ví dụ như Mẫu giày hay Đơn đặt hàng), cần phải có một quá trình chuyển đổi từ Business Object sang Client Object. Trong tất cả các phần của Dự án, mỗi khi cần ghi một Business Object được tạo ra từ Client GUI vào database, thì chỉ tốn khoảng 4 dòng code để ghi Business Object vào database, kể cả khởi tạo transaction, nhưng phải tốn kèm vào đó khoảng 100 dòng code để copy các thuộc tính từ Client Object sang Business Object (Đây là đã có cải tiến sau khi loại bỏ Data Transfer Object).

Do có nhu cầu gửi thông tin giữa các lớp (layer) khác nhau của Hệ thống, Kiến trúc sư Phần mềm của Dự án nảy sinh ra ý định sử dụng một Design Pattern rất cơ bản là Data Transfer Object (DTO). DTO Design Pattern đúng là được sử dụng để truyền thông tin giữa các lớp (layer) khác nhau của một hệ thống phần mềm nhiều lớp (multi-layer system), nhưng chỉ dùng trong những trường hợp sau đây:

–          Dùng để gửi nhiều thông tin rời rạc trong cùng một lần gửi. (Ví dụ như để gửi username và password từ cửa sổ login tới authentication service để kiểm tra, thay vì gửi hai String riêng biệt username và password, mất hai lần communication qua các layer, chương trình sẽ đóng gói username và password thành thuộc tính của một đối tượng là AuthenticationInfo và gửi đối tượng này đi, như vậy chỉ tốn một lần communication).

–          Dùng để làm giảm số lần giao tiếp từ xa (remote request) trên mạng. Nhiều thông tin (nhiều thuộc tính hoặc nhiều đối tượng) sẽ được đóng gói vào trong một đối tượng là  Data Transfer Object  và gửi qua các thành phần phân tán (distributed component) trên mạng, do đó làm giảm số lần trao đổi qua lại trên mạng, làm giảm network traffic và tăng application performance. Ví dụ như client có yêu cầu cần biết về Đơn đặt hàng (Sample Request) và Thông tin Vận tải (ShipmentInfo) của Đơn đặt hàng, thay vì gửi Sample Request và ShipmentInfo trong hai lần gọi API qua mạng, thì hệ thống sẽ đóng gói Sample Request và ShipmentInfo vào trong một DTO object và gửi trong một lần gọi API qua mạng. (Đáng tiếc là hệ thống tại công ty N không được thiết kế như vậy).

Trong dự án tại công ty N, DTO Design Patter được sử dụng như sau: Bởi vì có hai loại đối tượng khác nhau biểu diễn cho cùng một dữ liệu là Client Object ở client side và Business Object ở server side, nên để truyền dữ liệu từ client side đến  server side và ngược lại, hệ thống sẽ sử dụng một loại đối tượng thứ ba gọi là Data Transfer Object (DTO).

Như vậy, trong hệ thống, tương ứng với mỗi loại dữ liệu sẽ có 3 loại đối tượng khác nhau là Client Object ở client side, Business Object ở server side và DTO Object dùng để gửi thông tin giữa client và server. Ví dụ một mẫu giày sẽ có ClientShoe, BusinessShoe và DTOShoe.

Quá trình ghi một mẫu giày được thiết kế từ GUI vào database sẽ được tiến hành như sau:

– Tại client side: Copy các thuộc tính (attributes) từ ClientShoe vào DTOShoe.

– Gửi DTOShoe tới server.

– Tại server side: Copy các thuộc tính từ DTOShoe vào BusinessShoe.

– Ghi BusinessShoe vào database.

Việc áp dụng DTO Design Pattern ở đây không làm giảm số lượng các thông tin rời rạc được gửi từ client tới server, vì thông tin trong ClientShoe và DTOShoe về mặt cơ bản là như nhau. DTO trong trường hợp này cũng không làm giảm số lần communication qua mạng, vì dù gửi ClientShoe hay gửi DTOShoe từ Client đến server cũng tốn một lần gửi một đối tượng.

Ngược lại, áp dụng DTO như trình bày ở trên tăng thêm 100 dòng code để copy các thuộc tính từ ClientShoe sang DTOShoe và 100 dòng code để copy từ DTOShoe sang BusinessShoe.

Sau 4 năm tìm tòi, nghiên cứu một cách cần cù và gian khổ, có lẽ nhận ra sự ngu xuẩn của việc áp dụng DTO Design Pattern một cách sai lầm của mình, Kiến trúc sư Phần mềm và Ban Lãnh đạo Dự án quyết định loại bỏ DTO Object, và gửi thẳng Client Object đến server side để copy sang Business Object.  Việc làm này được Ban Lãnh đạo Dự án đánh giá như một phát kiến vĩ đại, một bước đột phá để tăng năng suất lập trình (Programming Productivity), vì cho mỗi kiểu đối tượng, bớt đi được 100 dòng code phải viết, và tăng tốc độ thi hành chương trình (Program Performance), vì bớt đi 100 dòng code phải thi hành.

Nhưng bỏ DTO đi thì lại phát sinh ra một vấn đề mới là lúc này ClientObject có mang client code và logic hiển thị (presentation logic) được gửi tới server code, mà xuyên qua rất nhiều layer, đến tận Persistence Layer. Điều này đã phá vỡ hoàn toàn sự linh hoạt (flexibility) của một kiến trúc phần mềm nhiều lớp (multi-layer architecture), và làm cho client và server bị ràng buộc chặt chẽ (tightly-coupled) vào nhau. Một thay đổi nhỏ trong client code cũng sẽ dẫn đến thay đổi trong rất nhiều lớp của server code, từ business layer đến persistence layer và trong rất nhiều trường hợp, thậm chí thay đổi cả database schema. Thiết kế thiên tài này của công ty N đã đưa chúng ta về lại những năm 70 của thế kỷ 20 với kiến trúc phần mềm 2 lớp (2-tier) client-server, Lập trình có cấu trúc (Structural Programming) và gọi hàm từ xa (Remote Procedure Call).

Đồng thời sự phụ thuộc của server vào client code thông qua việc sử dụng Client Object trong server code làm cho trong rất nhiều trường hợp, việc phát triển song song server code và client code không thể thực hiện được, vì lập trình viên cho server code phải ngồi chơi, chờ đến khi lập trình viên cho client code hoàn thành việc lập trình cho Client Object. Do sự quản lý yếu kém và thiếu phối hợp trong Dự án, có nhiều trường hợp, lập trình viên cho client code viết code cho cửa sổ, menu và các đối tượng GUI trước khi viết code cho Client Object, và lập trình viên cho server code được hưởng niềm vui là ngồi chờ lâu hơn nữa.

Một Giải pháp tốt cho tình trạng này là thiết kế một Client tốt, tuân thủ chặt chẽ MVC Design Pattern, tức là không có presentation logic trong data model. Như vậy, Business Object sẽ được sử dụng như là một biểu diễn duy nhất cho một loại dữ liệu trong cả hệ thống, từ Persistence Layer tới Business Layer và Presentation Layer. Business Object sẽ được dùng để gửi thông tin về đối tượng giữa các lớp (layer) của hệ thống, và sẽ được dùng làm model trong hệ thống MVC của GUI.

Ngoài ra, do không phân biệt được các Design Patterns Delegate, Template và Strategy, các khái niệm và cài đặt được sử dụng một cách lung tung, bừa bãi và dẫn đến những cài đặt cực kỳ rắc rối, phức tạp (overly complicated implementation), dẫn đến khó bảo trì, phát triển và làm chậm tốc độ chạy chương trình.

Ở trên chỉ là một vài ví dụ trong rất nhiều trường hợp sử dụng sai Design Pattern trong Software Architecture của công ty N.

Hiểu biết về những nguyên tắc căn bản trong Lập trình Hướng đối tượng (OOP Fundamentals) của Ban Lãnh đạo Dự án cũng không khá hơn bao nhiêu so với hiểu biết về OOA/OOD. Những sai lầm về OOP Fundamentals trong dự án có rất nhiều, nhưng tôi chỉ dẫn ra một vài ví dụ điển hình.

Có một khẩu hiệu mà bất kỳ một lập trình viên tập việc nào cũng có đọc qua ít nhất một lần “Code to interfaces, not code to concrete implementations”, nghĩa là

“Lập trình gọi đến giao diện, chứ không  gọi đến các lớp cài đặt cụ thể.” . Mục đích của việc làm này là để tách riêng chức năng (functionality) khỏi các cài đặt cụ thể (implementation). Điều này có nghĩa là các thành phần (component) và các lớp (layer) của một hệ thống phần mềm chỉ giao tiếp với nhau thông qua một hệ thống chức năng/dịch vụ được định nghĩa trước, còn việc cài đặt các chức năng/dịch vụ đó như thế nào thì phụ thuộc vào các lớp cài đặt cụ thể (concrete implementation). Tuy nhiên, các lớp cài đặt cụ thể này không được bộc lộ (expose) ra khỏi component và layer, nên khi cách cài đặt hoặc thuật toán cho chức năng thay đổi, các component và layer khác hoàn toàn không bị ảnh hưởng, hoặc ảnh hưởng rất ít. Điều này làm tăng tính sử dụng lại, dễ bảo trì và dễ phát triển của component và của cả hệ thống. [6]

Nhưng do không biết (hoặc không hiểu) khẩu hiệu này, nên trong Hệ thống của công ty N, mặc dù trong hệ thống có định nghĩa các interface, nhưng các hàm API để giao tiếp giữa các lớp (layer) và các thành phần (component) của hệ thống chủ yếu sử dụng các lớp cụ thể (concrete class) như là tham số (parameters, arguments) và giá trị trả về (return value).

Một sai lầm khác về OOP Fundamentals trong dự án của công ty N là không phân biệt nổi Mở rộng chức năng cho đối tượng bằng Inheritance (Kế thừa)  và Mở rộng bằng Composition (tạm dịch là Bao gồm) hoặc Mở rộng bằng Design Pattern (ví dụ Decorator Pattern và Visitor Pattern), do đó, trong tất cả các phần của dự án, việc mở rộng, bổ sung chức năng cho các lớp đối tượng được thực hiện một cách duy nhất bằng Inheritance, tạo ra những họ (family) các lớp đối tượng lớn, các thành viên thực chất chả có liên quan đến nhau mấy, mà chỉ được tạo ra bởi nhu cầu mở rộng chức năng.[7]

Trong một hệ thống enterprise software, XML đóng một vai trò rất quan trọng. Và trong dự án tại công ty N, việc sử dụng XML cũng có nhiều sai lầm, bao gồm cả Lạm dụng XML (Overuse XML) và Sử dụng không hết chức năng của XML (Underuse XML).

Trình bày về chức năng và phương pháp sử dụng XML trong Enterprise Software Development hoàn toàn không nằm trong phạm vi bài viết này. Tôi chỉ xin dẫn ra một vài sai lầm căn bản trong việc sử dụng sai lầm trong dự án tại công ty N.

Một trong những sai lầm nghiêm trọng trong sử dụng XML trong dự án là đa số các file XML được viết trong quá trình phát triển dự án hoàn toàn không có biểu diễn cấu trúc và kiểm tra cấu trúc thông qua DTD (Document Type Definition) hoặc XSD (XM Schema Definition). Điều này dẫn đến tình trạng khá nguy hiểm là cấu trúc của file XML có thể bị thay đổi một cách bừa bãi, và có thể dẫn đến việc hệ thống hoạt động sai, sinh ra các lỗi thi hành (run-time error) nghiêm trọng.

Trường hợp điển hình về việc lạm dụng XML xảy ra trong việc xây dựng một hàm tiện ích ở server side có tên là getServerObject để tìm kiếm một Business Object trong database khi biết kiểu đối tượng ClientObject và Unique Identification của  object này vào thời điểm mà hàm API được gọi. Như đã trình bày trong phần trên, cho một kiểu dữ liệu nhất định, có ít nhất hai kiểu đối tượng tương ứng là ClientObject và BusinessObject. Quan hệ giữa ClientObject và ServerObject là quan hệ 1:1, điều này có nghĩa là vào thời điểm hàm getServerObject được gọi, nếu ta biết kiểu đối tượng (object type) của ClientObject, thì có nghĩa là ta cũng biết kiểu của BusinessObject, và chỉ việc gọi lệnh tìm kiếm trong database cho BusinessObject.

Tuy nhiên, theo yêu cầu của Kiến trúc sư Phần mềm (Software Architect) và Ban Lãnh đạo Dự án, nhằm mục đích tăng tính linh hoạt của hệ thống (?), vào lúc gọi hàm getServerObject, mặc dù đã biết rất rõ kiểu của ClientObject, ta phải giả vờ không biết kiểu của BusinessObject, và phải tìm trong một XML mapping file để xem kiểu (type) của BusinessObject là gì, rồi mới gọi lệnh tìm kiếm trong database cho BusinessObject. Ở đây, việc tồn tại của XML file và XML lookup là hoàn toàn thừa và làm giảm tốc độ thực hiện chương trình.

Trường hợp điển hình về không sử dụng hết chức năng của XML nằm trong N Search Framework dùng để tìm kiếm object trong database. Như đã trình bày ở trên, framework này là hoàn toàn thừa, và tạo nhiều rắc rối cho lập trình viên nhiều hơn là tạo công cụ. Framework này không chỉ có vấn đề về mặt chức năng, mà còn có rất nhiều vấn đề về mặt cài đặt. Một trong những vấn đề đó là: Đối với mỗi loại đối tượng (object type) khác nhau, cần phải có rất nhiều loại đối tượng phụ trợ (helper object) đi kèm thì mới thực hiện được việc tìm kiếm.  Và riêng về một hàm API phục vụ cho việc tìm kiếm, mỗi loại đối tượng phải có một hàm getObject khác nhau, trong đó sự khác biệt giữa các hàm getObject của các loại đối tượng khác nhau là:

–          Thêm các thuộc tính (attribute) làm điều kiện tìm kiếm và cần lấy từ database vào một danh sách các thuộc tính.

–          Lấy ra các giá trị (value) của thuộc tính của đối tượng từ kết quả trả về.

Các bước tiến hành khác trong các hàm API getObject này là giống hệt nhau. Như vậy có thể dùng một file XML để lưu các thuộc tính làm điều kiện tìm kiếm và các thuộc tính cần lấy từ database cho từng loại đối tượng.  Sau đó viết một hàm getObject cho tất cả các loại đối tượng (object type), trong đó kiểu đối ượng được truyền làm tham số cho hàm getObject, và tại hai phần khác biệt kể trên, chương trình sẽ căn cứ vào tham số object type để phân tích file cấu hình XML và tìm ra những điều kiện tìm kiếm và thuộc tính trả về cho từng loại đối tượng thích hợp. Nhưng đáng tiếc, trong cài đặt của N Search Framework, có hàng chục hàm getObject cho hàng chục kiểu đối tượng khác nhau, trong đó sự khác nhau giữa hàng chục hàm getObject này chỉ nằm ở hai bước có thể dùng XML để định cấu hình (configure) như đã miêu tả ở trên. Với đà phát triển hiện nay của dự án, số lượng các kiều object (object type) hoàn toàn có thể lên tới hàng nghìn, và sẽ có hàng nghìn hàm getObject đòi hỏi phải có sự bảo trì và sửa đổi mỗi khi có một sửa đổi trong thiết kế hoặc từ thực tế sản xuất.

Còn rất nhiều những sai lầm trong phân tích và thiết kế hệ thống cũng như việc thực hiện dự án, nhưng khuôn khổ bài viết có hạn, hơn nữa, những sai lầm còn lại mặc dù có những sai lầm nghiêm trọng nhưng không có tính điển hình, và phần nhiều là hệ quả của sự thiếu kiến thức, kinh nghiệm và những sai lầm đã có phân tích, vì thế tôi không đề cập tới.

V. Những bài học rút ra từ Dự án

Một quy trình tốt, được thực hiện đủ tất cả các bước không bảo đảm cho sự thành công của một Dự án phần mềm. Quy trình được sử dụng trong Dự án của công ty N là Rational Unified Process, một quy trình chuẩn công nghiệp được sử dụng rộng rãi trong phát triển phần mềm, nhưng do chi tiết thực hiện từng bước sai, nên không đem lại kết quả.

Sử dụng những công nghệ tốt, theo chuẩn công nghiệp không bảo đảm cho sự thành công của một Dự án phần mềm. Công nghệ được sử dụng trong Dự án của công ty N là J2EE và Oracle database, là những công nghệ tốt nhất hiện nay cho Enterprise Software, có chuẩn công nghiệp và chi tiết kỹ thuật (Technical Specification) rõ rang, với đầy đủ các công cụ (tool) và tiện ích (utility) để phát triển. Nhưng do sử dụng không có phương pháp, nên kết quả vẫn là phần mềm chắp vá, kém chất lượng, không sử dụng được.

Những công cụ lập trình và phần mềm tiện ích tốt cũng không đảm bảo cho sự thành công của một dự án phần mềm. Các công cụ được sử dụng trong dự án như ClearCase,Rational Rose, Eclipse, Aphelion, Apache, Tomcat … đều là những công cụ đã được thử thách và chứng tỏ là tốt trong Công nghệ Phần mềm. Nhưng do sử dụng không đúng, nên không giúp ích được nhiều cho quá trình làm việc, và không tạo ra được sản phẩm tốt

Con người chính là khâu quan trọng nhất trong một Dự án Phần mềm. Chính vì Ban Lãnh đạo Dự án và Kiến trúc sư Phần mềm của Dự án không có đủ năng lực để quản lý, thiết kế và thi hành Dự án, nên Dự án mới dẫn đến tình trạng như đã trình bày trong bài viết.

Khi bắt tay vào việc tiến hành một Hệ thống Phần mềm, việc đầu tiên là phải tìm được một đội ngũ nhân sự có trình độ thích hợp với quy mô và độ phức tạp dự tính sẽ có của Dự án, sau đó mới tiến hành thu thập thông tin, phân tích thiết kế và thực hiện.

Thực ra, phần chuẩn bị Nhân sự chính là phần khó khăn nhất của một Dự án phần mềm, vì nhiều công ty sản xuất và dịch vụ không có sẵn chuyên gia và nhân viên kỹ thuật có trình độ Phần mềm cao để có thể phỏng vấn và tuyển người cho Dự án. Ngay cả khi công ty sản xuất và dịch vụ có bộ phận IT riêng, thì những người trong các bộ phận này thường không có trình độ cao, vì yêu cầu công việc thường xuyên hàng ngày không đòi hỏi nhân viên phải có trình độ chuyên môn cao. Hơn nữa, khi khởi đầu việc tuyển người cho bộ phận IT nội bộ, có rất nhiều khả năng là công ty sản xuấtvà dịch vụ không có người có đủ trình độ để phỏng vấn và xét tuyển nhân viên.

Giải pháp cho vấn đề nhân sự cho những Dự án phần mềm lớn và phức tạp là: Đầu tiên phải  thuê một trong những công ty Tư vấn về Giải pháp Công nghệ Thông tin để thu thập thong tin sơ bộ và làm phác thảo ước tính về quy mô cũng như Độ Phức tạp của Dự án. Sau đó  dựa vào những công ty Cung cấp Nhân sự chuyên nghiệp để thuê những nhân viên quản trị Dự án (Project Manager) và Kiến trúc sư Phần mềm (Software Architect) có năng lực , để làm nhiệm vụ lãnh đạo Dự án, thu thập thong tin, phân tích đánh giá, lựa chọn công nghệ, công cụ, ngôn ngữ lập trình, phác thảo thiết kế …

Làm theo cách này, sẽ đảm bảo được tính chuyên môn hóa cao, vì các công ty chuyên về Tư vấn về Giải pháp Công nghệ Thông tin có chuyên môn cao trong việc thu thập thông tin thực tế và phác họa giải pháp, các công ty Cung cấp Nhân sự có chuyên môn cao và có chuyên gia với trình độ chuyên ngành cần thiết trong việc tìm kiếm, phỏng vấn và xét tuyển nhân viên. Tuy nhiên, do nhu cầu thị trường lớn, nên có nhiều công ty cung cấp dịch vụ Tư vấn Giải pháp và Cung cấp Nhân sự hoạt động, và rất nhiều trong số đó không có đủ kinh nghiệm, trình độ và kiến thức cần có cho những Dự án có quy mô lớn và phức tạp. Do đó, việc chọn công ty Tư vấn Giải pháp và Cung cấp Nhân sự để thuê cần phải được tiến hành hết sức cẩn thận.

Sau khi hoàn thành tốt khâu Chuẩn bị Nhân sự, thì các khâu khác của Dự án sẽ được tiến hành một cách thuận lợi, vì những Quản trị Dự án và Kiến trúc sư Phần mềm có kinh nghiệm, kiến thức sẽ biết phải điều hành dự án theo những Quy trình nào, tiến hành việc thu thập thông tin, phân tích, hệ thống, đánh giá ra sao, tổ chức đội ngũ và giao tiếp giữa các nhóm làm việc như thế nào, tuyển lập trình viên và nhân viên phân tích với tiêu chuẩn trình độ sao cho phù hợp, lựa chọn công cụ, tiện ích để quản lý, theo dõi công việc và công cụ lập trình một cách tối ưu. Tất nhiên, các công việc kể trên không phải là dễ dàng, nhưng với một đội ngũ Lãnh đạo tốt, có kinh nghiệm, kiến thức thì khả năng tiến hành tốt các bước của Dự án sẽ rất cao, và Dự án có khả năng thành công đúng thời hạn và trong phạm vi ngân sách.

Hy vọng là qua study case này, bạn đọc sẽ rút ra được những điểm yếu có thể xảy ra trong những khía cạnh khác nhau của một Dự án Phần mềm như Quy trình Quản lý Dự án (Project Management Process), Quy trình Phát triển Phần mềm (Software Development Process) và Kiến trúc Phần mềm (Software Architecture) và qua những giai đoạn (phase) khác nhau của một chu kỳ phát triển phần mềm (Software Development Lifecycle) như Khởi đầu (Inception), Dự thảo Chi tiết (Elaboration), Thực hiện xây dựng (Construction). Có điều, các giai đoạn được trình bày về Dự án tại công ty N này không phải là một Chu kỳ phát triển Phần mềm đầy đủ (Full Lifecycle Software Development) vì Dự án chưa có, và rất có thể không bao giờ có giai đoạn Chuyển giao (Transition).

U.S.A. 1-8-2005

JMS

————————————————

Chú thích

[1]  Trước đây tôi đã từng làm việc vài năm trong vị trí là Senior Software Engineer, Software Architect và R&D Team leader trong Windchill R&D (Research and Development) của PTC.

[2] Trong thời gian làm trong Windchill R&D, ngoài công việc nghiên cứu phát triển công nghệ và thiết kế Windchill foundation, tôi có tham gia hỗ trợ trực tiếp cho dự án triển khai Windchill ở Rolls Royce (Anh), Airbus (Pháp) và Tokyo Electron (Nhật).

[3] Frederik Phillips Brooks, Jr.: Kenan Professor of Computer Science, Department of Computer Science, University of North Carolina

Ông tốt nghiệp Cử nhân Khoa học ngành Vật lý với điểm tuyệt đối trong toàn bộ quá trình học (summa cum laude) trường Duke, Master và Ph.D. toán ứng dụng trường Harvard. Ông đã tham gia giảng dạy nhiều năm, làm nghiên cứu trong Bộ phận Nghiên cứu và Phát triển Công nghệ của IBM, tham gia Ban Nghiên cứu của Bộ Quốc phòng và nhiều Ủy ban Nghiên cứu Liên bang và Quốc gia khác. Các giải thưởng, huy chương về Phát minh và Công nghệ của ông được trao bởi Học Viện Hoàng gia Anh, Học viện Hoàng gia Hà lan, Viện nghiên cứu Liên bang Thụy sĩ, của các Viện nghiên cứu, trường Đại học và Ủy ban Quốc gia của Mỹ nếu liệt kê hết phải tốn nhiều trang giấy khổ A4. Ông có hai bằng Phát minh Sáng chế của Mỹ (U.S. Pattern) trong lĩnh vực Computer Science. Ông đã tham gia quản trị nhiều dự án nghiên cứu công nghệ và phát triển phần mềm trong công nghiệp.

Danh mục các tác phẩm khoa học bao gồm sách, bài viết, tài liệu nghiên cứu … nếu được liệt kê cũng tốn rất nhiều trang A4.

[4] Có một trường hợp áp dụng Memento Design Pattern trong Swing GUI của Dự án cũng khá lý thú, nhưng là do sáng tạo của một Swing Developer chứ không phải nằm trong thiết kế của dự án. Lác đác trong Java code của dự án cũng có một vài chỗ có ứng dụng tốt Design Pattern, nhưng toàn bộ là do các lập trình viên giàu kinh nghiệm trong dự án áp dụng, chứ không có trong tài liệu thiết kế (Design Document) và Mô hình Đối tượng (Object Model), và không phải từ Ban Lãnh đạo Dự án và Kiến trúc sư phần mềm mà có.

[5] MVC: Model-View-Controller. Chi tiết về lý thuyết và ví dụ về ứng dụng MVC Design Pattern trong lập trình Java có thể tìm thấy trong PC World Vietnam tháng 5 năm 2005.

[6] Trong ngôn ngữ lập trình Java, interface có 4 chức năng rất quan trọng:

–          Java không hỗ trợ (support) việc thừa kế từ nhiều lớp đối tượng (multiple inheritance), do đó interface cung cấp công cụ để một lớp đối tượng có thể cài đặt (implement) nhiều interface, và qua đó thừa kế các hành vi (behavior) của nhiều loại đối tượng khác nhau.

–          Java interface tách biệt chức năng (functionality) và cách cài đặt chức năng (implementation). Đây là một đặc điểm rất quan trọng, giúp cho các thành phần (component) trong một hệ thống OOP có thể tương tác với nhau, nhưng không phụ thuộc chặt chẽ vào cách cài đặt của nhau, do đó các thành phần có thể được dùng lại trong nhiều hệ thống, dễ bảo trì, mở rộng.

–          Java interface có tác dụng như một sự đánh dấu (marker interface), xác định với hệ thống là nếu một lớp đối tượng (class) cài đặt (implement) một interface, thì lớp đối tượng này có thể được hệ thống thao tác và sử dụng theo một số phương pháp nhất định. Một ví dụ về marker interface là Serializable interface.

–          Java interface có tác dụng là định nghĩa các phương thức (method) nhằm mục đích bắt buộc những lớp đối tượng (class) nào cài đặt (implement) interface này, thì cũng phải có những phương thức (method) có trong interface. Chức năng này dung để thiết kế các framework mà các hành vi cụ thể có thể mở rộng hoặc thay đổi cách thực hiện trong tương lai, hoặc các hành vi phải được thực hiện đã biết, nhưng cách thức thực hiện thì chưa được biết vào thời điểm viết chương trình, mà chỉ biết khi chạy chương trình (run-time) . Trong design pattern, chức năng này được sử dụng nhiều trong Template Method và Strategy pattern.

[7] Một ví dụ về mở rộng chức năng thông qua Kế thừa (Inheritance) và thông qua Bao gồm (Composition).

Giả sử trong một hệ thống dữ liệu về hàng điện tử ta có nhiều loại thiết bị cần quản lý, trong đó có Phone(Điện thoại), Camera (máy ảnh),  CameraPhone (Điện thoại có máy ảnh) và Digital Camera (Máy ảnh kỹ thuật số).

Ta nhận thấy CameraPhone có chức năng của Phone và Camera, có thể được mở rộng từ Phone và Camera. DigitalCamera thuộc về họ Camera, và có thể được mở rộng từ Camera.

Mở rộng thông qua kế thừa: Trong Java không có thừa kế từ nhiều lớp (multiple Inheritance), nên ta phải định nghĩa Camera và Phone là Interface, và định nghĩa CameraPhone là implementation của các interface Camera và interface Phone. Như vậy trong lớp CameraPhone, ta phải viết code cho các chức năng của Phone và Camera. Tương tự, ta có thể định nghĩa DigitalCamera là implementation của Camera, và trong Camera, ta phải viết code cho các chứ năng của Camera.

Lợi: Xây dựng được một hệ thống các lớp đối tượng có chung một số chức năng nhất định (ví dụ như DigitalCamera và CameraPhone có chung chức năng chụp ảnh).

Hại: Trùng lặp code (trong DigitalCamera và CameraPhone cùng có code cho chức năng chụp ảnh, và rất có thể là hoàn toàn giống nhau, vì cùng là chụp ảnh digital). Dễ gây ra tính thiếu tự nhiên trong thiết kế và lỗi khi chạy chương trình (ví dụ như một API dành cho interface Phone được gọi và truyền cho tham số là CameraPhone, sau đó dùng reflection để gọi các method trên đối tượng được truyền làm tham số, rất có thể API này sẽ gọi cả chức năng của Camera, là điều hoàn toàn sai và không được dự tính cho API này). Tạo ra nhiều lớp đối tượng một cách không cần thiết (mỗi lần cần mở rộng tính năng lại phải dẫn suất (derive) ra một lớp đối tượng mới).

Mở rộng thông qua Bao gồm (Composition)

Ta định nghĩa Phone như một class có các chức năng của điện thoại, và Camera là một class có chức năng của máy ảnh. Như vậy CameraPhone được định nghĩa như một lớp đối tượng có hai thành viên (member variable) là Camera và Phone. Khi chức năng Phone của CameraPhone được gọi, CameraPhone sẽ gửi lệnh gọi này tới biến thành viên (member) Phone, và khi chức năng Camera của CameraPhone được gọi, CameraPhone sẽ gửi lệnh gọi này tới thành viên Camera. Đối với DigitalCamera, ta có chọn lựa rộng rãi hơn, có thể kế thừa (inherit) và định nghĩa chồng (override) các chức năng của Camera, hoặc các chức năng được cài đặt cơ bản là giống nhau, thì có thể định nghĩa DigitalCamera có một biến thành viên là Camera, và gửi các lệnh gọi về chức năng của Camera tới thành viên này.

Lợi: Giảm được sự trùng lặp code. Tạo ra các chức năng mới một cách dễ dàng bằng cách bổ sung biến thành viên.

Hại: Trong trường hợp đối tượng mới cần có chức năng khác hơn chức năng có sẵn của biến thành viên (ví dụ chức năng chụp ảnh của DigitalCamera khác chưa năng chụp ảnh của Camera, còn các chức năng như nạp pin, lau ống kính thì giống), sẽ có dư thừa code (vì chức năng chụp ảnh phải viết mới, trong khi đó trong biến thành viên Camera cũng có chức năng chụp ảnh).

Tất nhiên, không có luật tuyệt đối đúng (hard and fast rule) cho việc trong trường hợp nào thì phải mở rộng chức năng bằng Inheritance, trong trường hợp nào thì phải sử dụng Composition hay Design Pattern. Có một khẩu hiệu cũng khá nổi tiếng trong giới lập trình “Prefer composition over Inheritance”. Tuy vậy, điều này phụ thuộc vào yêu cầu thực tế, trình độ, kỹ năng kinh nghiệm của kiến trúc sư phần mềm (Software Architect), và có tính nghệ thuật cao.

Nhưng một Dự án phần mềm mà chỉ có mở rộng chức năng đối tượng bằng Inheritance (trong khi có những trường hợp dùng các phương pháp khác tốt hơn) là tuyệt đối không được, thể hiện trình độ kém và thiếu hiểu biết của kiến trúc sư phần mềm.

/*
*
* Nguồn: Blog Châu Hồng Lĩnh ~ Project N
*
*/

Written by Xavier

January 25, 2011 at 10:20 am

Leave a comment