TIE-20200 Ohjelmistojen suunnittelu



Samankaltaiset tiedostot
TIE Ohjelmistojen suunnittelu

TIE Ohjelmistojen suunnittelu. Viimeinen luento: kertaus

TIE Ohjelmistojen suunnittelu. Viimeinen luento: kertaus

TIE Ohjelmistojen suunnittelu

TIE Ohjelmistojen suunnittelu

TIE Ohjelmistojen suunnittelu. Luento 8..9: moniperintä

TIE Ohjelmistojen suunnittelu

TIE Ohjelmistojen suunnittelu

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

TIE Ohjelmistojen suunnittelu

TIE Ohjelmistojen suunnittelu

T Olio-ohjelmointi Osa 5: Periytyminen ja polymorfismi Jukka Jauhiainen OAMK Tekniikan yksikkö 2010

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

TIE Samuel Lahtinen. Lyhyt UML-opas. UML -pikaesittely

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. IX Suunnittelumallit Proxy, Factory Method, Prototype ja Singleton

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

Aalto Yliopisto T Informaatioverkostot: Studio 1. Oliot ja luokat Javaohjelmoinnissa

Ohjelmointikielet ja -paradigmat 5op. Markus Norrena

Huonon suunnittelun oireita. Hajuja ja sääntöjä. Hyvän suunnittelun periaatteet. Paha haju

TIE Ohjelmistojen suunnittelu

15. Ohjelmoinnin tekniikkaa 15.1

Ohjelmistoarkkitehtuurit Syksy 2009 TTY Ohjelmistotekniikka 1

Kehyspohjainen ohjelmistokehitys

JReleaser Yksikkötestaus ja JUnit. Mikko Mäkelä

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

Rajapinnasta ei voida muodostaa olioita. Voidaan käyttää tunnuksen tyyppinä. Rajapinta on kuitenkin abstraktia luokkaa selvästi abstraktimpi tyyppi.

Tenttikysymykset. + UML-kaavioiden mallintamistehtävät

Osoitin ja viittaus C++:ssa

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. VII Suunnittelumallit Adapter ja Composite

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

TIE Ohjelmistojen suunnittelu

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Ohjelmistotekniikan menetelmät, suunnittelumalleja

Ohjelmistoarkkitehtuurit Komponentit Kevät 2014

9. Periytyminen Javassa 9.1

Esimerkkiprojekti. Mallivastauksen löydät Wroxin www-sivuilta. Kenttä Tyyppi Max.pituus Rajoitukset/Kommentit

Sisällys. 11. Rajapinnat. Johdanto. Johdanto

4. Luokan testaus ja käyttö olion kautta 4.1

Yksikkötestaus. import org.junit.test; public class LaskinTest public void testlaskimenluonti() { Laskin laskin = new Laskin(); } }

A) on käytännöllinen ohjelmointitekniikka. = laajennetaan aikaisemmin tehtyjä luokkia (uudelleenkäytettävyys)

Ohjelmoinnin jatkokurssi, kurssikoe

Olio-ohjelmoinnissa luokat voidaan järjestää siten, että ne pystyvät jakamaan yhteisiä tietoja ja aliohjelmia.

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

9. Periytyminen Javassa 9.1

Ohjelmistotuotanto. Luento

15. Ohjelmoinnin tekniikkaa 15.1

2. Olio-ohjelmoinista lyhyesti 2.1

P e d a c o d e ohjelmointikoulutus verkossa

12. Kehysarkkitehtuurit

TT00AA Ohjelmoinnin jatko (TT10S1ECD)

SEPA REFAKTOROINTI Antti Ahvenlampi, 57408L Erik Hakala, 57509T

JWT 2016 luento 11. to klo Aulikki Hyrskykari. PinniB Aulikki Hyrskykari

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Ylläpitodokumentti. Boa Open Access. Helsinki Ohjelmistotuotantoprojekti HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Muutamia peruskäsitteitä

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

Kehyksillä toteuttettujen tuotelinjojen rakenteellinen optimointi

<e.g. must, essential, conditional>

Rajapinta (interface)

3. Komponentit ja rajapinnat

812336A C++ -kielen perusteet,

Sisällys. JAVA-OHJELMOINTI Osa 6: Periytyminen ja näkyvyys. Luokkahierarkia. Periytyminen (inheritance)

Olio-ohjelmointi Javalla

Rajapinnat ja olioiden välittäminen

Jypelin käyttöohjeet» Miten voin liittää törmäyksiin tapahtumia?

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Pakkaukset ja määreet

Olio-ohjelmointi: Luokkien toteuttaminen. Jukka Juslin

BlueJ ohjelman pitäisi löytyä Development valikon alta mikroluokkien koneista. Muissa koneissa BlueJ voi löytyä esim. omana ikonina työpöydältä

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Ohjelmointi 2 / 2010 Välikoe / 26.3

Kertaus: yleistys-erikoistus ja perintä

C++11 Syntaksi. Jari-Pekka Voutilainen Jari-Pekka Voutilainen: C++11 Syntaksi

Ohjelmistojen mallintaminen. Luento 11, 7.12.

Ohjelmistojen mallintaminen, suunnittelumalleja

Encapsulation. Imperative programming abstraction via subprograms Modular programming data abstraction. TTY Ohjelmistotekniikka

Olio-ohjelmointi Suunnittelumallit Proxy, Factory Method, Prototype ja Singleton. 1. Proxy (Edustaja)

Lyhyt kertaus osoittimista

Virtuaalifunktiot ja polymorfismi

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

1 Tehtävän kuvaus ja analysointi

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. VIII Suunnittelumallit Observer ja State

Graafisen käyttöliittymän ohjelmointi Syksy 2013

Javan perusteita. Janne Käki

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

Ohjelmistojen mallintaminen, arkkitehtuuria ja rajapintoja

Ohjelmistotuotanto. Luento

Olio-ohjelmointi Suunnittelumallit Adapter ja Composite. 1. Adapter

1. Olio-ohjelmointi 1.1

11. Kehysarkkitehtuurit

Java kahdessa tunnissa. Jyry Suvilehto

Ohjelmistotuotanto. Luento

Ohjelmistojen mallintaminen. Luento 7,

Ohjelmistoarkkitehtuurit kevät

Linkitetystä listasta perittyä omaa listaa käytetään muun muassa viestiin liittyvien vastausten säilömiseen.

TIE Ohjelmistojen suunnittelu

Sokkelon sisältö säilötään linkitetyille listalle ja tekstitiedostoon. Työ tehdään itsenäisesti yhden hengen ryhmissä. Ideoita voi vaihtaa koodia ei.

UML Luokkakaavio 14:41

Graafisen käyttöliittymän ohjelmointi Syksy 2013

Transkriptio:

TIE-20200 Ohjelmistojen suunnittelu Luento 7: SOLID ja olioiden rakentelumalleja TIE-20200 Samuel Lahtinen 1

Ajankohtaista Harjoitustyössä suunnittelusessioiden ajanvaraus auki Viikkoharjoituksissa tehtaaseen/rakennuttajiin tutustumista (ja periytymisen käyttöä)

Ohjelmassa tänään Hippusellinen lisätarinaa MVC:stä (yms. jutuista) Harkkatöiden suunnitteluvaiheeseen soveltuvaa kamaa Olioiden luomista, Abstrakti tehdas yms. SOLID, yleisiä olio-ohjelmoinnin suunnitteluperiaatteita

SOLID, hyviä periaatteita Viisi olio-ohjelmoinnin perusperiaatetta, muistisääntö S Single responsibility principle O Open/closed principle L Liskov substitution principle I Interface segregation principle D Dependency inversion principle Ei estä ketterää kehitystä tai muutakaan mukavaa, päin vastoin helpottaa näitä Muutokset, laajentaminen, päivittäminen helpompaa, voidaan toimia ketterästi ilman loppuunasti hiottua suunnitelmaa

Single responsibility principle Single responsibility principle (SRP) a class should have only a single responsibility. Vain yksi vastuualue/luokka Pohjautuu reason-to-change ajetelmaan, jokaisella luokalla pitäisi olla vain yksi huolehdittava asia, vain yksi syy, miksi luokan toteutusta pitäisi muuttaa. Jos luokalla kaksi tai useampi muutossyy, voi muutoksella yhden vastuualueen toimiin olla helposti vaikutusta toisen toimintaan (korjataan yhtä, rikotaan toinen) Uudelleenkäyttö ja eriyttäminen vaikeampaa, kun mukana tulee ylimääräistä kuormaa

Single responsibility principle Saman luokan kaksi vastuuta (reason for change), muutos toiseen voi rikkoa toisen puolen toiminnallisuuden Vastuualueiden jako (esim. GUI-versio käyttää GeometrisenSuorakaiteen palveluita, laskentapuolella käytetään vain geom. osaa) Suorakaide +laskeala(): double +piirraruudulle() GUI Matemaattinen laskentaosuus GUIsovellus Vaarat: turha kompleksisuuden lisääminen, jos vastuualueet muuttuvat aina yhdessä, ei niiden eriyttämisestä ole iloa TIE-20200 Samuel Lahtinen Yleinen kompromissiratkaisu, tehdään erilliset rajapinnat, sama toteuttaja. Helpompi muuntaa ja korjata, jos tarve ilmenee.

Open-closed principle Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification You should be able to extend a classes behavior, without modifying it. Moduulit ja luokat: Ovat avoimia laajennuksille, toiminnallisuutta voidaan lisätä, rajapintaa laajentaa uusilla palveluilla Suljettu muutoksilta: moduulin tai luokan toteutusta ei saa muuttaa Koodi testattu, katselmoitu jne, sitä ei enää muuteta Kuulostaa ristiriitaiselta, ideana hyödyntää abstraktioita Voidaan käyttää hyväksi perintää, (abstrakteja) kantaluokkia Ohjelmat, joissa hyödynnetään open-closed periaatetta, muutetaan lisäämällä uutta koodia, ei muuttamalla olemassa olevaa Ei realistisesti mahdollista päästä tilanteeseen, jossa 100% koodista suljettuna muutoksilta pitää tehdä päätöksiä siitä, mihin panostetaan, missä ohjelman osissa tulee todennäköisimmin muutoksia? Abstraktiot, ja osan ohjelmakoodin sulkeminen.

Open-closed principle Vinkkejä noudattamisen helpottamiseen: Ei julkisia tai protected jäsenmuuttujia, ei globaaleja muuttujia Vältä: Olioiden omistaminen arvoina, arvoparametrien käyttö (C++) Viitteet, osoittimet, voidaan antaa käyttöön erikoistettu versio jne. Älä käytä dynamic_castiä tyyppitarkastusten tekemiseen, vain laajennettuun rajapintaan kiinni pääsemiseen (tai toteutetun rajapinnan toteuttamisen tarkastamiseen), esimerkki huonosta tavasta(taululle)

Liskov substitution principle Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. Derived classes must be substitutable for their base classes Mikä tahansa aliluokan instanssi kelpaa kantaluokkaolion tilalle (ilman että ohjelman toiminta kärsii/muuttuu virheelliseksi) C++-maailmassa: mikä tahansa viitteen tai osoittimen luokkaan ottavan funktion on pystyttävä käyttämään mitä tahansa luokan aliluokkaa ilman että funktion toteutuksessa täytyy tietää todellinen tyyppi (taas vääränlaiset tyyppimuunnokset jne.) Toiminnalliset aliluokat: Toiminnallinen lisävaatimus pelkän syntaksivaatimuksen lisäksi (semantiikka), ei pelkkä syntaktinen yhteensopivuus (samat funktion protyypit jne.)

Liskov substitution principle, Rikkomisen seuraamuksia Otetaan esimerkkinä (taas) suorakaide ja siitä peritty neliö, vektori ja järjestetty vektori, perustietovarasto ja tilaoptimoiva tietovarasto Päästään takaisin is-a-suhteen merkitykseen Is-a-suhdetta ja Liskovin periaatetta ei pidä rikkoman koodirivejä säästääkseen tai pelkän käsitteellisen sukulaisuuden takia Sopimussuunnittelu ja Liskov: aliluokat eivät saa rikkoa kantaluokan sopimuksia Vain periaatetta noudattamalla on mahdollista kirjoittaa luokkia käyttävää koodia ja luottaa siihen, että uudet lisäykset (uudet luokat) eivät hajota olemassa olevan koodin toimintaa void testaa( Suorakaide& s ) { s.asetakorkeus( 6 ); s.asetaleveys( 3 ); assert( s.leveys()*s.korkeus() == 18 ); } class Suorakaide { public: virtual void asetakorkeus( int k ); virtual void asetaleveys( int l ); int leveys() const; int korkeus() const; private: int korkeus_; int leveys_; }; class Nelio: public Suorakaide { public: virtual void asetakorkeus( int k ); virtual void asetaleveys( int l ); };

Interface segregation principle many client-specific interfaces are better than one general-purpose interface. Make fine grained interfaces that are client specific Rajapinnan käyttäjän ei pidä olla riippuussuhteessa palveluihin/funktioihin joita se ei tarvitse/käytä Jaetaan isommat rajapinnat pienemmiksi roolien mukaan, saadaan roolirajapintoja (role interfaces) Isompi ohjelma, jossa paljon keskinäisiä riippuvuuksia ja isoja möhkälerajapintoja pienikin muutos heijastuu joka puolelle muutoksen tekijä joutuu tonkimaan muutettavat asiat muun turhan sälän seasta yksittäiseen asiaan liittyvän toteutuksen vaihtaminen vaatii copy-pastea vanhoista koodeista Uusien ominaisuuksien lisääminen vaatii uuden asian lisäämisen lisäksi vanhan huomioimista

Interface segregation Anti-versio periaatteesta, yksi iso möhkäleluokka, joka tarjoaa lähes kaikki toiminnot. Vaikea hallita, päivittää, muuttaa, jos rinnakkaisuutta, saadaan suorituskykyongelmat mukaan Lihavat rajapinnat (fat interfaces), rajapintojen saastuminen (interface pollution)

Asiakas 1 Asiakas 2 palvelu Asiakas 3 Asiakas 1 Asiakas 2 Asiakas 3 Rajapinta 1 Rajapinta 2 Rajapinta 3 Palvelun toteutus

Interface segregation principle Rajapintojen saastuminen ja perintä: Ajastus, ovi, ajastettu ovi Tuote, Peli, CD, housut Käyttäjä (sisäänkirjautumisessa): aliluokat, vieras, normi, admin Mitä kantaluokkaan, mitä erillisiin rajapintoihin, mitä aliluokkiin?

Dependency inversion principle A) High-level modules should not depend on low-level modules. Both should depend on abstractions. B) Abstractions should not depend upon details. Details should depend upon abstractions. http://www.objectmentor.com/resources/articles/dip.pdf Riippuvuudet abstraktioihin, ei konkreettisiin toteutuksiin Huonon suunnittelun kriteeristöä: Ei siirrettävää koodia, ohjelman rakenne täynnä riippuvuuksia, komponentteja ei voi uudelleen käyttää tai siirtää näiden takia Jäykkyys, yksittäinen muutos vaikuttaa moneen muuhun osaan Hauraus, muutos yhteen osaan rikkoo asioita muualla

Korkea taso (sovelluslogiikan kannalta) Abstraktio(kerros) Rajapinnat Matalamman tason toteutus

Dependency inversion principle Korkeamman tason komponentit eivät saa olla riippuvaisia matalan tason toteutusyksityiskohdista, jotain ratkaisutapoja: Dependency injection Adapter-pattern, fasadit, sillat yms. Kerrosarkkitehtuurit Rajapinnat C++ ja toteutus- ja otsikkotiedoston erottaminen ei tarkoita rajapinnan tai toteutusriippuvuuden poistumista Tärkeimpiä tapoja tehdä koodista: Muunneltavampaa, kestävämpää muutoksille (toteutusten muuttaminen ei hajota koko ohjelmaa) Ylläpidettävämpää Helpommin uudelleen käytettävää

Olioiden luominen Uuden olion luominen, normaalissa tilanteessa pitää tietää oikea rakentaja, oikeat parametrit, muuttuu työläämmäksi erityisesti, jos paljon eri vaihtoehtoja koodi riippuvaista toteutuksesta, jokainen uusi lisätty luokka vaatii toteutuskoodin puukottamista Ongelmaan tarjolla erilaisia ratkaisuja, rakentajametodit, rakentajaluokat, erilaiset tehtaat

Ongelma: Miten varmistaa yhdenmukaiset oliot? Alusta TAI MUTTA EI:

Abstrakti tehdas suunnittelumalli AbsFactory createproducta(): ProductA createproductb(): ProductB ProductA2 opera ProductA opera ProductA1 opera Alusta ProductB operb ProductB2 ProductB1 operb operb Factory1 <<create>> Factory2 <<create>>

Abstract Factory abstrakti tehdas Tehdasmallin idea, käyttäjälle annetaan abstrakti tehdas (tai tehdasrajapinta) jonka avulla rakentaa komponentteja Erilaisia konkreettisia tehtaita, jotka toteuttavat varsinaisen rakentamisen Rakennettavat komponentit, abstrakti kantaluokka/rajapinta ja konkreettiset vastineet Tehtaan käyttäjä pyytää rakentamaan esim. uuden nappulan, tehdas Vertailu ideatasolla: olioiden kopiointi, virtuaalinen kopiointifunktio Fokus komponenttijoukon rakentamisessa

Abstract Factory abstrakti tehdas Erikoistetut tehtaat, eri ympäristöön, eri käyttöliittymään, eri käyttäjäprofiilille, jne. oma tehtaansa. Pyydetään haluttua tehdasta luomaan ohjelman käyttämät komponentit. Tehtaan käyttö samanlaista riippumatta rakennettavien olioiden tyypistä (esim. käyttöliittymäkomponenttitehdas ja eri ympäristöt, profiilit) Esimerkki: käyttöliittymäperhe ja eri ympäristöt/kirjastot Käyttöliittymätehdas rakentaa ikkunan ja sen eri osat (luox,y,z) Ikkuna kantaluokkana, erikoistetut versiot jokaiselle ympäristölle erikseen Käyttöliittymätehtaan erikoistetut versiot (vastaavat kuin komponenttien erikoistus) Mainissa tms. tarkistus, mitä versiota käytetään ja luodaan/otetaan käyttöön oikea tehdas. Muualla käytetään annettua tehdasta ja komponentteja, muu koodi toimii samoin riippumatta käytössä olevasta versiosta

Tehdasmetodi (Factory method) Editori, jonka pitäisi osata avata oikeanlainen tiedosto, eri tiedostojen avaamista ja käsittelyä varten omat tiedostolukijansa. Perinteinen tapa, jokainen eri tiedostotyyppi pitää rakentaa erikseen, if-elsejä tai vastaavia hässäköitä. Uuden tiedostotyypin lisääminen vaatii Editorin koodin puukottelua. Sama tapahtuu tiedoston muuntamisessa muodosta toiseen Olisi huomattavasti mukavampaa, jos saman voisi tehdä automaattisesti ja uusien tyyppien lisääminen ei vaatisi olemassa olevan koodin käpistelyä FileConverter Editor FileReader.rtf.doc.txt.rtf.doc.txt.docx TIE-20200 Samuel Lahtinen.docx

Tehdasmetodi (Factory method) Yksinkertaisin rakentajametodi, tehdään kantaluokkaan luokkafunktio (static member function) joka hoitaa rakentamisen. Osaa päättää parametrin perusteella, mikä hierarkian olioista halutaan rakentaa Esimerkki tiedostojuttujen kanssa: Hifistelyä, jokainen aliluokka osaa rekisteröityä (automaattisesti) rakentajalle ja kertoa esim. parametrien sisällöstä (kuten tiedostotyyppi), rakentajafunktio/olio kutsuu parametrin perusteella oikeaa rakennusmetodia ja uusi oikeantyyppinen oli syntyy Funktion käyttäjän ei tarvitse tietää mitään toteutuksesta tai luokkahierarkiasta FileConverter Editor FileReader.rtf.doc.txt.rtf.doc.txt.docx TIE-20200 Samuel Lahtinen.docx

Rakennuttajien automaattisesta rekisteröinnistä Automaattisesti tehtaalle/rakennuttajalle rekisteröityvien luokkien tekeminen Uusi luokka vaatii vain käännöksen ja kaikki toimii kivasti toteutustapoja luokkamuuttujat, luokkafunktiot static-muuttujat, joiden arvo alustetaan rekisteröintifunktion avulla Template-hässäkät C++11 ja lambdat Ongelmia: Kääntäjät turhan innokkaita optimoimaan ja saattavat jättää esim. muuttujien alustuksen tekemättä ennen kuin niitä käytetään ensimmäistä kertaa Lisää kompleksisuutta

Object Pool (olioiden kierrättämistä) Olioiden luominen ja tuhoaminen voi olla raskasta erityisesti jos niihin liittyy vähänkään monimutkaisempia alustustoimenpiteitä Uusien luomisen sijaan tarjotaankin olioita käytettäväksi olioaltaasta Kun tarve tulee, object poolista voi noutaa olion ja käytön jälkeen palauttaa sen takaisin (kuten keilahalli ja keilakengät) Voidaan kontrolloida käytössä olevien olioiden määrää, saadaan kapseloitua olioiden luominen Käyttäjä ei huomaa eroa, kutsuna pyydetään olioita ja tuloksena voi olla joko uusi olio, tai jo jonkun aikaisemmin palauttama

Resource Acquisition is Initialization (RAII) Programming idiom (C++), ei siis suunnittelu/toteutusmalli (yleistettävyys) Idea: resurssin vapauttamisesta huolehtii purkaja (ja varaamisesta rakentaja) Resurssin varaus näkyvyysalueen mukaan, automaattinen vapauttaminen, ei muistamisongelmaa/poikkeustilanneongelmaa jne.

Yhteenveto SOLID-periaatteet, samoja tavoitteita ja ideoita kuin muissakin kurssilla opituissa tekniikoissa. Esim. suunnittelumallit tarjoavat hyväksi havaittuja ratkaisuja näiden saavuttamiseen Olioiden luomiseen liittyvät patternit, helpottavat laajennettavuutta, vähentävät suoria toteutusriippuvuuksia Lisäävät koodin määrää, tekevät ohjelmasta hieman monimutkaisemman Usein lähes pakollisia ohjelman muokattavuuden ja laajennettavuuden säilyttämiseksi Lähdemateriaalia ja lisäluettavaa: http://www.objectmentor.com/resources/articles/principles_and_patterns.pdf TIE-20200 Samuel Lahtinen 30