Ten post został ostatnio edytowany przez Summer 27.9.2017 o 15:32
Ten artykuł to opowiadanie naśladujące Q&A, a autor używa humorystycznego stylu, by krótko przeanalizować pracę architektów: chcę zostać architektem oprogramowania. To świetna opcja dla młodych programistów. Chcę kierować zespołem i podejmować ważne decyzje dotyczące baz danych i frameworków, serwerów internetowych itd. Och, to w ogóle nie chcesz być architektem oprogramowania. Oczywiście chciałam podejmować ważne decyzje. To w porządku, ale nie uwzględniasz ważnych decyzji na liście, które są nieistotne. Co masz na myśli? Czy mówisz, że bazy danych to nie ważne decyzje, czy wiesz, ile na nie wydajemy? Może to kosztuje za dużo. Jednak bazy danych nie należą do najważniejszych decyzji. Jak możesz tak mówić? Baza danych jest rdzeniem systemu, gdzie wszystkie dane są systematyzowane, klasyfikowane, indeksowane i dostępne. Bez bazy danych nie byłoby systemu. Baza danych to po prostu urządzenie IO, które oferuje przydatne narzędzia do klasyfikacji, zapytań i raportowania informacji, ale są to jedynie funkcje pomocnicze architektury systemu. Pomoc? To jest skandal. Dokładnie, to jest pomocnicze. Zasady biznesowe systemu mogą wykorzystywać niektóre z tych narzędzi, ale te narzędzia nie są wpisane w odpowiednie reguły biznesowe. Jeśli zajdzie taka potrzeba, możesz wymienić istniejące na inne narzędzia; A zasady biznesowe się nie zmienią. No tak, ale musiało to zostać przekodowane, bo te narzędzia były używane w oryginalnej bazie danych. To twój problem. Co masz na myśli? Twój problem polega na tym, że uważasz, iż zasady biznesowe zależą od narzędzi bazodanowych, ale tak nie jest. A przynajmniej nie powinno tak być, dopóki nie zostanie dostarczona dobra architektura. To po prostu szaleństwo. Jak tworzyć zasady biznesowe, które nie wykorzystują tych narzędzi? Nie twierdzę, że nie korzystają z narzędzi bazodanowych, ale nie są od nich zależni. Zasady biznesowe nie muszą wiedzieć, z jakiej bazy danych korzystasz. Jak więc uzyskać zasady biznesowe, nie wiedząc, jakich narzędzi używać? Odwróć zależności tak, aby baza danych zależała od reguł biznesowych. Upewnij się, że reguły biznesowe nie zależą od bazy danych. Mówisz bzdury. Wręcz przeciwnie, używam języka architektury oprogramowania. To jest zasada odwrócenia zależności: standardy niskiego poziomu powinny opierać się na standardach wysokich poziomów. Bzdura! Kryteria wysokiego poziomu (zakładając odwoływanie się do zasad biznesowych) Wywoływanie kryteriów niskiego poziomu (zakładając, że odnosi się do baz danych). Dlatego kryterium wysokiego poziomu opiera się na kryterium niskiego poziomu zgodnie z zasadą, że dzwoniący zależy od osoby wzywanej. Wszyscy o tym wiedzą! To prawda w czasie działania. Ale podczas kompilacji chcemy inwersji zależności. Kod źródłowy wytycznych wysokiego poziomu nie powinien zawierać kodu źródłowego wytycznych niskiego poziomu. Daj spokój! Jak możesz podjąć decyzję, nie wspominając o tym? Oczywiście, że nie ma problemu. Na tym polega zorientowanie obiektowe. Orientacja obiektowa polega na tworzeniu modeli w rzeczywistym świecie, łączącym dane, funkcjonalność i spójne obiekty. Chodzi o organizowanie kodu w intuicyjną strukturę. Tak mówią? Jak wszyscy wiemy, to oczywista prawda. Tak, jednak przy użyciu wytycznych obiektowych można je wywołać bez wspominania o tym. No to jak to zrobić? W projektowaniu obiektowym obiekty wysyłają sobie nawzajem wiadomości. Oczywiście, że tak. Gdy nadawca wysyła wiadomość, nie zna typu odbiorcy. To zależy od użytego języka. W Javie nadawca zna przynajmniej podstawowy typ odbiorcy. W Ruby nadawca przynajmniej wie, że odbiorca jest w stanie obsłużyć otrzymane wiadomości. Zgadza się. W każdym razie nadawca nie zna konkretnego typu odbiorcy. Dokładnie, no właśnie. Dlatego nadawca może zaprojektować odbiornik tak, aby wykonywał określoną funkcję, nie podając konkretnego typu odbiornika. Zgadza się, zgadza się. Rozumiem. Jednak nadawca nadal zależy od odbiorcy. To prawda w czasie działania. Jednak jest inna po skompilacji. Kod źródłowy nadawcy nie wspomina ani nie zależy od kodu źródłowego odbiorcy. W rzeczywistości kod źródłowy odbiorcy zależy od kodu źródłowego nadawcy. W żadnym bądź razie! Nadawca nadal zależy od klasy, którą wysyła. Może z jakiegoś kodu źródłowego będzie to wyraźniejsze. Poniższy akapit został napisany w Javie. Na początek to nadawca: nadawca paczek; public class Sender { prywatny odbiorca odbiorcy; publiczny Nadawca (Odbiorca r) { odbiorca = r; } public void doCoś () { receiver.receiveThis (); } public interface Receiver { void receiveThis (); } }Oto odbiornik: odbiornik pakietu; Nadawca importujący. Nadawca; klasa public SpecificReceiver implementuje Sender.Receiver { public void receiveThis () { //do something interesting. } }Uwaga: Odbiorca zależy od nadawcy, SpecyficznOdbiorca zależy od nadawcy, a w nadawcy nie ma informacji związanych z odbiorcą. Tak, ale kłamiesz, umieszczasz interfejs odbiorcy w klasie nadawcy. Zaczynasz rozumieć. Co ty wiesz? Oczywiście, to zasada architektury. Nadawca ma interfejs, który odbiorca musi zaimplementować. Jeśli to oznacza, że muszę używać klas zagnieżdżonych, to ...... Zagnieżdżone klasy to tylko jeden ze środków do celu, są też inne sposoby. No to chwileczkę. Co to ma wspólnego z bazami danych? Zaczęliśmy rozmawiać o bazach danych. Przyjrzyjmy się temu kodowi trochę bliżej. Pierwsza to prosta zasada biznesowa: pakiety biznesoweReguły; importować podmioty. Coś; public class BusinessRule { prywatna brama BusinessRuleGateway; public BusinessRule (brama BusinessRuleGateway) { this.gateway = brama; } public void execute (String ID) { gateway.startTransaction (); Something thing = gateway.getSomething (id); thing.makeChanges (); gateway.saveSomething (rzecz); gateway.endTransaction (); } }Zasady biznesowe nie mają dużej wagi. To tylko jeden przykład. Mogłoby istnieć więcej takich klas implementujących różne reguły biznesowe. Dobrze, czym dokładnie jest Gateway? Zapewnia wszystkie metody dostępu do danych poprzez reguły biznesowe. Zaimplementuj ją w następujący sposób: pakiety biznesoweReguły; importować podmioty. Coś; public interface BusinessRuleGateway { Something getSomething (identyfikator ciągu znaków); void startTransaction (); void saveSomething (Coś Thing); void endTransaction (); }Uwaga: To dotyczy Reguł biznesowych. Dobra, czym jest klasa Something? Reprezentuje prosty obiekt biznesowy. Umieszczam to w bytach. podmioty pakietowe; public class Something { public void makeChanges () { //... } }Ostatecznie implementacja BusinessRuleGateway, ta klasa zna prawdziwą bazę danych: baza pakietów; import businessRules.BusinessRuleGateway; importować podmioty. Coś; public class MySqlBusinessRuleGateway implementuje BusinessRuleGateway { public Something getSomething (String id) { // użyj MySql, aby uzyskać thing. } public void startTransaction () { // start MySql transaction } public void saveSomething (Something) { // save thing in MySQL } public void endTransaction () { // end Transakcja MySQL } }Dodatkowo należy zauważyć, że reguły biznesowe wywołują bazę danych w czasie działania; Jednak w czasie kompilacji baza danych obejmuje i zależy od reguł biznesowych. Myślę, że rozumiem. Używasz polimorfizmu, by ukryć fakt, że baza danych jest zaimplementowana przed regułami biznesowymi. Jednak nadal potrzebny jest interfejs, który zapewni wszystkie narzędzia bazodanowe regułom biznesowym. Nie, wcale nie. Nie próbowaliśmy dostarczać narzędzi bazodanych do reguł biznesowych. Zamiast tego korzystają z reguł biznesowych do tworzenia interfejsów dostosowanych do potrzeb. Wdrożenie tych interfejsów pozwala wywołać odpowiednie narzędzia. Tak, ale jeśli musisz używać wszystkich narzędzi do wszystkich reguł biznesowych, to po prostu umieść narzędzie w interfejsie bramy. Ach, chyba nadal nie rozumiesz. Rozumieć co? To już jest jasne. Każda reguła biznesowa definiuje tylko jeden interfejs dla potrzebnych narzędzi do dostępu do danych. Poczekaj chwilę, co powiesz? To jest zasada segregacji interfejsów. Każda klasa reguł biznesowych korzysta tylko z określonych funkcji bazy danych. Dlatego interfejsy udostępniane przez każdą regułę biznesową mogą uzyskać dostęp tylko do odpowiednich obiektów. Oznacza to jednak, że istnieje wiele interfejsów i wiele małych klas implementacyjnych, które wywołują inne klasy bazy danych. Świetnie, zaczynasz rozumieć. Ale to zbyt chaotyczne i strata czasu. Dlaczego to robić? To jest zorganizowane i oszczędza czas. No dalej, zdobądź dużo kodu dla samego kodu. Wręcz przeciwnie, nieistotne decyzje mogą być opóźnione przez ważne decyzje architektoniczne. Co to oznacza? Pamiętam, że na początku mówiłeś, że chcesz zostać architektem oprogramowania, prawda? Chcesz podejmować wszystkie decyzje, które naprawdę się liczą. Tak, właśnie tak myślałem. Chcesz podejmować decyzje dotyczące baz danych, serwerów internetowych i frameworków, prawda? Tak, mówisz, że to wszystko nie ma znaczenia. Po prostu nieistotne treści. Zgadza się. To wszystko. Ważne decyzje podejmowane przez architektów oprogramowania to te, które pozwalają podejmować decyzje dotyczące baz danych, serwerów internetowych i frameworków. Ale najpierw musisz zdecydować, które z nich! Nie, to nie działa. W rzeczywistości można je rozstrzygnąć później w cyklu rozwoju, gdy informacji jest więcej. Katastrofą jest, jeśli architekci identyfikują frameworki z wyprzedzeniem, tylko po to, by okazać się, że nie zapewniają one wymaganej wydajności lub wprowadzają nie do zniesienia ograniczenia. Dopiero gdy architekt zdecyduje się odroczyć decyzję, podejmie decyzję, gdy informacje będą wystarczające; Zespoły, które nie korzystają z wolnych i wymagających zasobów urządzeń IO oraz frameworków, mogą tworzyć szybkie, lekkie środowiska testowe według uznania architektów. Tylko jego architekci dbają o to, co naprawdę ważne, i opóźniają tych, którzy tego nie robią, a taki zespół ma szczęście. Bzdura, w ogóle nie rozumiem, co masz na myśli. Cóż, dokładnie przeczytaj ten artykuł, bo inaczej będziesz musiał poczekać kolejne 10 lat, by to rozgryźć.
|