2008-08-19 25 views
18

Sau khi tôi bị thuyết phục rằng các nhãn bị hỏng/tiếp tục là tổng "không phải" trên here, tôi cần trợ giúp để xóa nhãn khỏi mã của tôi.Tái cấu trúc các vòng nhãn có nhãn

Tôi có ma trận vuông và vectơ có cùng độ dài. Vectơ đã có một số giá trị trong nó một phụ thuộc vào các giá trị trong ma trận mà vectơ được thay đổi trong vòng lặp.

Tôi hy vọng, các mã fragment về cơ bản là dễ hiểu ...

vectorLoop: 
for(int idx = 0; idx < vectorLength; idx++) { 
    if(conditionAtVectorPosition(v, idx)) continue vectorLoop; 

    matrixLoop: 
    for(rowIdx = 0; rowIdx < n; rowIdx++) { 
     if(anotherConditionAtVector(v, rowIdx)) continue matrixLoop; 
     if(conditionAtMatrixRowCol(m, rowIdx, idx)) continue vectorLoop; 
    } 
    setValueInVector(v, idx); 
}  

Hãy thuyết phục tôi, rằng có một/phiên bản dễ đọc hơn tốt hơn mà không có nhãn.

Trả lời

34

Nhìn vào những giải pháp được trình bày cho đến nay:

  • Tất cả họ đều trông ít có thể đọc được so với bản gốc, trong đó họ liên quan đến chi tiêu nhiều mã về cơ chế mã hơn là trên các thuật toán riêng của mình

  • Một số trong số chúng bị hỏng hoặc trước khi chúng được chỉnh sửa. Hầu hết các damning là một thực tế là mọi người đang phải suy nghĩ khá khó khăn về cách viết mã mà không có nhãn và không phá vỡ bất cứ điều gì.

  • Một số đi kèm với một hình phạt hiệu suất chạy cùng một thử nghiệm hai lần, điều này có thể không phải lúc nào cũng tầm thường. Việc thay thế cho điều đó là lưu trữ và truyền các boolean tròn, điều này trở nên xấu xí.

  • Tái cấu trúc phần có liên quan của mã thành phương thức có hiệu quả là no-op: nó sắp xếp lại cách mã được đặt trong tệp nhưng không ảnh hưởng đến cách mã được thực thi.

Tất cả điều này làm cho tôi tin rằng, ít nhất trong trường hợp của câu hỏi này như được phân tích, nhãn là giải pháp đúng và không cần phải được refactored away. Chắc chắn có những trường hợp nhãn được sử dụng không chính xác và nên được tái cấu trúc. Tôi chỉ không nghĩ rằng nó nên được coi là một số quy tắc không thể phá vỡ.

+1

Chúc tôi có thể upvote điều này nhiều lần. –

1

Dễ dàng, người đàn ông tốt của tôi.

for(int idx = 0; idx < vectorLength; idx++) { 
    if(conditionAtVectorPosition(v, idx)) continue; 

    for(rowIdx = 0; rowIdx < n; rowIdx++) { 
    if(anotherConditionAtVector(v, rowIdx)) continue; 
    if(conditionAtMatrixRowCol(m, rowIdx, idx)) break; 
    } 
    if(!conditionAtMatrixRowCol(m, rowIdx, idx)) 
    setValueInVector(v, idx); 
} 

EDIT: Đúng là bạn là Anders. Tôi đã chỉnh sửa giải pháp của mình để tính đến điều đó.

1

@Patrick bạn đang giả định gọi setValueInVector (v, idx); ở cuối vòng lặp thứ hai là OK. Nếu mã phải giống hệt nhau, hợp lý, mã phải được viết lại thành một số thứ như sau:

for(int idx = 0; idx
0

Điều này có phù hợp với bạn không? Tôi trích ra vòng lặp bên trong thành một phương pháp CheckedEntireMatrix (bạn có thể đặt tên cho nó tốt hơn so với tôi) - Cũng java của tôi là một chút gỉ .. nhưng tôi nghĩ rằng nó được thông điệp trên

for(int idx = 0; idx < vectorLength; idx++) { 
    if(conditionAtVectorPosition(v, idx) 
    || !CheckedEntireMatrix(v)) continue; 

    setValueInVector(v, idx); 
} 

private bool CheckedEntireMatrix(Vector v) 
{ 
    for(rowIdx = 0; rowIdx < n; rowIdx++) { 
     if(anotherConditionAtVector(v, rowIdx)) continue; 
     if(conditionAtMatrixRowCol(m, rowIdx, idx)) return false; 
    } 
    return true; 
} 
0

Gishu có ý tưởng đúng:

for(int idx = 0; idx < vectorLength; idx++) { 
    if (!conditionAtVectorPosition(v, idx) 
     && checkedRow(v, idx)) 
     setValueInVector(v, idx); 
} 

private boolean checkedRow(Vector v, int idx) { 
    for(rowIdx = 0; rowIdx < n; rowIdx++) { 
     if(anotherConditionAtVector(v, rowIdx)) continue; 
     if(conditionAtMatrixRowCol(m, rowIdx, idx)) return false; 
    } 
    return true; 
} 
0

Tôi không quá chắc chắn để hiểu tiếp tục đầu tiên. Tôi sẽ sao chép Gishu và viết một cái gì đó như (xin lỗi nếu có một số sai sót):

for(int idx = 0; idx < vectorLength; idx++) { 
    if(!conditionAtVectorPosition(v, idx) && CheckedEntireMatrix(v)) 
     setValueInVector(v, idx); 
} 

inline bool CheckedEntireMatrix(Vector v) { 
    for(rowIdx = 0; rowIdx < n; rowIdx++) 
     if (!anotherConditionAtVector(v,rowIdx) && conditionAtMatrixRowCol(m,rowIdx,idx)) 
      return false; 
    return true; 
} 
1

Từ đọc mã của bạn.

  • Tôi nhận thấy việc loại bỏ các vị trí véc-tơ không hợp lệ ở điều kiệnAtVectorPosition sau đó bạn xóa các hàng không hợp lệ tại anotherConditionAtVector.
  • Dường như việc kiểm tra hàng tại anotherConditionAtVector là thừa vì bất kể giá trị idx là gì, anotherConditionAtVector chỉ phụ thuộc vào chỉ mục hàng (giả sử anotherConditionAtVector không có tác dụng phụ).

Vì vậy, bạn có thể làm điều này:

  • Lấy vị trí hợp lệ đầu tiên sử dụng conditionAtVectorPosition (đây là các cột có giá trị).
  • Sau đó nhận các hàng hợp lệ bằng cách sử dụngConditionAtVector khác.
  • Cuối cùng, hãy sử dụng điều kiệnAtMatrixRowCol bằng các cột và hàng hợp lệ.

Tôi hy vọng điều này sẽ hữu ích.

0

@Sadie:

Tất cả họ đều trông ít có thể đọc được so với bản gốc, trong đó họ liên quan đến chi tiêu nhiều mã về cơ chế mã hơn là trên các thuật toán riêng của mình

Externalizing thứ hai vòng lặp bên ngoài thuật toán không nhất thiết là ít có thể đọc được. Nếu tên phương thức được chọn tốt, nó có thể cải thiện khả năng đọc.

Một số trong số chúng bị hỏng hoặc trước khi chúng được chỉnh sửa. Hầu hết các damning là một thực tế là mọi người đang phải suy nghĩ khá khó khăn về cách viết mã mà không có nhãn và không phá vỡ bất cứ điều gì.

Tôi có quan điểm khác: một số trong số đó bị hỏng vì khó có thể xác định được hành vi của thuật toán gốc.

Một số đi kèm với một hình phạt hiệu suất chạy cùng một thử nghiệm hai lần, điều này có thể không phải lúc nào cũng tầm thường. Việc thay thế cho điều đó là lưu trữ và truyền các boolean tròn, điều này trở nên xấu xí.

Hình phạt hiệu suất là nhỏ. Tuy nhiên tôi đồng ý rằng chạy thử nghiệm hai lần không phải là một giải pháp tốt đẹp.

Tái cấu trúc phần có liên quan của mã thành phương thức hiệu quả là no-op: nó sắp xếp lại cách mã được đặt trong tệp nhưng không ảnh hưởng đến cách mã được thực thi.

Tôi không thấy điểm. Đúng, nó không thay đổi hành vi, như ... tái cấu trúc?

Chắc chắn có trường hợp nhãn được sử dụng không chính xác và phải được cấu trúc lại. Tôi chỉ không nghĩ rằng nó nên được coi là một số quy tắc không thể phá vỡ.

Tôi hoàn toàn đồng ý. Nhưng như bạn đã chỉ ra, một số người trong chúng ta gặp khó khăn trong khi tái cấu trúc ví dụ này. Ngay cả khi ví dụ ban đầu có thể đọc được thì rất khó để duy trì.

+1

Đây phải là nhận xét. (Tôi biết tính năng này không thoát khi đăng bài này.) – Laurel

1

@Nicolas

Một số trong số họ bị phá vỡ, hoặc là trước khi chúng được chỉnh sửa. Hầu hết các damning là một thực tế là mọi người đang phải suy nghĩ khá khó khăn về cách viết mã mà không có nhãn và không phải phá vỡ bất cứ điều gì.

Tôi có quan điểm khác: một số trong số đó bị hỏng vì khó có thể hiểu được hành vi của thuật toán gốc.

Tôi nhận ra rằng đó là chủ quan, nhưng tôi không gặp khó khăn khi đọc thuật toán gốc. Nó ngắn hơn và rõ ràng hơn các thay thế được đề xuất.

Tất cả các phép tái cấu trúc trong chuỗi này là mô phỏng hành vi của nhãn bằng các tính năng ngôn ngữ khác - như thể bạn đang chuyển mã sang ngôn ngữ không có nhãn.

1
Một số đi kèm với một hình phạt hiệu suất chạy cùng một thử nghiệm hai lần, điều này có thể không phải lúc nào cũng tầm thường. Việc thay thế cho điều đó là lưu trữ và truyền các boolean tròn, điều này trở nên xấu xí.
Hình phạt về hiệu suất là nhỏ. Tuy nhiên tôi đồng ý rằng chạy thử nghiệm hai lần không phải là một giải pháp tốt đẹp.

Tôi tin rằng câu hỏi là cách xóa nhãn chứ không phải cách tối ưu hóa thuật toán. Nó xuất hiện với tôi rằng các poster ban đầu đã không biết làm thế nào để sử dụng 'tiếp tục' và 'phá vỡ' từ khóa mà không có nhãn, nhưng tất nhiên, giả định của tôi có thể sai.

Khi nói đến hiệu năng, bài viết không cung cấp bất kỳ thông tin nào về việc thực hiện các chức năng khác, vì vậy tôi biết rằng họ cũng có thể tải xuống kết quả qua FTP như các tính toán đơn giản được trình biên dịch đưa vào.

Điều đó đang được nói, thực hiện cùng một thử nghiệm hai lần không phải là tối ưu — theo lý thuyết.

EDIT: Trên suy nghĩ thứ hai, ví dụ này thực sự không phải là sử dụng nhãn khủng khiếp. Tôi đồng ý rằng "goto is a no-no", nhưng không phải vì mã như thế này. Việc sử dụng nhãn ở đây không thực sự ảnh hưởng đến khả năng đọc của mã một cách đáng kể. Tất nhiên, chúng không bắt buộc và có thể dễ dàng bị bỏ qua, nhưng không sử dụng chúng đơn giản chỉ vì "sử dụng nhãn là xấu" không phải là một đối số tốt trong trường hợp này. Sau khi tất cả, loại bỏ các nhãn không làm cho mã dễ đọc hơn, như những người khác đã nhận xét.

1

Câu hỏi này không phải là về tối ưu hóa các thuật toán - nhưng nhờ anyway ;-)

Đồng thời tôi đã viết nó, tôi coi là nhãn tiếp tục như một giải pháp có thể đọc được.

Tôi đã hỏi SO question về quy ước (có nhãn ở tất cả các mũ hoặc không) cho các nhãn trong Java.

Về cơ bản, mọi câu trả lời đều nói với tôi rằng "không sử dụng chúng - luôn có cách tốt hơn! Refactor!". Vì vậy, tôi đã đăng câu hỏi này để yêu cầu giải pháp dễ đọc hơn (và do đó tốt hơn?).

Cho đến bây giờ, tôi không hoàn toàn bị thuyết phục bởi các lựa chọn thay thế được trình bày cho đến thời điểm này.

Xin đừng hiểu lầm tôi. Nhãn hầu hết là ác.

Nhưng trong trường hợp của tôi, các bài kiểm tra có điều kiện là khá đơn giản và thuật toán được lấy từ một bài toán học và do đó rất có khả năng không thay đổi trong tương lai gần. Vì vậy, tôi thích có tất cả các phần liên quan có thể nhìn thấy cùng một lúc thay vì phải di chuyển đến phương thức khác có tên là checkMatrixAtRow (x).

Đặc biệt là ở các thuật toán toán học phức tạp hơn, tôi thấy nó khá khó khăn để tìm thấy "tốt" chức năng-tên - nhưng tôi đoán rằng lại là một câu hỏi

1

Tôi nghĩ rằng vòng dán nhãn rất phổ biến mà bạn có thể chọn bất cứ điều gì phương pháp ghi nhãn hoạt động cho bạn - những gì bạn có ở đó làm cho ý định của bạn tiếp tục hoàn toàn rõ ràng.


Sau khi lãnh đạo phụ trách để đề nghị sắp xếp các vòng trong câu hỏi ban đầu và bây giờ nhìn thấy mã trong câu hỏi, tôi nghĩ rằng bạn đã có một vòng lặp rất có thể đọc được ở đó.

Điều tôi tưởng tượng là một đoạn mã rất khác nhau - đưa ví dụ thực tế lên, tôi có thể thấy nó sạch hơn nhiều so với tôi nghĩ.

Tôi xin lỗi vì sự hiểu lầm.

Các vấn đề liên quan