Struktur og orden i større .NET løsning

Tags:    programmering

<< < 12 > >>
Jeg tror jeg har haft et lignende spørgsmål før angående temperatur kontrol, men det her er langt mere overordnet.

En del af jer ved sikkert at jeg har noget hjemme automatisering kørende i et godt stykke tid. Det virker fint og er alt sammen guld og grønne skove.

Men nu har jeg for nyligt tilføjet en fingeraftrykscanner. Og som sædvanlig er det super let lige at flække en hurtig demo sammen. MEN som altid er det super svært at implementere ind i mit system. Det hele kører i en EXE og kræver lidt knofedt at få nye koncepter ind i.


Så jeg sørger efter lidt svar / sparing med nogle af jer udviklere herinde, som nok har gjort den slags her noget længere tid end jeg selv har gjort.

Hvordan styrer man sådanne større projekter?


Jeg kører 2 pc'er, en er en touch screen som har fingeraftrykscanner og magnetisk kortlæser sat til. Det er også der det meste daglige kontrol af værelset nok foregår.

Så har vi mediacentret / hjemmeautomatiseringserveren som har nogle USB/TTL porte (Dvs seralle porte i .NET) som kommunikerer med hardwaren. Jeg har også nogle virtuelle kontrollag som fx kan styre min mobil og min bærbare pc.

Systemet har også (og skal beholde funktionen) et vækkeur. Det vækkeur henter også information ind fra nettet om nuværende tilstand i verden ( :D )... Systemet skulle også gerne integreres med gymnasiets systemer på sigt. Og også gerne muligheder for at få facebook osv ind. Så generelt skal det være åbent for udvidelse uden at ændre alting igen.


Jeg ønsker helst at holde lagene ret separerede så jeg næsten bare kan slette en del eller lave en ny, og den skal være praktisk talt en del af systemet øjeblikkeligt, eller systemet skal bare selv hægte den fra.

Jeg ville også foretrække at holde logikken samlet et sted. Og helst undgå alle kald fra en klasse til en anden. Netop det der med at de ikke må være for afhængige af hinanden, men at jeg i stedet bare har en klump lim eller en "central" der router deres information rundt uden at gøre noget betydningsfuldt.

Jeg ved ikke helt hvor meget I forstod, og om jeg fik specificeret mine tanker klart nok. Men jeg håber at I kan følge mig langt hen af vejen. For jeg er lidt blank.


Jeg har overvejet noget hvor der er en master EXE som så kan loade DLL filer dynamisk ind i nye app domains og så kunne nogle "events" og kommandoer køre rundt mellem dem. Sådan lidt ligesom at de blev broadcastet ud til alle andre plugins. Generelt meget uoverskueligt -.-



16 svar postet i denne tråd vises herunder
5 indlæg har modtaget i alt 31 karma
Sorter efter stemmer Sorter efter dato
Jeg synes vi een gang for alle skal få dit automatiseringssystem ind i en rigtig arkitektur :-)

1: Du skal vænne dig til at kode mod interfaces i stedet for at kode mod klasser. Objektorienteret programmerings første bud er at man skal kode mod interfaces, ikke mod implementeringer. Det tager lidt tid at vænne sig til, men det er bedre på sigt (og du har nemt ved at styre alt dit grej)

2: Glem din pluginarkitektur indtil videre, fokuser på at få det til at virke med interfaces i din eksisterende arkitektur. (se evt på .NET MEF det er til plugins senere http://mef.codeplex.com/)

3: Find ud af hvad hvert enkelt af dine elementer har til fælles (de skal starte, de skal melde tilbage???)

4: Lav et "server" interface: fx. IServer (man plejer at skrife I foran interfaces.

Se evt. på dette projekt jeg har lavet: http://bit.ly/pjtHI3 (fjerner koden om nogle uger, så gem den) - det viser hvordan man starter med det, det udnytter interfaces helt så godt som man kan, men det er godt på vej.



Du skal have lavet dig en web service. Således det kun er din "server" der tilgår din database, alle dine andre programmer mv. de kalder op til en service og beder om fx. GetAllFingerprints(); eller lignende. De skal være helt uvidende omkring din database og om du bruger en database, en txt fil, eller noget helt tredje. Det er helt klart den bedste arkitektur.

Med hensyn til kommunikationen er alt hvad der hedder tcp, remoting etc er blevet erstattet af WCF, det er utroligt nemt at arbejde med og du kan køre over Internettet eller lokalt på dit hjemmenetværk - eller på samme
maskine.

Det er helt klart at det skal du bruge til a kommunikere med din server med, din server er således den eneste (ENESTE) der skal snakke med databasen, ellers dør du af vedligehold. Alle dine klienter (fingertryksscanner) bliver så tynde (dumme) klienter, der ikke indeholder meget funktionalitet - hvilket er helt fint.

Nede i din server skal du have fat i databsen, for at blive i tråden omkring din arkitektur, vil jeg foreslå at du kigger på et "repository" pattern, og eventuelt bruger et bibliotek der hedder "StructureMap" til at lave dine interfaces med. MEd det tager du brugen af interfaces til næste niveau - nemlig der hvod du aldrig skal bekymre dig om hvilken implementation af dine interfaces du skal have, det er alt sammen placeret i en klasse eller en xml fil.

Giver det mening, eller skal jeg til tasterne :-)

**EDIT**
Dette kunne være et bud på en arkitektur: http://screencast.com/t/YCGWwlQjeOZ

Når du har det hele via en service som eks WCF tilyder, er du ligeglad om det er dit væreslse, stuen, et andet hus, eller noget helt andet. Alt tilgår bare din maskine og din server.

Når du skal lave en ny klient skal du "bare" lave en ny WCF klient og skrive den logik der skal hertil, sørge for at serveren kender til de data, og vupti, så kører du.

Der skelnes ikke mellem noget til output (styring af lys) eller noget til input (fingeraftryk) det skal der heller ikke. Det er op til klienten at implementere dette.



Indlæg senest redigeret d. 26.09.2011 11:50 af Bruger #2730
Hvis du tillader remote-access, er det bare vigtigt at du har en form for overvågning over access forsøg til din database, så du ikke risikere at miste dit password over for bruteforcing.

Den eneste måde hvorpå din database kan tilgås er jo igennem et login med dit password, så hvis dit password er stærkt nok og hvis du har en ordentlig overvågning kørende synes jeg ikke at remote-access lyder som en dum idé.

Jeg er personligt typen der ville skrive API lag udover databasen, hvorfra mine klientprogrammer så kunne tilgå data vha. API'et, men det er en smagssag og hvis performance er af højeste prioritet er det vel hurtigere med direkte forbindelse til databasen.



IServer er der for det kan jo være du vil have det ud af din main form og ind et andet sted. Det du kan gøre er at lave en simpel implementation af IServer, kalde den og det eneste den gør er at skrive Console.Writeline("Server startet");, så kan du teste om hele dit system kører (ud over din server) - det samme gælder for alle dine automationItem. Lav en "tom implementering" af interfacet og bare lad det skrive til command linien, så kan du teste det hele (første skridt mod unit test)

Mht dit SetLight etc. Så er en metode til det, at lave dit interface eksponere en metode der hedder eks.: SendCommand(string cmd, string data); og det skal hver enkelt så reagere på, hvis du sender fx.: SendCommand("Light", "5"); til lys enheden, sætter den lysstyrken til 5, det samme kan du med varmen.

Der hvor det bliver smart er at du skal have dem alle i en liste fx.: List<IAutomationItem> items = new List<IAutomationItem>();

så kan du i din server have nogle generelle metoder fx. ShutdownAll(); der lukker alt ned, fx. når du tager hjemmefra om morgenen. Den løber så alle items i din liste igennem og kalder fx. en metode der hedder "Shutdown()" på dem alle. Du skal igen ikke vide om det er lys, eller varme - det er bare et interface, hvordan dit lysItem skal reagere/implementere den metode bestemmer den selv, måske skal den slukke lyset, måske skal den kun dæmpe det...

Ideen er at hver kilde skal være "selvkørende" og hverken server eller automationItem skal være afhængig af at kende til hinanden. De kender kun til et generelt interface.




Centraliseret database virker klart at foretrække, men før du med det samme kaster dig over MySQL monstret, så gør dig selv den tjeneste også at sætte dig ind i NoSQL database systemer som fx MongoDB. Umiddelbart virker din fingeraftryksdatabase som noget der med fordel kunne udtrykkes i datastrukturer i stedet for i tabeller.
(OG MongoDB er virkelig hurtig...)



Inversion of Control (IoC) kan gøre underværker i missionen om at holde de enkelte lag adskilt med en så smal integrationsflade som muligt. Indlæringskurven kan dog være stejl og hvis man ikke behersker det ordentligt, kan man gøre mere skade end gavn og ende op med en arkitektur som er helt umulig at gennemskue. Men hvis gjort rigtigt, kan det hjælpe rigtig meget og højne genbrugligheden af kodebasen.

Se evt. på Castle Windsor: http://docs.castleproject.org/Windsor.MainPage.ashx
Eller linfu: http://code.google.com/p/linfu/




Jeg synes vi een gang for alle skal få dit automatiseringssystem ind i en rigtig arkitektur :-)

1: Du skal vænne dig til at kode mod interfaces i stedet for at kode mod klasser. Objektorienteret programmerings første bud er at man skal kode mod interfaces, ikke mod implementeringer. Det tager lidt tid at vænne sig til, men det er bedre på sigt (og du har nemt ved at styre alt dit grej)

2: Glem din pluginarkitektur indtil videre, fokuser på at få det til at virke med interfaces i din eksisterende arkitektur. (se evt på .NET MEF det er til plugins senere http://mef.codeplex.com/)

3: Find ud af hvad hvert enkelt af dine elementer har til fælles (de skal starte, de skal melde tilbage???)

4: Lav et "server" interface: fx. IServer (man plejer at skrife I foran interfaces.

Se evt. på dette projekt jeg har lavet: http://bit.ly/pjtHI3 (fjerner koden om nogle uger, så gem den) - det viser hvordan man starter med det, det udnytter interfaces helt så godt som man kan, men det er godt på vej.


Haha genialt :P

Jeg vidste godt at det nok snart var tid til interfaces men vidste ikke at der var så hårdt brug for dem. Læste noget om at det kunne være en god idé at bygge HELE sit projekt op som interfaces sådan at man fik et overblik, og så først implementere tingene derefter?

Jeg er glad for at du har gidet lave det projekt der. Går igennem det nu.

Må jeg spørge hvorfor du anvender en IServer? Kan godt se idéen i IAutomationItem, men jeg har lidt svært ved at se hvorfor du har IServer?

Er det bare fordi at du så holder en fast regel for hvordan en server implementering skal se ud, eller hvad?

Det der også undrer mig er... Hvad med de ting de IKKE har til fælles?

Som fx. lysstyring vs varmestyring.

Lysstyringen ville have en ting som "SetLight" og varme ville have "SetTemperature"

Hvad så med de interfaces? Bliver det så ikke sværere at finde rundt i lige pludselig? Eller skal elementerne kodes så de implementerer flere interfaces?
Så varmekontrol fx. implementerer sit eget interface ud over IAutomationItem.



Indlæg senest redigeret d. 18.09.2011 11:49 af Bruger #14381
Har du et klasse diagram for opbygningen? Så vi kan se hvordan du reelt set har bygget din arkitektur op.



Har du et klasse diagram for opbygningen? Så vi kan se hvordan du reelt set har bygget din arkitektur op.


Nej det er sgu pinligt. Jeg duer slet ikke til arkitektur i .NET ... Ved godt de eksisterer men har aldrig lært at bruge den slags.



IServer er der for det kan jo være du vil have det ud af din main form og ind et andet sted. Det du kan gøre er at lave en simpel implementation af IServer, kalde den og det eneste den gør er at skrive Console.Writeline("Server startet");, så kan du teste om hele dit system kører (ud over din server) - det samme gælder for alle dine automationItem. Lav en "tom implementering" af interfacet og bare lad det skrive til command linien, så kan du teste det hele (første skridt mod unit test)

Mht dit SetLight etc. Så er en metode til det, at lave dit interface eksponere en metode der hedder eks.: SendCommand(string cmd, string data); og det skal hver enkelt så reagere på, hvis du sender fx.: SendCommand("Light", "5"); til lys enheden, sætter den lysstyrken til 5, det samme kan du med varmen.

Der hvor det bliver smart er at du skal have dem alle i en liste fx.: List<IAutomationItem> items = new List<IAutomationItem>();

så kan du i din server have nogle generelle metoder fx. ShutdownAll(); der lukker alt ned, fx. når du tager hjemmefra om morgenen. Den løber så alle items i din liste igennem og kalder fx. en metode der hedder "Shutdown()" på dem alle. Du skal igen ikke vide om det er lys, eller varme - det er bare et interface, hvordan dit lysItem skal reagere/implementere den metode bestemmer den selv, måske skal den slukke lyset, måske skal den kun dæmpe det...

Ideen er at hver kilde skal være "selvkørende" og hverken server eller automationItem skal være afhængig af at kende til hinanden. De kender kun til et generelt interface.


Hmmm.. Kan godt se det smarte. Relateret til det her. Hvad så med ting der er nød til at være globale? Eller om ikke andet tilgås globalt.

En Serial port kan kun åbnes et sted af gangen. Fx lys og låsesystem kører i samme Serial Port. Så hvordan går man omkring det i forhold til interfaces?



<< < 12 > >>
t