Czy uważa się, że w tym samym pliku zdefiniowano wiele klas w języku Python?

31

Podczas pracy z pythonem po raz pierwszy odkryłem, że kończę pisanie wielu klas w tym samym pliku, co jest sprzeczne z innymi językami, takimi jak Java, która używa jednego pliku na klasę.

Zazwyczaj klasy te składają się z 1 abstrakcyjnej klasy bazowej, z 1-2 konkretnymi implementacjami, których użycie różni się nieznacznie. Poniżej zamieściłem jeden taki plik:

class Logger(object):

    def __init__(self, path, fileName):
        self.logFile = open(path + '/' + filename, 'w+')
        self.logFile.seek(0, 2)

    def log(self, stringtoLog):
        self.logFile.write(stringToLog)

    def __del__(self):
        self.logFile.close()

class TestLogger(Logger):   

    def __init__(self, serialNumber):
        Logger.__init__('/tests/ModuleName', serialNumber):

    def readStatusLine(self):
        self.logFile.seek(0,0)
        statusLine = self.logFile.readLine()
        self.logFile.seek(0,2)
        return StatusLine

    def modifyStatusLine(self, newStatusLine):
        self.logFile.seek(0,0)
        self.logFile.write(newStatusLine)
        self.logFile.seek(0,2)

class GenericLogger(Logger):

    def __init__(self, fileName):
        Logger.__init__('/tests/GPIO', fileName):

    def logGPIOError(self, errorCode):
        self.logFile.write(str(errorCode))

Jak widać powyżej, mam klasę bazową Logger, z kilkoma różnicami w implementacji poniżej.

Pytanie: Czy ten standard jest dla Pythona, czy dla dowolnego języka? Jakie problemy mogą wyniknąć z korzystania z tej implementacji, jeśli występują?

EDYCJA: Tak naprawdę nie szukam wskazówek na temat tego konkretnego pliku, ale w bardziej ogólnym sensie. Co jeśli klasy zakończyły się 3-5 umiarkowanie złożonymi metodami? Czy miałoby to sens, aby je podzielić? Gdzie jest granica dla powiedzenia, że ​​powinieneś podzielić plik?

Ampt
źródło
3
Ograniczenie do jednej klasy na plik NIE jest kwestią C ++. Java to jedyny znany mi język, w którym uważa się, że należy go unikać. W C ++ niezwykle często zdarza się, że pojedynczy plik .h / .cpp ma jedną klasę podstawową i wiele klas pomocniczych, które mogą, ale nie muszą być prywatne dla klasy podstawowej.
Gort the Robot
@StevenBurnap Usunąłem c ++ jako przykład, ponieważ masz rację.
Ampt
1
Jest to również zrobione w php, aby ułatwić automatyczne ładowanie. Z drugiej strony w php możesz jawnie zadeklarować przestrzeń nazw.
Bodo

Odpowiedzi:

24

W porządku. Dla odniesienia jest również w C ++.

Utrzymywanie ściśle ze sobą powiązanych rzeczy to rozsądna praktyka. Unikanie niewłaściwego łączenia jest również dobrą praktyką. Znalezienie właściwej równowagi nie jest kwestią ścisłych zasad, ale, no cóż, znalezienia równowagi między różnymi problemami.

Kilka praktycznych zasad:

  1. Rozmiar

    Zbyt duże pliki mogą być brzydkie, ale w tym przypadku tak nie jest. Brzydota jest prawdopodobnie wystarczającym powodem do podzielenia pliku, ale rozwijanie tego wyczucia estetycznego jest w dużej mierze kwestią doświadczenia, więc nie pomaga ci dowiedzieć się, co zrobić a priori

  2. Rozdzielenie obaw

    Jeśli Twoje konkretne implementacje mają bardzo różne obawy wewnętrzne, w jednym pliku gromadzone są wszystkie obawy. Na przykład implementacje z nie nakładającymi się na siebie zależnościami sprawiają, że pojedynczy plik zależy od sumy wszystkich tych zależności.

    Czasami uzasadnione może być rozważenie powiązania podklas z ich zależnościami, które przeważają nad sprzężeniem z interfejsem (lub odwrotnie, problem implementacji interfejsu jest słabszy niż problem wewnętrzny związany z tą implementacją).

    Jako konkretny przykład weź ogólny interfejs bazy danych. Konkretne implementacje wykorzystujące odpowiednio DB w pamięci, SQL RDBMS i zapytanie sieciowe mogą nie mieć nic wspólnego poza interfejsem, a zmuszanie wszystkich, którzy chcą, aby lekka wersja w pamięci importowała również bibliotekę SQL, jest paskudne.

  3. Kapsułkowanie

    Chociaż może napisać dobrze kapsułkach zajęcia w tym samym module, to mogłoby zachęcić niepotrzebnego sprzęgło tylko dlatego, że masz dostęp do szczegółów implementacyjnych, które w przeciwnym razie nie można wywieźć poza modułem.

    Myślę, że to po prostu kiepski styl, ale możesz wymusić lepszą dyscyplinę, dzieląc moduł, jeśli naprawdę nie możesz zerwać z nałogiem.

Bezużyteczny
źródło
2
Twoja odpowiedź byłaby silniejsza, gdyby zacytował odniesienia zewnętrzne, które pokazują normalność łączenia klas w jednym pliku lub dostarczając więcej wyjaśnień wskazujących, dlaczego jest to w porządku.
1
Zredagowałem pytanie, aby podkreślić, że jest to po prostu przykład tego, co mam na myśli i nie do końca odzwierciedla naturę pytania. Dlaczego lepiej jest przechowywać je w tym samym pliku niż importować je w razie potrzeby?
Ampt
Posiadanie wielu małych plików może być tak trudne do zarządzania, jak posiadanie kilku gigantycznych plików. Python jest dość zwięzłym językiem. Twój przykład to pokazuje. Te trzy klasy są bezpośrednio powiązane i prawdopodobnie mieszczą się w jednym oknie edytora bez przewijania.
Gort the Robot
1
@ GlenH7 - Nie jestem pewien co do referencji, ponieważ one po prostu przechodzą ode mnie, składając roszczenie bezpośrednio, do mnie, twierdząc, że moje nastawienie do selekcji jest prawidłowe. Zamiast tego próbowałem skupić się na wyjaśnieniu.
Bezużyteczne
7

Moje zwykłe dokumenty referencyjne, aby wiedzieć, co to jest python.

Prosty jest lepszy niż złożony.

Mieszkanie jest lepsze niż zagnieżdżone.

Z Zen Of Python

Niemal bez wyjątku nazwy klas korzystają z konwencji CapWords.

Nazwy pakietów i modułów Moduły powinny mieć krótkie, małe litery. [...] Nazwy modułów są mapowane na nazwy plików

Od PEP 8

Moją interpretacją jest to, że wszystko jest w porządku, ponieważ byłoby proste i płaskie. Ponadto, ponieważ nazwy klas i nazwy plików mają różne przypadki, i tak nie powinny być identyczne, więc nie widziałbym problemu w pakowaniu wielu powiązanych klas w pliku.

SylvainD
źródło
7
Czy możesz sprowadzić to do części istotnych dla pytania? Przeczytałem oba z nich wiele razy, ale trudno mi wybrać , które części odnoszą się w szczególności do mojego obecnego pytania.
Ampt
1
Rzeczywiście, zredagowałem swoją odpowiedź.
SylvainD
1

To, co masz teraz, jest w porządku. Przejrzyj standardową bibliotekę - w jednym pliku jest mnóstwo modułów z wieloma powiązanymi klasami. W pewnym momencie sprawy stają się większe i ostatecznie będziesz chciał zacząć korzystać z modułów z wieloma plikami, ale nie ma prawdziwych reguł określających, kiedy. Rzeczy po prostu się dzielą, gdy jeden plik zaczyna wydawać się „za duży”.

Sean McSomething
źródło
0

Jest to zdecydowanie w porządku i zachęcam do posiadania kilku klas w jednym pliku, o ile są one realizowane. Ogólnie rzecz biorąc, twoje klasy powinny pozostać krótkie i zwięzłe i powinieneś raczej podzielić zachowanie na dwie lub więcej klas niż budować ogromne monolityczne. Podczas pisania kilku małych klas naprawdę konieczne i pomocne jest trzymanie tych, które są powiązane w tym samym pliku.

wirrbel
źródło
-1

W skrócie - do diabła tak.

Co więcej, posiadanie wielu klas w jednym pliku jest czasami bardzo przydatne. Niektóre pakiety ( six, bottle) jawnie są dostarczane w jednym pliku, aby można je było łatwo zintegrować z dowolnym modułem innej firmy bez konieczności instalowania pip (czasem pożądane). Pamiętaj jednak, aby dobrze uporządkować kod. Intensywnie używaj komentarzy do kodu i bloków separacji, aby był bardziej czytelny.

Artur Barseghyan
źródło
3
to nie wydaje się, aby dodać nic znaczącego na wcześniejszej odpowiedzi pisał kilka lat temu
gnat