MVC kan være så mangt

Som Rails-utvikler har man god erfaring med en måte å gjøre MVC-programmering på. Cocoa viser oss en helt annen.

Cocoa, rammeverket for Mac-applikasjoner, er på samme måte som Rails basert på MVC – Model View Controller. Begrepet ble lansert av Trygve Reenskaug da han besøkte Xerox PARC (du vet, der Steve Jobs fikk alle de gode ideene) i 1978, Reenskaug beskriver det slik:

I created the Model-View-Controller pattern as an obvious solution to the general problem of giving users control over their information as seen from multiple perspectives.

MVC er ikke så mye en fasit for hvordan man bygger noe som et ideal eller prinsipp. Rails gjør det på sin måte, primært ved å gi oss tre mapper i Railsprosjektene vi lager: controllers, views og models. Ettersom webben er tilstandsløs (webserveren “husker” ingenting fra forespørsel til forespørsel) har controlleren typisk et tungt lass å dra på webben; den skal håndtere HTTP-headere, request-parametre, routing, styring av innholdstyper osv. I Rails er mange av disse oppgavene håndtert av selve rammeverket, men idet Rails overlater kontrollen til en controller-action du har skrevet har det allerede foregått mye i kulissene.

Hvis man sammenligner med en vanlig GUI-applikasjon er ting ganske annerledes. Her har programmet gjerne all tilstand selv, og svarer umiddelbart idet brukeren klikker på en knapp eller velger noe fra en meny. I motsetning til en webapplikasjon, der nettleseren først skal koble seg til serveren, sende over parametre, vente på svar og gjøre noe med responsen, foregår alt dette i samme prosess i en GUI-applikasjon.

I Cocoa er det en mye tettere integrasjon mellom viewene og controllerne enn på web, noe som har gitt meg ny innsikt i det egentlige forholdet mellom disse to. Veldig mye av controller-koden i en typisk Rails-applikasjon er ca 50% initialisering av tilstand og objekter, innlesing av parametre osv. I Cocoa er controlleren mer som en lydig slave for viewet. Et bra eksempel er når du skal bruke en tabell som skal inneholde en liste med data i en Cocoa-applikasjon. Du kan da bruke en NSTableView-kontroll i GUI-et ditt. Denne kontrollen kan du gi en datakilde (data source), som er ansvarlig for å levere data til tabellen og håndtere innlegging av nye rader, sletting osv. Og her er det Cocoa virkelig skiller seg fra webutvikling. Istedet for at man så forteller datakilden (eller viewet) at den skal legge inn en rad med kolonner x, y og z i tabellen er det helt omvendt i Cocoa. Tabellen vil istedet sende hovedsaklig to meldinger til viewet:

tableView:numberOfRowsInSection:
tableView:objectValueForTableColumn:row:

Ikke la deg skremme av at dette er Objective C, dette er bare to meldinger som et objekt som er satt til å være datakilde for en tabell vil motta. Den første meldingen spør datakilden om hvor mange rader tabellen skal inneholde, den andre spør om hvilken verdi som skal vises i en gitt kolonne i en gitt rad. Cocoa vil altså først spørre hvor mange rader tabellen skal ha, og så vise det antall rader som er synlig i grensesnittet ved å spørre etter verdier for hver kolonne i hver rad. Idet brukeren scroller nedover i tabellen vil datakilden igjen spørre etter nye rader og kolonner – viewet sørger altså selv for å hente de dataene som er relevante for grensesnittet.

Det har de siste månedene blitt ganske populært å erstatte paginerte sider (med Google-lignende linker for hver side i resultatsettet) med lister som scroller uendelig – der nye data hentes idet brukeren scroller siden. Jeg har ikke sett nøye på hvordan dette løses, men en god kandidat kunne vært å bruke Cocoas tilnærming.

Igår satt jeg og fiklet litt med hvordan man lager iPhone webapplikasjoner med Dashcode, da jeg oppdaget at Apple bruker akkurat samme tilnærming når man skal lage en dynamisk liste i HTML/javascript for iPhone. Jeg la inn en liste-widget i GUIet og sa at denne skulle bruke en datakilde for å hente data, hvorpå Dashcode laget et javascript-objekt som så slik ut:

// This object implements the dataSource methods for the list.
var listDataSource = {

    // Sample data for the content of the list. 
    // Your application may also fetch this data remotely via XMLHttpRequest.
    _rowData: ["Item 1", "Item 2", "Item 3"],

    // The List calls this method to find out how many rows should be in the list.
    numberOfRows: function() {
        return this._rowData.length;
    },

    // The List calls this method once for every row.
    prepareRow: function(rowElement, rowIndex, templateElements) {
        // templateElements contains references to all elements that have an id in the template row.
        // Ex: set the value of an element with id="label".
        if (templateElements.label) {
            templateElements.label.innerText = this._rowData[rowIndex];
        }

        // Assign a click event handler for the row.
        rowElement.onclick = function(event) {
            // Do something interesting
            alert("Row "+rowIndex);
        };
    }
};

Her har man altså et javascript-objekt med to funksjoner der den ene skal returnere antall rader i lista og den andre skal returnere data for en rad i lista. Man har altså en widget for websida som bruker en slags protokoll for å snakke med datakilden sin. Det er jo – som eksempelkoden antyder – trivielt å bruke datakilder på nettet til å drive listene, for eksempel med Ajax/XmlHttpRequest. Det virkelig interessante er å introdusere et slags controller-lag i javascript, ettersom dette er tilgjengelig mens siden kjører. Om man ønsker å oppdatere dataene i en slik liste trenger man ikke løpe gjennom alle radene på nytt, man sender istedet en melding til objektet:

document.getElementById("list").object.reloadData();

Her har vi et HTML-element som heter list, der vi forteller datakilden (object) å laste dataene på nytt. Det som da skjer er at datakilden vår vil bli sendt meldingene numberOfRows() og prepareRow() på samme måte som før.

Jeg tror vi ser omrisset av en ny generasjon webapplikasjoner der ute nå.

No_gravatar

Problemet er at folk har misforstått begrepene i MVC og dermed redefinert terminologien <a href=”http://c2.com/cgi/wiki?WhatsaControllerAnyway”>opptil flere ganger</a> slik at man ikke lenger vet om man snakker om samme ting. MVC (modellen, ikke prinsippet om lagdeling) har ingenting med web å gjøre, siden kontrolleren (som uansett er en relativt liten komponent som limer sammen model og view) for en stor grad utføres av webserverprosessen.

For å unngå utvanning av begrepene burde man heller snakke om lagene Data + Logic + Presentation for webutvikling så man ikke blir totalt forvirret når man forsøker å overføre sine egne vrangforestillinger over på GUI-programmer hvor begrepene betyr noe helt annet (og mer korrekt).

1919bfc4fa95c7f6b231e583da677a17?d=http%3a%2f%2fshortcut.no%2fimages%2fno_gravatar

comment3, http://www.hcch.net viagra sale, :-OO,

0439110abb55c7455edf1180a114ec38?d=http%3a%2f%2fshortcut.no%2fimages%2fno_gravatar

Hi! NVbdAYDw


Gravatar-aktivert. Les mer om gravatar.
E-postadressen vil ikke vises på siden