Là phương pháp riêng tư với một phong cách xấu tham khảo duy nhất?


139

Nói chung tôi sử dụng các phương thức riêng để đóng gói chức năng được sử dụng lại ở nhiều nơi trong lớp. Nhưng đôi khi tôi có một phương thức công khai lớn có thể được chia thành các bước nhỏ hơn, mỗi phương thức riêng. Điều này sẽ làm cho phương thức công khai ngắn hơn, nhưng tôi lo lắng rằng việc ép buộc bất kỳ ai đọc phương thức này nhảy sang các phương thức riêng tư khác nhau sẽ làm hỏng khả năng đọc.

Có một sự đồng thuận về điều này? Là tốt hơn để có các phương pháp công cộng dài, hoặc chia chúng thành các phần nhỏ hơn ngay cả khi mỗi phần không thể tái sử dụng?



7
Tất cả các câu trả lời đều dựa trên ý kiến. Các tác giả gốc luôn nghĩ rằng mã ravioli của họ dễ đọc hơn; biên tập viên tiếp theo gọi nó là ravioli.
Frank Hileman

5
Tôi đề nghị bạn đọc Clean Code. Nó đề xuất phong cách này và có rất nhiều ví dụ. Nó cũng có một giải pháp cho vấn đề "nhảy lung tung".
Kat

1
Tôi nghĩ điều này phụ thuộc vào nhóm của bạn và những dòng mã nào được chứa.
Hy vọng có ích vào

1
Không phải toàn bộ khung của STRUTS dựa trên các phương thức Getter / Setter sử dụng một lần, tất cả đều là phương thức sử dụng một lần?
Zibbobz

Câu trả lời:


203

Không, đây không phải là một phong cách xấu. Trong thực tế nó là một phong cách rất tốt.

Các chức năng riêng không cần tồn tại đơn giản vì khả năng sử dụng lại. Đó chắc chắn là một lý do tốt để tạo ra chúng, nhưng có một lý do khác: sự phân hủy.

Hãy xem xét một chức năng mà làm quá nhiều. Nó là một trăm dòng dài, và không thể lý do về.

Nếu bạn chia chức năng này thành các phần nhỏ hơn, nó vẫn "hoạt động" nhiều như trước đây, nhưng trong các phần nhỏ hơn. Nó gọi các chức năng khác cần có tên mô tả. Hàm chính đọc gần giống như một cuốn sách: làm A, sau đó làm B, sau đó làm C, v.v ... Các chức năng mà nó gọi có thể chỉ được gọi ở một nơi, nhưng bây giờ chúng nhỏ hơn. Bất kỳ chức năng cụ thể nào nhất thiết phải được hộp cát từ các chức năng khác: chúng có phạm vi khác nhau.

Khi bạn phân tách một vấn đề lớn thành các vấn đề nhỏ hơn, ngay cả khi những vấn đề (chức năng) nhỏ hơn đó chỉ được sử dụng / giải quyết một lần, bạn sẽ nhận được một số lợi ích:

  • Dễ đọc. Không ai có thể đọc một chức năng nguyên khối và hiểu những gì nó làm hoàn toàn. Bạn có thể tiếp tục nói dối chính mình, hoặc chia nó thành những miếng nhỏ có kích thước vừa phải.

  • Địa phương tham khảo. Bây giờ không thể khai báo và sử dụng một biến, sau đó sử dụng biến đó và sử dụng lại 100 dòng sau đó. Các chức năng này có phạm vi khác nhau.

  • Kiểm tra. Mặc dù chỉ cần kiểm tra đơn vị các thành viên công cộng của một lớp, nhưng cũng có thể mong muốn kiểm tra một số thành viên tư nhân nhất định. Nếu có một phần quan trọng của một hàm dài có thể có lợi từ việc kiểm tra, thì không thể kiểm tra nó một cách độc lập mà không trích xuất nó thành một hàm riêng biệt.

  • Tính mô đun. Bây giờ bạn có các chức năng riêng tư, bạn có thể tìm thấy một hoặc nhiều trong số chúng có thể được trích xuất thành một lớp riêng biệt, cho dù nó chỉ được sử dụng ở đây hoặc có thể tái sử dụng. Đến thời điểm trước, lớp riêng biệt này cũng có khả năng dễ kiểm tra hơn, vì nó sẽ cần một giao diện chung.

Ý tưởng chia mã lớn thành các phần nhỏ dễ hiểu hơn và kiểm tra là một điểm chính trong cuốn sách Clean Code của chú Bob . Tại thời điểm viết câu trả lời này, cuốn sách đã chín tuổi, nhưng ngày nay vẫn còn phù hợp như hồi đó.


7
Đừng quên duy trì mức độ trừu tượng nhất quán và các tên hay để đảm bảo nhìn trộm bên trong các phương thức sẽ không làm bạn ngạc nhiên. Đừng ngạc nhiên nếu toàn bộ một đối tượng đang trốn trong đó.
candied_orange

14
Đôi khi các phương pháp chia tách có thể tốt, nhưng giữ mọi thứ thẳng hàng cũng có thể có lợi thế. Ví dụ, nếu kiểm tra ranh giới có thể được thực hiện một cách hợp lý bên trong hoặc bên ngoài một khối mã, việc giữ cho khối mã đó thẳng hàng sẽ giúp bạn dễ dàng xem liệu kiểm tra ranh giới có được thực hiện một lần, nhiều lần hay không . Kéo khối mã vào chương trình con của chính nó sẽ làm cho những điều đó trở nên khó khăn hơn để xác định.
supercat

7
Viên đạn "dễ đọc" có thể được dán nhãn "Trừu tượng". Đó là về sự trừu tượng. Các "khối kích cỡ cắn" làm một việc , một điều ở mức độ thấp mà bạn không thực sự quan tâm đến các chi tiết khó chịu khi bạn đọc hoặc bước qua phương pháp công khai. Bằng cách trừu tượng hóa nó đến một chức năng, bạn có thể bước qua nó và tập trung vào sơ đồ lớn của mọi thứ / phương thức công khai đang làm ở mức cao hơn.
Mathieu Guindon

7
"Thử nghiệm" viên đạn là nghi vấn IMO. Nếu các thành viên riêng của bạn muốn được kiểm tra, thì có lẽ họ thuộc về lớp của họ, với tư cách là thành viên công cộng. Cấp, bước đầu tiên để trích xuất một lớp / giao diện là trích xuất một phương thức.
Mathieu Guindon

6
Tách một chức năng hoàn toàn bằng số dòng, khối mã và phạm vi biến mà không quan tâm đến chức năng thực tế là một ý tưởng tồi tệ, và tôi cho rằng giải pháp thay thế tốt hơn là chỉ để nó trong một chức năng. Bạn nên phân chia chức năng theo chức năng. Xem câu trả lời của DaveGauer . Bạn có phần gợi ý về điều này trong câu trả lời của bạn (với đề cập đến tên và vấn đề), nhưng tôi không thể không cảm thấy khía cạnh này cần tập trung hơn rất nhiều, vì tầm quan trọng và mức độ liên quan của nó liên quan đến câu hỏi.
Dukeling

36

Có lẽ đó là một ý tưởng tuyệt vời!

Tôi có vấn đề với việc tách các chuỗi hành động tuyến tính dài thành các hàm riêng biệt hoàn toàn để giảm độ dài chức năng trung bình trong cơ sở mã của bạn:

function step1(){
  // ...
  step2(zarb, foo, biz);
}

function step2(zarb, foo, biz){
  // ...
  step3(zarb, foo, biz, gleep);
}

function step3(zarb, foo, biz, gleep){
  // ...
}

Bây giờ bạn đã thực sự thêm các dòng nguồn giảm tổng số khả năng đọc đáng kể. Đặc biệt là nếu bây giờ bạn chuyển nhiều tham số giữa mỗi chức năng để theo dõi trạng thái. Rất tiếc!

Tuy nhiên , nếu bạn đã quản lý để trích xuất một hoặc nhiều dòng thành một hàm thuần phục vụ một mục đích rõ ràng duy nhất ( ngay cả khi chỉ được gọi một lần ), thì bạn đã cải thiện khả năng đọc:

function foo(){
  f = getFrambulation();
  g = deglorbFramb(f);
  r = reglorbulate(g);
}

Điều này có thể sẽ không dễ dàng trong các tình huống trong thế giới thực, nhưng các phần chức năng thuần túy thường có thể bị trêu chọc nếu bạn nghĩ về nó đủ lâu.

Bạn sẽ biết bạn đang đi đúng hướng khi bạn có các chức năng với tên động từ đẹp và khi chức năng cha mẹ của bạn gọi chúng và toàn bộ thực tế đọc giống như một đoạn văn xuôi.

Sau đó, khi bạn trở lại vài tuần sau để thêm nhiều chức năng hơn và bạn thấy rằng bạn thực sự có thể sử dụng lại một trong những chức năng đó, thì ôi, niềm vui sướng trào dâng! Thật tuyệt vời rạng rỡ thỏa thích!


2
Tôi đã nghe lập luận này trong nhiều năm, và nó không bao giờ diễn ra trong thế giới thực. Tôi đang nói cụ thể về một hoặc hai hàm dòng, được gọi từ chỉ một nơi. Trong khi tác giả ban đầu luôn nghĩ rằng nó "dễ đọc hơn", các biên tập viên tiếp theo thường gọi nó là mã ravioli. Điều này phụ thuộc vào độ sâu cuộc gọi, nói chung.
Frank Hileman

34
@FrankHileman Công bằng mà nói, tôi chưa bao giờ thấy bất kỳ nhà phát triển nào khen ngợi mã của người tiền nhiệm của mình.
T. Sar

4
@TSar nhà phát triển trước đó là nguồn gốc của mọi vấn đề!
Frank Hileman

18
@TSar Tôi thậm chí chưa bao giờ khen nhà phát triển trước đó khi tôi là nhà phát triển trước đó.
IllusiveBrian

3
Điều thú vị về việc phân tách là sau đó bạn có thể sáng tác : foo = compose(reglorbulate, deglorbFramb, getFrambulation);;)
Warbo

19

Câu trả lời là nó phụ thuộc nhiều vào tình huống. @Snowman bao gồm các mặt tích cực của việc phá vỡ chức năng công cộng lớn, nhưng điều quan trọng cần nhớ là cũng có thể có những tác động tiêu cực, vì bạn rất quan tâm.

  • Rất nhiều chức năng riêng tư với các hiệu ứng phụ có thể làm cho mã khó đọc và khá dễ hỏng. Điều này đặc biệt đúng khi các chức năng riêng này phụ thuộc vào tác dụng phụ của nhau. Tránh có chức năng kết hợp chặt chẽ.

  • Trừu tượng bị rò rỉ . Mặc dù thật tuyệt khi giả vờ cách một hoạt động được thực hiện hoặc cách lưu trữ dữ liệu không thành vấn đề, có những trường hợp thực hiện và điều quan trọng là xác định chúng.

  • Ngữ nghĩa và vấn đề bối cảnh. Nếu bạn không nắm bắt rõ ràng chức năng làm gì trong tên của nó, bạn một lần nữa có thể giảm khả năng đọc và tăng tính mong manh của chức năng công cộng. Điều này đặc biệt đúng khi bạn bắt đầu tạo các hàm riêng với số lượng lớn các tham số đầu vào và đầu ra. Và trong khi từ chức năng công cộng, bạn thấy chức năng riêng mà nó gọi là gì, từ chức năng riêng tư, bạn không thấy chức năng công cộng gọi nó là gì. Điều này có thể dẫn đến một "sửa lỗi" trong một chức năng riêng tư phá vỡ chức năng công cộng.

  • Mã bị phân hủy nặng nề luôn rõ ràng đối với tác giả so với những người khác. Điều này không có nghĩa là nó vẫn không thể rõ ràng với người khác, nhưng thật dễ dàng để nói rằng nó có ý nghĩa hoàn hảo bar()phải được gọi trước đó foo()tại thời điểm viết.

  • Tái sử dụng nguy hiểm. Chức năng công khai của bạn có khả năng hạn chế những gì đầu vào có thể đối với từng chức năng riêng tư. Nếu các giả định đầu vào này không được nắm bắt chính xác (ghi lại TẤT CẢ các giả định là khó), ai đó có thể sử dụng lại một trong các chức năng riêng tư của bạn một cách không chính xác, đưa lỗi vào cơ sở mã.

Phân tách các chức năng dựa trên sự gắn kết và khớp nối bên trong của chúng, không phải là chiều dài tuyệt đối.


6
Bỏ qua khả năng đọc, chúng ta hãy xem xét khía cạnh báo cáo lỗi: nếu người dùng báo cáo rằng đã xảy ra lỗi MainMethod(đủ dễ nhận, thường có các ký hiệu và bạn nên có tệp biểu thị biểu tượng) là 2k dòng (số dòng không bao giờ được bao gồm trong báo cáo lỗi) và đó là một NRE có thể xảy ra ở mức 1k trong số những dòng đó, tôi sẽ bị nguyền rủa nếu tôi xem xét điều đó. Nhưng nếu họ nói với tôi rằng nó đã xảy ra SomeSubMethodAvà 8 dòng và ngoại lệ là NRE, thì có lẽ tôi sẽ tìm và sửa nó đủ dễ.
410_Gone

2

IMHO, giá trị của việc rút ra các khối mã hoàn toàn như một phương tiện phá vỡ sự phức tạp, thường sẽ liên quan đến sự khác biệt về độ phức tạp giữa:

  1. Một mô tả đầy đủ và chính xác bằng ngôn ngữ của con người về những gì mã làm, bao gồm cả cách nó xử lý các trường hợp góc

  2. Các mã chính nó.

Nếu mã phức tạp hơn nhiều so với mô tả, việc thay thế mã nội tuyến bằng lệnh gọi hàm có thể làm cho mã xung quanh dễ hiểu hơn. Mặt khác, một số khái niệm có thể được diễn đạt dễ đọc bằng ngôn ngữ máy tính hơn là ngôn ngữ của con người. Tôi sẽ coi w=x+y+z;, ví dụ, như dễ đọc hơn w=addThreeNumbersAssumingSumOfFirstTwoDoesntOverflow(x,y,z);.

Khi một chức năng lớn được phân tách, sẽ có sự khác biệt ngày càng ít giữa sự phức tạp của các chức năng phụ so với mô tả của chúng và lợi thế của các phân ngành tiếp theo sẽ giảm. Nếu mọi thứ được phân chia đến mức mô tả sẽ phức tạp hơn mã, việc chia tách tiếp theo sẽ làm cho mã trở nên tồi tệ hơn.


2
Tên chức năng của bạn là sai lệch. Không có gì trên w = x + y + z chỉ ra bất kỳ loại điều khiển tràn nào, trong khi tên phương thức tự nó dường như ngụ ý khác. Một tên tốt hơn cho chức năng của bạn sẽ là "add ALL (x, y, z)", ví dụ, hoặc thậm chí chỉ là "Sum (x, y, z)".
T. Sar

6
Vì đang nói về các phương thức riêng tư , nên câu hỏi này không thể đề cập đến C. Dù sao, đó không phải là quan điểm của tôi - bạn chỉ có thể gọi cùng một hàm là "tổng" mà không cần phải giải quyết giả định về chữ ký phương thức. Theo logic của bạn, bất kỳ phương thức đệ quy nào cũng phải được gọi là "Do ThisAssumingStackDoesntOverflow", chẳng hạn. Điều tương tự cũng xảy ra với "FindSubopesAssumingStartingPointIsInsideBound".
T. Sar

1
Nói cách khác, các giả định cơ bản, bất kể chúng có thể là gì (hai số sẽ không tràn, stack sẽ không tràn, chỉ mục được truyền chính xác) không nên xuất hiện trên tên phương thức. Những điều đó nên được ghi lại, tất nhiên, nếu cần, nhưng không phải trên chữ ký phương thức.
T. Sar

1
@TSar: Tôi đã hơi khó tính với cái tên này, nhưng điểm mấu chốt là (chuyển sang trung bình vì đó là một ví dụ tốt hơn) một lập trình viên nhìn thấy "(x + y + z + 1) / 3" trong ngữ cảnh sẽ là tốt hơn nhiều để biết liệu đó có phải là một cách tính toán trung bình phù hợp với mã cuộc gọi, hơn là một người đang xem định nghĩa hoặc trang web của cuộc gọi int average3(int n1, int n2, int n3). Việc tách ra chức năng "trung bình" có nghĩa là ai đó muốn xem liệu nó có phù hợp với yêu cầu hay không thì phải tìm ở hai nơi.
supercat

1
Nếu chúng tôi lấy C # làm ví dụ, bạn sẽ chỉ có một phương thức "Trung bình" duy nhất, có thể được thực hiện để chấp nhận bất kỳ số lượng tham số nào. Trên thực tế, trong c #, nó hoạt động trên bất kỳ tập hợp số nào - và tôi chắc chắn rằng nó dễ hiểu hơn so với việc giải toán toán thô vào mã.
T. Sar

2

Đó là một thách thức cân bằng.

Finer là tốt hơn

Phương thức riêng tư cung cấp một cách hiệu quả tên cho mã được chứa và đôi khi là một chữ ký có ý nghĩa (trừ khi một nửa các tham số của nó là dữ liệu tramp ad-hoc hoàn toàn với các phụ thuộc không rõ ràng, không có giấy tờ).

Đặt tên cho các cấu trúc mã nói chung là tốt, miễn là các tên gợi ý một hợp đồng có ý nghĩa cho người gọi và hợp đồng của phương thức riêng tương ứng chính xác với những gì tên cho thấy.

Bằng cách buộc bản thân nghĩ ra các hợp đồng có ý nghĩa cho các phần nhỏ hơn của mã, nhà phát triển ban đầu có thể phát hiện ra một số lỗi và tránh chúng một cách không đau đớn ngay cả trước bất kỳ thử nghiệm dev nào. Điều này chỉ hoạt động nếu nhà phát triển đang cố gắng đặt tên ngắn gọn (nghe có vẻ đơn giản nhưng chính xác) và sẵn sàng điều chỉnh các ranh giới của phương thức riêng tư để có thể đặt tên ngắn gọn.

Bảo trì sau đó cũng được giúp đỡ, bởi vì việc đặt tên bổ sung giúp làm cho mã tự ghi lại .

  • Hợp đồng trên các đoạn mã nhỏ
  • Các phương thức cấp cao hơn đôi khi biến thành một chuỗi các cuộc gọi ngắn, mỗi cuộc gọi thực hiện một cái gì đó có ý nghĩa và được đặt tên rõ ràng - đi kèm với lớp xử lý lỗi chung, ngoài cùng. Một phương pháp như vậy có thể trở thành một tài nguyên đào tạo có giá trị cho bất cứ ai phải nhanh chóng trở thành một chuyên gia về cấu trúc tổng thể của mô-đun.

Cho đến khi nó trở nên quá tốt

Có thể lạm dụng việc đặt tên cho các đoạn mã nhỏ và kết thúc với quá nhiều phương thức riêng tư quá nhỏ không? Chắc chắn rồi. Một hoặc nhiều triệu chứng sau đây cho thấy các phương pháp đang trở nên quá nhỏ không hữu ích:

  • Quá nhiều quá tải không thực sự đại diện cho chữ ký thay thế cho cùng một logic thiết yếu, mà là một ngăn xếp cuộc gọi cố định duy nhất.
  • Từ đồng nghĩa được sử dụng chỉ để chỉ cùng một khái niệm lặp đi lặp lại ("đặt tên giải trí")
  • Rất nhiều trang trí đặt tên chiếu lệ như XxxInternal, hoặc DoXxxđặc biệt là nếu không có kế hoạch thống nhất trong việc giới thiệu chúng.
  • Tên vụng về gần như dài hơn bản thân việc thực hiện, như LogDiskSpaceConsumptionUnlessNoUpdateNeeded

1

Trái với những gì người khác đã nói, tôi sẽ lập luận rằng một phương pháp công khai dài là mùi thiết kế không được điều chỉnh bằng cách phân tách thành các phương thức riêng tư.

Nhưng đôi khi tôi có một phương thức công khai lớn có thể được chia thành các bước nhỏ hơn

Nếu đây là trường hợp thì tôi sẽ tranh luận mỗi bước nên là công dân hạng nhất của riêng mình với mỗi trách nhiệm duy nhất. Trong mô hình hướng đối tượng, tôi khuyên bạn nên tạo giao diện và triển khai cho từng bước theo cách sao cho mỗi người có một trách nhiệm duy nhất, dễ nhận biết và có thể được đặt tên theo cách rõ ràng về khả năng đáp ứng. Điều này cho phép bạn kiểm tra đơn vị phương thức công khai lớn (trước đây), cũng như từng bước riêng lẻ độc lập với nhau. Tất cả chúng nên được ghi lại là tốt.

Tại sao không phân hủy thành phương pháp riêng tư? Dưới đây là một vài lý do:

  • Khớp nối chặt chẽ và khả năng kiểm tra. Bằng cách giảm kích thước của phương thức công khai, bạn đã cải thiện khả năng đọc của nó, nhưng tất cả các mã vẫn được liên kết chặt chẽ với nhau. Bạn có thể đơn vị kiểm tra các phương thức riêng tư (sử dụng các tính năng nâng cao của khung kiểm tra), nhưng bạn không thể dễ dàng kiểm tra phương thức công khai độc lập với các phương thức riêng tư. Điều này đi ngược lại các nguyên tắc của thử nghiệm đơn vị.
  • Quy mô lớp học và độ phức tạp. Bạn đã giảm độ phức tạp của một phương thức, nhưng bạn đã tăng độ phức tạp của lớp. Phương thức công khai dễ đọc hơn, nhưng lớp bây giờ khó đọc hơn vì nó có nhiều hàm xác định hành vi của nó. Sở thích của tôi là dành cho các lớp học đơn trách nhiệm nhỏ, vì vậy một phương thức dài là dấu hiệu cho thấy lớp đang làm quá nhiều.
  • Không thể tái sử dụng dễ dàng. Nó thường là trường hợp như một cơ thể của mã trưởng thành tái sử dụng là hữu ích. Nếu các bước của bạn là trong các phương thức riêng tư, chúng không thể được sử dụng lại ở bất kỳ nơi nào khác mà không cần trích xuất chúng trước bằng cách nào đó. Ngoài ra, nó có thể khuyến khích sao chép-dán khi cần một bước ở nơi khác.
  • Chia theo cách này có thể là tùy ý. Tôi sẽ lập luận rằng việc chia tách một phương thức công khai dài sẽ không mất nhiều suy nghĩ hay thiết kế như thể bạn muốn chia nhỏ các phản hồi thành các lớp. Mỗi lớp phải được chứng minh bằng một tên, tài liệu và bài kiểm tra thích hợp, trong khi một phương thức riêng không được xem xét nhiều.
  • Che giấu vấn đề. Vì vậy, bạn đã quyết định chia phương thức công khai của bạn thành các phương thức riêng tư nhỏ. Bây giờ không có vấn đề! Bạn có thể tiếp tục thêm nhiều bước hơn bằng cách thêm nhiều phương thức riêng tư hơn! Trái lại, tôi nghĩ đây là một vấn đề lớn. Nó thiết lập một mô hình để thêm độ phức tạp vào một lớp sẽ được theo sau bởi các sửa lỗi và triển khai tính năng tiếp theo. Chẳng bao lâu phương pháp riêng tư của bạn sẽ phát triển và chúng sẽ phải được chia ra.

nhưng tôi lo lắng rằng việc ép buộc bất cứ ai đọc phương pháp nhảy qua các phương thức riêng tư khác nhau sẽ làm hỏng khả năng đọc

Đây là một cuộc tranh cãi mà tôi đã có với một trong những đồng nghiệp của tôi gần đây. Ông lập luận rằng việc có toàn bộ hành vi của một mô-đun trong cùng một tệp / phương thức sẽ cải thiện khả năng đọc. Tôi đồng ý rằng mã dễ theo dõi hơn khi tất cả cùng nhau, nhưng mã ít dễ dàng hơn để lý giải khi độ phức tạp tăng lên. Khi một hệ thống phát triển, nó trở nên khó hiểu với toàn bộ mô-đun. Khi bạn phân tách logic phức tạp thành nhiều lớp, mỗi lớp có một trách nhiệm duy nhất, thì việc suy luận về từng phần sẽ trở nên dễ dàng hơn nhiều.


1
Tôi sẽ không đồng ý. Quá nhiều trừu tượng hoặc quá sớm dẫn đến mã phức tạp không cần thiết. Một phương thức riêng tư có thể là bước đầu tiên trong một con đường có khả năng cần phải được giao thoa và trừu tượng hóa, nhưng cách tiếp cận của bạn ở đây cho thấy đi lang thang xung quanh những nơi có thể không bao giờ cần đến.
WillC

1
Tôi hiểu nơi bạn đang đến từ, nhưng tôi nghĩ rằng mã mùi giống như một OP được hỏi về được dấu hiệu cho thấy nó sẵn sàng cho một thiết kế tốt hơn. Sự trừu tượng hóa sớm sẽ được thiết kế các giao diện này trước khi bạn gặp phải vấn đề đó.
Samuel

Tôi đồng ý với phương pháp này. Thực tế, khi bạn theo dõi TDD, đó là sự tiến triển tự nhiên. Một người khác nói rằng nó quá trừu tượng quá sớm, nhưng tôi thấy việc nhanh chóng chế giễu một chức năng tôi cần trong một lớp riêng biệt (đằng sau một giao diện), hơn là phải thực hiện nó theo một phương thức riêng tư để thử nghiệm vượt qua .
Eternal21
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.