Co to jest prosty proces projektowania systemu OOP przed jego zakodowaniem?

10

Ilekroć musiałem zbudować projekt, zawsze udało mi się go zbudować, nie wcześniej opracowując plan lub projekt, ale po napisaniu potrzebnej klasy, opracowując cały projekt, budując od podstaw. Teraz wiem, że nie jest to właściwy sposób tworzenia oprogramowania, ale nie jest mi łatwo owinąć głowę tym, co nazywa się analizą i projektowaniem obiektowym. Mogę łatwiej zrozumieć odgórny projekt proceduralny, ponieważ polega on jedynie na rozbiciu zadań na zadania cząstkowe, które mają swój odpowiednik w kodzie, funkcje. Ale analiza i projektowanie obiektowe nie mogę łatwo zrozumieć, ponieważ nie rozumiem, skąd można wiedzieć, jakich klas będą potrzebować i jak będą oddziaływać, chyba że będą wiedzieć, jak je kodują.

Gdy raz wprowadzimy pojęcie klas i obiektów do procesu projektowania, nie możemy już projektować odgórnie, ponieważ nie dzielimy już naszych problemów na te rzeczy, które można zaimplementować jako procedury. Zamiast tego, zgodnie z tym, co przeczytałem na ten temat, musimy określić, jakie klasy są potrzebne, i stworzyć różne artefakty w Unified Modeling Language, z których będziemy mogli korzystać podczas wdrażania oprogramowania. Ale tego rodzaju proces projektowania nie rozumiem. Bo skąd wiadomo, jakich klas będą potrzebować i jak będą wchodzić w interakcje, chyba że już wymyślili cały system?

To jest mój problem. Nie rozumiem, jak zaprojektować system obiektowy, chociaż rozumiem pojęcia programowania obiektowego i mogę korzystać z tych pojęć w dowolnym znanym mi języku programowania obiektowego. Dlatego potrzebuję kogoś, kto wyjaśni mi, jaki prosty proces mogę wykorzystać do zaprojektowania systemów zorientowanych obiektowo w sposób, który ma dla mnie sens.

g.arbia777
źródło
8
„Teraz wiem, że nie jest to właściwy sposób tworzenia oprogramowania” - kto ci to powiedział? Wydaje się, że w jakiś sposób wpadłeś w popularną pułapkę przekonania, że ​​„projektowanie jest czymś, co robisz przed kodowaniem, być może poprzez rysowanie fantazyjnych diagramów UML”. Aby wyleczyć cię z tego nieporozumienia, polecam zacząć od „Code as Design” Jacka Reevesa.
Doc Brown
@DocBrown. Czy nie uważasz, że projektowanie podczas kodowania sprawia, że ​​nasza praca jest tak rzemieślnicza? Nie wyobrażam sobie innych inżynierów działających podobnie. Wyobraź sobie architekta, pillingującego cegły i zaprawę i projektującego po drodze budynek / most.
Laiv
5
@Laiv: „kodowania” jest częścią tego, co w innych dyscyplinach inżynierskich jest zwana konstrukcja. W budownictwie domowym krok od zaprojektowania do produktu końcowego odbywa się za pomocą cegieł i zaprawy murarskiej. Podczas programowania ten krok jest wykonywany przez kompilator podczas tłumaczenia projektu (= programu) na produkt końcowy (= wykonywalny plik binarny). I to nie jest nowa mądrość. Eseje Reeves mają 25 lat.
Doc Brown
@DocBrown, programista. * Nie jest już kuratorem? Przycisk subskrypcji jest na przykład uszkodzony.
radarbob

Odpowiedzi:

20

Od góry do góry OOAD nie gwarantuje, że kod, który piszesz, jest w ogóle zorientowany obiektowo. Widziałem góry tego kodu, który jest ściśle produkowany przez OOAD. Jeśli OO Cię myli, nie szukaj tutaj pomocy. Nie znajdziesz tego. OO NIE wymaga projektowania od góry do dołu.

Jeśli lubisz nurkować w klasie, tak lubisz kodować, niech tak będzie. Pozwól, że powiem ci podpowiedź. Ociągać się.

To niesamowite, jak łatwo jest zaprojektować klasy, pisząc kod, który ich używa, nawet jeśli jeszcze nie istnieją. Zapomnij o procedurze. Zapomnij o strukturze. Po prostu zdobądź niezły poziom abstrakcji i trzymaj się go. Nie ulegaj pokusie i mieszaj w nim dodatkowe szczegóły. Wszystko, co wyciągnie cię z obecnej abstrakcji, można zrobić w jakiś sposób, który może być na innym obiekcie, który w jakiś sposób wie, co powinien wiedzieć. Nie buduj niczego, o co możesz poprosić o przekazanie ci.

Naucz się pisać w ten sposób, a przekonasz się, że robisz OO, nawet nie bardzo się starając. To zmusza Cię do spojrzenia na swoje obiekty z punktu widzenia ich wykorzystania (ich interfejsu) i tego, które obiekty wiedzą o tym, które inne obiekty. Zgadnij, jakie są główne dwa punkty diagramów UML?

Jeśli potrafisz wejść w ten sposób myślenia, pozostaje architektura. Wszyscy wciąż to rozgryzamy. Od MVC po czystą architekturę i projektowanie oparte na domenie. Studiuj je i baw się. Użyj tego, co działa. Jeśli znajdziesz coś w 100% niezawodnego, wróć i daj mi znać. Robię to od dziesięcioleci i wciąż szukam.

candied_orange
źródło
2
Albo okazuje się, że nie robisz OO, a jednak wszystko „jakoś” działa dobrze…
Derek Elkins opuścił SE
2
„To niesamowite, jak łatwo jest zaprojektować klasy, pisząc kod, który ich używa, nawet jeśli jeszcze nie istnieją” - nazywam ten odgórny projekt, ale wydaje mi się, że się mylę. Co to jest konstrukcja odgórna i jak to się nazywa? Czy programuje do interfejsu?
Piovezan
To nie jest po prostu odgórne. Musisz także chcieć nie budować rzeczy, o które możesz poprosić, akceptując parametry.
candied_orange
@Piovezan możesz to zrobić, nawet jeśli interfejs jeszcze nie istnieje. Po prostu zignoruj ​​trochę swojego kompilatora. Później sprawisz, że będzie istniał.
candied_orange
@CandiedOrange „Musisz także chcieć nie budować rzeczy, o które możesz prosić, akceptując parametry”. - Nie jestem pewien, czy rozumiem, czy mógłbyś wyjaśnić / podać krótki przykład (lub kontrprzykład w tej sprawie)?
Piovezan
4

Twierdzisz, że umiesz używać technik zorientowanych obiektowo w swoim kodzie, więc dzięki temu , że już wiesz, jak zaprojektować system zorientowany obiektowo , uważam, że twój problem polega raczej na tym, kiedy , czy nie. Wydaje się, że czujesz się komfortowo z projektowaniem obiektowym w krótkim, iteracyjnym sposobie, zamiast długoterminowego planowania.

Przy pierwszym opracowywaniu projektu planowanie i projektowanie może być bardzo trudne, wtedy bardziej zwinny rozwój jest preferowany niż tworzenie wodospadu , ponieważ duży zakres planu wodospadu często nie uwzględnia wszystkich złożoności projektu oprogramowania.

Twierdzisz, że opracowywanie w locie bez „wstępnego planu” to:

„... niewłaściwy sposób tworzenia oprogramowania ...”

Jeśli twoim problemem jest to, że twój początkowy plan nie jest wystarczająco szczegółowy, poświęć trochę więcej czasu na wyjaśnienie swoich pierwszych przemyśleń. Jaką pierwszą część programu planujesz napisać? Czego będzie potrzebował ? Być może nawet nie myśl o tym, od czego zacząć, zamiast tego zastanów się, jakie funkcje i stamtąd zacznij.

Jeśli masz problem z tym, że nie jesteś pewien swoich umiejętności dokumentowania / projektowania / UML , przećwicz dokumentowanie istniejącego projektu.

Osobiście polecam nie martwić się, że twoje projekty są idealnie zorientowane obiektowo, większość systemów nie jest w 100% zorientowana obiektowo. Celem jest lepsze zrozumienie i wizualizacja systemu, a nie idealna abstrakcja. Orientacja obiektowa to nie srebrna kula, to po prostu kolejne narzędzie na pasku.

Erdrik Ironrose
źródło
Chciałem też wspomnieć, choć nieco nie na temat odpowiedzi ... Twoje plany nie muszą być bardzo duże! Czasami plan to po prostu kwestia: „Chcę go uruchomić i coś robi”. To wystarczy, jeśli to naprawdę wszystko.
Erdrik Ironrose,
2

OOAD to utopia. Nie mam na myśli tego, że jest to najlepsze podejście, mam na myśli, że moim skromnym zdaniem nigdy tak naprawdę nie jest możliwe do osiągnięcia. Z mojego doświadczenia wynika, że ​​zawsze coś się zmienia, bez względu na to, czy są to wymagania lub specyfika, czy nawet konflikt zależności, który zmusza cię do całkowitego zastąpienia zależności. Czy to dlatego, że nauczyłem się w ten sposób, czy dlatego, że przychodzi mi najbardziej naturalnie, moje pomysły na projekt przychodzą najłatwiej, gdy piszę kod. Jeśli mam zamiar napisać kod i nie mam jasnego pojęcia, jak go ustrukturyzować, postanowię poświęcić czas na prawdziwe zrozumienie problemu, chociaż częściej widzę konieczność na zajęcia i dam radę.

Moja rada jest taka, że ​​najlepszą rzeczą, jaką możesz zrobić dla siebie, jest kodowanie za pomocą fasad , zapewniające prosty interfejs dla danych wejściowych i wyjściowych, i mam nadzieję, że dane wejściowe i wyjściowe nie zmieniają się często. Chociaż nawet jeśli tak, wiedzą, że nie jest to problem projektowy, ale problem specyfikacji (zmiana konieczności / działania / funkcjonalności). To sprawi, że twój program będzie nieco odporny na problemy rezonujące w twoim programie w stosunku do tych, którzy wywołują twój program lub sekcję kodu i odwrotnie.

Jeśli chodzi o projektowanie systemu obiektowego, należy coś powiedzieć o próbie uczynienia wszystkiego zorientowanym obiektowo, kiedy nie powinno. Jest to powszechny błąd wśród języków programowania OOP, takich jak C #, a Java polega na próbie traktowania wszystkiego jako obiektu, co często skutkuje utworzeniem pojedynczej instancji klasy w celu wykonania metod, które w przeciwnym razie byłyby metodami statycznymi, które nie zmieniałyby żadnego stanu. To powiedziawszy, oczywiście powinieneś używać projektowania OOP tam, gdzie ma to zastosowanie, ale nie myśl, że robisz to źle, gdy pisanie metody statycznej jest bardziej naturalne. Nie zawsze jest to zły instynkt.

Powinieneś rozważyć skorzystanie z klasy, kiedy odpowiesz „tak” na którekolwiek z poniższych pytań:

  • Czy mam grupę informacji dotyczących tego samego pojęcia (tj. Imię, nazwisko, adres)?
  • Czy muszę wykonać operację wymagającą kilku informacji (tj. calculatePrice(basePrice, quantity, tax))?
  • Czy mam coś innego, jeśli duże bloki kodu wykonują nieco inne operacje z tymi samymi lub podobnymi informacjami (tj. if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak())
  • Czy mam istniejącą klasę, która wykonuje więcej niż jedno konkretne zadanie i staje się nieco za duża?

Po chwili tworzenie drugiej klasy stanie się drugą naturą. Nie obawiaj się ich używać, jeśli Twój kod mieści się w jednym z powyższych przypadków. Mam nadzieję że to pomogło!

Neil
źródło
2

Myślę, że uwagi doktora Browna w komentarzach zasługują na znacznie większą widoczność niż komentarz, ponieważ ma absolutną rację:

Teraz wiem, że nie jest to właściwy sposób tworzenia oprogramowania ” - kto ci to powiedział? Wydaje się, że w jakiś sposób wpadłeś w popularną pułapkę przekonania, że ​​„projektowanie jest czymś, co robisz przed kodowaniem, być może poprzez rysowanie fantazyjnych diagramów UML”. Aby wyleczyć cię z tego nieporozumienia, polecam zacząć od „Code as Design” Jacka Reevesa. - Doc Brown 21 czerwca o 5:27

@Laiv: „kodowanie” jest częścią tego, co w innych dyscyplinach inżynieryjnych nazywa się projektowaniem. W budownictwie domowym krok od zaprojektowania do produktu końcowego odbywa się za pomocą cegieł i zaprawy murarskiej. Podczas programowania ten krok jest wykonywany przez kompilator podczas tłumaczenia projektu (= programu) na produkt końcowy (= wykonywalny plik binarny). I to nie jest nowa mądrość. Eseje Reeves mają 25 lat. - Doc Brown 21 czerwca o 6:39

Ten sam sentyment odbija się także w innych miejscach. Rozważ przemówienia Glenna Vanderburga na temat „Inżynierii prawdziwego oprogramowania”, a do pewnego stopnia jego „Rzemiosło, inżynieria i esencja programowania” oraz „Rzemiosło i inżynieria oprogramowania”. Weź również pod uwagę strony / dyskusje WhatIsSoftwareDesign i TheSourceCodeIsTheDesign na wiki wiki C2.

Koncepcja kodu będącego projektem nie jest specyficzna dla żadnego paradygmatu. Może być stosowany w równym stopniu do obiektowego, funkcjonalnego, proceduralnego, logiki lub cokolwiek innego. Pomysł jest taki sam - projekt jest samym kodem źródłowym. Akt konstrukcyjny to proces, w którym kod źródłowy (projekt) zamienia się w użyteczną rzecz przez interpretera lub kompilatora.

W złożonym systemie prawdopodobnie istnieje pewien projekt architektoniczny na wyższym poziomie - identyfikujący podsystemy, komponenty, moduły, usługi i przydzielający im wymagania przed rozpoczęciem pisania kodu. Możesz używać UML jako sposobu na tworzenie, dokumentowanie i pomoc w dyskusjach wokół tego projektu architektonicznego. Rozważ ideę trybów UML omawianą przez Martina Fowlera , szczególnie UML jako Szkic i UML jako Notatki . Również rozważyć kilka pomysłów z Agile Modeling - Początkowa Architecture Modeling , iteracja Modelowania i ledwo dobre modele Wystarczające .

Wszystko to oznacza, że ​​właściwym sposobem na zbudowanie oprogramowania nie jest opracowanie całego projektu. Ma spędzić wystarczająco dużo czasu na zrozumieniu najbardziej krytycznych (w danym momencie) wymagań, zidentyfikowaniu technicznych zależności i kompromisów między wymaganiami, a następnie skorzystaniu z faktu, że oprogramowanie jest miękkie. Należy również pamiętać, że koszt podjęcia projektu i wyprodukowania czegoś jest niewiarygodnie niski (szczególnie w porównaniu z wykonaniem projektu i wyprodukowaniem czegoś w wielu innych dyscyplinach inżynierskich). Powtórz więc swoje działania związane z projektowaniem (kodowaniem) i skorzystaj z tego, jak łatwe i tanie jest stopniowe budowanie lub modyfikowanie tego, co zrobiłeś.

Thomas Owens
źródło
1

OOAD polega na identyfikowaniu bytów i modelowaniu rzeczywistych obiektów lub koncepcji do pewnego stopnia abstrakcji. Będziesz postrzegał to jako łatwiejsze, jeśli zamiast pisać klasy, najpierw napisz interfejsy, ponieważ tak naprawdę nie musisz ich jeszcze implementować, ale kod się kompiluje.

OOAD nie wyklucza możliwości myślenia w systemie jako dużych modułów. Nadal możesz to zrobić. Każdy moduł istnieje, aby zaspokoić zestaw historii użytkowników (przypadki użycia). Takie historie użytkowników wymagają klas, które współpracują w celu ich spełnienia.

Jedną z kluczowych różnic między podejściami proceduralnymi a OO jest to, że zwykle myślenie proceduralne odwzorowuje wymagania na ekrany, podczas gdy OOD ma tendencję do myślenia o tym, co dzieje się pod maską, pozostawiając przód innej osoby lub w sposób inny niż OO.

W Programowaniu Ekstremalnym istnieje technika o nazwie Karty CRC . CRC oznacza „klasowych współpracowników”.

Zasadniczo identyfikujesz oczywiste klasy i przypisujesz kartę do każdej z nich. Powiedzmy, że klasa Invoicema własną kartę.

Dla każdej klasy trzymającej karty piszesz, jaka byłaby odpowiedzialność tej klasy, na przykład „oblicza sumę całkowitą” .

Również dla każdej klasy trzymającej kartę piszesz, o co inne klasy muszą poprosić o coś, aby wypełnić swoje własne obowiązki. Tutaj możesz odkryć Invoicepotrzebę współpracy, InvoiceDetaila nawet odkryć, że taka klasa jest potrzebna w pierwszej kolejności.

Możesz odkryć, że niektóre obowiązki, do których Twoim zdaniem należały Invoce, naprawdę należą do jednego z jego współpracowników.

Po ćwiczeniu każda karta staje się klasą, każda odpowiedzialność staje się metodą, a każda relacja współpracy może stać się kompozycją, agregacją lub zwykłym wezwaniem.

Ćwiczenie to można (i należy) wykonać w grupie, w której uczestniczą nawet ludzie biznesu.

Możesz dowiedzieć się więcej o tej technice w tych linkach:

http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

Przykłady kart CRC:

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Tulains Córdova
źródło
0

Podstawowym wyzwaniem dla nas, jako społeczności praktyków oprogramowania; a ściślej rzeczoznawcy projektowania, polegają na zmaterializowaniu wszystkich naszych problemów / zadań w części programistycznej. Czy to zadania - reprezentowane jako funkcje, czy też aktorzy zadań - reprezentowane jako interfejsy / klasy [w kierunku OOAD]. W miarę rozwoju naszych nawyków związanych z projektowaniem oprogramowania, stale zdobywamy wiedzę na temat różnych metodologii / frameworków. Nasz punkt widzenia jest coraz bardziej dopracowywany w celu wyraźnego rozdzielenia obiektów i tego, który obiekt spełniałby jaką funkcję.

Jeśli chodzi o dzielenie swoich problemów na podproblemy z obecnością przedmiotów w pobliżu, nadal możesz to zrobić wygodnie, ponieważ TY masz całkowitą kontrolę nad tym, które wszystkie obiekty chcesz być obecne. Masz również wygodę przekazywania natury i celu swoim przedmiotom i interfejsom. Wystarczy wizualizować opis problemu i zastanowić się, jaki cel / funkcjonalność można przypisać do danego obiektu.

Spróbuję wyjaśnić dalej za pomocą przykładu gamy samochodów i przedstawię dwa różne sposoby wizualizacji tego samego modelu obiektowego.

Weźmy przykład producenta samochodów, który obejmuje różne kategorie samochodów: pojazdy użytkowe, samochody konsumenckie (sedany, hatchbacki, kombi) itp.

Aby producent miał wyraźny podział na kategorie i cele, istnieje wiele sposobów, dzięki którym mogą tworzyć tam klasy.

Producent pojazdu OOAD

  1. W oparciu o kategorię (sektor rynku) pojazdu: pojazd ciężki, pojazd użytkowy [sedan, hatchback, kombi itp.]

  2. Na podstawie pojemności silnika i sposobu jazdy: 800-1500 CC,> 1500 CC itp.

Wybierając najlepszy sposób, w jaki producent może indywidualnie nadawać funkcje obiektom należącym do każdej z tych klasyfikacji, może wybrać odpowiedni projekt obiektu leżącego u jego podstaw i zbudować na nim model.

Akash Mishra
źródło
Zaczynasz dobrze, ale ostatni kawałek wygląda na błąd, że OOD polega na kategoryzacji rzeczy, a nie na grupowaniu podobnych zachowań.
Pete Kirkham