1. Statyczny vs. instancja
Myślę, że istnieją bardzo jasne wytyczne dotyczące tego, co jest dobrym projektem OO, a co nie. Problem polega na tym, że blogosfera utrudnia oddzielenie dobra od zła i brzydoty. Możesz znaleźć jakieś referencje wspierające nawet najgorsze praktyki, jakie możesz wymyślić.
A najgorszą praktyką, jaką mogę wymyślić, jest stan globalny, w tym wspomniana statystyka i ulubiony Singleton każdego. Niektóre fragmenty klasycznego artykułu Misko Hevery na ten temat .
Aby naprawdę zrozumieć zależności, programiści muszą przeczytać każdy wiersz kodu. Powoduje to upiorne działanie na odległość: podczas uruchamiania zestawów testów stan globalny zmutowany w jednym teście może spowodować nieoczekiwany błąd kolejnego lub równoległego testu. Przerwij statyczną zależność za pomocą ręcznego lub wtrysku zależności Guice.
Upiorna akcja na odległość ma miejsce, gdy uruchamiamy jedną rzecz, która naszym zdaniem jest odizolowana (ponieważ nie przekazaliśmy żadnych odniesień), ale niespodziewane interakcje i zmiany stanu zachodzą w odległych lokalizacjach systemu, o których nie mówiliśmy obiektowi. Może się to zdarzyć tylko przez państwo globalne.
Być może wcześniej nie myślałeś o tym w ten sposób, ale za każdym razem, gdy używasz stanu statycznego, tworzysz tajne kanały komunikacji i nie wyjaśniasz ich w interfejsie API. Upiorne działanie na odległość zmusza programistów do przeczytania każdego wiersza kodu, aby zrozumieć potencjalne interakcje, obniża produktywność programistów i dezorientuje nowych członków zespołu.
Sprowadza się to do tego, że nie powinieneś dostarczać statycznych odniesień do niczego, co ma jakiś stan przechowywania. Jedynym miejscem, w którym używam statyki, są wyliczone stałe i mam wątpliwości co do tego.
2. Metody z parametrami wejściowymi i zwracanymi wartościami a metody bez żadnych
Należy zdać sobie sprawę z tego, że metody, które nie mają parametrów wejściowych i parametrów wyjściowych, są w zasadzie pewne, że działają na jakimś wewnętrznie przechowywanym stanie (w przeciwnym razie, co robią?). Istnieją całe języki oparte na unikaniu stanu przechowywanego.
Za każdym razem, gdy zapisujesz stan, masz możliwość wystąpienia działań niepożądanych, więc upewnij się, że zawsze używasz go ostrożnie. Oznacza to, że powinieneś preferować funkcje ze zdefiniowanymi wejściami i / lub wyjściami.
W rzeczywistości funkcje, które mają zdefiniowane wejścia i wyjścia, są znacznie łatwiejsze do przetestowania - nie musisz tutaj uruchamiać funkcji i patrzeć tam, aby zobaczyć, co się stało, i nie musisz gdzieś ustawiać właściwości jeszcze przed uruchomieniem testowanej funkcji.
Możesz również bezpiecznie używać tego typu funkcji jako statyki. Jednak nie zrobiłbym tego, ponieważ gdybym później chciał gdzieś użyć nieco innej implementacji tej funkcji, zamiast zapewnić inną instancję z nową implementacją, utknąłem bez możliwości zastąpienia tej funkcji.
3. Pokrywające się kontra odrębne
Nie rozumiem pytania. Jaka byłaby korzyść z 2 nakładających się metod?
4. Prywatny vs. publiczny
Nie narażaj niczego, czego nie musisz ujawniać. Jednak nie jestem też wielkim fanem prywatnych. Nie jestem programistą C #, ale programistą ActionScript. Spędziłem dużo czasu w kodzie Flex Framework firmy Adobe, który został napisany około 2007 roku. I dokonali naprawdę złych wyborów, co zrobić, aby stać się prywatnym, co czyni z tego koszmaru próbę rozszerzenia swoich klas.
Więc jeśli nie uważasz, że jesteś lepszym architektem niż programiści Adobe około 2007 r. (Z twojego pytania powiedziałbym, że masz jeszcze kilka lat, zanim będziesz mieć szansę na złożenie takiego oświadczenia), prawdopodobnie chcesz po prostu wybrać domyślną ochronę .
Występują pewne problemy z przykładami kodu, co oznacza, że nie są one dobrze zaprojektowane, więc nie można wybrać A lub B.
Po pierwsze, prawdopodobnie powinieneś oddzielić tworzenie obiektu od jego użycia . Więc zwykle nie masz new XMLReader()prawa obok miejsca, w którym jest używany.
Ponadto, jak mówi @djna, powinieneś obudować metody używane w czytnikach XML, aby interfejs API (przykład instancji) mógł zostać uproszczony w celu:
_document Document = reader.read(info);
Nie wiem, jak działa C #, ale ponieważ pracowałem z wieloma technologiami internetowymi, podejrzewałbym, że nie zawsze będziesz w stanie natychmiast zwrócić dokument XML (z wyjątkiem może jako obietnicy lub przyszłego typu) obiekt), ale nie mogę udzielić porady na temat obsługi obciążenia asynchronicznego w języku C #.
Zauważ, że dzięki temu podejściu możesz stworzyć kilka implementacji, które mogą przyjąć parametr, który mówi im, gdzie / co mają odczytać i zwrócić obiekt XML, i zamieniać je w zależności od potrzeb projektu. Na przykład możesz czytać bezpośrednio z bazy danych, ze sklepu lokalnego lub, jak w oryginalnym przykładzie, z adresu URL. Nie możesz tego zrobić, jeśli używasz metody statycznej.