Dlaczego warto podzielić program na wiele klas? [Zamknięte]

62

Nadal jestem uczniem szkoły średniej (rozpoczynam naukę w 10 klasie) i muszę jeszcze wziąć udział w kursie komputerowym w szkole. Wszystko, co do tej pory zrobiłem, to książki. Te książki nauczyły mnie takich pojęć, jak dziedziczenie, ale w jaki sposób podział programu na wiele klas pomaga? Książki nigdy mi nie powiedziały.

Pytam o to głównie z powodu ostatniego projektu. Jest to zręcznościowa gra wideo, przypominająca grę Flash, jak powiedzieli niektórzy ludzie (chociaż nie mam pojęcia, czym jest gra Flash ). Chodzi o to, że to tylko jedna klasa. Działa idealnie dobrze (z niewielkim opóźnieniem) tylko z jedną klasą. Pytam więc, w jaki sposób podzielenie go na wiele klas pomogłoby.

Ten projekt był napisany w Javie i jestem jedyną osobą nad nim pracującą.

kullalok
źródło
1
Aby każdy element oprogramowania był prostszy! infoq.com/presentations/Simple-Made-Easy-QCon-London-2012
TehShrike
49
Czy podczas czytania książek podzielono je na rozdziały i sekcje? Podzieliliśmy program na klasy w celu uporządkowania rzeczy, podobnie jak książki dzielą tekst na rozdziały w celu uporządkowania rzeczy.
riwalk
12
Rzymianie zwykli mawiać: divide et impera.
Giorgio
7
@Giorgio: lub w języku angielskim, ponieważ łaciński nie jest już używany: Divide And Conquer .
Matthieu M.
40
Biorąc pod uwagę, że jesteś w klasie 10 i jesteś już w stanie sformułować inteligentne pytanie, podając wszystkie szczegóły niezbędne do uzyskania dobrych odpowiedzi, zapewniając kontekst i swoje względne doświadczenie, a także podstawowe informacje o tym, dlaczego zadajesz pytanie; jesteś już bardziej wykwalifikowany niż wiele osób, z którymi obecnie współpracuję ...
CaffGeek

Odpowiedzi:

71

Najprostsza odpowiedź jest taka, że ​​jeśli umieścisz wszystko w jednej klasie, będziesz musiał martwić się o wszystko od razu podczas pisania nowego kodu. Może to działać w przypadku małych projektów, ale w przypadku dużych aplikacji (mówimy o setkach tysięcy linii) szybko staje się to prawie niemożliwe.

Aby rozwiązać ten problem, dzielisz elementy funkcjonalności na ich własne klasy i hermetyzujesz całą logikę. Następnie, gdy chcesz pracować nad klasą, nie musisz myśleć o tym, co jeszcze dzieje się w kodzie. Możesz po prostu skupić się na tym małym fragmencie kodu. Jest to nieocenione dla wydajnej pracy, jednak trudno to docenić bez pracy z dużymi aplikacjami.

Oczywiście istnieje wiele innych korzyści z dzielenia kodu na mniejsze części: kod jest łatwiejszy w utrzymaniu, bardziej testowalny, bardziej wielokrotnego użytku itp., Ale dla mnie największą korzyścią jest to, że sprawia, że ​​zarządzanie dużymi programami jest możliwe dzięki zmniejszeniu ilości kodu muszę pomyśleć o jednym czasie.

Oleksi
źródło
7
Wiele koncepcji / pomysłów w programowaniu (zasady OO, rozproszona kontrola źródła, standardy kodowania) ma sens tylko wtedy, gdy pracujesz w stosunkowo dużych projektach w zespole. Zrozumiesz, dlaczego faktycznie pracujesz nad takimi projektami.
joshin4colours
40
Warto zauważyć, że samo podzielenie projektu na wiele klas / plików niewiele pomaga. Naprawdę ważne jest posiadanie samodzielnych klas, więc zmiana jednej klasy nie wymaga wiedzy o programie (a korzystanie z klasy nie wymaga żadnej wiedzy o tym, jak została zaimplementowana). Mówię o tym, ponieważ często widzę kod z wieloma klasami, ale bez prawdziwej enkapsulacji. Kapsułkowanie jest ważną częścią - jak to osiągnąć, to tylko szczegóły.
Przywróć Monikę
2
Niektóre słowa kluczowe to „sprzęganie” lub „oddzielanie”, „enkapsulacja”, „ukrywanie informacji”.
marktani
@BrendanLong, zgadzam się i dodam również, że hermetyzacja jest prawie niemożliwa. O ile oczywiście nie piszesz osobnych programów ... ALE zwykle jest wiele części, które nie zależą od siebie, ale mają tylko wspólne zależności
Jo So
29

Cóż, najprostszą odpowiedzią może być „Pomaga uporządkować rzeczy”. Jeśli nic więcej, możesz porównać to do sekcji w zeszycie - jest to po prostu prostsze, jeśli masz tutaj „wszystkie rzeczy związane z interfejsem użytkownika” i „wszystkie rzeczy związane z grą”.

Bardziej wyrafinowaną odpowiedzią jest to, że dzielenie pracy jest nie tylko wygodne, ale bardzo ważne w zarządzaniu złożonością (a „zarządzanie złożonością” jest właściwie nazwą gry, jeśli chodzi o programowanie). Klasy lub inne rodzaje modułów pozwalają „rozdzielić obawy”. Nie tylko wiesz, gdzie szukać „rzeczy związanych z interfejsem użytkownika”, ale możesz być pewien, że jeśli chcesz wprowadzić zmiany w interfejsie, możesz to zrobić w jednym miejscu i nie musisz tego robić martw się „czy to jedyne miejsce, w którym ustawiłem czcionkę na Comic Sans?”. Możesz dokonać zmiany i wiedzieć, że skutek tej zmiany jest tylko w jakimkolwiek (małym) zakresie, który jest odpowiedni. Jeśli wszystko jest w jednej klasie lub module, zasadniczo wszystko jest globalne,

W konkretnym przypadku klas jako typu modułu oprogramowania istnieje również wiele zachowań związanych z klasą, a większość programistów w paradygmacie obiektowym uważa, że ​​bardzo pomocne jest posiadanie znaczących nazw powiązanych z klasami, które są powiązane z grupą działa razem. Więc prawdopodobnie nie miałbyś UIklasy, prawdopodobnie miałbyś Buttonklasę. Istnieje cała wiedza i techniki związane z obiektowym projektowaniem klas i jest to najczęstszy sposób organizowania dużych systemów w głównym nurcie programowania.

Larry OBrien
źródło
12

To dobre pytanie! Prosty i zadany. Cóż ... odpowiedź nie jest tak łatwa do zrozumienia dla studenta, który studiuje informatykę i prawdopodobnie nie wie w głębokim OO i prawdopodobnie nie ma doświadczenia w pracy.

Mogę więc odpowiedzieć, opisując scenariusz i sprawiając, że wyobrażasz sobie, jak oprogramowanie wieloklasowe jest lepsze niż oprogramowanie monolityczne (wykonane tylko przez jedną klasę):

  • Czytelność : O wiele trudniej jest przeglądać i pisać kod w pliku zawierającym 10000 linii niż kilka małych i uporządkowanych plików.
  • Ponowne użycie : jeśli napiszesz jedną klasę, możesz popaść w duplikację kodu . Oznacza to więcej wierszy kodu i prawdopodobnie więcej błędów (!)
  • Testowalność : co z testowaniem pojedynczej funkcjonalności? Jeśli wyodrębnisz jedną funkcję logiczną w jednej klasie, twoje życie będzie łatwiejsze.
  • Konserwowalność kodu : Możesz naprawić błąd lub zwiększyć funkcjonalność za pomocą mnożenia klas w jednym miejscu: Ładne małe klasy.
  • Struktura projektu : oooo, czy możesz sobie wyobrazić, jak brzydki będzie projekt z jednym plikiem źródłowym?
AngeloBad
źródło
Podoba mi się twoja odpowiedź i właśnie wprowadziłem kilka zmian (które wciąż wymagają weryfikacji). Brakuje mi łatwiejszego wykrywania zmian w systemach wersjonowania oprogramowania, takich jak SVN / GIT. Łatwiej jest także pracować z wieloma programistami równolegle dla jednego projektu.
Martin Thoma,
Powiedziałbym, że rozdzielenie obaw, spójności i oddzielenia płatności jest pojęciem o wiele szerszym niż dyscyplina OOP. Niezbędni, logiczni i funkcjonalni programiści dążą do wysokiej spójności i niskiego sprzężenia.
sara
8

Jest tu wiele dobrych odpowiedzi i zdecydowanie się z nimi zgadzam, ale czuję, że jest coś więcej, o czym warto wspomnieć.

W tej chwili, jak powiedziałeś, pracujesz solo nad swoim projektem. Jednak w przyszłości będą chwile, kiedy będziesz musiał pracować w zespole. W tych czasach będziesz dzielić pracę (przypuszczalnie projekt będzie dość duży). W rezultacie istnieje kilka (tak naprawdę dwie główne ) różnych opcji. Możesz mieć wiele kopii jednego pliku i pracować nad osobnymi „kawałkami” pliku, a następnie „połączyć” je z kopią i wkleić później, a następnie zmodyfikować, aby części mogły ze sobą współpracować, lub możesz całkiem podzielić te „kawałki” łatwo na różne klasy i przedyskutuj, w jaki sposób będziesz pisać te klasy, i wykorzystaj tę wiedzę, aby zacząć.

Nadal będzie trzeba pracować, aby zintegrować wszystkie oddzielne elementy razem, ale będzie o wiele łatwiejsze do utrzymania. Ponieważ plik x zawiera kod y i jest to kod, który musisz zmodyfikować. To dotyczy organizacji, o której mówi większość innych odpowiedzi.

Trzymanie programu w głowie. Link z Giorgio

Sephallia
źródło
1
+1: Ważna jest także praca zespołowa! Zobacz np. Paulgraham.com/head.html i akapit z tytułem „Nie pozwól wielu osobom edytować tego samego kodu”.
Giorgio
@Giorgio Ja tylko przejrzałem to, ale wydaje się, że to niesamowite źródło! Dodam to do mojej odpowiedzi po prostu dlatego, że niektórzy ludzie mogą nie patrzeć w sekcji komentarzy. Zdecydowanie poświęcę mu więcej czasu na przeczytanie.
Sephallia
Dotyczy to również kontroli wersji - praca na osobnych plikach oznacza mniej konfliktów i scalanie.
Przywróć Monikę
7

W rezultacie to, co zrobiłeś, to na nowo opracowane programowanie proceduralne. Pamiętaj, że można w ten sposób pisać oprogramowanie, a kompilator prawdopodobnie nie będzie tego obchodził. Tak robiono przez wiele lat, dopóki komputery nie stały się szybsze, a narzędzia lepsze.

Mówiąc to, jeśli podzielisz swój kod na różne jednostki logiczne (klasy, moduły itp.), Możesz mieć wiele krótkich, łatwych do zrozumienia fragmentów kodu. które można zachować później. Wiele z moich modułów ma mniej niż 20 linii kodu. Wiem, że cały kod na dany temat znajduje się w określonym miejscu. Oznacza to również, że jeśli ktoś dołączy do projektu, będzie miał o wiele łatwiej znaleźć rzeczy.

Jak powiedział Gerald Sussman, nasze programy powinny być napisane jako pierwsze, aby ludzie mogli je przeczytać, a następnie, aby komputer mógł je uruchomić. (A jeśli nie przeczytałeś jeszcze „Struktury i interpretacji programów komputerowych”, powinieneś)

Zachary K.
źródło
4

Jedna używa wielu klas, ponieważ gdy wchodzisz w większe rzeczy, nie możesz po prostu śledzić wszystkiego, gdy jest to jeden wielki stos kodu.

Musisz po prostu podzielić i podbić, aby sobie z tym poradzić.

Loren Pechtel
źródło
3

Programowanie obiektowe to najlepszy pomysł, jaki kiedykolwiek widziałem w programowaniu. Ale nie jest to najlepsza rzecz we wszystkich przypadkach, potrzebujesz trochę doświadczenia w programowaniu, aby zrozumieć sens tego, a wiele osób twierdzi, że robi OOP, gdy nie jest.

Jeśli możesz poszukać „programowania strukturalnego”, prawdopodobnie znajdziesz coś bardziej przydatnego od razu. (Pamiętaj, aby przeczytać o starym programowaniu strukturalnym. Stare terminy często zyskują nowe, bardziej wymowne znaczenia i nie potrzebujesz jeszcze nic wymyślnego.) Jest to dość prosta koncepcja dzielenia programu na podprogramy, co jest o wiele łatwiejsze niż rozkładając go na przedmioty. Chodzi o to, że twoim głównym programem jest krótka procedura, która wywołuje podprogramy („metody” w Javie) w celu wykonania pracy. Każdy podprogram zna tylko jego parametry. (Jednym z tych parametrów może być nazwa pliku, więc możesz trochę oszukiwać.) Tak więc spojrzenie na nagłówek podprogramu / metody daje szybki obraz tego, co robi, robi prawie na pierwszy rzut oka.

Następnie wszystkie podprogramy są dzielone podobnie, dopóki kilka wierszy kodu bez żadnych wywołań metod wykona zadanie. Główny program, który wywołuje kilka metod, z których każda wywołuje kilka metod, z których każda .... Do małych prostych metod wykonujących pracę. W ten sposób możesz spojrzeć na dowolną część bardzo dużego programu (lub małego programu) i szybko zrozumieć, co on robi.

Java jest specjalnie zaprojektowana dla osób, które piszą kodowanie obiektowe. Ale nawet najbardziej intensywny program OO korzysta z programowania strukturalnego i zawsze możesz obalić dowolny język. (Zrobiłem OO w zwykłym C.) Więc możesz robić SP lub cokolwiek innego, w Javie. Zapomnij o klasach i skup się na dużych metodach, które można podzielić na małe, łatwe do zarządzania. Powinienem dodać, że SP bardzo pomaga w ponownym użyciu kodu, a także z zasadą DRY (google, ale oznacza to „Don't Repeat Yourself”).

Mam nadzieję, że wyjaśniłem, dlaczego i jak podzielić swój kod na wiele części bez wprowadzania „klas”. Są świetnym pomysłem i są przeznaczone do gier, a Java to świetny język dla OOP. Ale lepiej wiedzieć, dlaczego robisz to, co robisz. Pozostaw OOP w spokoju, dopóki nie zacznie to mieć dla ciebie sensu.

RalphChapin
źródło
0

Jedną z korzyści jest możliwość ponownego użycia. Program to w zasadzie pogrupowane instrukcje grupowe. Przekonasz się, że niektóre z tych instrukcji są odpowiednie również dla innych programów.

Powiedzmy, że robisz grę w skokach. Później, kiedy zdecydujesz się stworzyć grę armatnią, okaże się, że przydatne są tutaj obliczenia fizyki użyte w grze w skokach.

Zamiast pisać go ponownie lub gorzej kopiować i wklejać do nowego programu, tworzysz klasę. Więc następnym razem, gdy stworzysz inną grę, w której mechanika gry wymaga fizyki, możesz po prostu jej użyć ponownie. Oczywiście jest to zbyt uproszczone, ale mam nadzieję, że to ma sens.

gorengpisang
źródło
0

Przede wszystkim zwróć uwagę, że jestem C ++ i Pythonem, a nie Javą, więc niektóre z nich mogą nie mieć tak pełnego zastosowania. Popraw mnie, jeśli popełniam nieprawidłowe założenia dotyczące działania klas w Javie.

Klasy są przede wszystkim przydatne, gdy są tworzone. Klasa, w której nie są tworzone żadne instancje, jest naprawdę tylko uwielbioną przestrzenią nazw. Jeśli użyjesz wszystkich swoich klas w ten sposób, wówczas korzyści płynące z przenoszenia rzeczy z przestrzeni nazw do przestrzeni nazw mogą wydawać się nieistotne - co najwyżej wygrasz, posiadając prywatne dane w każdej z nich, a tym samym nieco podsumowując.

Jednak nie w tym miejscu zabłysną klasy. Zastanów się nad Stringklasą: możesz mieć te same funkcje za pomocą chartablic i niektórych funkcji statycznych. W tym momencie funkcje dają ci trochę więcej bezpieczeństwa i cukru syntaktycznego. Możesz pisać string.length()zamiast length(char_array); to nie jest wielka sprawa, ale wielu ludzi nadal to lubi. Co więcej, wiesz, że jeśli ktoś ci dał String, został utworzony za pomocą Stringkonstruktora i że musi działać z lengthfunkcją - jeśli wersja tablicowa nie może obsłużyć jakiegoś znaku, to nie ma żadnego sposobu, aby uniemożliwić ci umieszczenie go tam .

Ale wciąż nie o to chodzi. Kluczową kwestią jest to, że klasy łączą dane i funkcje, które na nich działają, i usuwają je obie. Kiedy masz metodę void f(Builder b), wiesz, że dostaniesz Builder, i możesz oczekiwać, że będzie ona wspierać określone zachowanie. Jednak nic nie wiesz o danych ani wykonywanych funkcjach - w rzeczywistości definicje obu mogą nie zostać jeszcze napisane podczas pisania i kompilacji f.

Pierwszym punktem, który należy zrozumieć, jest to, że klasy ułatwiają przekazywanie danych, jednocześnie upewniając się, że nie są uszkodzone. Po drugie, zarówno to, jakie dane, jak i jaką funkcję (implementację) ma obiekt, jest czymś o obiekcie, a nie czymś, co można po prostu powiedzieć po jego typie.

Anton Golov
źródło
0

Cały pomysł opiera się na ogólnej zasadzie dziel i zwyciężaj .
Z tego paradygmatu można korzystać prawie wszędzie; dzielisz problem na mniejsze, a następnie rozwiązujesz te małe, proste i dobrze znane problemy.
Podział programu na klasy jest jednym z rodzajów podziału, który zaczął być powszechny w ostatniej dekadzie. W tym paradygmacie programowania modelujemy nasz problem za pomocą niektórych obiektów i próbujemy rozwiązać problem, wysyłając wiadomości między tymi obiektami.
Niektórzy ludzie mogą powiedzieć, że takie podejście jest łatwiejsze do zrozumienia, rozszerzenia i debugowania.
Chociaż niektórzy się nie zgadzają :)

Rsh
źródło
0

Nie chodzi o dzielenie programu na klasy, ale o sposób modelowania aplikacji, tj. Sposób wizualizacji części aplikacji. Dzielenie rzeczy to tylko mechanizm, którego używamy do lepszego zrozumienia złożonych rzeczy. Dotyczy to nie tylko programowania. Wyobraź sobie płytkę drukowaną z wieloma splecionymi ze sobą drutami, tworzącymi złożoną strukturę z każdym drutem łączącym się gdzieś (kod spaghetti). Będziesz musiał podążać za każdym drutem do końca, aby znaleźć połączenia. Przeciwnie, wyobraź sobie przewody, które są pogrupowane i oznaczone kolorami zgodnie z ich funkcją. Łatwiej jest to naprawić.

Chodzi o to, że nie zaczynasz od długiego programu, a następnie dzielisz go na klasy. Ale najpierw modelujesz aplikację pod kątem obiektów / klas, a następnie łączysz je w celu tworzenia aplikacji.

Vamsi
źródło