Jak faktycznie dowiedzieć się, co należy zrobić w projektowaniu obiektowym?

12

Najpierw zastrzeżenie: Naprawdę nie wiem, czy to pytanie pasuje do tej witryny, ale nadal uważam to za istotne pytanie nie tylko dla mnie, ale dla innych osób, które są początkujące. Jeśli pytanie można poprawić, aby pasowało tutaj, proszę zaznaczyć int komentarze. Jeśli to nie pasuje, daj mi również znać, a jeśli to możliwe, daj mi znać, gdzie można to omówić, ponieważ nie znalazłem żadnych dobrych forów na ten temat.

Nauczyłem się programować w 2009 roku, kiedy studiowałem PHP. Później w 2012 roku przeniosłem się do C # i .NET. W każdym razie kodowanie nie jest problemem, zapisywanie algorytmów nie jest moim problemem. Mój rzeczywisty problem polega na tym, aby wiedzieć, co należy zakodować, aby osiągnąć wymaganie, i gdzie należy go zakodować.

Większość kursów dostępnych w Internecie dotyczy tego, jak - jak pisać kod w określonym języku, jak korzystać z niektórych zestawów interfejsów API itp. Nie o to mi chodzi.

Przez te lata dużo czytałem o wielu rzeczach: analiza i projektowanie obiektowe, wzorce projektowe, projektowanie oparte na domenie i tak dalej. Rozumiem na przykład zasady SOLID, niektóre z głównych idei DDD, takie jak konieczność zaangażowania ekspertów w dziedzinie, rozwój wszechobecnego języka i tak dalej. Odważyłbym się powiedzieć, że mam przynajmniej teoretyczne podstawy.

Ale jeśli chodzi o praktykę, czuję się jak katastrofa. Jakiś czas temu musiałem kontynuować rozwój systemu finansowego, który był już opracowywany przez kogoś innego. Jest to rodzaj „starego systemu” opracowanego przy użyciu C # i WinForms. Po raz pierwszy wybrałem projekt o prawdziwej złożoności domen, z wieloma regułami biznesowymi i tak dalej.

Przyznaję, że kiedy otrzymuję wymagania przez większość czasu, myślę „jak, u licha, można to zrobić?” - Nie mam pojęcia, jak zacząć pracę nad wymaganiami, aby dowiedzieć się, co należy zrobić. Uważam, że moje główne nieporozumienia dotyczą tego, co muszę kodować, jakie klasy, interfejsy i gdzie idzie każda logika, na której klasie musi być każda rzecz. Problem polega na tym, że nie wiem od czego zacząć.

Przez większość czasu, z dość dużą ilością przemyśleń, kończę na kilku pomysłach, ale nigdy nie wiem, jak ocenić, czy mój pomysł jest poprawny, czy nie.

Mam na myśli, że nie sądzę, że to brak teorii, ponieważ powiedziałem, że przeczytałem o wielu rzeczach na temat architektury oprogramowania i orientacji obiektu, które mi zalecono, ale nie pomogło to w określeniu, co należy zrobić w praktyce .

W jaki sposób można nauczyć się naprawdę zrobić obiektowego projektowania? Chcę się nauczyć: podane wymagania wiedzą, jak rozpocząć pracę nad nimi w procesie, który prowadzi do ustalenia, co należy zrobić i gdzie należy każdy fragment kodu. Jak mogę nauczyć się oceniać, czy mój pomysł jest poprawny, czy nie?

Uważam, że pełne wyjaśnienie tego jako odpowiedzi tutaj nie byłoby możliwe. To, czego szukam, może być zgodne ze stylem strony, to odpowiedzi, które dają przegląd i wskazanie pewnych referencji (książek, kursów online itp.), Które można wykorzystać do rozwinięcia pomysłów i prawdziwej nauki tych rzeczy.

użytkownik1620696
źródło
1. Czy rozumiesz już wszystkie podstawowe koncepcje języka C #, w tym rzeczy takie jak różnica między przeciążeniem operatora a nadpisaniem operatora, czym jest klasa abstrakcyjna i czym różni się od interfejsu, enkapsulacji, polimorfizmu itp.? Znajomość tych rzeczy w pierwszej kolejności jest niezbędna do pełnego zrozumienia OO w C #. Zobacz c-sharpcorner.com/technologies/oop-ood .
Robert Harvey
2
2. Starsze aplikacje napisane w Winformach zwykle zamieniają się w duże kule błota, chyba że są odpowiednio zaprojektowane. Rozdzielenie obaw staje się najważniejsze. Zobacz winformsmvp.codeplex.com
Robert Harvey
1
Tak naprawdę nie ma procesu. W projektowaniu chodzi przede wszystkim o to, jak się organizować, co wiąże się z doświadczeniem. Zasady SOLID są dobrym początkiem, ale nie wystarczą, a ludzie gubią się w SOLID i zapominają, dlaczego te zasady istnieją.
Robert Harvey
1
Zacznij mało. Wymagania to problemy. Jeden problem może być tak duży, jak „Chcemy stworzyć następną stronę Stackexchange” lub tak mało, jak „chcemy, aby nasza następna Stackexchange miała login”. Zamień duży problem w wielu, ale mniejszych. Ogólnie rzecz biorąc, daj sobie szansę zrobienia rzeczy „źle” i poprawy z czasem.
Laiv
1
Chcę jednocześnie głosować i vtc to ...
svidgen

Odpowiedzi:

21

Jak mogę się nauczyć projektowania obiektowego? Chcę się nauczyć: podane wymagania wiedzą, jak rozpocząć pracę nad nimi w procesie, który prowadzi do ustalenia, co należy zrobić i gdzie należy każdy fragment kodu. Jak mogę nauczyć się oceniać, czy mój pomysł jest poprawny, czy nie?

Po pierwsze, przestań myśleć o projektowaniu obiektowym jako poprawnym. To tak, jakby myśleć o angielskim jako poprawnym.

Zorientowany obiektowo paradygmat jest nieprawidłowy. Ma pewne zalety i wady. To jest ideał. To nie jest nasz jedyny. To lepsze niż nic, ale na pewno nie wszystko.

Koduję od dziesięcioleci. Studiowałem te rzeczy prawie tak długo, jak istniały pomysły. Wciąż uczę się, co to znaczy. Eksperci wciąż uczą się, co to znaczy. Całe nasze pole ma mniej niż 100 lat.

Więc kiedy weźmiesz stos wymagań i okaże się, że kod je spełnia, a mimo to czujesz, że napisany kod to tragiczny bałagan, nie jesteś sam. Działający kod jest po prostu pierwszym krokiem do doskonałego kodu. Kod, który nie tylko działa, ale który inni mogą łatwo odczytać i zrozumieć. Kod, który można szybko dostosować, gdy zmieniają się wymagania. Kod, który sprawia, że ​​chcesz usiąść i powiedzieć „Wow, to takie proste”.

Problem polega na tym, że nie otrzymujemy zapłaty za to wszystko. Robimy to wszystko, ponieważ jesteśmy profesjonalistami. Musimy zrobić to wszystko, gdy szef nie patrzy, ponieważ zawsze jest termin. Ale chcemy wrócić za 5 lat i powiedzieć początkującym: „O tak, napisałem to. Nadal działa, prawda? Fajnie”.

Jak się tam dostałeś? Ćwiczyć. Nie akceptuj ŻADNEGO pomysłu na wiarę. Ktoś nie chce się zamykać na temat tego, jak projektowanie sterowane zdarzeniami uprości ten projekt? Nie jesteś pewien, czy mają rację? Zbuduj własny projekt zabawki w domu, który wykorzystuje wzorzec obserwatora. Bałagan z tym. Spróbuj znaleźć rzeczy, w których NIE pomaga.

Czytać. Pytanie. Test. Powtarzać.

Kiedy dojdziesz do tego, że robisz to przez 80% swojego życia, będziesz tak samo zdezorientowany jak ja.

Przyznaję, że kiedy otrzymuję wymagania przez większość czasu, myślę „jak, u licha, można to zrobić?” - Nie mam pojęcia, jak zacząć pracę nad wymaganiami, aby dowiedzieć się, co należy zrobić. Uważam, że moje główne nieporozumienia dotyczą tego, co muszę kodować, jakie klasy, interfejsy i gdzie idzie każda logika, na której klasie musi być każda rzecz. Problem polega na tym, że nie wiem od czego zacząć.

Czułam to samo. Potem odkryłem radość z refaktoryzacji. Chętnie dostosowuj projekty podczas pisania kodu. Trudnym sposobem jest wypracowanie wszystkiego na papierze. Napisz kod, który można udowodnić, że jest błędny, udowodnij, że jest błędny i napraw go.

candied_orange
źródło
2
To świetna odpowiedź. Programuję od 15 lat i dodam, że cała dziedzina inżynierii oprogramowania (mój zawód) jest „niewyraźna” - to połączenie sztuki i funkcji, a zależnie od dewelopera jest więcej niż jedno. Mogę wymyślić pomysł na architekturę na papierze, ale nie mogę nigdy dopracować szczegółów projektu OO, dopóki nie popadnę w błoto, nie zepsuję się i nie znajdę, co działa, a co nie.
jropella
Dziękuję za odpowiedź! Więc masz na myśli: kiedy mamy co najmniej jedno rozwiązanie do wdrożenia wymagania, a ono działa, wdrażamy je, a następnie, gdy widzimy, jak odnosi się to do drugiego kodu i innych wymagań, dokonujemy refaktoryzacji, aby było lepiej? Ale wciąż są sytuacje, w których otrzymuję pewne wymagania i nie mam pojęcia, jak zacząć. Czy w takich przypadkach masz jakieś porady, jak zacząć? Czasami uważam, że najlepiej byłoby omówić wymagania i możliwe wdrożenia, ale pracuję sam. Czy istnieje forum, na którym taka dyskusja jest mile widziana?
user1620696
2
Po pierwsze, przestań pracować sam. Nawet posiadanie nieświadomego początkującego, który spowalnia cię do wyjaśniania rzeczy, jest lepsze niż to. Po drugie naucz się rozkładać wymagania na części. Rób to tak długo, aż będziesz mieć coś, co da się opanować. W razie potrzeby napisz kod potwierdzający koncepcję w zupełnie innym środowisku. Po prostu zrób coś, co wyraża twoje zrozumienie tego, co jest potrzebne. Następnie przetestuj to wyrażenie. Uważasz, że dokonałeś złych założeń. Dobre. Bądź gotów je zmienić.
candied_orange
1

Rozwój oprogramowania sprowadza się do dostarczenia działającego oprogramowania na czas, zgodnie z budżetem, przy jednoczesnym spełnieniu wszystkich kryteriów akceptacji. Zakładając, że udało ci się to zrobić, postrzegana jakość kodu lub jego struktury jest kwestią drugorzędną.

Problem polega oczywiście na tym, że pisanie nowego kodu Greenfield jest zwykle znacznie tańsze i łatwiejsze niż utrzymywanie starszego kodu, więc zamiast być zbytnio rozłączonym z jakością kodu lub architekturą, pamiętaj, że twoim prawdziwym problemem jest łatwość konserwacji.

Zazwyczaj kod uważa się za możliwy do utrzymania, gdy koszty, czas i ryzyko związane ze zmianą tego kodu są wystarczająco niskie, aby naprawianie błędów lub wprowadzanie zmian w wymaganiach było nadal opłacalne, a przez wdrożenie tych zmian nie utrwala się „spirali śmierci” „entropii kodu.

I odwrotnie, kod jest uważany za niemożliwy do utrzymania, gdy nie można z ufnością zmienić lub zrefaktoryzować bez poważnego ryzyka uszkodzenia lub poświęcenia nadmiernej ilości czasu / pieniędzy, aby upewnić się, że nic nie jest zepsute - tj. Gdy czas, koszty i ryzyko związane z pracą z tym kodem wynosi nieproporcjonalnie wysoki w porównaniu z korzyściami wynikającymi ze zmian (tj. pracodawca lub klient nie traci pieniędzy dodając nowe funkcje, naprawiając błędy itp.)

Pamiętaj, że nawet najbardziej diaboliczny bałagan spaghetti może być potencjalnie możliwy do utrzymania, jeśli masz wystarczająco dużo zapasów wokół bałaganu, aby uchronić się przed przełamywaniem zmian (chociaż takie przypadki są rzadkie). Problem z bałaganem spaghetti polega na tym, że ochrona przed przełamywaniem zmian jest zwykle dość droga i nieefektywna - zwłaszcza jeśli robisz to z mocą wsteczną.

Być może najbardziej niezawodnym sposobem na upewnienie się, że napisałeś możliwy do utrzymania kod, jest napisanie (tam, gdzie jest to racjonalnie możliwe) odpowiedniego zestawu automatycznych testów jednocześnie (przy jednoczesnym pełnym wykorzystaniu wszelkich innych dostępnych narzędzi analizy statycznej).

Nie musisz szczególnie przestrzegać ścisłej metodologii programistycznej, takiej jak TDD / BDD, aby uzyskać wystarczającą liczbę zautomatyzowanych testów umożliwiających dokonanie refaktoryzacji; potrzebujesz tylko tyle, aby zabezpieczyć kod przed przypadkowymi zmianami w przyszłości.

Jeśli Twój kod jest objęty automatycznymi testami, możesz zrelaksować się przy jego projektowaniu i strukturze, wiedząc, że jesteś objęty tymi testami; w późniejszym terminie możesz agresywnie zrefaktoryzować lub nawet wyrzucić go i zacząć od nowa.

To nasuwa pytanie, jak napisać łatwo testowalny kod; jest to zazwyczaj główny argument przemawiający za przestrzeganiem zasad SOLID; w rzeczywistości cechą kodową, która jest zgodna z zasadami SOLID, jest to, że pisanie testów jednostkowych jest łatwe i oszczędne czasowo / kosztowo.

Oczywiście czasami nie masz czasu na pisanie testów jednostkowych; jeśli jednak napisałeś cały kod, pamiętając o pytaniu „Jak napisać w tym celu automatyczne testy?” (nawet jeśli nie wdrożyłeś tych testów), prawdopodobnie udało ci się również znaleźć projekt, który można w rozsądny sposób utrzymać.

Ben Cottrell
źródło
1
nigdy nie mamy czasu na pisanie testów automatycznych, ale zawsze mamy ciągłe testy ręczne ...
Nick Keighley
Podobnie, nigdy nie mamy czasu na napisanie kodu „poprawnie” i „czysto” za pierwszym razem, ale wydaje się, że mamy nieskończony czas, aby wracać i naprawiać go w kółko, z powodu błędnego, ale tak rozpowszechnionego sposobu myślenia przedstawionego w ten post.
Dunk
@Dunk Nie sądzę, że realistyczne jest oczekiwanie, że kod nigdy nie powinien ulec zmianie ani zostać ponownie odwiedzony. Praktyki testowania jednostkowego i wytyczne SOLID polegają na zachęcaniu do praktyk, które powodują, że kod jest łatwy i tani do zmiany, gdy zajdzie nieunikniona sytuacja - np. Ktoś znajduje naprawdę dziwny, niejasny błąd, którego deweloper nie rozważał w tym czasie lub klient widzi rozwiązanie i zmienia wymagania, a nawet oryginalny kod zawierał błędy, ponieważ programiści są tylko ludźmi; a może deweloper źle zrozumiał wymagania lub odkrył nieznane wcześniej ograniczenia techniczne ...
Ben Cottrell
1
@BenCottrell - całkowicie się zgadzam. Kod zawsze będzie wymagał rewizji. Jednak z tego powodu ludzie wskazują, że należy poświęcić czas na wykonanie „wstępnego projektu” i napisanie nieco „czystego kodu” jako pewnego rodzaju niepowodzenia. Używają mantry „na czas” i „na budżet”, aby usprawiedliwić zły kod / projekt. Możesz użyć wszystkich „praktyk”, które chcesz, ale nie kupi ci „kodu, który można łatwo i tanio zmienić” bez dobrego projektu i stosunkowo „czystego kodu” na początek. Dobry projekt i „czysty kod” będą skutkiem ubocznym faktycznego osiągnięcia celu na czas i budżetu.
Dunk
@Dunk To brzmi jak mówisz, że wielu programistów po prostu nie dba o jakość kodu, co nie wydaje mi się, że tak jest zwykle. W rzeczywistości myślę, że istnieją dwa większe problemy - po pierwsze, podczas gdy programiści mogą być tymi, którzy podają szacunkowy budżet i termin, szacunki mogą łatwo okazać się błędne. Po drugie, interesariusze projektu mają decydujący wpływ na czas / koszty, co oznacza, że ​​ryzyko, budżet i terminy przeważają nad problemami technicznymi. Biorąc pod uwagę wybór między „zdecydowanie spóźnionym / nadmiernym budżetem” lub „potencjalnie złym kodem”, zainteresowane strony często wybierają ten drugi.
Ben Cottrell,