Kun käsittelemme Angularin käyttöä nykyaikaisissa sovelluksissa, on tärkeää ymmärtää, miten valita oikeat arkkitehtuuriset lähestymistavat ja teknologiat. Edellisessä luvussa tutustuimme yksinkertaiseen LocalCast Weather -sovellukseen, joka osoitti, kuinka Angular voi olla erinomainen valinta pienille, dynaamisille sovelluksille. Se kuitenkin vain raapaisee pintaa siitä, mitä voidaan saavuttaa suuremmissa, liiketoiminnan ydinprosesseja tukevissa sovelluksissa (LOB, Line-of-Business). Tässä luvussa keskitymme juuri tällaisiin sovelluksiin ja tarkastelemme, miten Angularin ominaisuuksia voidaan hyödyntää suurissa ja skaalautuvissa projekteissa.

LOB-sovellukset ovat tärkeimpiä yritysohjelmiston kategorioita. Ne käsittelevät usein asiakas- tai liiketoimintatarpeita, kuten varastonhallintaa, asiakasrekistereitä ja muita liiketoiminnan ydintoimintoja. Tällaisilla sovelluksilla on monia erityispiirteitä, mutta myös universaaleja suunnittelumalleja, jotka tekevät niistä erityisen houkuttelevia Angularin kaltaisten teknologioiden käyttöön. Tässä vaiheessa on tärkeää ottaa huomioon, että Angularin avulla voidaan rakentaa tehokkaita ja skaalautuvia sovelluksia, mutta se vaatii harkittua arkkitehtuuria ja oikeiden työkalujen valintaa.

Angularin tarjoama mahdollisuus käyttää komponentteja ilman jakelumoduuleja (standalone components) on merkittävä etu. Se auttaa vähentämään yli- ja alikonsolidoitumisen ongelmia, joita monimutkaisessa projektissa voi esiintyä. Samalla se parantaa koodin luettavuutta ja vähentää rakenteellista monimutkaisuutta. Tämän lisäksi Angular Signals -ominaisuus tuo lisää tehokkuutta, vaikka se ei vielä ole täysin valmis suurten sovellusten kehitykseen. Signals-toiminto on suunniteltu yksinkertaistamaan ja parantamaan suorituskykyä, mutta sen täysi potentiaali paljastuu vasta myöhemmissä versioissa.

Kun siirrymme kohti suurempia sovelluksia, on tärkeää pitää mielessä, että teknologian valinta ei riitä yksin. Kuten monissa projekteissa, myös suurten yrityssovellusten kehittämisessä on oleellista ottaa huomioon tiimityöskentely, projektinhallinta ja pitkäjänteinen suunnittelu. On tärkeää valita työkalut ja arkkitehtuurit, jotka tukevat jatkuvaa kehitystä ja skaalautuvuutta. Erityisesti on suositeltavaa käyttää kanban-tyyppisiä suunnittelumenetelmiä, kuten GitHub-projekteja, jotka auttavat tiimejä pysymään järjestäytyneinä ja tehokkaina.

Kun suunnittelet suurta LOB-sovellusta, kannattaa miettiä myös niin sanottua 80-20-sääntöä. Tämä periaate kertoo, että voit saavuttaa suurimman osan tavoitteistasi suhteellisen pienellä vaivalla, mutta samalla on tärkeää tunnistaa kriittiset toiminnot ja varmistaa, että sovellus vastaa niitä mahdollisimman suoraviivaisesti ja skaalautuvasti. Esimerkiksi, jos rakennat varastonhallintajärjestelmää, voit keskittyä aluksi vain tärkeimpiin toimintoihin, kuten tuotteiden lisäämiseen ja varastotietojen tarkistamiseen, ja laajentaa sovellusta tarpeen mukaan.

Skaalautuvuuden varmistaminen on olennainen osa LOB-sovellusten kehittämistä. Rakentamalla sovellus niin, että sen eri osat voidaan helposti päivittää ja laajentaa, voit vastata muuttuvien liiketoimintatarpeiden vaatimuksiin ilman suuria arkkitehtonisia muutoksia. Router-First-arkkitehtuuri on yksi tehokas tapa saavuttaa tämä. Se perustuu komponenttien uudelleenkäytettävyyteen ja navigaatiokomponenttien keskittämiseen. Tämä tekee sovelluksesta joustavan ja modulaarisen, samalla kun se parantaa suorituskykyä ja käyttäjäkokemusta.

LOB-sovellusten kehittämisessä on myös tärkeää ymmärtää, että liiallinen monimutkaisuus ja ylikompensointi voivat johtaa turhiin kustannuksiin ja viivästyksiin. Toisaalta, liian yksinkertaiset ratkaisut voivat estää sovelluksen kasvun ja laajentamisen tulevaisuudessa. Tasapaino on avainasemassa, ja juuri siksi on tärkeää osata valita oikeat työkalut ja suunnitteluratkaisut.

Mikäli lähdet rakentamaan suurta LOB-sovellusta, on suositeltavaa valita ensin muutama keskeinen toiminnallisuus, joka tukee yrityksen liiketoimintaprosesseja, ja kehittää niitä asteittain. Tällöin voit arvioida käyttäjien palautteen perusteella, mitkä osat sovelluksesta kaipaavat kehitystä, ja laajentaa toiminnallisuuksia tarpeen mukaan. Tämän lähestymistavan etu on, että voit nopeasti tuottaa toimivia osia sovelluksesta ja iteratiivisesti parantaa sitä.

LOB-sovellusten suunnittelussa ei kannata unohtaa myöskään käyttäjäkokemusta. Vaikka sovelluksen taustalla oleva teknologia on tärkeää, yhtä tärkeää on, kuinka käyttäjät kokevat sen käytön. Hyvin suunniteltu ja intuitiivinen käyttöliittymä voi merkittävästi parantaa sovelluksen tehokkuutta ja vähentää virheitä, joita käyttäjät tekevät. On myös tärkeää varmistaa, että sovellus on turvallinen ja että käyttäjien henkilötiedot suojataan asianmukaisesti.

Kuinka toteuttaa virheilmoitusten hallinta Angularissa?

Virheilmoitusten näyttäminen ja käsitteleminen on olennainen osa modernin web-sovelluksen käyttökokemusta, erityisesti lomakkeiden validoinnissa. Tässä käsitellään Angular-sovelluksessa käytettävän virheilmoitusten hallinnan toteutusta, joka on suunniteltu tarjoamaan dynaamiset ja tehokkaat virheilmoitukset.

Virheilmoitusten näyttäminen voidaan tehdä luomalla oma direktiivi, joka liittää lomakekentät tiettyihin virhetilanteisiin ja näyttää käyttäjälle asianmukaiset viestit. Yksi keskeinen etu tämän lähestymistavan käytössä on virheilmoitusten hallinnan keskittäminen ja koodin uudelleenkäytettävyyden parantaminen. Tämä tarkoittaa, että virheilmoitusten luonti ja näyttäminen ei tarvitse toistua jokaiseen lomakekenttään erikseen, vaan ne voidaan hoitaa yhdellä yleisellä mekanismilla.

Virheviestien luontiin voidaan käyttää koodia, joka tarjoaa vakioitua virheilmoitusta eri virhetyypeille, kuten "required" (kenttä on pakollinen), "minlength" (kenttä ei ole tarpeeksi pitkä) ja "maxlength" (kenttä ylittää sallitun pituuden). Virheilmoitus sisältää aina kentän nimen tai "Input"-sanan, ja dynaamisesti haetaan kentän pituusvaatimukset, jos sellaisia on.

typescript
getStandardErrorMessage(error: ValidationError): string {
const label = this.fieldLabel || 'Input'
switch (error) { case 'required': return `${label} is required` case 'minlength': return `${label} must be at least ${this.fieldControl?.getError(error)?.requiredLength ?? 2} characters` case 'maxlength':
return `${label} can't exceed ${this.fieldControl?.getError(error)?.requiredLength ?? 50} characters`
case 'invalid': return `A valid ${label} is required` } }

Tämä funktio tarkistaa virheen tyypin ja luo vastaavan virheilmoituksen. Tämä lähestymistapa tekee virheilmoitusten hallinnasta dynaamisen, koska se voi automaattisesti mukautua kentän määritettyihin pituusrajoihin, mikä vähentää manuaalista koodin kirjoittamista ja helpottaa sovelluksen ylläpitoa.

Seuraavaksi luodaan toiminto, joka käy läpi kaikki virhetilanteet ja näyttää ne käyttäjälle. Tässä käytetään funktionaalisia delegaatteja, joiden avulla virheilmoituksia käsitellään tehokkaasti ja koodin suoritus siirretään vain tarvittaessa. Tämä parantaa suorituskykyä, koska virheiden tarkistuksia ja virheilmoitusten luontia ei suoriteta turhaan, vaan ne tehdään vain, kun se on välttämätöntä.

typescript
updateErrorMessage() { const errorsToDisplay: string[] = []
const errors = Array.isArray(this.appFieldError)
?
this.appFieldError : [this.appFieldError] errors.forEach((error: ValidationError | { error: ValidationError; message: string }) => {
const errorCode = typeof error === 'object' ? error.error : error
const message = typeof error === 'object' ? () => error.message : () => this.getStandardErrorMessage(errorCode) const errorChecker = errorCode === 'invalid' ? () => this.fieldControl?.invalid
: () => this.fieldControl?.hasError(errorCode)
if (errorChecker()) { errorsToDisplay.push(message()) } }) this.renderErrors(errorsToDisplay.join('')) }

Tämä funktio tarkistaa, onko kenttä virheellinen ja tarvittaessa näyttää virheilmoituksen. Se tukee myös dynaamisia virheilmoituksia, jotka voivat olla joko vakioituja tai räätälöityjä viestejä.

Jotta tämä prosessi toimisi kunnolla, on tärkeää liittää lomakekenttä oikeaan formControl-kontrolliin ja kuunnella sen tilan muutoksia. Kun lomakekenttä muuttuu ja on virheellinen, suoritetaan päivitystoiminto virheilmoitusten näyttämiseksi.

typescript
initFieldControl() {
if (this.input && this.group) { const controlName = this.input.getAttribute('formControlName') ?? '' this.fieldControl = this.fieldControl || this.group.get(controlName) if (!this.fieldControl) {
throw new Error(`[appFieldError] couldn't bind to control ${controlName}`)
}
this.unsubscribe() this.controlSubscription = this.fieldControl?.valueChanges .pipe( filter(() => this.fieldControl?.status === 'INVALID'),
tap(() => this.updateErrorMessage())
) .
subscribe() } }

Tässä koodissa tarkistetaan, että kenttä on oikeassa muodossa, ja liitetään se lomakkeen kontrolliin. Jos kenttä ei ole kelvollinen, heitetään virhe, joka auttaa tunnistamaan koodivirheen. Tämän jälkeen määritellään myös ngOnDestroy-metodi, jolla varmistetaan, ettei tilauksen peruutusta unohdeta ja vältetään muistivuotoja.

Kun kenttä ja sen virheilmoitukset on liitetty oikein, voimme varmistaa, että virheilmoitukset päivittyvät aina, kun kenttä saa uuden arvon. Tämä mahdollistaa dynaamisen ja reaktiivisen virheilmoituksen esittämisen.

typescript
ngOnChanges(changes: SimpleChanges): void {
this.initFieldControl() if (changes.input.firstChange) { if (this.input) { this.input.onblur = () => this.updateErrorMessage() this.fieldLabel = this.fieldLabel || this.input.placeholder || this.input.getAttribute('aria-label') || '' } else {
throw new Error(`appFieldError.[input] couldn't bind to any input element`)
} } }

Lopuksi on tärkeää huolehtia siitä, että virheilmoitukset näkyvät vain silloin, kun kenttä on virheellinen, ja että mahdolliset dynaamiset muutokset, kuten kenttien lisääminen tai poistaminen, otetaan huomioon.

Virheilmoitusten keskitetty hallinta parantaa sovelluksen ylläpidettävyyttä ja käyttöliittymän johdonmukaisuutta. Käyttäjä näkee aina samanlaisen ja selkeän virheilmoituksen, riippumatta siitä, missä lomakekentässä virhe esiintyy. Tämä yksinkertaistaa kehitystä ja varmistaa, että virheilmoitukset ovat aina oikea-aikaisia ja tarkkoja.