Dostęp domyślny nie powoduje, że modyfikator dostępu prywatnego jest zbędny.
Stanowisko projektantów języka znajduje odzwierciedlenie w oficjalnym samouczku - Kontrolowanie dostępu do członków klasy i jest dość jasne (dla Twojej wygody, odpowiednie oświadczenie w cytacie pogrubione ):
Wskazówki dotyczące wyboru poziomu dostępu:
Jeśli inni programiści używają twojej klasy, chcesz mieć pewność, że nie wystąpią błędy wynikające z niewłaściwego użycia. Poziomy dostępu mogą ci w tym pomóc.
- Użyj najbardziej restrykcyjnego poziomu dostępu, który ma sens dla konkretnego członka. Używaj prywatnego, chyba że masz dobry powód, aby tego nie robić.
- Unikaj pól publicznych oprócz stałych. (Wiele przykładów w tym samouczku używa pól publicznych. Może to pomóc zwięźle zilustrować niektóre punkty, ale nie jest zalecane w przypadku kodu produkcyjnego.) Pola publiczne mają tendencję do łączenia cię z określoną implementacją i ograniczają twoją elastyczność w zmienianiu kodu.
Twoje odwołanie do testowalności jako uzasadnienia całkowitego usunięcia prywatnego modyfikatora jest błędne, o czym świadczą np. Odpowiedzi w New to TDD. Czy powinienem teraz unikać prywatnych metod?
Oczywiście możesz mieć metody prywatne i oczywiście możesz je przetestować.
Albo jest jakiś sposób na uruchomienie prywatnej metody, w którym to przypadku możesz to przetestować, albo nie ma sposobu na uruchomienie prywatnej, w takim przypadku: dlaczego, do cholery, próbujesz ją przetestować, po prostu usuń tę cholerną rzecz ...
Stanowisko projektantów języków na temat celu i korzystania z dostępu na poziomie pakietu zostało wyjaśnione w innym oficjalnym samouczku, Tworzenie i korzystanie z pakietów i nie ma nic wspólnego z pomysłem porzucenia prywatnych modyfikatorów (dla Twojej wygody odpowiednie oświadczenie w pogrubionej wycenie ) :
Powinieneś spakować te klasy i interfejs w pakiet z kilku powodów, w tym:
- Ty i inni programiści możecie łatwo ustalić, że te typy są powiązane ...
- Możesz zezwolić typom w pakiecie na nieograniczony dostęp do siebie, a jednocześnie ograniczyć dostęp dla typów spoza pakietu ...
<rant "Myślę, że słyszałem dość marudzenia. Chyba czas powiedzieć głośno i wyraźnie ...">
Metody prywatne są korzystne dla testów jednostkowych.
Uwaga poniżej zakłada, że znasz zakres kodu . Jeśli nie, poświęć trochę czasu na naukę, ponieważ jest to bardzo przydatne dla osób zainteresowanych testowaniem jednostkowym i testowaniem w ogóle.
W porządku, więc mam tę prywatną metodę i testy jednostkowe, a analiza zasięgu mówi mi, że jest luka, moja prywatna metoda nie jest objęta testami. Teraz...
Co zyskuję, zachowując prywatność
Ponieważ metoda jest prywatna, jedynym sposobem na kontynuację jest przestudiowanie kodu, aby dowiedzieć się, jak jest on używany przez nieprywatny interfejs API. Zazwyczaj takie badanie ujawnia, że przyczyną luki jest brak konkretnego scenariusza użycia w testach.
void nonPrivateMethod(boolean condition) {
if (condition) {
privateMethod();
}
// other code...
}
// unit tests don't invoke nonPrivateMethod(true)
// => privateMethod isn't covered.
Ze względu na kompletność, innymi (rzadziej) przyczynami takich luk w zasięgu mogą być błędy w specyfikacji / projekcie. Nie zagłębię się tutaj głęboko, aby wszystko było proste; wystarczy powiedzieć, że jeśli osłabisz ograniczenie dostępu „tylko po to, aby metoda była testowalna”, stracisz szansę dowiedzenia się, że te błędy w ogóle istnieją.
W porządku, aby naprawić lukę, dodaję test jednostkowy na brakujący scenariusz, powtarzam analizę pokrycia i sprawdzam, czy luka zniknęła. Co mam teraz Mam jako nowy test jednostkowy do konkretnego użycia nieprywatnego API.
Nowy test gwarantuje, że oczekiwane zachowanie dla tego użycia nie zmieni się bez powiadomienia, ponieważ jeśli się zmieni, test się nie powiedzie.
Zewnętrzny czytelnik może przyjrzeć się temu testowi i dowiedzieć się, jak powinien on używać i zachowywać się (tutaj, zewnętrzny czytelnik obejmuje moje przyszłe ja, ponieważ zwykle zapominam o kodzie miesiąc lub dwa po tym, jak skończę z nim).
Nowy test jest odporny na refaktoryzację (czy refaktoryzuję metody prywatne? Założycie się!) Cokolwiek zrobię privateMethod
, zawsze będę chciał przetestować nonPrivateMethod(true)
. Bez względu na to, co zrobię privateMethod
, nie będzie potrzeby modyfikowania testu, ponieważ metoda nie jest wywoływana bezpośrednio.
Nie jest zły? Stawiasz zakład
Co tracę z osłabienia ograniczenia dostępu
Teraz wyobraź sobie, że zamiast wyżej, po prostu osłabiam ograniczenie dostępu. Pomijam przestudiowanie kodu używającego tej metody i przechodzę od razu do testu, który mnie wywołuje exPrivateMethod
. Świetny? Nie!
Czy dostaję test na określone użycie nieprywatnego API wymienionego powyżej? Nie: wcześniej nie było testu nonPrivateMethod(true)
i teraz nie ma takiego testu.
Czy czytelnicy z zewnątrz mają szansę lepiej zrozumieć wykorzystanie klasy? Nie. "- Hej, jaki jest cel testowanej tutaj metody? - Zapomnij, to jest wyłącznie do użytku wewnętrznego. - Ups."
Czy toleruje refaktoryzację? Nie ma mowy: cokolwiek się zmieni exPrivateMethod
, prawdopodobnie przerwie test. Zmień nazwę, połącz się z inną metodą, zmień argumenty i test po prostu przestanie się kompilować. Bół głowy? Obstawiasz!
Podsumowując , trzymanie się metody prywatnej przynosi mi użyteczne, niezawodne ulepszenie w testach jednostkowych. W przeciwieństwie do tego, osłabienie ograniczeń dostępu „do testowalności” daje mi tylko niejasny, trudny do zrozumienia fragment kodu testowego, który dodatkowo jest narażony na stałe ryzyko złamania przez jakiekolwiek drobne refaktoryzacja; szczerze mówiąc, to, co dostaję, wygląda podejrzanie jak dług techniczny .
</rant>