Ohjelmoinnin suunnittelumallit (design patterns) käyttöliittymissä Vanhin ja keskeisin lähde Gamma E., Helm R., Johnson R., Vlissides J., Design Patterns. Addison-Wesley, USA, 1994. Ajatus ohjelmoinnin design patterneista perustui Christopher Alexanderin talojen ja kaupunkien arkkitehtuurista esittämien ajatusten (1977-1979) soveltamiseen ohjelmointiin. Veto-visualisointityökalu Yksi glyyfi esittää yhtä taulukkomuotoisen datan riviä. Piirrettäviä rivejä on tyypillisesti 500-10 000. 10 000 samankaltaisen olion luominen olisi muistin käytön kannalta järjetöntä, koska data on jo kertaalleen esitettynä taulukkorakenteessa ja ajoympäristön (Java-tulkki) suorituskyky ei riitä näin monen olion hallintaan. Ratkaisu: Kaikki datapisteet piirrettiin yhdellä glyyfi- 1
Flyweight Veto-projektissa Glyph draw(). 768 riviä Flyweight Ongelma: Suuri määrä dataa, jonka instantioiminen olioiksi veisi liikaa muistia. Ratkaisu: Jaetaan yhtä pientä oliota kaikkien dataalkioiden kesken. Tyypillinen sovellus käyttöliittymissä: datan tai komponenttien piirtäminen, Edit-in-Place -ratkaisujen 2
Flyweight Esimerkki 2 Javan Swing-kirjasto: JTable Syötekenttä, jolla solun arvoja editoidaan, on monimutkainen komponentti. Jos jokainen taulukon solu on syötekenttä, ajoympäristö joutuu suorituskykyongelmiin (muisti, tapahtumahallinta, Todellisessa käyttötilanteessa käyttäjä voi editoida vain yhtä solua kerrallaan. Ratkaisu: Kun käyttäjä klikkaa solua muuttaakseen sen arvoa, siirretään editorikomponentti kyseisen solun kohdalle, kopioidaan solun sisältö siihen ja annetaan käyttäjän editoida solun sisältöä. Kun editointi päättyy, editori piilotetaan ja sen sisältö kopioidaan soluun. Vastaava ratkaisu: Editointi Excelissä Flyweight JTablessa Editoitava solu 3
Muut solut on piirretty sarakekohtaisella JLabel- Bookmark Scrollbar vastaavaan kohtaan 4
Bookmark Scrollbar -toteutus Visual Basicin tukema ohjelmointitapa: jokainen Tag-olio komentaa scrollbaria suoraan siirtämään thumbin oikeaan Toimii pienissä sovelluksissa. Johtaa suuremmissa sovelluksissa siihen, että kaikki komponentit viittaavat suoraan toisiinsa. Tällöin jos yksikin komponentti poistetaan, pahimmillaan kaikkien muiden koodia pitää muuttaa. Javan tukema ohjelmointitapa: jokaisella Tag-olioilla on lista, johon kaikki sen tilasta kiinnostuneet komponentit (mm. scrollbar) ilmoittautuvat. Kun käyttäjä klikkaa Tagoliota, se lähettää siitä tapahtuman (event) kaikille listalaisille, jolloin esim. scrollbar osaa siirtää thumbin. Riippuvuuksien määrä leikkaantuu puoleen edellisestä. Observer Ongelma: Kun olion tila muuttuu, kaikkien siitä riippuvien olioiden pitäisi päivittyä automaattisesti. Ratkaisu: Muuttuvalla oliolla on lista, johon olion tilasta kiinnostuneet muut oliot ilmoittautuvat ajon aikana. Kun olion tila muuttuu, listalaisia tiedotetaan siitä. Tyypillisiä sovelluksia käyttöliittymissä: Kaikenlaisten synkronointiongelmien perusratkaisu Käyttöliittymäkomponenttien riippuvuudet (mm. harmaannuttaminen) Komponentin uudelleenpiirtäminen, kun sen data on muuttunut (Model View) 5
Observer Bookmark Scrollbar Observable: kaikki Tagit Observer = Scrollbar, TagArea Tapahtumia TagAdded TagDeleted Siirry tähän kohtaan -pyyntö Airis Admin Center Ikkunassa on useita komponentteja, jotka vaikuttavat kaikki toistensa tiloihin. Miten tapahtumanhallinta ratkaistaan siten, että vältetään hajautettu riippuvuusverkkospagetti? 6
Riippuvuuksia Valinnat Raahauksen interaktio Taulukoiden uudet rivit Rivien poistaminen Tietokantamuutokset Mediator - Airis Admin Center Kaikki tapahtumanhallinta on keskitetty ikkunan taustapaneeliin. Paneeli huolehtii kaikkien sen sisältämien komponenttien tilojen päivittämisestä. Tapahtumia DragStart DragEnd CompanySelected ServiceInstalled AdminCenterFrame 7
Mediator Ongelma: Riippuvuusverkon hallinta. Kun olioiden välillä on paljon riippuvuuksia, kokonaiskuvan muodostaminen järjestelmän riippuvuuksista ja tiloista on vaikeaa. Jos kaikki toisistaan riippuvat olioit ovat tietoisia toisistaan => spagettimainen viittausverkosto. Ratkaisu: Keskitetään tilanhallinta ja riippuvuudet yhteen olioon, joka osaa päivittää muiden olioiden tilat, kun jonkin olion tila muuttuu. Tyypillinen sovellus käyttöliittymissä: yksittäisen ikkunan komponenttien riippuvuudet. Mediator MFC / Visual C++ Microsoftin Visual C++-ohjelmointiympäristö tukee Mediator-patternia komponenttien tapahtumankäsittelyssä: kun käyttäjä lisää komponentille tapahtumankäsittelijän, VC++ lisää sen komponentin sisältävän ikkunan metodiksi. Vertaa tätä esim. Visual Basiciin, jossa ympäristö lisää tapahtumankäsittelijän automaattisesti komponentin omaksi sisäiseksi metodiksi. 8
Patternien etuja Ongelmatilanteiden tunnetuille ratkaisutavoille on nyt olemassa nimi ja kuvaus => syntyy uusia korkean tason käsitteitä, ilmaisuvoimainen yhteinen kieli. Seurauksia Ohjelmoijien välinen kommunikointi tehostuu. Järjestelmiä voidaan dokumentoida tehokkaammin. Aiempaa monimutkaisempia ratkaisuja on nyt nopeampi Ohjelmoijien muistiyksiköt (chunk) ovat ilmaisuvoimaisempia. Ohjelmoijien tuottavuus ja ratkaisujen laatu paranevat. Hyvä ohjelmointitaito? Samat toteutusongelmat toistuvat sovelluksesta toiseen: Tämän olen ratkaissut jo joskus aiemmin Kokemus = aiempien hyvien ratkaisujen uudelleenkäyttäminen. Hyvien ratkaisujen taustalla olevat keskeiset periaatteet ja ratkaisustrategiat voidaan esittää design patterneina. 9