Piszę zestaw klas testowych junit w Javie. Istnieje kilka stałych, na przykład ciągi, których będę potrzebować w różnych klasach testowych. Myślę o interfejsie, który je definiuje i każda klasa testowa go zaimplementuje.
Korzyści, które tam widzę to:
- łatwy dostęp do stałych:
MY_CONSTANT
zamiastThatClass.MY_CONSTANT
- każda stała zdefiniowana tylko raz
Czy to podejście jest raczej dobrą czy złą praktyką? Mam ochotę trochę nadużyć koncepcji interfejsów.
Możesz ogólnie odpowiedzieć na temat interfejsów / stałych, ale także na temat testów jednostkowych, jeśli jest w tym coś wyjątkowego.
java
design
programming-practices
constants
FabianB
źródło
źródło
Odpowiedzi:
Joshua Bloch odradza to w swojej książce Effective Java :
Możesz uzyskać ten sam efekt z normalną klasą, która definiuje stałe, a następnie użyj
import static com.example.Constants.*;
źródło
W naszym przypadku robimy to, ponieważ wartości stałych reprezentują kontrakt dla stanów końcowych, które musi zapewnić implementacja usługi. Umieszczenie tych stałych w interfejsie określa stany końcowe jako część kontraktu, a jeśli jakakolwiek implementacja interfejsu ich nie wykorzysta, nie wykona swojego zadania.
CZASAMI stałe są szczegółami implementacji. CZASAMI nie są. Jak zwykle inżynier musi użyć swojego mózgu, aby zdecydować, co robić, a nie polegać na szerokim schemacie lub praktyce.
źródło
Nie sądzę, że dobrze jest mieć interfejsy tylko dla stałych.
Ale jeśli interfejs definiujący zachowanie (metody implementujące klasy powinny implementować), ma stałe, to jest OK. Jeśli „wycieknie jakiś szczegół implementatora” do API, to właśnie tak powinno być. Nieszczelne są także to, że implementator implementuje metody foo i bar.
Weźmy na przykład interfejs java.awt.Transparency. Ma stałe OPAQUE, BITMASK i TRANSLUCENT, ale ma również metodę getTransparency ().
Jeśli projektant umieści tam te stałe, to dlatego, że pomyślał, że będzie wystarczająco stabilny, aby być częścią interfejsu, tak jak getTransparency ().
źródło
Pomyśl, że jest to punkt widzenia najbardziej popularny w miejscach, w których dominuje projektowanie na podstawie umowy.
Interfejsy to umowy. Umieszczenie stałych w interfejsach oznacza, że każda klasa, która przestrzega umowy, zgadza się na wartość / koncepcję określoną przez stałą.
źródło
"at most expose their names"
bez ujawniania wartości?Firma, w której pracowałem, intensywnie korzystała z 1 stałych importowanych przez interfejs . Nie wydaje mi się, żeby wynikało z tego jakaś szkoda.
Pytanie, które powinieneś sobie zadać, brzmi: jak ważna jest dla ciebie przestrzeń nazw? W przypadku stałych tak naprawdę wszystko działa jak klasa. Jeśli masz tysiące stałych, możesz nie chcieć, aby wszystkie były zawsze dostępne.
Fajną rzeczą w interfejsach jest to, że daje ci to korzyści z pracy w jedną stronę - weź wszystkie potrzebne przestrzenie nazw lub żaden z nich (i uzyskaj do nich bezpośredni dostęp
MyInterface.CONSTANT
). Prawie to samoimport static MyInterface.*
, ale nieco bardziej oczywiste.1: Jeśli nie znasz Javy, nie mam na myśli tego
import
słowa kluczowego, mam na myśli wprowadzone przezimplements MyConstantsInterface
źródło
Pochodzę z tła, na które największy wpływ mają przede wszystkim „sposób Ada” i „sposób .Net”. Powiedziałbym, że nie, że prawdopodobnie nie najlepiej jest deklarować stałe w interfejsach. Jest to technicznie niedozwolone w języku c #.
Powodem, dla którego mówię „nie”, jest to, że interfejs jest formą umowy, która określa zachowanie, a nie stan lub strukturę. Stała implikuje pewien rodzaj stanu (prymitywny) lub aspekt stanu (złożony lub agregowany).
Mogę docenić potrzebę udostępnienia wartości domyślnych i predefiniowanych wszystkim, którzy implementują interfejs, ale być może stan domyślny zostałby lepiej opisany w abstrakcyjnym lub wartościowym obiekcie lub szablonie, w którym wartości domyślne miałyby co najmniej minimalny kontekst.
Aby uzyskać bardziej techniczny przewodnik: download.oracle.com/javase/1.5.0/docs/guide/language/static-import.html
źródło
So when should you use static import? Very sparingly! Only use it when you'd otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import.
Odniesienie z Oracle DocsNie, to nie jest ogólna zła praktyka.
Chodzi o to, że stałe, jak każdy inny artefakt, należy wprowadzić zgodnie z zasadami minimalnej widoczności i odpowiedniego poziomu abstrakcji.
Używanie składni tylko dlatego, że możesz, to prawdziwy problem.
źródło