Khi tôi chia các phương thức (hoặc thủ tục hoặc hàm) lớn - câu hỏi này không dành riêng cho OOP, nhưng vì tôi làm việc trong các ngôn ngữ OOP 99% thời gian, đó là thuật ngữ mà tôi thấy thoải mái nhất) thành nhiều thuật ngữ nhỏ , Tôi thường thấy mình không hài lòng với kết quả. Lý do về các phương thức nhỏ này trở nên khó khăn hơn so với khi chúng chỉ là các khối mã trong một phương thức lớn, bởi vì khi tôi trích xuất chúng, tôi mất rất nhiều giả định cơ bản xuất phát từ ngữ cảnh của người gọi.
Sau này, khi tôi xem mã này và thấy các phương thức riêng lẻ, tôi không biết ngay chúng được gọi từ đâu và nghĩ về chúng như các phương thức riêng tư thông thường có thể được gọi từ bất kỳ đâu trong tệp. Ví dụ, hãy tưởng tượng một phương thức khởi tạo (hàm tạo hoặc cách khác) chia thành một loạt các phương thức nhỏ: trong bối cảnh của chính phương thức đó, bạn biết rõ trạng thái của đối tượng vẫn không hợp lệ, nhưng trong một phương thức riêng tư thông thường bạn có thể đi từ giả định đối tượng đó đã được khởi tạo và ở trạng thái hợp lệ.
Giải pháp duy nhất tôi thấy cho điều này là where
mệnh đề trong Haskell, cho phép bạn xác định các hàm nhỏ chỉ được sử dụng trong hàm "cha". Về cơ bản, nó trông như thế này:
len x y = sqrt $ (sq x) + (sq y)
where sq a = a * a
Nhưng các ngôn ngữ khác tôi sử dụng không có bất cứ thứ gì như thế này - điều gần nhất là định nghĩa lambda trong phạm vi địa phương, điều này có lẽ còn khó hiểu hơn.
Vì vậy, câu hỏi của tôi là - bạn có gặp phải điều này không, và bạn thậm chí có thấy đây là một vấn đề không? Nếu bạn làm như vậy, làm thế nào để bạn thường giải quyết nó, đặc biệt là trong các ngôn ngữ OOP "chính thống", như Java / C # / C ++?
Chỉnh sửa về các bản sao: Như những người khác nhận thấy, đã có những câu hỏi thảo luận về các phương pháp phân tách và các câu hỏi nhỏ là một lớp. Tôi đọc chúng và họ không thảo luận về vấn đề giả định cơ bản có thể xuất phát từ ngữ cảnh của người gọi (ví dụ ở trên, đối tượng được khởi tạo). Đó là điểm của câu hỏi của tôi và đó là lý do tại sao câu hỏi của tôi khác.
Cập nhật: Nếu bạn theo dõi câu hỏi và thảo luận bên dưới, bạn có thể thích bài viết này của John Carmack về vấn đề này , đặc biệt:
Bên cạnh nhận thức về mã thực tế đang được thực thi, các hàm nội tuyến cũng có lợi ích là không thể gọi hàm từ các nơi khác. Nghe có vẻ vô lý, nhưng có một điểm cho nó. Khi một codebase phát triển qua nhiều năm sử dụng, sẽ có rất nhiều cơ hội để thực hiện một phím tắt và chỉ cần gọi một chức năng chỉ thực hiện công việc mà bạn nghĩ cần phải hoàn thành. Có thể có một hàm FullUpdate () gọi PartialUpdateA () và PartialUpdateB (), nhưng trong một số trường hợp cụ thể, bạn có thể nhận ra (hoặc nghĩ) rằng bạn chỉ cần thực hiện PartialUpdateB () và bạn đang làm việc hiệu quả bằng cách tránh công việc. Rất nhiều và rất nhiều lỗi bắt nguồn từ điều này. Hầu hết các lỗi là kết quả của trạng thái thực thi không chính xác như bạn nghĩ.