{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
    "<div class=\"alert alert-block alert-info\">\n",
    "<h1> Systemy informatyczne</h1>\n",
    "<h2> 12. Ocena jakości systemu informatycznego</i>[wykład]</h2> \n",
    "<h3>Krzysztof Jassem (2022)</h3>\n",
    "</div>\n",
    "\n",
    "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. Czym jest jakość produktu?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-block alert-success\">\n",
    "  \n",
    "<h3>Definicja wg Toma de Marco</h3> \n",
    "    \n",
    "Jakość produktu to funkcja tego, jak bardzo zmienia on świat na lepsze.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-block alert-success\">\n",
    "  \n",
    "<h3>Definicja wg Geralda Weinberga</h3> \n",
    "    \n",
    "Jakość to subiektywnie pojmowana wartość.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-block alert-success\">\n",
    "  \n",
    "<h3>Definicja wg Josepha Jurana</h3> \n",
    "  \n",
    "1. Jakość składa się z tych cech produktu, które spełniają potrzeby klientów i dostarczają im satysfakcji. \n",
    "2. Jakość to brak braków.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-block alert-success\">\n",
    "  \n",
    "<h3>Definicja wg Armanda Feigenbauma</h3> \n",
    "  \n",
    "Jakość to coś, co określa tylko i wyłącznie klient - a nie inżynier, dział marketiingu, czy też kierownictwo.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-block alert-success\">\n",
    "  \n",
    "<h3>Definicja wg Williama Edwardsa Deminga</h3> \n",
    "  \n",
    "Cała trudność w zdefiniowaniu jakości polega na przełożeniu przyszłych potrzeb użytkownika na wymierne cechy w taki sposób, aby produkt dawał klientowi satysfakcję za akceptowalną cenę.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. Definicja jakości oprogramowania"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info alert-success\">\n",
    "    \n",
    "<h3>Jakość oprogramowania</h3> \n",
    "  \n",
    "<b> Jakość oprogramowania </b> to funkcja wypadkowa wartości określonych właściwości oprogramowania.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1. Proces określania jakości oprogramowania\n",
    "Proces określenia jakości oprogramowania składa się z dwóch etapów:\n",
    "1. Zdefiniowanie funkcji jakości oprogramowania:\n",
    "\n",
    " > 1. Określ właściwości istotne dla danego typu oprogramowania (np. rozmiar, funkcjonalność, użyteczności, dostępność).\n",
    " > 2. Dla każdej włąsciwości zdefiniuj zakres wartości liczbowych lub kategorii, określających, w jakim stopniu spełnia ona oczekiwania użytkowników.\n",
    " > 3. Zdefiniuj jakość oprogramowania jako funkcję wartości poszczególnych właściwości:  \n",
    " >   **Quality = q(wartości właściwości)**\n",
    " \n",
    "2. Ocena jakości oprogramowania\n",
    " > 1. Wyznacz wartości poszczególnych cech oprogramowania.\n",
    " > 2. Oblicz jakość oprogramowania za pomocą zdefiniowanej funkcji *Quality*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. Jakość kodu źródłowego\n",
    "Cechy kodu żródłowego:\n",
    " * rozmiar,\n",
    " * złożoność"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.1. Metryki rozmiaru kodu źródłowego\n",
    "\n",
    "### 3.1.1. Liczba wierszy (LOC - Lines of Code)\n",
    "LOC mierzy **liczbę wierszy** w metodzie, klasie lub całej aplikacji.\n",
    "\n",
    "W obliczaniu LOC trzeba podjąć kilka nieoczywistych decyzji.\n",
    "\n",
    "Przykłady:\n",
    "\n",
    "<table>\n",
    "    <caption> Jak mierzyć liczbę wierszy w metryce LOC </caption>    \n",
    "<tr> \n",
    "    <td> Decyzja </td> <td> Rekomendacja </td>\n",
    "</tr>\n",
    "<tr>\n",
    "    <td> Czy liczyć puste wiersze?</td> <td> NIE </td>\n",
    "</tr>\n",
    "<tr>\n",
    "    <td> Czy liczyć komentarze?</td> <td> NIE </td>\n",
    "</tr>\n",
    "<tr>\n",
    "    <td> Czy liczyć liczbę wierszy czy liczbę instrukcji?</td> <td> Liczbę wierszy </td>\n",
    "</tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info alert-success\">\n",
    "  \n",
    "<h3>Reguła 30</h3> \n",
    "  \n",
    "Jeśli element zawiera wiecej niż 30 podelementów, to najprawdopodobniej w działaniu wystąpi jakiś poważny problem.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> **Methods**  should not have more than an average of 30 code lines (not counting line spaces and comments).  \n",
    "> **A class** should contain an average of less than 30 methods, resulting in up to 900 lines of code.  \n",
    "> **A package** shouldn’t contain more than 30 classes, thus comprising up to 27,000 code lines.  \n",
    "> **Subsystems** with more than 30 packages should be avoided. Such a subsystem would count up to 900 classes with up to 810,000 lines of code.  \n",
    "> **A system** with 30 subsystems would thus possess 27,000 classes and 24.3 million code lines.  \n",
    "[Przeczytaj w Internecie](https://dzone.com/articles/rule-30-%E2%80%93-when-method-class-or)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1.2. Punkty funkcyjne\n",
    "\n",
    "**Punkty Funkcyjne** - metryka, która wyznacza liczbę funkcjonalności dostarczaną przez system.\n",
    "\n",
    "**Współczynnik produktywności języka programowania**: ile (średnio) linii kodu potrzeba do zakodowania jednego punktu funkcyjnego? \n",
    "\n",
    "Wartość kodu w punktach funkcyjnych wyznacza się, dzieląc wartośćLOC przez współczynnik produktywności.\n",
    "\n",
    "**Tablica produktywności języków programowania**\n",
    "<figure>\n",
    "<img src=\"obrazy/LOC vs FP.jpg\" alt=\"Tablica produktywności\" width=500px>\n",
    "<figcaption> Tablica produktywności. Źródło: Adam Roman, \"Testowanie i jakość oprogramowania\" </figcaption>    \n",
    "</figure>\n",
    "\n",
    "[Porównaj w Internecie](https://www.qsm.com/resources/function-point-languages-table)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1.3. Liczba tokenów - metryka Halsteada\n",
    "\n",
    "Metryka Halsteada wyznacza objętość (wielkość) kodu na podstawie liczby unikatowych tokenów.\n",
    "Wyróżniane są dwa typy tokenów:\n",
    " * operatory (funkcje, słowa kluczowe itp.),\n",
    " * operandy (zmienne, stałe, wartości).\n",
    " \n",
    "Wartości metryk Halsteada (w przeciwieństwie do LOC) nie zależą od długości przyjętego nazewnictwa.\n",
    "\n",
    "<figure>\n",
    "<img src=\"obrazy/Halstead1.png\" alt=\"Liczby tokenów\" width=300px>\n",
    "<figcaption> Liczby tokenów. Źródło: wikipedia </figcaption>    \n",
    "</figure>\n",
    "\n",
    "Na podstawie liczby tokenów można oszacować objętość (wielkość) programu:\n",
    "\n",
    "<figure>\n",
    "<img src=\"obrazy/Halstead2.png\" alt=\"wielkość programu\" width=300px>\n",
    "<figcaption> Objętość programu. Źródło: wikipedia </figcaption>    \n",
    "</figure>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.2. Metryki oceny złożoności kodu źródłowego "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2.1. Metryki złożoności Halsteada\n",
    "Złożoność programu szacowana jest pod kilkoma aspektami - na podstawie liczby tokenów:\n",
    " * D: trudność implementacji,\n",
    " * L: poziom programu (im wyższy tym program jest mniej podatny na błędy),\n",
    " * E: wysiłek implementacji,\n",
    " * T: czas implementacji\n",
    " * B: liczba błędów.\n",
    "<figure>\n",
    "<img src=\"obrazy/Halstead3.png\" alt=\"metryki złożoności Halsteada\" width=100px>\n",
    "<figcaption> Metryki złożoności Halsteada. Źródło: wikipedia </figcaption>      \n",
    "</figure>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2.2. Złożoność cyklomatyczna\n",
    "**Złożoność cyklomatyczna** określa liczbę niezależnych ścieżek przebiegu programu.  \n",
    "\n",
    "Jeśli program reprezentowany jest w postaci schematu blokowego (grafu), to:\n",
    "\n",
    "> CC = e - n + 2 * p   \n",
    "> e – liczba krawędzi grafu  \n",
    "> n – liczba węzłów grafu  \n",
    "> p – liczba składowych grafu  \n",
    "\n",
    "Złożoność cykolmatyczną można łatwo wyliczyć na podstawie wzoru:\n",
    "\n",
    "> CC = d + 1, gdzie d oznacza liczbę węzłów decyzyjnych, np. instrukcji:  \n",
    "> * if   \n",
    "> * while  \n",
    "> * for  \n",
    "> * case"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2.3. Uśrednione metody na klasę (Weighted Methods per Class - WMC)\n",
    "\n",
    "Metryka uwzględnia zarówno liczbę metod w klasie, jak i ich złożoność cyklomatyczną: (n oznacza liczbę metod w klasie, a c<sub>i</sub> oznacza złożoność cykolomatyczną i-tej metody).\n",
    "\n",
    "<img src=\"obrazy/WMC.png\" alt=\"Uśrednione metody na klasę \" width=150px>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2.4. Odpowiedzialność klasy (Response for a Class - RFC)\n",
    "\n",
    "Metryka RFC oznacza całkowitą liczbę metod, które mogą być potencjalnie wywołane w odpowiedzi na komunikat odebrany przez obiekt klasy.  \n",
    "\n",
    "Wysoka wartość RFC oznacza większą funkcjonalność, ale zarazem i wyższą złożoność."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. Właściwości produktu wpływające na ocenę jakości oprogramowania"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.1. Przydatność funkcjonalna (Functional Suitability - F)\n",
    "**Przydatność funkcjonalna** określa stopień, w jakim program dostarcza oczekiwane funkcjonalności.\n",
    "\n",
    "Wartość przydatności funkcjonalnej można wyznaczyć podczas testowania:\n",
    "\n",
    "> **M = 1 - A/B**\n",
    ">  * A = funkcjonalności problemowe  \n",
    ">  * B = wszystkie testowane funkcjonalności"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.2. Niezawodność\n",
    "\n",
    "**Niezawodność** określa prawdopodobieństwo, że wykonanie operacji przez program będzie bezbłędne.\n",
    "\n",
    "Wartość niezawodności można wyznaczyć podczas testowania:\n",
    "\n",
    "> **M = A/B**  \n",
    ">  * A = liczba testów ukończonych pomyślnie, \n",
    ">  * B = liczba wszystkich testów"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.3. Użyteczność (Usability - U)\n",
    "\n",
    "**Użyteczność** określa łatwość użytkowania.\n",
    "\n",
    "Wartość użyteczności można wyznaczyć podczas testów użyteczności:\n",
    "\n",
    "> **M = A/B**\n",
    ">  * A = liczba funkcjonalności odkryta przez użytkownika,  \n",
    ">  * B = liczba wszystkich funkcjonalości."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.4. Wydajność (Performance Efficiency)\n",
    "**Wydajność** określa liczbę wykonanych operacji w odniesieniu do czasu i zużytych zasobów.\n",
    "\n",
    "Przykładowe metryki pomiaru wydajności:\n",
    "\n",
    "> * Czas odpowiedzi:  **M = T1 (end) - T2 (start)** \n",
    "> * Czas postoju: **M = T1 (waiting time) / T2 (total time)**\n",
    "> * Przepustowość = Liczba zadań wykonanych w jednostce czasu  \n",
    "> * Zużycie pamięci (w bajtach)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.5. Łatwość konserwacji (Maintainability - M)\n",
    "**Łatwość konserwacji** to łatwość, z jaką program jest utrzymywany w celu:\n",
    " * poprawiania błędów,\n",
    " * wprowadzania nowych funkcji.\n",
    "\n",
    "Przykładowa metryka: Ile czasu zajmuje średnio naprawienie błędu?\n",
    "\n",
    "> **M = SUM(czas naprawy) / N**  \n",
    "> * N oznacza liczbę napraw"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.6. Przenośność (Portability - P)\n",
    "**Przenośność** to Łatwość przenoszenia systemu pomiędzy różnymi środowiskami platformami / systemami operacyjnymi. \n",
    "\n",
    "Przykładowe metryki:\n",
    " * łatwość adaptacji\n",
    " > **M = T**  \n",
    " > * T oznacza czas adaptacji do nowego środowiska\n",
    "\n",
    " * łatwość instalacji:  \n",
    "  > **M = A / B**\n",
    "  >  * A = przypadki pomyślnej instalacji  \n",
    "  >  * B = wszystkie przypadki instalacji  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.7. Dostępność (Availibility - A)\n",
    "**Dostępność** to czas, w którym program zobowiązany jest odpowiadać zgodnie z oczekiwaniami.\n",
    "\n",
    "* Metryka:\n",
    "\n",
    "> **M = A / B**\n",
    "> * A = Czas dostępności  \n",
    "> * B = Czas całkowity  \n",
    "\n",
    "* Przykładowe wartości metryki dostępności:\n",
    "\n",
    "<table>\n",
    "    <caption> Wartości metryki dostępności </caption>\n",
    "<tr> \n",
    "    <td> Miara dostępności </td> <td> Czas niedostępności w roku </td>\n",
    "</tr>\n",
    "<tr>\n",
    "    <td> 99,999 </td> <td> 5 minut 20 sekund </td>\n",
    "</tr>\n",
    "<tr>\n",
    "    <td> 99,8</td> <td> 17 godzin 30 minut </td>\n",
    "</tr>\n",
    "<tr>\n",
    "    <td> 97,5 </td> <td> 219 godzin </td>\n",
    "</tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.8. Kompatybilność (Compatibility)\n",
    "**Kompatybilność** to możliwość współpracowania z systemami zewnętrznymi."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.9. Bezpieczeństwo (Security - S)\n",
    "**Bezpieczeństwo** to możliwość chronienia danych przetwarzanych przez aplikację.\n",
    "\n",
    "* Przykładowa metryka:\n",
    "\n",
    "> **M = A / B**  \n",
    "> * A = Liczba przetestowanych funkcji programu uznanych jako bezpieczne\n",
    "> * B = Liczba wszystkich przetestowanych funkcji  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. Schematy oceny jakości\n",
    "\n",
    "Aby ocenić jakość oprogramowania należy wybrać właściwości oprogramowania, które wchodzą w skład oceny. Służą do tego **schematy oceny jakości**.\n",
    "\n",
    "## 5.1. CUMPRIMDSO (schamat wprowadzony przez IBM)\n",
    "* Capability (odpowiednik przydatności funkcjonalnej)\n",
    "* Usability (użyteczność)\n",
    "* Performance – wydajność\n",
    "* Reliability – niezawodność\n",
    "* Installability – łatwość instalacji\n",
    "* Maintainibility – łatwość utrzymania (pielęgnowalność)\n",
    "* Documentation – dokumentacja\n",
    "* Service – serwis\n",
    "* Overall - ocena ogólna\n",
    "\n",
    "## 5.2. CUMPRIMDA\n",
    "* Capability (odpowiednik przydatności funkcjonalnej)\n",
    "* Usability (użyteczność)\n",
    "* Performance – wydajność\n",
    "* Reliability – niezawodność\n",
    "* Installability – łatwość instalacji\n",
    "* Maintainibility – łatwość utrzymania (pielęgnowalność)\n",
    "* Documentation – dokumentacja\n",
    "* Availibility - dostępność\n",
    "\n",
    "## 5.3. FURPS (schemat wprowadzony przez Hewlett-Packard)\n",
    "* Functionality\n",
    "* Usability\n",
    "* Reliability\n",
    "* Performance\n",
    "* Supportability – łatwość wspierania"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 6. Funkcja oceny jakości oprogramowania"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.1. Pojęcie korelacji\n",
    "\n",
    "**Korelacja** to miara zależności pomiędzy dwoma zmiennymi (cechami).\n",
    "\n",
    "Korelacja przyjmuje wartości z przedziału [-1, 1]. \n",
    "* korealacja > 0 → korelacja dodatnia\n",
    "  * gdy wartości jednej cechy rosną, to drugiej również rosną.\n",
    "* r < 0 → korelacja ujemna\n",
    "  * gdy wartości jednej cechy rosną, to drugiej maleją i odwrotnie\n",
    "* r = 0 → korelacja zerowa\n",
    "  * brak związku między cechami.\n",
    "  \n",
    "Przykłady korelacji: \n",
    "<figure>\n",
    "<img src=\"obrazy/korelacja.png\" alt=\"korelacja Pearsona\" width=600px>\n",
    "    <figcaption>źródło: https://cyrkiel.info/statystyka/korelacja-pearsona/</figcaption>\n",
    "</figure>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.2. Korelacja między właściwościami oprogramowania\n",
    "Korelację między poszczególnymi właściwościami oprogramowania obrazuje tabela:\n",
    "\n",
    "<figure>\n",
    "<img src=\"obrazy/korelacja właściwości.png\" alt=\"Korelacja między właściwościomi oprogramowania\" width=600px>\n",
    "    <figcaption> Korelacje między właściwościami oprogramowania źródło: opracowanie własne na podstawie: Stephen H. Kan \"Metryki i modele w inżynierii jakości oprogramowania\"</figcaption>\n",
    "</figure>\n",
    "\n",
    "Tabela wskazuje, że polepszenie jednej cechy oprogramowania (np. przydatności funkcjonalnej) może pogorszyć inną cechę (np. wydajność), bo cechy te są ujemnie skorelowane."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.3. Waga właściwości oprogramowania\n",
    "Istotność poszczególnych właściwości oprogramowania zależy od typu programu.\n",
    "\n",
    "Stephen H. Kan (\"Metryki i modele w inżynierii jakości oprogramowania\") podaje, że dla metryki UPRIMDA najbardziej odpowiednie kolejności właściwości są następujące:  \n",
    "* RUIPMDA\n",
    "* RUAIMPD"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.4. Wzór na ocenę jakości oprogramowania\n",
    "\n",
    "Procedura opracowania wzoru na ocenę jakości oprogramowania odpowiedniego dla danego typu programu:\n",
    "\n",
    "> 1. Wybierz schemat (np. FURPS)  \n",
    ">  \n",
    "> 2. Zdefiniuj typ funkcji (np. funkcja liniowa)  \n",
    "> **Quality = a + b*F + c*U +d*R + e*P + f*S** \n",
    ">  \n",
    "> 3. Zdefiniuj współczynniki tak, by korelacja z oceną ludzką była jak najwyższa."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Przykładowy proces dostrajania współczynników jakości\n",
    "\n",
    "> 1. Zorganizuj grupę użytkowników (co najmniej 5 osób).  \n",
    "> 2. Zbierz od użytkowników oceny poszczególnych właściwości oprogramowania.  \n",
    "> 3. Zbierz od użytkowników oceny ogólne jakości.  \n",
    "> 4. Określ heurystycznie wartości współczynników we wzorze na ocenę ogolną.  \n",
    "> 5. Oblicz współczynnik korelacji między:\n",
    ">  * ocenami ogólnymi jakości podanymi przez użytkowników,  \n",
    ">  * ocenami ogólnymi jakości wyznaczonymi przez wzór na oceną ogólną na podstawie ocen cząstkowych użytkownikow.\n",
    "> 6.  Jeśli korelacja jest niska, to powróć do punktu 4."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Podsumowanie\n",
    " * Istnieje wiele definicji jakości programowania.\n",
    "   * Na wykładzie zdefiniowano jakość jako funkcję poszczególnych właściwości oprogramowania.\n",
    "\n",
    "* Istnieją metryki oceny **kodu źrodłowego**. \n",
    "   * Na ich podstawie można ocenić jakość kodu.\n",
    "   \n",
    " * Jakość oprogramowania można oceniać również z punktu widzenia klienta. \n",
    "   * Stosowane są różne schematy oceny, które biorą pod uwagę różne właściwości oprogramowania.\n",
    "   \n",
    " * Ocenę ogólną oprogramowania (z punktu widzenia klienta) można zdefiniować jako **funkcję liniową** ocen poszczególnych właściwości."
   ]
  }
 ],
 "metadata": {
  "author": "Krzysztof Jassem",
  "email": "jassem@amu.edu.pl",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "lang": "pl",
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  },
  "subtitle": "12. Ocena jakości systemu informatycznego[wykład]",
  "title": "Przygotowanie do projektu badawczo-rozwojowego",
  "year": "2021"
 },
 "nbformat": 4,
 "nbformat_minor": 4
}