Separacja obaw - Separation of concerns

W informatyce , oddzielenie obawy ( SoC ) jest zasada projektowania do rozdzielania program komputerowy na odrębne sekcje. Każda sekcja dotyczy oddzielnego problemu , zestawu informacji, które wpływają na kod programu komputerowego. Obawa może być tak ogólna, jak „szczegóły dotyczące sprzętu dla aplikacji” lub tak szczegółowa, jak „nazwa klasy do utworzenia instancji”. Program, który dobrze uosabia SoC, nazywa się programem modułowym . Modułowość, a co za tym idzie, rozdzielenie obaw, osiąga się poprzez zamknięcie informacji w sekcji kodu, która ma dobrze zdefiniowany interfejs. Enkapsulacja to sposób na ukrycie informacji . Projekty warstwowe w systemach informatycznych są kolejnym przykładem separacji obaw (np. warstwa prezentacji, warstwa logiki biznesowej, warstwa dostępu do danych, warstwa trwałości).

Oddzielenie problemów daje więcej stopni swobody w przypadku niektórych aspektów projektowania, wdrażania lub użytkowania programu. Powszechną wśród nich jest zwiększona swoboda upraszczania i utrzymywania kodu. Gdy obawy są dobrze rozdzielone, istnieje więcej możliwości aktualizacji modułów, ponownego wykorzystania i samodzielnego rozwoju. Ukrycie szczegółów implementacji modułów za interfejsem umożliwia ulepszanie lub modyfikowanie sekcji kodu pojedynczego koncernu bez konieczności znajomości szczegółów innych sekcji i bez konieczności wprowadzania odpowiednich zmian w tych innych sekcjach. Moduły mogą również udostępniać różne wersje interfejsu, co zwiększa swobodę uaktualniania złożonego systemu w sposób fragmentaryczny bez przejściowej utraty funkcjonalności.

Separacja obaw jest formą abstrakcji . Podobnie jak w przypadku większości abstrakcji, rozdzielenie problemów oznacza dodanie dodatkowych interfejsów kodu, generalnie tworząc więcej kodu do wykonania. Tak więc pomimo wielu korzyści wynikających z dobrze oddzielonych obaw, często wiąże się to z karą egzekucji.

Realizacja

Mechanizmy programowania modułowego lub obiektowego, które są dostarczane przez język programowania, są mechanizmami, które umożliwiają programistom dostarczanie SoC. Na przykład języki programowania zorientowane obiektowo , takie jak C# , C++ , Delphi i Java, mogą rozdzielać problemy na obiekty , a wzorce projektowe architektoniczne , takie jak MVC lub MVP, mogą oddzielać zawartość od prezentacji i przetwarzanie danych (model) od zawartości. Projektowanie zorientowane na usługi może rozdzielać problemy na usługi . Języki programowania proceduralnego , takie jak C i Pascal, mogą rozdzielać problemy na procedury lub funkcje . Języki programowania zorientowane aspektowo mogą rozdzielać problemy na aspekty i obiekty .

Oddzielenie obaw jest ważną zasadą projektowania również w wielu innych obszarach, takich jak planowanie urbanistyczne , architektura i projektowanie informacji . Celem jest bardziej efektywne zrozumienie, projektowanie i zarządzanie złożonymi, współzależnymi systemami, tak aby funkcje mogły być ponownie wykorzystywane, optymalizowane niezależnie od innych funkcji i izolowane od potencjalnej awarii innych funkcji.

Typowe przykłady to podział przestrzeni na pokoje, tak aby aktywność w jednym pomieszczeniu nie wpływała na ludzi w innych pokojach, oraz utrzymywanie pieca na jednym obwodzie, a światła na drugim, aby przeciążenie przez piec nie wyłączało światła. Przykład z pokojami pokazuje hermetyzację, w której informacje wewnątrz jednego pokoju, takie jak stopień zabrudzeń, nie są dostępne dla innych pomieszczeń, z wyjątkiem interfejsu, którym są drzwi. Przykład z obwodami pokazuje, że aktywność w jednym module, który jest obwodem z podłączonymi odbiornikami energii elektrycznej, nie wpływa na aktywność w innym module, więc każdy moduł nie jest zainteresowany tym, co dzieje się w drugim.

Początek

Termin separacja obaw został prawdopodobnie ukuty przez Edsgera W. Dijkstrę w swoim artykule z 1974 roku „O roli myśli naukowej”.

Pozwolę sobie wyjaśnić, co w moim guście jest charakterystyczne dla wszelkiego inteligentnego myślenia. Chodzi o to, że chce się dogłębnie studiować aspekt swojego tematu w izolacji ze względu na jego spójność, cały czas wiedząc, że zajmuje się tylko jednym z aspektów. Wiemy, że program musi być poprawny i możemy go studiować tylko z tego punktu widzenia; wiemy też, że powinna być wydajna, a jej efektywność możemy, że tak powiem, zbadać innego dnia. W innym nastroju możemy zadać sobie pytanie, czy, a jeśli tak: dlaczego program jest pożądany. Ale nic nie osiąga się — wręcz przeciwnie! — przez jednoczesne zajmowanie się tymi różnymi aspektami. Jest to coś, co czasami nazywam „oddzieleniem obaw”, co, nawet jeśli nie jest całkowicie możliwe, jest jednak jedyną dostępną techniką skutecznego porządkowania myśli, jaką znam. To właśnie rozumiem przez „skupienie uwagi na jakimś aspekcie”: nie oznacza to ignorowania innych aspektów, ale po prostu oddanie sprawiedliwości temu, że z punktu widzenia tego aspektu, drugi jest nieistotny. To jedno- i wielotorowe myślenie jednocześnie.

Piętnaście lat później stało się oczywiste, że pojęcie separacji obaw staje się akceptowaną ideą. W 1989 roku Chris Reade napisał książkę zatytułowaną Elementy programowania funkcjonalnego, w której opisuje rozdzielenie obaw:

Programista musi robić kilka rzeczy jednocześnie, a mianowicie:

  1. opisać, co ma być obliczone;
  2. organizować sekwencjonowanie obliczeń w małych krokach;
  3. organizować zarządzanie pamięcią podczas obliczeń.

Reade nadal mówi:

Idealnie, programista powinien być w stanie skoncentrować się na pierwszym z trzech zadań (opisywanie tego, co ma zostać obliczone) bez rozpraszania się pozostałymi dwoma, bardziej administracyjnymi zadaniami. Oczywiście administracja jest ważna, ale oddzielając ją od głównego zadania, prawdopodobnie uzyskamy bardziej wiarygodne wyniki i złagodzimy problem programistyczny, automatyzując znaczną część administracji.

Rozdzielenie obaw ma również inne zalety. Na przykład dowodzenie programu staje się znacznie bardziej wykonalne, gdy w programie nie ma szczegółów dotyczących sekwencjonowania i zarządzania pamięcią. Co więcej, opisy tego, co ma być obliczane, powinny być wolne od tak szczegółowych opisów krok po kroku, jak to zrobić, jeśli mają być oceniane za pomocą różnych architektur maszyn. Sekwencje małych zmian w obiekcie danych przechowywanym w magazynie mogą być nieodpowiednim opisem sposobu obliczania czegoś, gdy używana jest wysoce równoległa maszyna z tysiącami procesorów rozproszonych po całej maszynie i lokalnych, a nie globalnych magazynach.

Automatyzacja aspektów administracyjnych oznacza, że ​​implementator języka musi sobie z nimi radzić, ale ma znacznie więcej możliwości wykorzystania bardzo różnych mechanizmów obliczeniowych przy różnych architekturach maszyn.

Przykłady

Stos protokołów internetowych

Rozdzielenie obaw ma kluczowe znaczenie dla projektowania Internetu. W pakiecie Internet Protocol Suite dołożono wszelkich starań, aby rozdzielić problemy na dobrze zdefiniowane warstwy . Pozwala to projektantom protokołów skupić się na problemach w jednej warstwie i zignorować inne warstwy. Na przykład protokół SMTP warstwy aplikacji jest zaniepokojony wszystkimi szczegółami prowadzenia sesji e-mail przez niezawodną usługę transportową (zwykle TCP ), ale nie ma najmniejszego znaczenia, w jaki sposób usługa transportowa czyni tę usługę niezawodną. Podobnie protokół TCP nie jest zainteresowany routingiem pakietów danych, który jest obsługiwany w warstwie internetowej .

HTML, CSS, JavaScript

HyperText Markup Language (HTML), Cascading Style Sheets (CSS) i JavaScript (JS) to języki uzupełniające używane przy tworzeniu stron internetowych i witryn internetowych. HTML służy głównie do organizacji zawartości strony internetowej, CSS służy do definiowania stylu prezentacji treści, a JS określa, w jaki sposób treść oddziałuje i zachowuje się z użytkownikiem. Historycznie tak nie było: przed wprowadzeniem CSS HTML pełnił zarówno obowiązki definiowania semantyki, jak i stylu.

Programowanie tematyczne

Programowanie zorientowane przedmiotowo pozwala na rozwiązywanie oddzielnych problemów jako oddzielnych konstrukcji oprogramowania, z których każda jest na równi z innymi. Każdy problem zapewnia własną strukturę klasową, w której zorganizowane są wspólne obiekty, oraz wnosi stan i metody do wyniku złożonego, w którym przecinają się one nawzajem. Reguły korespondencji opisują, w jaki sposób klasy i metody w różnych problemach są ze sobą powiązane w punktach, w których wchodzą w interakcję, umożliwiając zachowanie złożone dla metody, która może pochodzić z kilku problemów. Wielowymiarowa separacja obaw pozwala manipulować analizą i kompozycją obaw jako wielowymiarową „macierzą”, w której każdy problem zapewnia wymiar, w którym wyliczane są różne punkty wyboru, a komórki macierzy zajmują odpowiednie artefakty oprogramowania.

Programowanie aspektowe

Programowanie zorientowane aspektowo umożliwia traktowanie problemów przekrojowych jako głównych. Na przykład większość programów wymaga pewnej formy zabezpieczeń i rejestrowania . Bezpieczeństwo i rejestrowanie to często kwestie drugorzędne, podczas gdy głównym problemem jest często realizacja celów biznesowych. Jednak podczas projektowania programu, jego bezpieczeństwo musi być wbudowane w projekt od samego początku, a nie traktowane jako drugorzędna sprawa. Późniejsze zastosowanie zabezpieczeń często skutkuje niewystarczającym modelem zabezpieczeń, który pozostawia zbyt wiele luk dla przyszłych ataków. Można to rozwiązać za pomocą programowania aspektowego. Na przykład aspekt może zostać napisany w celu wymuszenia, że ​​wywołania określonego interfejsu API są zawsze rejestrowane lub że błędy są zawsze rejestrowane po zgłoszeniu wyjątku, niezależnie od tego, czy kod proceduralny programu obsługuje wyjątek, czy go propaguje.

Poziomy analizy w sztucznej inteligencji

W kognitywistyce i sztucznej inteligencji często odwołuje się do poziomów analizy Davida Marra . W dowolnym momencie badacz może koncentrować się na (1) tym, jaki aspekt inteligencji musi obliczyć, (2) jaki algorytm wykorzystuje lub (3) jak ten algorytm jest zaimplementowany w sprzęcie. To rozdzielenie obaw jest podobne do rozróżnienia interfejsu /implementacji w inżynierii oprogramowania i sprzętu.

Systemy znormalizowane

W znormalizowanych systemach separacja obaw jest jedną z czterech zasad przewodnich. Przestrzeganie tej zasady jest jednym z narzędzi, które pomaga zredukować efekty kombinatoryczne, które z czasem pojawiają się w utrzymywanym oprogramowaniu. W Znormalizowanych Systemach separacja obaw jest aktywnie wspierana przez narzędzia.

SoC przez klasy częściowe

Separacja obaw może być zaimplementowana i wymuszana za pomocą klas częściowych .

SoC przez częściowe klasy w Ruby

polowanie na niedźwiedzie.rb
class Bear
  def hunt
    forest.select(&:food?)
  end
end
niedźwiedź_jeść.rb
class Bear
  def eat(food)
    raise "#{food} is not edible!" unless food.respond_to? :nutrition_value
    food.nutrition_value
  end
end
niedźwiedź.rb
class Bear
  attr_accessor :hunger
  def monitor_hunger
    if hunger > 50
      food = hunt
      hunger -= eat(food)
    end
  end
end

Zobacz też

Bibliografia

Zewnętrzne linki