Program komputerowy -Computer program

W programowaniu imperatywnym program komputerowy to sekwencja instrukcji w języku programowania, które komputer może wykonać lub zinterpretować. W programowaniu deklaratywnym program komputerowy jest zbiorem instrukcji . Program komputerowy to element oprogramowania — który obejmuje również dokumentację i inne elementy niematerialne.

Program komputerowy w formie czytelnej dla człowieka nazywa się kodem źródłowym . Kod źródłowy wymaga innego programu komputerowego do wykonania , ponieważ komputery mogą wykonywać tylko swoje instrukcje maszynowe . Dlatego kod źródłowy można przetłumaczyć na instrukcje maszynowe przy użyciu kompilatora języka . ( Programy w języku maszynowym są tłumaczone przy użyciu asemblera .) Wynikowy plik nazywa się plikiem wykonywalnym . Alternatywnie kod źródłowy może być wykonywany w interpreterze języka . Język programowania Java kompiluje się do postaci pośredniej, która jest następnie wykonywana przez interpreter Java .

Jeśli plik wykonywalny jest wymagany do wykonania, system operacyjny ładuje go do pamięci i uruchamia proces . Jednostka centralna wkrótce przełączy się na ten proces, dzięki czemu będzie mogła pobierać, dekodować, a następnie wykonywać każdą instrukcję maszynową.

Jeśli zażądano wykonania kodu źródłowego, system operacyjny ładuje odpowiedni interpreter do pamięci i rozpoczyna proces. Interpreter następnie ładuje kod źródłowy do pamięci, aby przetłumaczyć i wykonać każdą instrukcję . Uruchamianie kodu źródłowego jest wolniejsze niż uruchamianie pliku wykonywalnego. Ponadto tłumacz musi być zainstalowany na komputerze.

Witaj na świecie program

Witaj świecie!” program służy do zilustrowania podstawowej składni języka . Składnia interpretowanego języka Basic (1964) została celowo ograniczona, aby uczynić język łatwym do nauczenia. Na przykład zmienne nie są deklarowane przed użyciem. Ponadto zmienne są automatycznie inicjowane na zero. Oto podstawowy program do uśredniania listy liczb:

10 INPUT "How many numbers to average?", A
20 FOR I = 1 TO A
30 INPUT "Enter number:", B
40 LET C = C + B
50 NEXT I
60 LET D = C/A
70 PRINT "The average is", D
80 END

Po poznaniu mechaniki podstawowego programowania komputerowego dostępne są bardziej wyrafinowane i zaawansowane języki do budowy dużych systemów komputerowych.

Historia

Ulepszenia w rozwoju oprogramowania są wynikiem ulepszeń sprzętu komputerowego . Na każdym etapie historii sprzętu zadanie programowania komputerowego zmieniało się diametralnie.

Silnik analityczny

Opis Lovelace z przypisu G.

W 1837 roku Charles Babbage został zainspirowany krosnem Jacquard do próby zbudowania maszyny analitycznej . Nazwy komponentów urządzenia liczącego zapożyczono z przemysłu tekstylnego. W przemyśle włókienniczym przędzę sprowadzano ze sklepu do mielenia. Urządzenie posiadało „magazyn”, który był pamięcią do przechowywania 1000 liczb po 50 cyfr dziesiętnych każda. Numery ze „sklepu” przeniesiono do „młyna” w celu przetworzenia. Został zaprogramowany przy użyciu dwóch zestawów kart perforowanych. Jeden zestaw kierował operacją, a drugi wprowadzał zmienne. Jednak po ponad 17 000 funtów brytyjskich pieniędzy rządowych tysiące kół zębatych i przekładni nigdy w pełni nie współpracowały ze sobą.

Ada Lovelace pracowała dla Charlesa Babbage'a, aby stworzyć opis maszyny analitycznej (1843). Opis zawierał przypis G, w którym szczegółowo opisano metodę obliczania liczb Bernoulliego przy użyciu silnika analitycznego. Ta notatka jest uznawana przez niektórych historyków za pierwszy na świecie program komputerowy.

Uniwersalna maszyna Turinga

Uniwersalna maszyna Turinga.svg

W 1936 roku Alan Turing wprowadził maszynę Universal Turing — urządzenie teoretyczne, które może modelować każde obliczenie. Jest to maszyna skończona, która ma nieskończenie długą taśmę do odczytu/zapisu. Maszyna może przesuwać taśmę do przodu i do tyłu, zmieniając jej zawartość podczas wykonywania algorytmu . Maszyna uruchamia się w stanie początkowym, przechodzi przez sekwencję kroków i zatrzymuje się, gdy napotka stan zatrzymania. Wszystkie współczesne komputery są kompletne pod względem Turinga .

ENIAC

Glenn A. Beck zmienia tubę w ENIAC-u.

Electronic Numerical Integrator And Computer ( ENIAC) został zbudowany między lipcem 1943 a jesienią 1945 roku. Był to kompletny , uniwersalny komputer Turinga, który używał 17 468 lamp próżniowych do tworzenia obwodów . W swej istocie była to seria połączonych ze sobą paskalin . Jego 40 jednostek ważyło 30 ton, zajmowało 1800 stóp kwadratowych (167 m 2 ) i zużywało 650 dolarów na godzinę ( w walucie lat 40. ) w postaci energii elektrycznej w stanie bezczynności. Miała 20 akumulatorów bazowych . Programowanie ENIAC trwało do dwóch miesięcy. Trzy stoły funkcyjne były na kółkach i należało je przetoczyć do stałych paneli funkcyjnych. Tabele funkcyjne zostały połączone z panelami funkcyjnymi poprzez wpięcie ciężkich czarnych kabli do tablic wtyczek . Każdy stół funkcyjny miał 728 obrotowych pokręteł. Programowanie ENIAC obejmowało również ustawienie niektórych z 3000 przełączników. Debugowanie programu zajęło tydzień. Działał od 1947 do 1955 roku na poligonie w Aberdeen , obliczając parametry bomby wodorowej, przewidując wzorce pogodowe i tworząc tabele ostrzału do celowania z dział artyleryjskich.

Komputery z programem przechowywanym

Zamiast podłączać przewody i przełączać przełączniki, komputer z przechowywanym programem ładuje swoje instrukcje do pamięci, tak jak ładuje swoje dane do pamięci. Dzięki temu komputer można było szybko zaprogramować i wykonywać obliczenia z bardzo dużą szybkością. Presper Eckert i John Mauchly zbudowali ENIAC. Obaj inżynierowie przedstawili koncepcję programu zapisanego w pamięci w trzystronicowej notatce datowanej na luty 1944 r. Później, we wrześniu 1944 r., dr John von Neumann rozpoczął pracę nad projektem ENIAC. 30 czerwca 1945 r. von Neumann opublikował pierwszy szkic raportu na temat EDVAC , który zrównał struktury komputera ze strukturami ludzkiego mózgu. Projekt stał się znany jako architektura von Neumann . Architektura została jednocześnie wdrożona w konstrukcjach komputerów EDVAC i EDSAC w 1949 roku.

IBM System/360 ( 1964) był linią sześciu komputerów, z których każdy miał taką samą architekturę zestawu instrukcji . Model 30 był najmniejszy i najtańszy. Klienci mogą aktualizować i zachować to samo oprogramowanie aplikacyjne . Model 75 był najbardziej premium. Każdy model System/360 cechował się wieloprogramowaniem — posiadanie wielu procesów w pamięci jednocześnie. Gdy jeden proces czekał na wejście/wyjście , inny mógł wykonać obliczenia.

IBM zaplanował, że każdy model będzie programowany za pomocą PL/1 . Powstał komitet, w skład którego weszli programiści COBOL , Fortran i ALGOL . Celem było opracowanie języka, który byłby wszechstronny, łatwy w użyciu, rozszerzalny i miałby zastąpić Cobol i Fortran. W rezultacie powstał duży i złożony język, którego kompilacja zajęła dużo czasu .

Przełączniki do ręcznego wprowadzania danych w urządzeniu Data General Nova 3, wyprodukowanym w połowie lat 70.

Komputery produkowane do lat 70. miały przełączniki na panelu przednim do ręcznego programowania. Program komputerowy został napisany na papierze w celach informacyjnych. Instrukcja była reprezentowana przez konfigurację ustawień włącz/wyłącz. Po ustawieniu konfiguracji naciśnięto przycisk wykonania. Ten proces został następnie powtórzony. Programy komputerowe były również automatycznie wprowadzane za pomocą taśmy papierowej lub kart dziurkowanych . Po załadowaniu nośnika adres początkowy został ustawiony przełącznikami i naciśnięty został przycisk wykonania.

Integracja na bardzo dużą skalę

Matryca z układem scalonym VLSI .

Ważnym kamieniem milowym w rozwoju oprogramowania było wynalezienie obwodu integracji o bardzo dużej skali (VLSI) (1964). Po II wojnie światowej technologię lampową zastąpiono tranzystorami stykowymi (1947) i tranzystorami bipolarnymi (koniec lat pięćdziesiątych) montowanymi na płytce drukowanej . W latach 60. przemysł lotniczy zastąpił płytkę drukowaną układem scalonym .

Robert Noyce , współzałożyciel Fairchild Semiconductor (1957) i Intel (1968), osiągnął postęp technologiczny w celu udoskonalenia produkcji tranzystorów polowych (1963). Celem jest zmiana oporności elektrycznej i przewodnictwa złącza półprzewodnikowego . Po pierwsze, naturalnie występujące minerały krzemianowe są przekształcane w pręty polikrzemowe przy użyciu procesu Siemensa . Proces Czochralskiego przekształca następnie pręciki w monokrystaliczny krzem , kryształ boule . Kryształ jest następnie cienko krojony w celu utworzenia podłoża waflowego . Planarny proces fotolitografii integruje następnie tranzystory unipolarne, kondensatory , diody i rezystory na płytce w celu zbudowania matrycy tranzystorów z tlenku metalu i półprzewodników (MOS). Tranzystor MOS jest podstawowym elementem układów scalonych .

Pierwotnie układy scalone miały swoją funkcję ustawianą podczas produkcji. W latach sześćdziesiątych sterowanie przepływem elektrycznym przeszło do programowania macierzy pamięci tylko do odczytu (ROM). Matryca przypominała dwuwymiarową tablicę bezpieczników. Proces osadzania instrukcji na matrycy polegał na wypaleniu niepotrzebnych połączeń. Było tak wiele połączeń, programiści oprogramowania układowego napisali program komputerowy na innym chipie, aby nadzorować wypalanie. Technologia stała się znana jako programowalna pamięć ROM . W 1971 roku Intel zainstalował program komputerowy na chipie i nazwał go mikroprocesorem Intel 4004 .

Procesor IBM System/360 (1964) nie był mikroprocesorem.

Terminy mikroprocesor i jednostka centralna (CPU) są obecnie używane zamiennie. Jednak procesory wyprzedzają mikroprocesory. Na przykład IBM System/360 (1964) miał procesor wykonany z płytek drukowanych zawierających elementy dyskretne na podłożach ceramicznych .

Stan worka 8008

Artystyczne przedstawienie mikrokomputera Intel 8008 z Sacramento State University (1972).

Intel 4004 (1971) był 4- bitowym mikroprocesorem zaprojektowanym do obsługi kalkulatora Busicom . Pięć miesięcy po premierze Intel wypuścił Intel 8008 — 8-bitowy mikroprocesor. Bill Pentz kierował zespołem w Sacramento State, który zbudował pierwszy mikrokomputer wykorzystujący Intel 8008 — Sac State 8008 (1972). Jego celem było przechowywanie dokumentacji medycznej pacjentów. Komputer obsługiwał dyskowy system operacyjny umożliwiający uruchomienie 3 - megabajtowego dysku twardego Memorex . Miał kolorowy wyświetlacz i klawiaturę w jednej konsoli. Dyskowy system operacyjny został zaprogramowany przy użyciu języka IBM Basic Assembly Language (BAL) . Aplikacja dokumentacji medycznej została zaprogramowana za pomocą interpretera BASIC . Jednak komputer był ślepą uliczką ewolucyjną, ponieważ był niezwykle kosztowny. Został również zbudowany w publicznym laboratorium uniwersyteckim w konkretnym celu. Niemniej projekt przyczynił się do rozwoju zestawu instrukcji Intel 8080 (1974) .

seria x86

Oryginalny komputer osobisty IBM (1981) wykorzystywał mikroprocesor Intel 8088.

W 1978 roku, kiedy Intel uaktualnił Intel 8080 do Intel 8086 , powstało nowoczesne środowisko programistyczne . Intel uprościł Intel 8086 do produkcji tańszego Intel 8088 . IBM przyjął Intel 8088, kiedy wszedł na rynek komputerów osobistych (1981). Wraz ze wzrostem zapotrzebowania konsumentów na komputery osobiste rósł rozwój mikroprocesorów Intela. Kolejność rozwoju znana jest jako seria x86 . Asembler x86 jest rodziną instrukcji maszynowych zgodnych wstecz . Instrukcje maszynowe utworzone we wcześniejszych mikroprocesorach zostały zachowane podczas aktualizacji mikroprocesora. Umożliwiło to konsumentom zakup nowych komputerów bez konieczności zakupu nowego oprogramowania . Główne kategorie instrukcji to:

Środowisko programistyczne

DEC VT100 ( 1978) był szeroko stosowanym terminalem komputerowym .

Obwody VLSI umożliwiły środowisku programistycznemu przejście od terminala komputerowego (do lat 90.) do komputera z graficznym interfejsem użytkownika (GUI). Terminale komputerowe ograniczały programistów do pojedynczej powłoki działającej w środowisku wiersza poleceń . W latach 70. pełnoekranowa edycja kodu źródłowego stała się możliwa dzięki tekstowemu interfejsowi użytkownika . Niezależnie od dostępnej technologii, celem jest programowanie w języku programowania .

Języki programowania

Język programowania to zestaw słów kluczowych , symboli , identyfikatorów i reguł, za pomocą których programiści mogą przekazywać instrukcje komputerowi. Działają zgodnie z zestawem reguł zwanym składnią .

Języki programowania czerpią swoją podstawę z języków formalnych . Celem zdefiniowania rozwiązania pod kątem jego języka formalnego jest wygenerowanie algorytmu do rozwiązania problemu podkreślenia. Algorytm to sekwencja prostych instrukcji, które rozwiązują problem .

Generacje języka programowania

Ewolucja języka programowania rozpoczęła się, gdy EDSAC (1949) użył pierwszego zapisanego programu komputerowego w swojej architekturze von Neumanna . Programowanie EDSAC było w pierwszej generacji języka programowania .

  • Drugą generacją języka programowania jest język asemblerowy . Język asemblera pozwala programiście na używanie instrukcji mnemonicznych zamiast zapamiętywania numerów instrukcji. Asembler tłumaczy każdy mnemonik języka asemblera na jego numer języka maszynowego. Na przykład na PDP-11 operacja 24576 może być oznaczona jako ADD w kodzie źródłowym. Cztery podstawowe operacje arytmetyczne mają instrukcje składania, takie jak ADD, SUB, MUL i DIV. Komputery mają również instrukcje, takie jak DW (Define Word ), aby rezerwować komórki pamięci . Następnie instrukcja MOV może kopiować liczby całkowite między rejestrami i pamięcią.
  • Podstawowa struktura instrukcji asemblera to etykieta, operacja, operand i komentarz.
  • Etykiety umożliwiają programiście pracę z nazwami zmiennych . Asembler później przetłumaczy etykiety na fizyczne adresy pamięci .
  • Operacje pozwalają programiście pracować z mnemonikami. Asembler później przetłumaczy mnemoniki na numery instrukcji.
  • Operandy mówią asemblerowi, które dane operacja będzie przetwarzać.
  • Komentarze pozwalają programiście wyartykułować narrację, ponieważ same instrukcje są niejasne.
Kluczową cechą programu w języku asemblerowym jest to, że tworzy odwzorowanie jeden-do-jednego na odpowiadający mu docelowy język maszynowy.
  • Trzecia generacja języka programowania wykorzystuje kompilatory i interpretery do wykonywania programów komputerowych. Cechą wyróżniającą język trzeciej generacji jest jego niezależność od konkretnego sprzętu. Zaczęli od języków Fortran (1958), COBOL (1959), ALGOL (1960) i BASIC (1964). W 1973 r. język programowania C pojawił się jako język wysokiego poziomu, który generował wydajne instrukcje języka maszynowego. Podczas gdy języki trzeciej generacji historycznie generowały wiele instrukcji maszynowych dla każdej instrukcji, C ma instrukcje, które mogą generować pojedynczą instrukcję maszynową. Co więcej, kompilator optymalizujący może unieważnić programistę i generować mniej instrukcji maszynowych niż instrukcji. Dziś cały paradygmat języków wypełnia imperatywne spektrum trzeciej generacji .
  • Czwarta generacja języka programowania kładzie nacisk na to, jakie wyniki wyjściowe są pożądane, a nie na to, jak należy konstruować instrukcje programowania. Języki deklaratywne próbują ograniczyć skutki uboczne i umożliwiają programistom pisanie kodu ze stosunkowo niewielką liczbą błędów. Jeden z popularnych języków czwartej generacji nosi nazwę Structured Query Language (SQL). Deweloperzy baz danych nie muszą już przetwarzać każdego rekordu bazy danych pojedynczo. Ponadto prosta instrukcja może generować rekordy wyjściowe bez konieczności rozumienia, w jaki sposób jest pobierana.
  • Piąta generacja języka programowania wykorzystuje narzędzia wizualne do generowania kodu źródłowego. Zintegrowane środowisko programistyczne umożliwia programiście rysowanie graficznego interfejsu użytkownika (GUI) na ekranie za pomocą myszy . Programista pisze funkcje obsługi zdarzeń , które zostaną wykonane, gdy pola zostaną najechane na pola, zostaną wprowadzone lub wyjdą z nich. System programistyczny łączy funkcje z GUI i generuje program komputerowy . Program komputerowy może być również generowany z serwera aplikacji . Dane wejściowe do serwera to lista parametrów, takich jak tabele bazy danych . Serwer następnie konstruuje dostosowany pakiet oprogramowania. Przykładowe pakiety obejmują rozrachunki z dostawcami i płace .

Języki imperatywne

Program komputerowy napisany w języku imperatywnym

Języki imperatywne określają algorytm sekwencyjny za pomocą deklaracji , wyrażeń i instrukcji :

  • Deklaracja wprowadza do programu komputerowego nazwę zmiennej i przypisuje ją do typu danych – na przykład:var x: integer;
  • Wyrażenie daje wartość – na przykład: 2 + 2daje 4
  • Instrukcja może przypisać wyrażenie do zmiennej lub użyć wartości zmiennej do zmiany przepływu sterowania w programie – na przykład:x := 2 + 2; if x = 4 then do_something();

Przykłady języków imperatywnych można znaleźć na stronie Imperative_programming#Examples .

Języki deklaratywne

Języki imperatywne mają jedną główną krytykę: przypisanie wyrażenia do zmiennej nielokalnej może wywołać niezamierzony efekt uboczny . Języki deklaratywne zazwyczaj pomijają instrukcję przypisania i przepływ sterowania. Opisują , jakie obliczenia należy wykonać, a nie jak je obliczyć. Dwie szerokie kategorie języków deklaratywnych to języki funkcjonalne i języki logiczne .

W matematyce funkcja jest regułą, która odwzorowuje elementy z wyrażenia na zakres wartości . Rozważ funkcję:

times_10(x) = 10 * x

Wyrażenie jest mapowane 10 * x przez funkcję times_10()na zakres wartości . Jedna wartość to 20. Dzieje się tak, gdy x wynosi 2. Tak więc zastosowanie funkcji jest matematycznie zapisane jako:

times_10(2) = 20

Kompilator języka funkcjonalnego nie przechowuje tej wartości w zmiennej. Zamiast tego wstawi wartość na stos komputera przed ustawieniem licznika programu z powrotem na funkcję wywołującą. Funkcja wywołująca następnie zdejmie wartość ze stosu.

Języki imperatywne obsługują funkcje. Dlatego programowanie funkcjonalne można osiągnąć w języku imperatywnym, jeśli programista stosuje dyscyplinę. Jednak język funkcjonalny wymusza tę dyscyplinę na programiście poprzez swoją składnię. Języki funkcjonalne mają składnię dostosowaną do podkreślenia tego, co .

Program funkcjonalny jest tworzony z zestawem podstawowych funkcji, po których następuje pojedyncza funkcja sterownika. Rozważ fragment :

function max(a,b){ /* code omitted */}

function min(a,b){ /* code omitted */}

function difference_between_largest_and_smallest(a,b,c) {

return max(a,max(b,c)) - min(a, min(b,c));

}

Prymitywy to max()i min(). Funkcja sterownika to difference_between_largest_and_smallest(). Wykonanie:

put(difference_between_largest_and_smallest(10,4,7));wygeneruje 6.

Języki funkcjonalne są wykorzystywane w badaniach informatycznych do odkrywania nowych funkcji językowych. Co więcej, ich brak skutków ubocznych sprawił, że stały się popularne w programowaniu równoległym i programowaniu współbieżnym . Jednak twórcy aplikacji preferują zorientowane obiektowo cechy języków imperatywnych .

Aby zapoznać się z przykładami języków deklaratywnych, odwiedź stronę Declarative_programming#Examples .

Programowanie komputerowe

Przed przystąpieniem do języków programowania Betty Jennings i Fran Bilas programowali ENIAC , przesuwając kable i ustawiając przełączniki.

Programowanie komputerów (część tworzenia oprogramowania i inżynierii oprogramowania ) to proces pisania lub edycji kodu źródłowego . W sformalizowanym środowisku analityk systemowy zbierze od menedżerów informacje o wszystkich procesach organizacji w celu zautomatyzowania. Ten profesjonalista następnie przygotowuje szczegółowy plan dla nowego lub zmodyfikowanego systemu. Plan jest analogiczny do planu architekta.

Cele dotyczące wydajności

Analityk systemowy ma na celu dostarczenie właściwych informacji właściwej osobie we właściwym czasie. Czynnikami krytycznymi dla osiągnięcia tego celu są:

  1. Jakość wyjścia. Czy wyniki są przydatne do podejmowania decyzji?
  2. Dokładność wyniku. Czy to odzwierciedla prawdziwą sytuację?
  3. Format danych wyjściowych. Czy wynik jest łatwy do zrozumienia?
  4. Szybkość wyjścia. Informacje wrażliwe na czas są ważne podczas komunikacji z klientem w czasie rzeczywistym.

Cele kosztowe

Osiągnięcie celów dotyczących wydajności powinno być zrównoważone ze wszystkimi kosztami, w tym:

  1. Koszty rozwoju.
  2. Wyjątkowość kosztuje. System wielokrotnego użytku może być drogi. Jednak może być preferowany w stosunku do systemu o ograniczonym użyciu.
  3. Koszty sprzętu.
  4. Koszty operacyjne.

Zastosowanie procesu rozwoju systemu złagodzi aksjomat: im później w procesie zostanie wykryty błąd, tym kosztowniejszy będzie jego naprawienie.

Model wodospadu

Model kaskadowy to implementacja procesu rozwoju systemów . Jak sugeruje etykieta kaskady , podstawowe fazy nakładają się na siebie:

  1. Faza dochodzenia ma na celu zrozumienie podstawowego problemu.
  2. Faza analizy ma na celu zrozumienie możliwych rozwiązań.
  3. Faza projektowania polega na zaplanowaniu najlepszego rozwiązania.
  4. Faza wdrożenia polega na zaprogramowaniu najlepszego rozwiązania.
  5. Faza konserwacji trwa przez cały okres eksploatacji systemu. Mogą być konieczne zmiany w systemie po jego wdrożeniu. Mogą istnieć błędy, w tym błędy specyfikacji, błędy projektowe lub błędy kodowania. Mogą być konieczne ulepszenia. Adaptacja może być konieczna, aby zareagować na zmieniające się środowisko.

Programista komputerowy

Programista komputerowy to specjalista odpowiedzialny za napisanie lub modyfikację kodu źródłowego w celu realizacji szczegółowego planu. Zespół programistów będzie prawdopodobnie potrzebny, ponieważ większość systemów jest zbyt duża, aby mógł je ukończyć pojedynczy programista. Jednak dodanie programistów do projektu nie może skrócić czasu realizacji. Zamiast tego może obniżyć jakość systemu. Aby były skuteczne, moduły programu muszą być zdefiniowane i rozesłane do członków zespołu. Ponadto członkowie zespołu muszą komunikować się ze sobą w znaczący i skuteczny sposób.

Programowanie w małym to programowanie komputerowe w ramach jednego modułu. Są szanse, że moduł wykona moduły znajdujące się w innych plikach kodu źródłowego. Programowanie na dużą skalę to projektowanie modułów tak, aby skutecznie się ze sobą łączyły.

Moduły programowe

Programowanie modułowe to technika udoskonalania programów w języku imperatywnym w celu łagodzenia starzenia się oprogramowania . Moduł programu to sekwencja instrukcji, które są ograniczone do bloku i razem identyfikowane przez nazwę. Moduły posiadają funkcję , kontekst i logikę :

  • Funkcją modułu jest to , co robi.
  • Kontekst modułu to elementy, na których są wykonywane .
  • Logika modułu to sposób, w jaki wykonuje on funkcję .

Nazwę modułu należy wyprowadzić najpierw z jego funkcji , a następnie z jego kontekstu . Jego logika nie powinna być częścią nazwy. Na przykład function compute_square_root( x )lub function compute_square_root_integer( i : integer )są odpowiednimi nazwami modułów. Jednak function compute_square_root_by_division( x )tak nie jest.

Stopień interakcji w module to jego poziom spójności . Spójność to ocena relacji między nazwą modułu a jego funkcją . Stopień interakcji między modułami to poziom sprzężenia . Sprzężenie to ocena relacji między kontekstem modułu a elementami, które są wykonywane.

Spójność

Poziomy spójności od najgorszego do najlepszego to:

  • Koincydentalna spójność : moduł ma koincydentną spójność, jeśli wykonuje wiele funkcji, a funkcje są całkowicie niepowiązane. Na przykład function read_sales_record_print_next_line_convert_to_float(). Przypadkowa spójność występuje w praktyce, gdy kierownictwo wymusza głupie zasady. Na przykład „Każdy moduł będzie zawierał od 35 do 50 instrukcji wykonywalnych”.
  • Spójność logiczna: Moduł ma spójność logiczną, jeśli ma dostęp do szeregu funkcji, ale wykonywana jest tylko jedna z nich. Na przykład function perform_arithmetic( perform_addition, a, b ).
  • Spójność czasowa : moduł ma spójność czasową, jeśli wykonuje funkcje związane z czasem. Jeden przykład, function initialize_variables_and_open_files(). Inny przykład, stage_one(), stage_two(), ...
  • Spójność proceduralna : moduł ma spójność proceduralną, jeśli wykonuje wiele funkcji, ale tylko luźno powiązanych. Na przykład function read_part_number_update_employee_record().
  • Spójność komunikacyjna : moduł ma spójność komunikacyjną, jeśli wykonuje wiele funkcji, ale jest blisko powiązanych. Na przykład function read_part_number_update_sales_record().
  • Spójność informacyjna : moduł ma spójność informacyjną, jeśli wykonuje wiele funkcji, ale każda funkcja ma swoje własne punkty wejścia i wyjścia. Ponadto funkcje mają tę samą strukturę danych. Na tym poziomie działają klasy obiektowe.
  • Spójność funkcjonalna : moduł ma spójność funkcjonalną, jeśli osiąga jeden cel, działając tylko na zmiennych lokalnych. Co więcej, może być wielokrotnego użytku w innych kontekstach.

Sprzęganie

Poziomy sprzężenia od najgorszego do najlepszego to:

  • Łączenie treści : moduł posiada łączenie treści, jeśli modyfikuje zmienną lokalną innej funkcji. COBOL robił to za pomocą czasownika alter .
  • Wspólne sprzężenie : Moduł ma wspólne sprzężenie, jeśli modyfikuje zmienną globalną.
  • Sprzężenie sterowania : Moduł posiada sprzężenie sterowania, jeśli inny moduł może modyfikować jego przepływ sterowania . Na przykład perform_arithmetic( perform_addition, a, b ). Zamiast tego kontrola powinna dotyczyć składu zwróconego obiektu.
  • Stamp Coupling : Moduł posiada funkcję Stamp Coupling, jeśli element struktury danych przekazany jako parametr zostanie zmodyfikowany. Na tym poziomie działają klasy obiektowe.
  • Data Coupling : Moduł posiada sprzężenie danych, jeśli wszystkie jego parametry wejściowe są potrzebne i żaden z nich nie jest modyfikowany. Ponadto wynik funkcji zwracany jest jako pojedynczy obiekt.

Analiza przepływu danych

Przykładowy diagram przepływu danych na poziomie funkcji.

Analiza przepływu danych jest metodą projektowania wykorzystywaną do osiągnięcia modułów spójności funkcjonalnej i łączenia danych . Dane wejściowe do metody to diagram przepływu danych . Diagram przepływu danych to zestaw owali reprezentujących moduły. Nazwa każdego modułu jest wyświetlana w jego owalu. Moduły mogą znajdować się na poziomie wykonywalnym lub na poziomie funkcji.

Na schemacie znajdują się również strzałki łączące ze sobą moduły. Strzałki wskazujące moduły reprezentują zestaw wejść. Każdy moduł powinien mieć tylko jedną strzałkę wskazującą od niego, aby reprezentować jego pojedynczy obiekt wyjściowy. (Opcjonalnie, dodatkowa strzałka wyjątku wskazuje.) Stokrotkowy łańcuch owali przedstawia cały algorytm . Moduły wejściowe powinny rozpocząć schemat. Moduły wejściowe powinny łączyć się z modułami transformacji. Moduły transformacji powinny łączyć się z modułami wyjściowymi.

Programowanie obiektowe

Programowanie obiektowe polega na wykonywaniu operacji ( funkcji ) na obiektach . Podstawową ideą jest pogrupowanie cech zjawiska w kontener obiektów i nadanie kontenerowi nazwy. W kontenerze zgrupowane są również operacje na zjawisku. Programowanie obiektowe opracowane przez połączenie potrzeby kontenerów i potrzeby bezpiecznego programowania funkcjonalnego . Ta metoda programowania nie musi być ograniczona do języka obiektowego . W języku obiektowym kontener obiektów nazywa się klasą . W języku niezorientowanym obiektowo struktura danych (znana również jako rekord ) może stać się kontenerem obiektów. Aby przekształcić strukturę danych w kontener obiektów, operacje muszą być napisane specjalnie dla struktury. Powstała struktura nazywana jest abstrakcyjnym typem danych . Jednak dziedziczenia będzie brakować. (Aby uzyskać punkt odniesienia, odwiedź Imperative_programming#C++ .) Niemniej jednak tę wadę można przezwyciężyć.

Oto plik nagłówkowy języka programowania C dla abstrakcyjnego typu danych GRADE w prostej aplikacji szkolnej:

/* grade.h */
/* ------- */

/* Used to allow multiple source files to include */
/* this header file without duplication errors.   */
/* ---------------------------------------------- */
#ifndef GRADE_H
#define GRADE_H

typedef struct
{
    char letter;
} GRADE;

/* Constructor */
/* ----------- */
GRADE *grade_new( char letter );

int grade_numeric( char letter );
#endif

Funkcja grade_new()wykonuje ten sam algorytm, co operacja konstruktora C++.

Oto plik źródłowy języka programowania C dla abstrakcyjnego typu danych GRADE w prostej aplikacji szkolnej:

/* grade.c */
/* ------- */
#include "grade.h"

GRADE *grade_new( char letter )
{
    GRADE *grade;

    /* Allocate heap memory */
    /* -------------------- */
    if ( ! ( grade = calloc( 1, sizeof( GRADE ) ) ) )
    {
        fprintf(stderr,
                "ERROR in %s/%s/%d: calloc() returned empty.\n",
                __FILE__,
                __FUNCTION__,
                __LINE__ );
        exit( 1 );
    }

    grade->letter = letter;
    return grade;
}

int grade_numeric( char letter )
{
    if ( ( letter == 'A' || letter == 'a' ) )
        return 4;
    else
    if ( ( letter == 'B' || letter == 'b' ) )
        return 3;
    else
    if ( ( letter == 'C' || letter == 'c' ) )
        return 2;
    else
    if ( ( letter == 'D' || letter == 'd' ) )
        return 1;
    else
    if ( ( letter == 'F' || letter == 'f' ) )
        return 0;
    else
        return -1;
}

W konstruktorze funkcja calloc()jest używana zamiast malloc()ponieważ każda komórka pamięci zostanie ustawiona na zero.

Oto plik nagłówkowy języka programowania C dla abstrakcyjnego typu danych PERSON w prostej aplikacji szkolnej:

/* person.h */
/* -------- */
#ifndef PERSON_H
#define PERSON_H

typedef struct
{
    char *name;
} PERSON;

/* Constructor */
/* ----------- */
PERSON *person_new( char *name );
#endif

Oto plik źródłowy języka programowania C dla abstrakcyjnego typu danych PERSON w prostej aplikacji szkolnej:

/* person.c */
/* -------- */
#include "person.h"

PERSON *person_new( char *name )
{
    PERSON *person;

    if ( ! ( person = calloc( 1, sizeof( PERSON ) ) ) )
    {
        fprintf(stderr,
                "ERROR in %s/%s/%d: calloc() returned empty.\n",
                __FILE__,
                __FUNCTION__,
                __LINE__ );
        exit( 1 );
    }

    person->name = name;
    return person;
}

Oto plik nagłówkowy języka programowania C dla abstrakcyjnego typu danych STUDENT w prostej aplikacji szkolnej:

/* student.h */
/* --------- */
#ifndef STUDENT_H
#define STUDENT_H

#include "person.h"
#include "grade.h"

typedef struct
{
    /* A STUDENT is a subset of PERSON. */
    /* -------------------------------- */
    PERSON *person;

    GRADE *grade;
} STUDENT;

/* Constructor */
/* ----------- */
STUDENT *student_new( char *name );
#endif

Oto plik źródłowy języka programowania C dla abstrakcyjnego typu danych STUDENT w prostej aplikacji szkolnej:

/* student.c */
/* --------- */
#include "student.h"
#include "person.h"

STUDENT *student_new( char *name )
{
    STUDENT *student;

    if ( ! ( student = calloc( 1, sizeof( STUDENT ) ) ) )
    {
        fprintf(stderr,
                "ERROR in %s/%s/%d: calloc() returned empty.\n",
                __FILE__,
                __FUNCTION__,
                __LINE__ );
        exit( 1 );
    }

    /* Execute the constructor of the PERSON superclass. */
    /* ------------------------------------------------- */
    student->person = person_new( name );
    return student;
}

Oto program sterownika do demonstracji:

/* student_dvr.c */
/* ------------- */
#include <stdio.h>
#include "student.h"

int main( void )
{
    STUDENT *student = student_new( "The Student" );
    student->grade = grade_new( 'a' );

    printf( "%s: Numeric grade = %d\n",
            /* Whereas a subset exists, inheritance does not. */
            student->person->name,
            /* Functional programming is executing functions just-in-time (JIT) */
            grade_numeric( student->grade->letter ) );

	return 0;
}

Oto plik makefile do kompilacji wszystkiego:

# makefile
# --------
all: student_dvr

clean:
    rm student_dvr *.o

student_dvr: student_dvr.c grade.o student.o person.o
    gcc student_dvr.c grade.o student.o person.o -o student_dvr

grade.o: grade.c grade.h
    gcc -c grade.c

student.o: student.c student.h
    gcc -c student.c

person.o: person.c person.h
    gcc -c person.c

Formalna strategia budowania obiektów obiektowych polega na:

  • Zidentyfikuj obiekty. Najprawdopodobniej będą to rzeczowniki.
  • Zidentyfikuj atrybuty każdego obiektu. Co pomaga opisać obiekt?
  • Zidentyfikuj działania każdego obiektu. Najprawdopodobniej będą to czasowniki.
  • Zidentyfikuj relacje między obiektem a obiektem. Najprawdopodobniej będą to czasowniki.

Na przykład:

  • Osoba to człowiek identyfikowany po imieniu.
  • Ocena to osiągnięcie oznaczone literą.
  • Student to osoba, która otrzymuje ocenę.

Kategorie funkcjonalne

Diagram przedstawiający interakcję użytkownika z oprogramowaniem aplikacji . Oprogramowanie aplikacji współdziała z systemem operacyjnym , który współdziała ze sprzętem .

Programy komputerowe można podzielić na kategorie według linii funkcjonalnych. Główne kategorie funkcjonalne to oprogramowanie aplikacyjne i oprogramowanie systemowe . Oprogramowanie systemowe obejmuje system operacyjny , który łączy sprzęt komputerowy z oprogramowaniem aplikacyjnym. Celem systemu operacyjnego jest zapewnienie środowiska, w którym oprogramowanie aplikacji działa w wygodny i wydajny sposób. Zarówno oprogramowanie użytkowe, jak i oprogramowanie systemowe uruchamiają programy użytkowe . Na poziomie sprzętowym program mikrokodowy kontroluje obwody w całej jednostce centralnej .

Oprogramowanie

Oprogramowanie użytkowe jest kluczem do uwolnienia potencjału systemu komputerowego. Oprogramowanie aplikacji dla przedsiębiorstw obejmuje aplikacje księgowe, kadrowe, klienckie i dostawców. Przykłady obejmują planowanie zasobów przedsiębiorstwa , zarządzanie relacjami z klientami oraz oprogramowanie do zarządzania łańcuchem dostaw .

Aplikacje korporacyjne mogą być opracowywane we własnym zakresie jako jedyne w swoim rodzaju zastrzeżone oprogramowanie . Alternatywnie można je kupić jako gotowe oprogramowanie . Zakupione oprogramowanie może zostać zmodyfikowane w celu dostarczenia oprogramowania niestandardowego . Jeśli aplikacja jest dostosowana, to albo wykorzystywane są zasoby firmy, albo zasoby są zlecane na zewnątrz. Tworzenie oprogramowania na zewnątrz może pochodzić od oryginalnego dostawcy oprogramowania lub od dewelopera zewnętrznego.

Zaletami oprogramowania zastrzeżonego są funkcje, a raporty mogą być zgodne ze specyfikacją. Kierownictwo może być również zaangażowane w proces rozwoju i oferować pewien poziom kontroli. Kierownictwo może podjąć decyzję o przeciwdziałaniu nowej inicjatywie konkurenta lub wdrożeniu wymagań klienta lub dostawcy. Fuzja lub przejęcie będzie wymagało zmian w oprogramowaniu przedsiębiorstwa. Wadami oprogramowania zastrzeżonego są koszty czasu i zasobów, które mogą być znaczne. Ponadto może pojawić się ryzyko związane z funkcjami i wydajnością.

Zaletami oprogramowania „z półki” są jego identyfikowalne koszty początkowe, podstawowe potrzeby powinny być spełnione, a jego wydajność i niezawodność mają udokumentowane osiągnięcia. Wadami oprogramowania „z półki” są jego niepotrzebne funkcje, które dezorientują użytkowników końcowych, może brakować w nim funkcji potrzebnych przedsiębiorstwu, a przepływ danych może nie odpowiadać procesom pracy przedsiębiorstwa.

Jednym ze sposobów ekonomicznego uzyskania dostosowanej aplikacji dla przedsiębiorstw jest skorzystanie z usług dostawcy usług aplikacyjnych . Firmy specjalistyczne zapewniają sprzęt, niestandardowe oprogramowanie i wsparcie dla użytkowników końcowych. Mogą przyspieszyć tworzenie nowych aplikacji, ponieważ posiadają wykwalifikowaną kadrę systemów informatycznych. Największą zaletą jest to, że uwalnia wewnętrzne zasoby od personelu i zarządzania złożonymi projektami komputerowymi. Wielu dostawców usług aplikacyjnych jest skierowanych do małych, szybko rozwijających się firm z ograniczonymi zasobami systemu informatycznego. Z drugiej strony, większe firmy z dużymi systemami prawdopodobnie będą miały swoją infrastrukturę techniczną. Jednym z zagrożeń jest powierzenie zewnętrznej organizacji poufnych informacji. Innym ryzykiem jest konieczność ufania niezawodności infrastruktury dostawcy.

System operacyjny

System operacyjny to oprogramowanie niskiego poziomu obsługujące podstawowe funkcje komputera, takie jak planowanie procesów i sterowanie urządzeniami peryferyjnymi .

W latach pięćdziesiątych programista, który był jednocześnie operatorem, pisał program i uruchamiał go. Po zakończeniu działania programu dane wyjściowe mogły zostać wydrukowane lub podziurkowane na taśmie papierowej lub kartach w celu późniejszego przetworzenia. Najczęściej program nie działał. Programista spojrzał następnie na światła konsoli i zaczął bawić się przełącznikami konsoli. Jeśli miał mniej szczęścia, wydrukowano pamięć do dalszych badań. W latach 60. programiści ograniczyli ilość marnowanego czasu, automatyzując pracę operatora. Przez cały czas w komputerze przechowywany był program zwany systemem operacyjnym .

Termin system operacyjny może odnosić się do dwóch poziomów oprogramowania. System operacyjny może odnosić się do programu jądra, który zarządza procesami , pamięcią i urządzeniami . Szerzej system operacyjny może odnosić się do całego pakietu oprogramowania centralnego. Pakiet zawiera program jądra, interpreter wiersza poleceń , graficzny interfejs użytkownika , programy narzędziowe i edytor .

Program jądra

Jądro łączy oprogramowanie aplikacji ze sprzętem komputera.

Głównym celem jądra jest zarządzanie ograniczonymi zasobami komputera:

Pamięć fizyczna jest rozproszona wokół pamięci RAM i dysku twardego. Pamięć wirtualna to jeden ciągły blok.
  • Kiedy jądro początkowo ładuje plik wykonywalny do pamięci, logicznie dzieli przestrzeń adresową na regiony . Jądro przechowuje tabelę master-region i wiele tabel na region procesu (pregion) — po jednej dla każdego uruchomionego procesu . Tabele te stanowią wirtualną przestrzeń adresową . Tablica master-region służy do określenia, gdzie w pamięci fizycznej znajduje się jej zawartość . Tabele pregion pozwalają każdemu procesowi mieć swój własny program (tekst) pregion, pregion danych i pregion stosu.
  • Program pregion przechowuje instrukcje maszynowe. Ponieważ instrukcje maszynowe się nie zmieniają, pregion programu może być współdzielony przez wiele procesów tego samego pliku wykonywalnego.
  • Aby zaoszczędzić czas i pamięć, jądro może ładować tylko bloki instrukcji wykonania z dysku, a nie cały plik wykonawczy.
  • Jądro odpowiada za tłumaczenie adresów wirtualnych na adresy fizyczne . Jądro może zażądać danych z kontrolera pamięci i zamiast tego otrzymać błąd strony . Jeśli tak, jądro uzyskuje dostęp do jednostki zarządzania pamięcią, aby wypełnić fizyczny obszar danych i przetłumaczyć adres.
  • Jądro alokuje pamięć ze sterty na żądanie procesu. Gdy proces zakończy się z pamięcią, proces może zażądać jej zwolnienia . Jeśli proces zakończy się bez żądania zwolnienia całej przydzielonej pamięci, jądro wykonuje odśmiecanie, aby zwolnić pamięć.
  • Jądro zapewnia również, że proces uzyskuje dostęp tylko do własnej pamięci, a nie do pamięci jądra lub innych procesów.
  • Program jądra powinien wykonywać zarządzanie systemem plików . Jądro zawiera instrukcje tworzenia, pobierania, aktualizowania i usuwania plików.
  • Program jądra powinien wykonywać zarządzanie urządzeniami . Jądro dostarcza programy do standaryzacji i uproszczenia interfejsu myszy, klawiatury, napędów dysków, drukarek i innych urządzeń. Ponadto jądro powinno decydować o dostępie do urządzenia, jeśli dwa procesy żądają go w tym samym czasie.
  • Program jądra powinien wykonywać zarządzanie siecią . Jądro przesyła i odbiera pakiety w imieniu procesów. Jedną z kluczowych usług jest znalezienie efektywnej drogi do systemu docelowego.
  • Program jądra powinien udostępniać funkcje na poziomie systemu, z których mogą korzystać programiści.
    • Programiści uzyskują dostęp do plików poprzez stosunkowo prosty interfejs, który z kolei wykonuje stosunkowo skomplikowany niskopoziomowy interfejs we/wy. Interfejs niskiego poziomu obejmuje tworzenie plików, deskryptory plików , wyszukiwanie plików, fizyczny odczyt i fizyczny zapis.
    • Programiści tworzą procesy za pomocą stosunkowo prostego interfejsu, który z kolei wykonuje stosunkowo skomplikowany interfejs niskopoziomowy.
    • Programiści wykonują arytmetykę daty/czasu za pomocą stosunkowo prostego interfejsu, który z kolei wykonuje stosunkowo skomplikowany niskopoziomowy interfejs czasu.
  • Program jądra powinien zapewniać kanał komunikacyjny między wykonywanymi procesami. W przypadku dużego systemu oprogramowania może być pożądane przekształcenie systemu w mniejsze procesy. Procesy mogą komunikować się ze sobą poprzez wysyłanie i odbieranie sygnałów .

Pierwotnie systemy operacyjne były programowane w asemblerze ; jednak nowoczesne systemy operacyjne są zazwyczaj pisane w językach wyższego poziomu, takich jak C , Objective-C i Swift .

Program użytkowy

Program narzędziowy ma na celu pomoc w administrowaniu systemem i wykonywaniu oprogramowania. Systemy operacyjne uruchamiają sprzętowe programy narzędziowe do sprawdzania stanu dysków, pamięci, głośników i drukarek. Program narzędziowy może zoptymalizować umieszczenie pliku na zatłoczonym dysku. Programy narzędziowe systemu monitorują wydajność sprzętu i sieci. Gdy metryka znajduje się poza dopuszczalnym zakresem, generowany jest alert wyzwalacza.

Programy narzędziowe obejmują programy do kompresji, dzięki czemu pliki danych są przechowywane na mniejszej przestrzeni dyskowej. Skompresowane programy oszczędzają również czas, gdy pliki danych są przesyłane przez sieć. Programy narzędziowe mogą sortować i scalać zestawy danych. Programy narzędziowe wykrywają wirusy komputerowe .

Program mikrokodu

NIE brama.
Bramka NAND.
Brama NOR.
I brama.
Brama LUB.

Program mikrokodu jest interpreterem niższego poziomu, który kontroluje ścieżkę danych komputerów sterowanych oprogramowaniem. (Postępy w sprzęcie spowodowały migrację tych operacji do sprzętowych obwodów wykonawczych ). Instrukcje mikrokodu umożliwiają programiście łatwiejsze zaimplementowanie poziomu logiki cyfrowej — prawdziwego sprzętu komputerowego. Poziom logiki cyfrowej stanowi granicę między informatyką a inżynierią komputerową .

Bramka logiczna to mały tranzystor , który może zwrócić jeden z dwóch sygnałów: włączony lub wyłączony.

  • Posiadanie jednego tranzystora tworzy bramkę NOT .
  • Połączenie dwóch tranzystorów szeregowo tworzy bramkę NAND .
  • Połączenie dwóch tranzystorów równolegle tworzy bramkę NOR .
  • Połączenie bramki NOT z bramką NAND tworzy bramkę AND .
  • Połączenie bramki NOT z bramką NOR tworzy bramkę OR .

Te pięć bramek tworzy elementy składowe algebry binarnej — cyfrowych funkcji logicznych komputera.

Instrukcje mikrokodu są mnemonikami , których programiści mogą używać do wykonywania cyfrowych funkcji logicznych zamiast tworzenia ich w algebrze binarnej. Są one przechowywane w magazynie sterowania jednostki centralnej (CPU) . Te instrukcje na poziomie sprzętowym przenoszą dane w całej ścieżce danych .

Cykl mikroinstrukcji rozpoczyna się, gdy mikrosekwencer używa swojego licznika mikroprogramów do pobrania następnej instrukcji maszynowej z pamięci o dostępie swobodnym . Następnym krokiem jest dekodowanie instrukcji maszynowej poprzez wybranie odpowiedniej linii wyjściowej do modułu sprzętowego. Ostatnim krokiem jest wykonanie instrukcji przy użyciu zestawu bramek modułu sprzętowego.

Symboliczna reprezentacja jednostki ALU.

Instrukcje wykonywania operacji arytmetycznych są przekazywane przez jednostkę arytmetyczno-logiczną (ALU). Jednostka ALU ma obwody do wykonywania podstawowych operacji dodawania, przesuwania i porównywania liczb całkowitych. Łącząc i zapętlając podstawowe operacje przez jednostkę ALU, procesor wykonuje swoją złożoną arytmetykę.

Instrukcje mikrokodu przenoszą dane między procesorem a kontrolerem pamięci . Instrukcje mikrokodu kontrolera pamięci manipulują dwoma rejestrami . Rejestr adresów pamięci jest używany do uzyskania dostępu do adresu każdej komórki pamięci. Rejestr danych pamięci służy do ustawiania i odczytywania zawartości każdej komórki.

Instrukcje mikrokodu przenoszą dane między procesorem a wieloma magistralami komputerowymi . Magistrala kontrolera dysku zapisuje i odczytuje z dysków twardych . Dane są również przenoszone między jednostką centralną a innymi jednostkami funkcjonalnymi za pośrednictwem ekspresowej magistrali połączeń elementów peryferyjnych.

Uwagi

Bibliografia