Mã tái cấu trúc và tối ưu hóa phù hợp ở đâu trong cả dòng thời gian xử lý nhanh và thác nước?


10

Dường như có khái niệm này trong nhóm quản lý dự án nói rằng "nó hoạt động" có nghĩa là nó sẽ được coi là hoàn thành 100%. Hầu hết các lập trình viên biết rằng không phải lúc nào cũng như vậy. Nếu tôi đang thử các phương pháp thay thế để làm cho một phần chức năng hoạt động, điều đó không nhất thiết có nghĩa là tôi đã tìm ra giải pháp tốt nhất hoặc nó sẽ không yêu cầu làm lại sau khi xem xét với các nhà phát triển khác. Tôi sẽ thường xuyên hoàn thành công việc gì đó, lùi lại và sau đó tự hỏi mình có thể làm gì tốt hơn sau khi các quy tắc kinh doanh được thỏa mãn. Thời gian "Tôi có thể làm tốt hơn" này có thực sự phù hợp ở đâu đó trong dòng thời gian không? Tôi cho rằng cách tiếp cận tốt nhất là bạn luôn để lại mã tốt hơn so với khi bạn tìm thấy nó (ở một mức độ nào đó), điều đó có nghĩa là tái cấu trúc bài khởi chạy. Tuy nhiên,

Câu trả lời:


13

Có một nguyên tắc bao trùm chi phối nhu cầu tái cấu trúc và tối ưu hóa, cả trong thác nước và Agile: YAGNI (You Ain't Gonna Need It). Một nguyên tắc thứ hai là hệ quả của thứ nhất: "Tối ưu hóa sớm là gốc rễ của mọi tội lỗi", tương đương mã hóa của câu tục ngữ chung "kẻ thù của sự xuất sắc là sự hoàn hảo".

Hãy dự đoán và áp dụng chúng. Bạn có yêu cầu xây dựng thuật toán ETL lấy một tệp thuộc loại cụ thể, trích xuất thông tin của nó, sau đó đưa thông tin đó vào cơ sở dữ liệu. Mục tiêu của bạn trong tuần này (vì mục đích của chúng tôi, không quan trọng bạn đang ở trong cửa hàng Agile hay SDLC) là để hoàn thành nó.

Bạn là một người thông minh, và bạn đã được nhìn thoáng qua bức tranh lớn. Bạn biết rằng đây không phải là loại tệp duy nhất mà dự án sẽ cần một ETL. Vì vậy, bạn xem xét việc triển khai thuật toán ETL này cũng hoạt động trên một loại tệp khác, chỉ có những khác biệt nhỏ. Làm điều này sẽ vi phạm YAGNI. Công việc của bạn không phải là phát triển thuật toán cho tập tin khác đó; đó là phát triển thuật toán cho một tệp cần thiết vào cuối tuần. Để đáp ứng mục tiêu đó và vượt qua các bài kiểm tra chấp nhận, bạn cần phát triển thuật toán đó và làm cho nó hoạt động chính xác. Bạn "không cần" mã bổ sung để làm cho nó hoạt động với tệp khác. Bạn có thể nghĩ rằng nó sẽ giúp bạn tiết kiệm thời gian để kết hợp nó ngay bây giờ, và bạn có thể đúng, nhưng bạn cũng có thể sai lầm khủng khiếp; thuật toán cho tệp khác có thể cần được sử dụng trong một khu vực của hệ thống mà mã của bạn không thể được sử dụng hoặc các yêu cầu đối với tệp mới có thể khác với các cách bạn không biết (trong Agile, những cách đó yêu cầu có thể chưa tồn tại). Trong khi đó, bạn đã lãng phí thời gian và tăng độ phức tạp của thuật toán một cách không cần thiết.

Bây giờ, đó là tuần tới, và như một phần thưởng đáng ngờ cho công việc xuất sắc của bạn trên thuật toán đầu tiên, bạn đã được giao nhiệm vụ tạo thuật toán cho hai loại tệp mới. Bây giờ, bạn cần mã bổ sung để làm cho thuật toán của bạn hoạt động với nhiều tệp hơn. Bạn có thể mở rộng thuật toán hiện tại của mình bằng cách sử dụng mẫu phương thức mẫu sẽ sử dụng mẫu cơ bản với các bước riêng cho từng tệp hoặc bạn có thể chỉ cần lấy giao diện chung từ thuật toán hiện tại của mình, phát triển hai mẫu mới theo giao diện và cắm chúng vào một đối tượng có thể chọn sử dụng thuật toán nào.

Trong khi phát triển, bạn biết rằng bạn có một yêu cầu là hệ thống có thể xử lý 10KB dữ liệu thô mỗi giây. Bạn thực hiện kiểm tra tải và tìm thuật toán dự thảo ban đầu của bạn xử lý 8KB / s. Chà, điều đó sẽ không vượt qua AAT. Bạn hãy xem và thấy rằng có một số cấu trúc vòng lặp linh hoạt O (Chúa tôi) trong thuật toán của bạn; bạn hợp lý hóa nó và nhận được 12KB / s. "Khá tốt", bạn nghĩ, "nhưng nếu tôi có một vòng lặp kém trong mã, tôi có thể cạo cái gì khác?". buzz Bạn vừa vi phạm quy tắc "tối ưu hóa sớm". Mã của bạn hoạt động, và vượt qua tất cả các yêu cầu. Bạn đã "hoàn thành", cho đến khi các yêu cầu được cập nhật để yêu cầu 15KB / s. Nếu và khi điều đó xảy ra, THÌ bạn kéo mã trở lại và tìm kiếm những thứ cần cải thiện.

Thực hiện theo quy trình đơn giản này trong khi phát triển, cho dù ở Agile hay SDLC truyền thống: "Trên đường chuyền đầu tiên, hãy làm cho nó hoạt động. Ở đường chuyền thứ hai, hãy làm cho nó đẹp. Ở đường chuyền thứ ba, hãy làm cho nó RẮN." Điều này có nghĩa là gì, khi bạn lần đầu tiên tạo một dòng mã, hãy làm cho mã đó thực hiện công việc của nó một cách chính xác và không có lỗi, nhưng đừng quá chú ý đến các quy tắc thiết kế trong mã này, như tất cả những gì bạn biết ngay bây giờ bạn ' Sẽ không bao giờ chạm vào khu vực này một lần nữa. Lần sau khi bạn truy cập vào dòng mã đó, bạn đã chứng minh rằng mình đã sai; nó không còn là một phần của hệ thống. Tái cấu trúc nó để dễ đọc, đồng nhất mã và / hoặc nguyên tắc DRY (bạn có thể đã sao chép một số mã để thực hiện điều gì đó năm lần; tái cấu trúc mã đó thành một vòng lặp và / hoặc gọi phương thức). Lần thứ ba bạn đang làm việc trong hoặc xung quanh dòng mã đó,


3
+1 vì O(my God)-complexitynếu không có gì khác, làm tôi cười!
Joel C

+1 cho Làm cho nó hoạt động đầu tiên. Quá nhiều người cố gắng viết các mẫu và tối ưu hóa sớm con dơi.
Justin Shield

Tôi thấy đây là một trong những vấn đề khó khắc phục nhất khi làm lập trình viên. Các kỹ sư có một mong muốn bẩm sinh để thử nghiệm, phát triển và tinh chỉnh, nhưng vào cuối ngày, bạn sẽ được trả tiền cho năng suất. Một sản phẩm hoàn hảo là gì nếu bạn dành quá nhiều thời gian và / hoặc tiền mà nó bị hủy do vượt quá?
ToddR

Tôi thích aproach thực dụng nhưng tôi gặp vấn đề với "Trên đường chuyền thứ hai, hãy làm cho nó thật đẹp": nếu đường chuyền thứ 2 là một năm sau đó và bạn không biết rằng tên biến và phương thức là số có nghĩa và các số ma thuật được thay thế bằng hằng số tượng trưng bạn có thể có vấn đề để hiểu mã. Làm thế nào để đối phó với điều này? "Làm cho nó đẹp" 1 giờ sau khi "làm cho nó hoạt động" rẻ hơn nhiều so với "làm cho nó đẹp" sau một tháng hoặc sau một năm. Tôi đồng ý rằng "làm cho nó đẹp" khi thay đổi mã tiếp theo là không cần thiết nếu việc "làm cho nó đẹp" không được thực hiện ngay từ đầu.
k3b

Trong Agile / TDD, kinh nghiệm của tôi là việc vượt qua lần thứ hai thường xảy ra khá sớm sau lần đầu tiên. Trong SLDC của Waterfall-ish, bạn đúng hơn; hàm có xu hướng được viết một lần và sau đó nằm ở đó cho đến khi vòng yêu cầu tiếp theo đi qua phương thức đó. Vì vậy, một số thực hành mã hóa tốt cần phải xảy ra lần đầu tiên, như tự viết mã, để khi bạn quay lại một năm sau, bạn có thể nhớ mã đó làm gì và tại sao bạn lại viết như vậy.
KeithS

10

Nếu nó hoạt động, và đã được thử nghiệm, thì tại sao phải sửa nó?

Điều này có thể đi ngược lại tính khí cá nhân của bạn với tư cách là một kỹ sư / lập trình viên, nhưng nếu nó hoạt động, giá trị kinh doanh nào để bạn tiếp tục tinh chỉnh nó? Nó sẽ làm cho nó dễ dàng hơn để duy trì theo thời gian? Nếu vậy, sau đó làm việc theo phương pháp nhanh, bạn sẽ có thể tạo các mục mới trong hồ sơ tồn đọng của mình để tinh chỉnh và cấu trúc lại mã hiện tại của bạn và những mục đó sẽ được ưu tiên với các mục khác trong hồ sơ tồn đọng. Đó là một phần giá trị của quy trình nhanh: nhóm quyết định cùng nhau những gì quan trọng nhất và những gì sẽ được thực hiện tiếp theo.

Nhóm của chúng tôi cũng theo dõi cái mà chúng tôi gọi là "nợ kỹ thuật", vì vậy nếu bạn nhận được một cái gì đó hoạt động nhưng bạn biết nó có thể được thực hiện tốt hơn, bạn ghi nó là nợ kỹ thuật. Chúng tôi sử dụng scrum và đôi khi bạn sẽ hoàn thành tất cả công việc trong giai đoạn nước rút sớm (bạn nên hoàn thành sớm hơn một nửa thời gian nếu bạn khá gần với ước tính), nhưng không còn đủ thời gian để hoàn thành một công việc hoàn toàn mới câu chuyện của người dùng, vì vậy chúng tôi dành thêm thời gian để quay lại và xử lý khoản nợ kỹ thuật của mình. Nó không được theo dõi chính thức như câu chuyện người dùng của chúng tôi trong hồ sơ tồn đọng của chúng tôi và chúng tôi có thể làm việc với nó bất cứ khi nào có thời gian.

Đó cũng ít nhiều là một lời kêu gọi phán xét từ phía bạn khi bạn gọi nhiệm vụ là "xong"; nếu bạn không hài lòng với trạng thái mã của mình, đừng đánh dấu nhiệm vụ hoàn thành.


2
Tôi đã trở thành một người hâm mộ khái niệm "nợ kỹ thuật", +1 để đưa nó lên trong bối cảnh này.
Patrick Hughes

Hoàn toàn quên mất ý tưởng về "nợ kỹ thuật"; nhiệm kỳ tốt. Nhưng, tôi được dạy rằng bất cứ điều gì đủ điều kiện là "nợ kỹ thuật", có nghĩa là nó sẽ đòi hỏi các chu kỳ phát triển quan trọng để tái cấu trúc, phải được tránh; "làm điều đó nhẹ" vẫn có nghĩa là "làm đúng", đừng đi "tháp ngà" trên mã có thể là một lần.
KeithS

5

Thời gian "Tôi có thể làm tốt hơn" này có thực sự phù hợp ở đâu đó trong dòng thời gian không?

Đúng.

Ngay trước khi bạn bắt đầu mã hóa bản phát hành tiếp theo .

Đừng tái cấu trúc dựa trên "trực giác".

Tái cấu trúc dựa trên những câu chuyện thực tế của nước rút tiếp theo.


2

Đừng đánh dấu mã là hoàn thành 100% cho đến khi bạn hài lòng với việc tái cấu trúc. Bạn chỉ cần liên tục đánh giá chi phí / lợi ích để tái cấu trúc mã bởi vì nếu bạn học đủ, bạn sẽ luôn thấy các cách để làm cho mã tốt hơn.

Tôi sử dụng phương pháp tái cấu trúc màu xanh lá cây màu đỏ của TDD. Vì vậy, tái cấu trúc của tôi được xây dựng vào sự phát triển của tôi. Đối với các phép tái cấu trúc lớn như thay đổi mô hình cơ bản hoặc một cái gì đó tương tự, tôi sẽ mua quản lý để dành thời gian đầu tiên.


1
Mã không "hoàn thành 100%" cho đến khi tất cả các sản phẩm mà nó cư trú đã chết. Giống như bạn không "hoàn thành" như một người cho đến khi trái tim bạn ngừng đập vĩnh viễn; bạn sẽ luôn tiếp thu thông tin mới và được yêu cầu làm những việc cụ thể mà bạn chưa từng làm trước đây hoặc làm điều tương tự theo cách mới hiệu quả hơn hoặc ít tốn kém hơn. Tương tự, cơ sở mã của bạn sẽ LUÔN cần công việc - các tính năng mới và các bản sửa lỗi cũ - cho đến khi không còn ai sử dụng phần mềm nữa.
KeithS

2

"Tái cấu trúc bài khởi chạy" có một chi phí ẩn trong kiểm tra hồi quy và thời gian QA mà bạn đang bỏ qua, cộng với đó là chi phí cơ hội của việc không làm việc với các lỗi được báo cáo và các tính năng và thay đổi mới / được yêu cầu. TANSTAAFL

Nếu nó đáng để làm, thì đáng để thực hiện một nhiệm vụ để được ưu tiên thông qua quy trình thông thường của bạn và không phải là một ngoại lệ đặc biệt. Rốt cuộc, bạn là một phần của một nhóm và làm việc theo các mục tiêu chung và tự ý kéo dài lịch trình của bạn để phù hợp với việc sửa mã làm việc cũng tác động đến chúng.

Vì vậy, để có câu trả lời thực sự: nếu bạn biết rằng bạn sẽ muốn cấu trúc lại thì hãy sắp xếp thời gian đó như một phần của nhiệm vụ. Nếu bạn đang thực hiện scrum / agile thì hãy đặt thời gian cho một nhiệm vụ dọn dẹp. Nếu bạn là thác nước / xoắn ốc thì hãy tạo phần tái cấu trúc của quy trình để mã xem lại và chấp nhận các mô-đun.


0

Nếu tôi đang thử các phương pháp thay thế để làm cho một phần chức năng hoạt động, điều đó không nhất thiết có nghĩa là tôi đã tìm ra giải pháp tốt nhất,

... Trong trường hợp bạn chưa hoàn thành 100% ...

hoặc nó sẽ không yêu cầu làm lại sau khi xem xét với các nhà phát triển khác.

Nếu đánh giá mã và làm lại sau đó là một phần trong vòng đời phát triển của bạn, một lần nữa tính năng này sẽ không được thực hiện cho đến khi tất cả những điều này kết thúc.

Tôi sẽ thường xuyên hoàn thành công việc gì đó, lùi lại và sau đó tự hỏi mình có thể làm gì tốt hơn sau khi các quy tắc kinh doanh được thỏa mãn. Thời gian "Tôi có thể làm tốt hơn" này có thực sự phù hợp ở đâu đó trong dòng thời gian không?

Nó phụ thuộc. Nếu nó có nghĩa là tái cấu trúc, nó phải là một phần của nhiệm vụ phát triển ban đầu. Nếu nó có nghĩa là thử nghiệm với một thuật toán có khả năng tốt hơn, nó có thể là một nhiệm vụ riêng biệt.

Tôi cho rằng cách tiếp cận tốt nhất là bạn luôn để lại mã tốt hơn so với khi bạn tìm thấy nó (ở một mức độ nào đó), điều đó có nghĩa là tái cấu trúc bài khởi chạy. Tuy nhiên, các nhóm dự án thường cực kỳ khó chịu với cách tiếp cận này bởi vì một lần nữa, nếu nó hoạt động và đã được thử nghiệm, thì tại sao phải sửa nó?

Tóm lại, bởi vì mã có thể bị phá vỡ trên nhiều cấp độ.

Đó là một điều mà nó hoạt động ngay bây giờ. Đó là một điều hoàn toàn khác cho dù nó sạch sẽ, có thể mở rộng và duy trì trong thời gian dài.

Để biết câu trả lời chi tiết hơn, xem chủ đề này .


0

Theo như tôi có thể thấy và đã đọc, đây là một câu hỏi chưa được giải quyết. Do đó, các câu trả lời tránh như "YAGNI" và phản hồi ngay lần đầu tiên. Thực tế là không có nơi nào trong Agile để tái cấu trúc - nhưng tôi sẽ lập luận rằng nên có.

Câu trả lời tốt nhất cho đến nay đề cập đến nợ kỹ thuật. Thật không may, đây là một thực tế đáng buồn của phần mềm ở nhiều doanh nghiệp, nơi mà việc vội vã đưa mọi thứ ra ngoài dù là phương pháp nhanh hay không nhanh đều phổ biến - nhưng theo Agile, các giải pháp nhanh và bẩn được hợp lý hóa là một cái gì đó tốt: "đáp ứng yêu cầu kinh doanh tối thiểu" và "YAGNI" (liên quan đến việc giữ sạch mã).

Sẽ thật tuyệt nếu mọi người đều làm TDD, và sẽ thật tuyệt nếu tất cả các nhà phát triển tái cấu trúc lần thứ hai hoặc thứ ba theo gợi ý của một câu trả lời. Nhưng điều đó không xảy ra trong thế giới thực. Các nhà phát triển ở các cấp độ kỹ năng khác nhau gần như luôn luôn bị phát hiện có những góc khuất trong quá trình theo đuổi các giải pháp nhanh chóng. Kết quả là mã phân rã thành hàng núi mã không thể xác định được, phải mất nhiều ngày để các nhà phát triển mới giải mã, điều này làm tổn hại đến năng suất và làm chậm thời hạn. Theo "không thể nhầm lẫn", ý tôi là các giải pháp sao chép và dán, 5000 lớp dòng, v.v ... Và tất cả các mã này và các bản sửa lỗi này khi sửa lỗi đều là cốt lõi của doanh nghiệp! - Trong những trường hợp giải pháp phụ gia này, tôi sẽ tranh luận, không có thứ gọi là YAGNI! Bạn sẽ cần mã sạch - LUÔN LUÔN. Nếu mã không sạch, bạn chắc chắn sẽ không cần nó - xem lời tiên tri tự hoàn thành? Các nhà phát triển sẽ cố gắng hết sức để không sử dụng mã đó vì quá khó để xem xét. Và vòng luẩn quẩn cứ lặp đi lặp lại cho đến khi toàn bộ quả bóng lớn phải được tặc lưỡi và viết lại.

Vì vậy, tôi nói - mặc dù tái cấu trúc mã không phải là một khái niệm Agile đúng kiểu, riêng biệt, xứng đáng với câu chuyện - chúng ta nên dành thời gian để cấu trúc lại. Một số cửa hàng hiện đang yêu cầu các đội dành 20% nước rút cho nợ kỹ thuật. Hy vọng, những người đề xướng nhanh nhẹn sẽ thay đổi suy nghĩ của họ về YAGNI và tạo ra một nơi để tái cấu trúc như một hoạt động phân bổ thời gian riêng biệt. Và nếu họ đã và tôi chưa nghe về nó, xin vui lòng chỉ đến nơi được mô tả bởi vì tôi rất muốn biết.


"Thực tế là không có nơi nào trong Agile để tái cấu trúc" - Tôi không nghĩ đó là một tuyên bố đúng. Trong nhanh nhẹn, có một nơi cho bất kỳ loại phát triển nào, bao gồm cả tái cấu trúc, miễn là có trường hợp kinh doanh cho nó. Nếu không có trường hợp kinh doanh cho nó, tại sao bạn làm điều đó?
Bryan Oakley

Tôi đoán bạn có một điểm nếu một chút đơn giản. Về lý thuyết, một nhà phát triển có thể chế tạo một trường hợp kinh doanh để sửa mã kém chất lượng ngay cả khi nó không tạo ra bất kỳ thay đổi chức năng nào, nhưng điều đó sẽ không có ý nghĩa với tinh thần nhanh nhẹn - sử dụng kinh doanh như một proxy để biện minh cho công việc. Sau đó, tôi sẽ lập luận rằng hoạt động tái cấu trúc nằm ngoài lãnh vực nhanh nhẹn - một loại hoạt động CYA nếu bạn muốn - sửa mã không thể nhầm lẫn để nó không gây tốn kém cho doanh nghiệp và các nhà phát triển bị đổ lỗi. Gọi nó là "tái cấu trúc nước rút" hoặc bất cứ điều gì, nhưng phải có một nơi chính thức cho nó.
Blindcodifier9734
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.