JRT: Difference between revisions

From ICO wiki
Jump to navigationJump to search
Jgavrilo (talk | contribs)
No edit summary
Kkilgi (talk | contribs)
Line 562: Line 562:


== Veebiteenuse Retsensioonid ==
== Veebiteenuse Retsensioonid ==
=== Meeskond CoverMe retsensioon meeskonnale SPOT ===
Meeskonna eesmärk oli luua veebiteenus, mis võimaldab saada infot pakutavate treeningute kohta, sisestada ja kuvada tunniplaani andmeid, registreerida osalejaid tundidesse ning end sealt eemaldada. Samuti oli ette nähtud, et administraatorid saavad lisada, muuta ja kustutada kõike sprodiklubiga seonduvat ning treenerid ja spordiklubi esindajad saavad toimetada treeningutega seotud andmete sisestamise ja muutmisega. Andmebaasimudel on tehtud väga põhjalikult ning tabelite kirjeldused on samuti välja toodud.
Meie hinnangul on eesmärk põhiosas täidetud, realiseeritud on enamus kavandatud must-have funktsionaalsusest (välja on jäänud logimine). Loodud on veebiteenus, mis kasutab REST arhitektuuri ja ASP.NET MVC Web Api tehnoloogiat.
Veebiteenuse struktuur on üles ehitatud kihiliselt, mis võimaldab vajadusel süsteemi osasid lihtsamini muuta,  täiendada ja vajadusel välja vahetada. Kihid on jaotatud järgmiselt:
BL - sisaldab DTO-sid ja nende koostamiseks vajalikke Factoreid. Samuti on siin Service klassid, milles on kirjas kõik päringud andmebaasist (Get mitmesugustes variantides, Add, Edit, Delete). Lisaks tavalistele CRUD meetoditele on tehtud ka spetsiifilisemad päringud , näiteks GetByIdForUser jne. Päringuid tehakse uow-de kaudu. Service’tele ja Factory’tele on loodud Interface’d.
DAL - kasutatakse EFRepositoryFactory ja EFRepositoryProvidery põhimõtteid. DbInitializeris antakse ette lähteandmete seed’imine. Repositooriumid on omaette kaustas, kuhu on lisaks EFRepository-st päritud meetoditele juurde kirjutatud palju erinevaid meetodeid funktsionaalsuse täiendamiseks.
Domain - andmebaasi mudelis  on kokku 12  olemit, mis on nõuetele vastav. Üldine andmebaasimudeli ülesehitus on loogiline ning listid on algselt väärtustatud, mis tagab selle, et ei pea NullReference Exceptione kontrollima. Vajalikesse kohtadesse on annotatsioonid juurde lisatud ja nendega ei ole üle pingutatud, et süsteemi liiga kirjuks ajada. Tõstame esile asjaolu, et kasutatud on  Base Entity’t, millest kõik ülejäänud olemid pärinevad. See ühtlustab rakenduse koodi ja on üldse väga hea mõte. Kasutatud on palju nullable tüüpi muutujaid, mis on antud juhul õigustatud, andes andmete sisestamisel paindlikkust, samas lisades mõneti riskantsust.
Interfaces - Kõikide repositooriumide jaoks on loodud ka interface´d. Samuti leidub seal UOW jaoks interface.
WebApi - Kokku on kasutusel 6 kontrollerit, milles on realiseeritud CRUD meetodid koos mõne spetsiifilisema meetodiga (näiteks GetFilteredForPeriod). Kontrollerid saavad oma sisu vastavatest service’itest. Identity rakendamiseks on kontrollerite meetoditel kasutatatud Authorize annotatsioone. Samuti on läbi mõeldud, et mõnda meetodit on autoriseeritud kasutama ainult “Admin”-kasutaja. Näiteks ainult  “Admin”, saab salvestada treenereid andmebaasi. Kontrollerites on kenasti kasutatud erinevaid Http-staatuskoode, mitte ainult Ok(), vaid ka Forbidden(), NotFound() jne. Samuti kasutatakse edukalt sõltuvuste süstimist (Dependency Injection). Kasutatud on OAuth bearer token authentication’it.
Lisaks peame oluliseks märkida, et kood on kirjutatud heas stiilis, kõikjal inglise keeles, ei esine keelte segunemist. Paljudes kohtades oli kood kommenteeritud, kuid see tundus olevat ise kaasa tulnud. Meeskonna enda kommentaare ei paistnud.
Kokkuvõtteks võib öelda, et tegemist on väga hästi kavandatud ja realiseeritud veebiteenusega ja meeskonnaliikmete panus on olnud märkimisväärne, eriti arvestades seda, et tegemist oli vaid kahe liikmega.
=== Retsensioon meeskonnale "SPOT" ===
=== Retsensioon meeskonnale "SPOT" ===


Retsenseeritavaks tööks oli valitud tiimi SPOT veebiteenus, mis on seotud spordiklubide treeningute haldamisega. Esialgses andmebaasi skeemis oli plaanitud teha 16 tabelit, millest 4 on entitytega seotud. Projektis oli ära tehtud 12 domeeni mudeleid + entitytega seotud automaatselt. Mudelid tunduvad loogilised olla. On kasutatud propertid, mida andmebaasi ei salvestata, aga kalkuleeritakse jooksvalt. On kasutatud ka BaseEntity, milles on CreatedAt jne, ja kõik teised olemid pärinevad sellest, minu arust väga hea lahendus. Teenuse seadistatus, et tagastada jsoni igasuguste settingutega. API Routing pole muudetud, eriolukordade jaoks kasutatakse routingu atribuutides. Rakenduses on realiseeritud Seed meetod, mis väärtustab andmebaasi testandmetega. On näha, et testandmete täitmisel on kasutatud üks väline xml fail, faili töötlemises on kasutatud nii foreach tsükleid, kui ka LINQ avaldisi. Oleks hea kui paljudes kohtades null reference exceptioni vältimiseks teeks checki, aga muidu kui võtta arvesse, et see XML ei muutu kunagi, siis tehtud/pakutud variant ka sobib. Data access layer on ilusasti tehtud, iga olemi jaoks tehtud repositoorium, mis oma korda implementeerib interface’i. Repositooriumide päringul on ka realiseeritud singletoni muster. Järgmisel tasemel on tehtud UOW, kus on kasutusel nii Custom Repo küsimine, kui ka Standard. NLOg logimine on ka ilusasti implementeeritud. Üldiselt DAL projekti vaadates tekib tunne, et tiim on seda läbi töötanud ja ilusasti häid praktikaid kasutades tegi ära. Järgmine projekt on “BL”, kohe näha, et projekt on ilusasti struktureeritud, kasutatakse factoreid ja serviceid, mil omakorda implementeerivad interface. Data Transfer objektides ei ole miksimist domeen olemitega, mis on hästi, kuna selline olukord tekitaks “lazy loading”-uga, et kõik seosed ja andmed tuleksid andmebaasist, mida pole vaja. DTO-des ei ole kasutatud atribuute, mis sõltuvalt olukorrast võib olla halb, kuna puudub igasugune kontroll mida kasutaja saadab teenuse peale. Nagu ennem oli öeldud, et interfacid on kasutusel, aga objekti loomisel ei kasutata DI mootorit, vaid luuakse otse new keyword’iga. Andmebaasi salvestamine käib läbi UOW. Kõik DTO-d, serviced ja factoryd tunduvad läbimõeldud. Solution’is eksisteerib projekt nimega “ConsoleApp” tundub, et tiim kasutas seda oma veebiteenuse testimiseks. Järgmine projekt on DataAnnotations, milles olemas ainuke klass “Precision”, Internetis otsides ja koodi vaadates, sain teada, et seda kasutatakse decimal täpsuse kindlaks tegemiseks ja sellist valmis lahenduse .net-is pole. SPOT tiimi solution’is ma kahjuks ei leidnud mitte ühtegi kohta kus seda kasutatakse. Järgmine projekt on Identity, kus on kõik olemid identity’ga seotud ja vajalikud services. Järgmine projekt ‘’Interfaces’’, kus hoitakse peaaegu kõik interfacid. Ja viimane projekt on “WebApi”, mis hoiab endas veebiteenuste kontrollereid, vaateid, scripte ja teisi faile. Kontrollerist on näha, et tiim tegi ümber Entity Useri primaarse võtme stringist integeri. On kasutusel Authorize atribuudid, mis piiravad liigipääsu erinevatele kontrolleritele/meetoditele. Samuti veebiteenuses eksisteerivad erinevad rollid (Admin ja treener), neid ka kasutatakse Authorize atribuutides. Samuti kontrollerites on kasutusel GET, POST, PUT ja DELETE päringute päised. Kontrollerites on implementeeritud sünkroonne lähenemine (pole kusagil olemas async võtmesõna). Kui rääkida tööst üldiselt, siis kohe näha, et tiim tegi suure töö (see pole mahulises mõttes lõpetatud, aga kogu baas on olemas, jäänud ainult DTO-de tegemine ja nende käsitlemine). Ainukesed puudused, mida ma näen, on DTO-des atribuutide puudumine. Aga muidu tuli välja ilus, loogiliselt struktureeritud veebiteenus.
Retsenseeritavaks tööks oli valitud tiimi SPOT veebiteenus, mis on seotud spordiklubide treeningute haldamisega. Esialgses andmebaasi skeemis oli plaanitud teha 16 tabelit, millest 4 on entitytega seotud. Projektis oli ära tehtud 12 domeeni mudeleid + entitytega seotud automaatselt. Mudelid tunduvad loogilised olla. On kasutatud propertid, mida andmebaasi ei salvestata, aga kalkuleeritakse jooksvalt. On kasutatud ka BaseEntity, milles on CreatedAt jne, ja kõik teised olemid pärinevad sellest, minu arust väga hea lahendus. Teenuse seadistatus, et tagastada jsoni igasuguste settingutega. API Routing pole muudetud, eriolukordade jaoks kasutatakse routingu atribuutides. Rakenduses on realiseeritud Seed meetod, mis väärtustab andmebaasi testandmetega. On näha, et testandmete täitmisel on kasutatud üks väline xml fail, faili töötlemises on kasutatud nii foreach tsükleid, kui ka LINQ avaldisi. Oleks hea kui paljudes kohtades null reference exceptioni vältimiseks teeks checki, aga muidu kui võtta arvesse, et see XML ei muutu kunagi, siis tehtud/pakutud variant ka sobib. Data access layer on ilusasti tehtud, iga olemi jaoks tehtud repositoorium, mis oma korda implementeerib interface’i. Repositooriumide päringul on ka realiseeritud singletoni muster. Järgmisel tasemel on tehtud UOW, kus on kasutusel nii Custom Repo küsimine, kui ka Standard. NLOg logimine on ka ilusasti implementeeritud. Üldiselt DAL projekti vaadates tekib tunne, et tiim on seda läbi töötanud ja ilusasti häid praktikaid kasutades tegi ära. Järgmine projekt on “BL”, kohe näha, et projekt on ilusasti struktureeritud, kasutatakse factoreid ja serviceid, mil omakorda implementeerivad interface. Data Transfer objektides ei ole miksimist domeen olemitega, mis on hästi, kuna selline olukord tekitaks “lazy loading”-uga, et kõik seosed ja andmed tuleksid andmebaasist, mida pole vaja. DTO-des ei ole kasutatud atribuute, mis sõltuvalt olukorrast võib olla halb, kuna puudub igasugune kontroll mida kasutaja saadab teenuse peale. Nagu ennem oli öeldud, et interfacid on kasutusel, aga objekti loomisel ei kasutata DI mootorit, vaid luuakse otse new keyword’iga. Andmebaasi salvestamine käib läbi UOW. Kõik DTO-d, serviced ja factoryd tunduvad läbimõeldud. Solution’is eksisteerib projekt nimega “ConsoleApp” tundub, et tiim kasutas seda oma veebiteenuse testimiseks. Järgmine projekt on DataAnnotations, milles olemas ainuke klass “Precision”, Internetis otsides ja koodi vaadates, sain teada, et seda kasutatakse decimal täpsuse kindlaks tegemiseks ja sellist valmis lahenduse .net-is pole. SPOT tiimi solution’is ma kahjuks ei leidnud mitte ühtegi kohta kus seda kasutatakse. Järgmine projekt on Identity, kus on kõik olemid identity’ga seotud ja vajalikud services. Järgmine projekt ‘’Interfaces’’, kus hoitakse peaaegu kõik interfacid. Ja viimane projekt on “WebApi”, mis hoiab endas veebiteenuste kontrollereid, vaateid, scripte ja teisi faile. Kontrollerist on näha, et tiim tegi ümber Entity Useri primaarse võtme stringist integeri. On kasutusel Authorize atribuudid, mis piiravad liigipääsu erinevatele kontrolleritele/meetoditele. Samuti veebiteenuses eksisteerivad erinevad rollid (Admin ja treener), neid ka kasutatakse Authorize atribuutides. Samuti kontrollerites on kasutusel GET, POST, PUT ja DELETE päringute päised. Kontrollerites on implementeeritud sünkroonne lähenemine (pole kusagil olemas async võtmesõna). Kui rääkida tööst üldiselt, siis kohe näha, et tiim tegi suure töö (see pole mahulises mõttes lõpetatud, aga kogu baas on olemas, jäänud ainult DTO-de tegemine ja nende käsitlemine). Ainukesed puudused, mida ma näen, on DTO-des atribuutide puudumine. Aga muidu tuli välja ilus, loogiliselt struktureeritud veebiteenus.

Revision as of 07:55, 15 June 2017

Meeskond

Riho Uusjärv
Jevgeni Gavrilov
Tiit Kuuskmäe

Blog

19.03.2017 - Meeskonna loomine, teema välja mõtlemine, XML, XSD ja XSLT koostamine
20.03.2017 - Teine XSLT koostamine ja valmis
26.03.2017 - Retsenseerimine
01.05.2017 - Analüüsi valmimine ja lisamine koos andmebaasi failiga
11.06.2017 - Projekti faili lisamine

Tööd

XML

Teema

Spordisaalis on erinevad trennid, milles käivad erinevad isikud. XSLT jaoks siis teeme erinevad valitud filtreeringud

Lae failid alla

Lae failid alla.

XML

<?xml version="1.0" encoding="utf-8" ?>
<users>
  <subscriptions>
    <subscription name="Balance">
      <prices>
        <price type="silver" currency="EUR">44.99</price>

        <price type="gold" currency="EUR">39.99</price>
        <price type="standard" currency="EUR">50.99</price>
      </prices>
    </subscription>
    <subscription name="Gym">
      <prices>
        <price type="gold" currency="EUR">69.99</price>
        <price type="silver" currency="EUR">79.99</price>
        <price type="standard" currency="EUR">89.99</price>
      </prices>
    </subscription>
    <subscription name="BodyPump">
      <prices>
        <price type="gold" currency="EUR">44.99</price>
        <price type="silver" currency="EUR">49.99</price>
        <price type="standard" currency="EUR">55.99</price>
      </prices>
    </subscription>
    <subscription name="Yoga">
      <prices>
        <price type="gold" currency="EUR">39.99</price>
        <price type="silver" currency="EUR">42.99</price>
        <price type="standard" currency="EUR">45.99</price>
      </prices>
    </subscription>
    <subscription name="HotYoga">
      <prices>
        <price type="gold" currency="EUR">49.99</price>
        <price type="silver" currency="EUR">52.99</price>
        <price type="standard" currency="EUR">55.99</price>
      </prices>
    </subscription>
  </subscriptions>
  <user id="1" status="gold">
    <firstName><![CDATA[Peeter]]></firstName>
    <lastName><![CDATA[Banaan]]></lastName>
    <born><![CDATA[11.12.2000]]></born>
    <sex><![CDATA[M]]></sex>
    <subscriptions>
      <subscription expires="2017-05-11"><![CDATA[Balance]]></subscription>
      <subscription expires="2017-08-26"><![CDATA[Gym]]></subscription>
      <subscription expires="2017-09-01"><![CDATA[Yoga]]></subscription>
    </subscriptions>
    <contacts>
      <contact type="phone"><![CDATA[55665566]]></contact>
      <contact type="email"><![CDATA[peeter@gmail.ee]]></contact>
      <contact type="skype"><![CDATA[PeeterB]]></contact>
    </contacts>
  </user>
  <user id="2" status="silver">
    <firstName><![CDATA[Merlin]]></firstName>
    <lastName><![CDATA[Kuusk]]></lastName>
    <born><![CDATA[11.07.1997]]></born>
    <sex><![CDATA[W]]></sex>
    <subscriptions>
      <subscription expires="2017-05-13"><![CDATA[BodyPump]]></subscription>
      <subscription expires="2017-09-11"><![CDATA[Balance]]></subscription>
    </subscriptions>
    <contacts>
      <contact type="phone"><![CDATA[5123123]]></contact>
    </contacts>
  </user>
  <user id="3" status="gold">
    <firstName><![CDATA[Maarika]]></firstName>
    <lastName><![CDATA[Tamm]]></lastName>
    <born><![CDATA[05.07.1999]]></born>
    <sex><![CDATA[W]]></sex>
    <subscriptions>
      <subscription expires="2017-08-11"><![CDATA[Yoga]]></subscription>
      <subscription expires="2017-11-23"><![CDATA[HotYoga]]></subscription>
    </subscriptions>
    <contacts>
      <contact type="email"><![CDATA[maarika@gmail.com]]></contact>
    </contacts>
  </user>
  <user id="4" status="gold">
    <firstName><![CDATA[Peeter]]></firstName>
    <lastName><![CDATA[Tamm]]></lastName>
    <born><![CDATA[22.03.2000]]></born>
    <sex><![CDATA[M]]></sex>
    <subscriptions>
      <subscription expires="2017-05-13"><![CDATA[BodyPump]]></subscription>
      <subscription expires="2017-05-13"><![CDATA[Gym]]></subscription>
    </subscriptions>
    <contacts>
      <contact type="phone"><![CDATA[55588899]]></contact>
      <contact type="email"><![CDATA[PeeterT@gmail.com]]></contact>
    </contacts>
  </user>
  <user id="5" status="silver">
    <firstName><![CDATA[Mihkel]]></firstName>
    <lastName><![CDATA[Koopov]]></lastName>
    <born><![CDATA[15.06.1994]]></born>
    <sex><![CDATA[M]]></sex>
    <contacts>
      <contact type="phone"><![CDATA[55588877]]></contact>
      <contact type="skype"><![CDATA[MKoopov]]></contact>
    </contacts>
  </user>
  <user id="6" status="standard">
    <firstName><![CDATA[Georg]]></firstName>
    <lastName><![CDATA[Karu]]></lastName>
    <born><![CDATA[03.03.1994]]></born>
    <sex><![CDATA[M]]></sex>
    <subscriptions>
      <subscription expires="2017-12-17"><![CDATA[Balance]]></subscription>
      <subscription expires="2017-09-01"><![CDATA[Gym]]></subscription>
    </subscriptions>
  </user>
  <user id="7" status="standard">
    <firstName><![CDATA[Liisa]]></firstName>
    <lastName><![CDATA[Leppmaa]]></lastName>
    <born><![CDATA[15.06.1991]]></born>
    <sex><![CDATA[W]]></sex>
    <subscriptions>
      <subscription expires="2017-09-11"><![CDATA[BodyPump]]></subscription>
      <subscription expires="2017-07-10"><![CDATA[HotYoga]]></subscription>
    </subscriptions>
    <contacts>
      <contact type="phone"><![CDATA[55512377]]></contact>
      <contact type="skype"><![CDATA[LLee]]></contact>
    </contacts>
  </user>
</users>

XML schema (XSD)

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="users">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="subscriptions">
          <xs:complexType>
            <xs:sequence>
              <xs:element maxOccurs="unbounded" name="subscription">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="prices">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element maxOccurs="unbounded" name="price">
                            <xs:complexType>
                              <xs:simpleContent>
                                <xs:extension base="xs:decimal">
                                  <xs:attribute name="type" type="xs:string" use="required" />
                                  <xs:attribute name="currency" type="xs:string" use="required" />
                                </xs:extension>
                              </xs:simpleContent>
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="name" type="xs:string" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element maxOccurs="unbounded" name="user">
          <xs:complexType>
            <xs:sequence>
              <xs:choice maxOccurs="unbounded">
                <xs:element name="firstName" type="xs:string" />
                <xs:element name="lastName" type="xs:string" />
                <xs:element name="subscriptions">
                  <xs:complexType>
                    <xs:sequence>
                      <xs:element maxOccurs="unbounded" name="subscription">
                        <xs:complexType>
                          <xs:simpleContent>
                            <xs:extension base="xs:string">
                              <xs:attribute name="expires" type="xs:date" use="required" />
                            </xs:extension>
                          </xs:simpleContent>
                        </xs:complexType>
                      </xs:element>
                    </xs:sequence>
                  </xs:complexType>
                </xs:element>
                <xs:element name="contacts">
                  <xs:complexType>
                    <xs:sequence>
                      <xs:element maxOccurs="unbounded" name="contact">
                        <xs:complexType>
                          <xs:simpleContent>
                            <xs:extension base="xs:string">
                              <xs:attribute name="type" type="xs:string" use="required" />
                            </xs:extension>
                          </xs:simpleContent>
                        </xs:complexType>
                      </xs:element>
                    </xs:sequence>
                  </xs:complexType>
                </xs:element>
                <xs:element name="born" type="xs:string" />
                <xs:element name="sex" type="xs:string" />
              </xs:choice>
            </xs:sequence>
            <xs:attribute name="id" type="xs:int" use="required" />
            <xs:attribute name="status" type="xs:string" use="required" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

XSLT 1

Kuvab inimeste nime, liikme staatuse, treeningud koos hindedega

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="html" indent="yes"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>
          Workout:
        </title>
      </head>
      <body>
        <h2>People list with workout and price:</h2>

        <xsl:for-each select="/users/user">
          <xsl:text>Name: </xsl:text>
          <xsl:value-of select="firstName"/>
          <xsl:text> </xsl:text>
          <xsl:value-of select="lastName"/>
          <br></br>
          <xsl:text>Member status: </xsl:text>
          <xsl:variable name="Status" select="@status"/>
          <xsl:value-of select="@status"/>
          <br></br>
            <xsl:if test="subscriptions/subscription != ''">
              <xsl:text>Workouts and prices: </xsl:text>
              <ul>
                <xsl:for-each select="subscriptions/subscription">
                  <li>
                    <xsl:text>     </xsl:text>
                    <xsl:variable name="SelectedSubscription" select="translate(text(), ' ', '')"/>
                    <xsl:for-each select="/users/subscriptions/subscription">
                      <xsl:variable name="Subscription" select="@name"/>
                      <xsl:if test="$Subscription= $SelectedSubscription">
                        <xsl:for-each select="prices/price">
                          <xsl:if test="$Status = @type">
                            <xsl:value-of select="$Subscription"/>
                            <xsl:text>: </xsl:text>
                            <xsl:value-of select="."/>
                            <xsl:value-of select="@currency"/>
                          </xsl:if>
                        </xsl:for-each>
                      </xsl:if>
                    </xsl:for-each>
                  </li>
                </xsl:for-each>
              </ul>
            </xsl:if>
          <br></br>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Näidis

XSLT 2

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <main>
      <xsl:for-each select="users/subscriptions/subscription">
        <subscription>
          <xsl:attribute name="id">
            <xsl:value-of select="position()"/>
          </xsl:attribute>
          <xsl:attribute name="name">
            <xsl:value-of select="@name"/>
          </xsl:attribute>
          <xsl:variable name="currentSubscription" select="@name" />
          <usersWithPrices>
            <xsl:for-each select="/users/user">
              <xsl:variable name="currentUser" select="."></xsl:variable>
              <xsl:for-each select="subscriptions/subscription">
                <xsl:variable name="sub" select="."/>
                <xsl:if test="$sub = $currentSubscription">
                  <userWithPrice>
                    <user>
                      <xsl:attribute name="id">
                        <xsl:value-of select="$currentUser/@id"/>
                      </xsl:attribute>
                      <xsl:value-of select="$currentUser/firstName"/>
                      <xsl:text> </xsl:text>
                      <xsl:value-of select="$currentUser/lastName"/>
                    </user>
                    <xsl:variable name="status" select="$currentUser/@status"/>
                    <xsl:for-each select="/users/subscriptions/subscription">
                      <xsl:variable name="subscr" select="."></xsl:variable>
                      <xsl:for-each select="$subscr/prices/price">
                        <xsl:if test="$subscr/@name = $currentSubscription">
                          <xsl:variable name="curObj" select="."/>
                          <xsl:if test="$curObj/@type = $status">
                            <price>
                              <xsl:attribute name="currency">
                                <xsl:value-of select="$curObj/@currency"/>
                              </xsl:attribute>
                              <xsl:attribute name="type">
                                <xsl:value-of select="$curObj/@type"/>
                              </xsl:attribute>
                              <xsl:value-of select="."/>
                            </price>
                          </xsl:if>
                        </xsl:if>
                      </xsl:for-each>
                    </xsl:for-each>
                  </userWithPrice>
                </xsl:if>
                <xsl:value-of select="@status"/>
              </xsl:for-each>
            </xsl:for-each>
          </usersWithPrices>
        </subscription>
      </xsl:for-each>
    </main>
  </xsl:template>
</xsl:stylesheet>

Näidis

<?xml version="1.0" encoding="utf-8"?>
<main>
  <subscription id="1" name="Balance">
    <usersWithPrices>
      <userWithPrice>
        <user id="1">Peeter Banaan</user>
        <price currency="EUR" type="gold">39.99</price>
      </userWithPrice>
      <userWithPrice>
        <user id="2">Merlin Kuusk</user>
        <price currency="EUR" type="silver">44.99</price>
      </userWithPrice>
      <userWithPrice>
        <user id="6">Georg Karu</user>
        <price currency="EUR" type="standard">50.99</price>
      </userWithPrice>
    </usersWithPrices>
  </subscription>
  <subscription id="2" name="Gym">
    <usersWithPrices>
      <userWithPrice>
        <user id="1">Peeter Banaan</user>
        <price currency="EUR" type="gold">69.99</price>
      </userWithPrice>
      <userWithPrice>
        <user id="4">Peeter Tamm</user>
        <price currency="EUR" type="gold">69.99</price>
      </userWithPrice>
      <userWithPrice>
        <user id="6">Georg Karu</user>
        <price currency="EUR" type="standard">89.99</price>
      </userWithPrice>
    </usersWithPrices>
  </subscription>
  <subscription id="3" name="BodyPump">
    <usersWithPrices>
      <userWithPrice>
        <user id="2">Merlin Kuusk</user>
        <price currency="EUR" type="silver">49.99</price>
      </userWithPrice>
      <userWithPrice>
        <user id="4">Peeter Tamm</user>
        <price currency="EUR" type="gold">44.99</price>
      </userWithPrice>
      <userWithPrice>
        <user id="7">Liisa Leppmaa</user>
        <price currency="EUR" type="standard">55.99</price>
      </userWithPrice>
    </usersWithPrices>
  </subscription>
  <subscription id="4" name="Yoga">
    <usersWithPrices>
      <userWithPrice>
        <user id="1">Peeter Banaan</user>
        <price currency="EUR" type="gold">39.99</price>
      </userWithPrice>
      <userWithPrice>
        <user id="3">Maarika Tamm</user>
        <price currency="EUR" type="gold">39.99</price>
      </userWithPrice>
    </usersWithPrices>
  </subscription>
  <subscription id="5" name="HotYoga">
    <usersWithPrices>
      <userWithPrice>
        <user id="3">Maarika Tamm</user>
        <price currency="EUR" type="gold">49.99</price>
      </userWithPrice>
      <userWithPrice>
        <user id="7">Liisa Leppmaa</user>
        <price currency="EUR" type="standard">55.99</price>
      </userWithPrice>
    </usersWithPrices>
  </subscription>
</main>

Jõusaali infosüsteemi analüüs

Lühikirjeldus

JRT on jõusaali kasutamise rakendus, mis on peamiselt mõeldud jõusaali külastajale, kes näevad erinevaid treeningkavasid ning harjutusi ja saavad üles märkida oma saavutusi.

Must have

Kasutusgruppide alla kuuluvad rakenduse tavakasutajad, administraatorid ja treenerid. Lõppkasutajal on võimalik luua oma konto, kuhu ta sisestab regulaarselt oma kehamõõtusid. Tavakasutaja saab valida omale füüsilise aktiivsuse kestuse, treeningu tüübi ning harjutused, millest see koosneb. Tavakasutajad näevad treenerite kontaktandmeid, et nendega ühendust võtta, saamaks treeningkavasse soovitusi või lasta treeneritel teha neile päris enda treeningkava.

Nice to have

Administraatoril on võimalik tutvuda statistikaga selle kohta, milliseid harjutusi kõige rohkem tehakse, millistele lihasegruppidele ning millistel aegadel on üht- või teistsugused harjutused populaarsemad. On loodud treenerite ja administraatorite kasutajaliides. Tavakasutajal on võimalik enda treeningute andmete põhjal tekitada igasuguseid graafikuid ja nende analüüsi. Tavakasutajal on võimalik saata teateid treeneritele ja teistele rakenduse tavakasutajatele. Treenerite kasutajaliidesest saab ülevaate selle kohta, millised tavakasutajad on tema õpilased, kuidas neil treeningutega läheb (statistika, teated) ning milline on tema enda eelseisev töögraafik. Administraatoril on võimalik saata kasutajatele teateid (näiteks, et klubi on suletud või et alanud on kampaaniaperiood).

Administraatori liides

Administraatoril on võimalus hallata kõiki andmeid (näiteks lisada ja kustutada: kasutajaid, harjutusi, treenigukavasid jne).

Kasutajaliides

Tavakasutaja liideses on võimalik sisestada oma keha kohta viimaseid andmeid, panna kirja infot viimase treeningu kohta ning lisada omale kontaktandmeid. Valida treeningukavasid ja paigutada need soovitud päevadele.

Andmebaasi kirjeldus

Projekti fail

Projekt tehtud siis kahe liikme poolt: Riho Uusjärv ja Jevgeni Gavrilov ja projekti fail asub aadressil: https://drive.google.com/open?id=0B3nb9qMzOVSuQ1NOdk02bmhUT3c

Retsensioonid

XML Retsensioonid

Retsensioon meeskonnale "PC KartKicker"

Meeskonna "PC KartKicker" XML failide sisu leiab [1]

  • XML

XML fail valideerimisel ei olnud ühtegi viga. On olemas nõutud 4 loogilist dimensiooni ning atribuute on ka piisavalt ning need on sammuti piisavalt spetsiifilised ehk kõik õppejõu märgitud kriteeriumid on täidetud. XML jaotus on korrektne ja kergesti arusaadav. CDATA oleks võinud kastusel olla.

  • Skeemifail (XSD)

XML ei vasta XSD kirjelduses nõutud väljade parameetrile ehk storages-> storage -> type on XSD-s puudu. Enda eelistused:

  • maxGpuLength string -> integer
  • maxCpuHeight string -> integer
  • cooler string -> boolean
  • ECC string -> boolean
  • speed string -> decimal
  • liquid string -> boolean
  • usb3 string -> boolean

Mitmed errorid:

Cvc-complex-type.3.2.2: Attribute 'type' Is Not Allowed To Appear In Element 'storage'., Line '102', Column '140'.
Cvc-datatype-valid.1.2.1: '' Is Not A Valid Value For 'integer'., Line '102', Column '140'.
Cvc-attribute.3: The Value '' Of Attribute 'rpm' On Element 'storage' Is Not Valid With Respect To Its Type, 'integer'., Line '102', Column '140'.
Cvc-complex-type.3.2.2: Attribute 'type' Is Not Allowed To Appear In Element 'storage'., Line '103', Column '142'.
Cvc-datatype-valid.1.2.1: '' Is Not A Valid Value For 'integer'., Line '103', Column '142'.
Cvc-attribute.3: The Value '' Of Attribute 'rpm' On Element 'storage' Is Not Valid With Respect To Its Type, 'integer'., Line '103', Column '142'.
Cvc-complex-type.3.2.2: Attribute 'type' Is Not Allowed To Appear In Element 'storage'., Line '104', Column '143'.
Cvc-datatype-valid.1.2.1: '' Is Not A Valid Value For 'integer'., Line '104', Column '143'.
Cvc-attribute.3: The Value '' Of Attribute 'rpm' On Element 'storage' Is Not Valid With Respect To Its Type, 'integer'., Line '104', Column '143'.
Cvc-complex-type.3.2.2: Attribute 'type' Is Not Allowed To Appear In Element 'storage'., Line '105', Column '153'.
Cvc-complex-type.3.2.2: Attribute 'type' Is Not Allowed To Appear In Element 'storage'., Line '106', Column '154'.
Cvc-complex-type.3.2.2: Attribute 'type' Is Not Allowed To Appear In Element 'storage'., Line '107', Column '148'.
  • Transformatsioonid

Vead:

  • Tegemist on mõlemal juhul vaid ühe for-each tsükliga
  • Pole kasutatud tingimusi
  • Pole tehtud eraldi HTML ja XML

Mõlemad XSLT-d ei vasta väljatoodud nõuetele

  • Kokkuvõtte

Lohakas töö, tundub et üks liige on selle kiirelt ära teinud, et õigeks ajaks valmis saada ja teised ei vaevunud vaatamagi. Validaatoriga oleks võinud vähemalt üle lasta ja pisi vead likvideerida aga sedagi pole tehtud. Oleks soovitanud vähem vaeva näha kirju XML-iga ja seda aega kulutada korrektse XSD ja XSLT-d tegemiseks.

Retsensioon meeskonnale "Ninjas in pyjamas"

  • XML

XML fail valideerub. Hea on see, et on kasutatud CDATA formaati. Siiski pole täidetud kõiki õppejõu poolt ettenähtud nõudeid: atribuute on (mis ei ole lihtsalt id) lisatud kahele dimensioonile ('ticket' ja 'user'), kuid peaks olema lisatud kolmele dimensioonile. Lisaks pole väga hästi arusaadav (lugedes ideekirjeldust), miks osa kasutaja andmeid (e-kiri, roll) on määratud atribuudina, teised (kasutajanimi) jällegi elemendina.Atribuut role antud kontekstis ei oma mingid konkreetset väärtust (rollidel on id, aga kus on nende nimekiri?). Teine küsimus miks priority Id on 1 täht, on selles mingi vajadus? Lihtam kasutada int. CDATA pole kasutusel kõikidel väljadel, mis võib olla ohtlik. Kuigi seda tõenäoliselt hetkel ei pea hindama, siis meeskonnale võib olla kasulik teada, et juhul kui süsteem peab võrdlema päringu saabumise aega sellele vastamise ajaga, siis XML-is ei ole kellaaega, vaid on kuupäev. Ühtlasi puudub XML-is info selle kohta, kas päring on lahendatud või mitte.

  • Skeemifail (XSD)

XSD puhul annab validaator järgmised veateated:

Not valid.
Error - Line 15, 90: org.xml.sax.SAXParseException; lineNumber: 15; columnNumber: 90; s4s-elt-must-match.1: The content of 'priority' must match (annotation?, (simpleType | complexType)?, (unique | key | keyref)*)). A problem was found starting at: attribute.
Error - Line 22, 93: org.xml.sax.SAXParseException; lineNumber: 22; columnNumber: 93; s4s-elt-must-match.1: The content of 'user' must match (annotation?, (simpleType | complexType)?, (unique | key | keyref)*)). A problem was found starting at: attribute.
Error - Line 35, 84: org.xml.sax.SAXParseException; lineNumber: 35; columnNumber: 84; s4s-elt-must-match.1: The content of 'attachment' must match (annotation?, (simpleType | complexType)?, (unique | key | keyref)*)). A problem was found starting at: attribute.

Veateadetest kõige ilmsem näib olevat element "priority", mis võiks olla mitte "string", vaid "int".

  • Transformatsioonid

Esimene XSLT valideerub (XSLT => HTML). Paraku on seal sisuliselt ainult üks for-each klausel (asi, mille eest õppejõud hoiatab). Siinkohal jääb natuke segaseks varasemas XSL-is sisse toodud "title" element. Mida selle all mõeldakse? Kas iga päring saab pealkirja, mis on erinev probleemi kirjeldusest ja kasutaja andmetest?

Teine XSLT (XSLT => XML) ei valideeru. Veateade on järgmine:

Not valid.
FatalError: javax.xml.transform.TransformerException: A location step was expected following the '/' or '//' token.

Sisulise poole pealt on tehtud üks "for-each" ja üks "sort", ülejäänud on "value-of"-id. Muidu kõik kena, kuid natuke lühike ehk?

  • Kokkuvõtte

Tööd on küll esitatud ja vaeva nähtud, kuid kõik lahenduste aspektid ei vasta siiski õppejõu poolt ettenähtud nõuetele. Lisaks on probleeme osade koodide valideerumisega (XSD ja üks XSLT). Need asjad tasuks rakenduse edasist arendamist silmas pidades üle vaadata.

Veebiteenuse Retsensioonid

Meeskond CoverMe retsensioon meeskonnale SPOT

Meeskonna eesmärk oli luua veebiteenus, mis võimaldab saada infot pakutavate treeningute kohta, sisestada ja kuvada tunniplaani andmeid, registreerida osalejaid tundidesse ning end sealt eemaldada. Samuti oli ette nähtud, et administraatorid saavad lisada, muuta ja kustutada kõike sprodiklubiga seonduvat ning treenerid ja spordiklubi esindajad saavad toimetada treeningutega seotud andmete sisestamise ja muutmisega. Andmebaasimudel on tehtud väga põhjalikult ning tabelite kirjeldused on samuti välja toodud.

Meie hinnangul on eesmärk põhiosas täidetud, realiseeritud on enamus kavandatud must-have funktsionaalsusest (välja on jäänud logimine). Loodud on veebiteenus, mis kasutab REST arhitektuuri ja ASP.NET MVC Web Api tehnoloogiat.

Veebiteenuse struktuur on üles ehitatud kihiliselt, mis võimaldab vajadusel süsteemi osasid lihtsamini muuta, täiendada ja vajadusel välja vahetada. Kihid on jaotatud järgmiselt: BL - sisaldab DTO-sid ja nende koostamiseks vajalikke Factoreid. Samuti on siin Service klassid, milles on kirjas kõik päringud andmebaasist (Get mitmesugustes variantides, Add, Edit, Delete). Lisaks tavalistele CRUD meetoditele on tehtud ka spetsiifilisemad päringud , näiteks GetByIdForUser jne. Päringuid tehakse uow-de kaudu. Service’tele ja Factory’tele on loodud Interface’d. DAL - kasutatakse EFRepositoryFactory ja EFRepositoryProvidery põhimõtteid. DbInitializeris antakse ette lähteandmete seed’imine. Repositooriumid on omaette kaustas, kuhu on lisaks EFRepository-st päritud meetoditele juurde kirjutatud palju erinevaid meetodeid funktsionaalsuse täiendamiseks. Domain - andmebaasi mudelis on kokku 12 olemit, mis on nõuetele vastav. Üldine andmebaasimudeli ülesehitus on loogiline ning listid on algselt väärtustatud, mis tagab selle, et ei pea NullReference Exceptione kontrollima. Vajalikesse kohtadesse on annotatsioonid juurde lisatud ja nendega ei ole üle pingutatud, et süsteemi liiga kirjuks ajada. Tõstame esile asjaolu, et kasutatud on Base Entity’t, millest kõik ülejäänud olemid pärinevad. See ühtlustab rakenduse koodi ja on üldse väga hea mõte. Kasutatud on palju nullable tüüpi muutujaid, mis on antud juhul õigustatud, andes andmete sisestamisel paindlikkust, samas lisades mõneti riskantsust. Interfaces - Kõikide repositooriumide jaoks on loodud ka interface´d. Samuti leidub seal UOW jaoks interface. WebApi - Kokku on kasutusel 6 kontrollerit, milles on realiseeritud CRUD meetodid koos mõne spetsiifilisema meetodiga (näiteks GetFilteredForPeriod). Kontrollerid saavad oma sisu vastavatest service’itest. Identity rakendamiseks on kontrollerite meetoditel kasutatatud Authorize annotatsioone. Samuti on läbi mõeldud, et mõnda meetodit on autoriseeritud kasutama ainult “Admin”-kasutaja. Näiteks ainult “Admin”, saab salvestada treenereid andmebaasi. Kontrollerites on kenasti kasutatud erinevaid Http-staatuskoode, mitte ainult Ok(), vaid ka Forbidden(), NotFound() jne. Samuti kasutatakse edukalt sõltuvuste süstimist (Dependency Injection). Kasutatud on OAuth bearer token authentication’it.

Lisaks peame oluliseks märkida, et kood on kirjutatud heas stiilis, kõikjal inglise keeles, ei esine keelte segunemist. Paljudes kohtades oli kood kommenteeritud, kuid see tundus olevat ise kaasa tulnud. Meeskonna enda kommentaare ei paistnud.

Kokkuvõtteks võib öelda, et tegemist on väga hästi kavandatud ja realiseeritud veebiteenusega ja meeskonnaliikmete panus on olnud märkimisväärne, eriti arvestades seda, et tegemist oli vaid kahe liikmega.


Retsensioon meeskonnale "SPOT"

Retsenseeritavaks tööks oli valitud tiimi SPOT veebiteenus, mis on seotud spordiklubide treeningute haldamisega. Esialgses andmebaasi skeemis oli plaanitud teha 16 tabelit, millest 4 on entitytega seotud. Projektis oli ära tehtud 12 domeeni mudeleid + entitytega seotud automaatselt. Mudelid tunduvad loogilised olla. On kasutatud propertid, mida andmebaasi ei salvestata, aga kalkuleeritakse jooksvalt. On kasutatud ka BaseEntity, milles on CreatedAt jne, ja kõik teised olemid pärinevad sellest, minu arust väga hea lahendus. Teenuse seadistatus, et tagastada jsoni igasuguste settingutega. API Routing pole muudetud, eriolukordade jaoks kasutatakse routingu atribuutides. Rakenduses on realiseeritud Seed meetod, mis väärtustab andmebaasi testandmetega. On näha, et testandmete täitmisel on kasutatud üks väline xml fail, faili töötlemises on kasutatud nii foreach tsükleid, kui ka LINQ avaldisi. Oleks hea kui paljudes kohtades null reference exceptioni vältimiseks teeks checki, aga muidu kui võtta arvesse, et see XML ei muutu kunagi, siis tehtud/pakutud variant ka sobib. Data access layer on ilusasti tehtud, iga olemi jaoks tehtud repositoorium, mis oma korda implementeerib interface’i. Repositooriumide päringul on ka realiseeritud singletoni muster. Järgmisel tasemel on tehtud UOW, kus on kasutusel nii Custom Repo küsimine, kui ka Standard. NLOg logimine on ka ilusasti implementeeritud. Üldiselt DAL projekti vaadates tekib tunne, et tiim on seda läbi töötanud ja ilusasti häid praktikaid kasutades tegi ära. Järgmine projekt on “BL”, kohe näha, et projekt on ilusasti struktureeritud, kasutatakse factoreid ja serviceid, mil omakorda implementeerivad interface. Data Transfer objektides ei ole miksimist domeen olemitega, mis on hästi, kuna selline olukord tekitaks “lazy loading”-uga, et kõik seosed ja andmed tuleksid andmebaasist, mida pole vaja. DTO-des ei ole kasutatud atribuute, mis sõltuvalt olukorrast võib olla halb, kuna puudub igasugune kontroll mida kasutaja saadab teenuse peale. Nagu ennem oli öeldud, et interfacid on kasutusel, aga objekti loomisel ei kasutata DI mootorit, vaid luuakse otse new keyword’iga. Andmebaasi salvestamine käib läbi UOW. Kõik DTO-d, serviced ja factoryd tunduvad läbimõeldud. Solution’is eksisteerib projekt nimega “ConsoleApp” tundub, et tiim kasutas seda oma veebiteenuse testimiseks. Järgmine projekt on DataAnnotations, milles olemas ainuke klass “Precision”, Internetis otsides ja koodi vaadates, sain teada, et seda kasutatakse decimal täpsuse kindlaks tegemiseks ja sellist valmis lahenduse .net-is pole. SPOT tiimi solution’is ma kahjuks ei leidnud mitte ühtegi kohta kus seda kasutatakse. Järgmine projekt on Identity, kus on kõik olemid identity’ga seotud ja vajalikud services. Järgmine projekt ‘’Interfaces’’, kus hoitakse peaaegu kõik interfacid. Ja viimane projekt on “WebApi”, mis hoiab endas veebiteenuste kontrollereid, vaateid, scripte ja teisi faile. Kontrollerist on näha, et tiim tegi ümber Entity Useri primaarse võtme stringist integeri. On kasutusel Authorize atribuudid, mis piiravad liigipääsu erinevatele kontrolleritele/meetoditele. Samuti veebiteenuses eksisteerivad erinevad rollid (Admin ja treener), neid ka kasutatakse Authorize atribuutides. Samuti kontrollerites on kasutusel GET, POST, PUT ja DELETE päringute päised. Kontrollerites on implementeeritud sünkroonne lähenemine (pole kusagil olemas async võtmesõna). Kui rääkida tööst üldiselt, siis kohe näha, et tiim tegi suure töö (see pole mahulises mõttes lõpetatud, aga kogu baas on olemas, jäänud ainult DTO-de tegemine ja nende käsitlemine). Ainukesed puudused, mida ma näen, on DTO-des atribuutide puudumine. Aga muidu tuli välja ilus, loogiliselt struktureeritud veebiteenus.