Avatar billede anders159 Nybegynder
30. november 2006 - 11:37 Der er 19 kommentarer og
1 løsning

n-tier execption handling

Hejsa

har lige problemer med at overskue den bedte måde at håndtere execptions på.

har en n-tier løsning og mit problem udspiller sig på BuisnesLogicalLayer og en webside.

på BLL håndtere jeg logik og forindelse til DataAccessLayer.

spørgsmålet er hvor jeg burde håndtere hvad. Hvilke execptions håndtere jeg på BLL og hvilke execptions sender jeg videre til overfladen.

Eks. databasen er nede eller brugeren er alle oprettet.
dette vil give 2 forskellige execptions...

fortolker jeg dem på BLL og sender så en ny execption op til webSiden, med en menneskelig forklaring.?? og hvis ja, hvordan håndtere jeg så de forskellige meddelser i websidens kode.

er lidt forvirret her, så håber nogen kender svaret ;)
Avatar billede jimgordon Nybegynder
30. november 2006 - 12:29 #1
Undtagelser skal kastes upad i din ntire som du skriver. Er de af ingen relevans for brugeren kan de fint håndteres i BLL og blive slået ned der. Er det en undtagelse skal den selvf. op til brugeren på overfladen, hvor den er tolket og beskrevet. Du kender baggrunden for meddelsen, så du ved hvordan den bedst preæsenteres for brugeren i en label eller pop up eller andet. Det farligste er at kastet den opad og der så ikke er nogen til at modtage den (unhandled). Der hvor du fanger din undtagelse først, ved du mest præcist hvad der er gået galt. Her kan du evt. allerede tolke og lægge en tekst til undtagelse. Når du længere oppe i din lagkodel fanger undtagelsen kan du bedre se hvorfor den blev kastet, se mere om 'inner exception' på http://msdn2.microsoft.com/en-us/library/hdwz4c0s(VS.80).aspx
Avatar billede anders159 Nybegynder
30. november 2006 - 13:38 #2
1000 tak for dit hurtige svar.

er dog stadig lidt forvirret. kan ikke rigtig se hvad der ikke skulle være relevant for brugerfladen. Det er vel kun informationen om havd der gik galt, der i visse tilfælde kan værer irellevant for brugeren.

mit billede er pt som følgende:
jeg burde sende to typer execptions op til brugeren. en der giver en melding angående ikke fatale fejl. og en Execption der melder fatale fejl.
Den sidste kan jo opstå på baggrund af mange forskellige fejl(execptions typer) men resultatet for brugeren er det samme...siden virker ikke(siden er nede)


Et pseudo eks på min nuværende forståelse.
--------------------------------------------------------------------
BLL

public metode1(string navn)
{

  try
  {
    //program code
  }
  catch(ExceptionType1 ex) 
  {
    //handle non fatal execption
    throw new MyExecption1("Brugernavnet findes allerede")
  }
  catch(ExceptionType2 ex)
  {
    //handle fatal execption
    throw new MyExecption2("Siden er midlertidig nede");
  }
  catch(ExceptionType3 ex)
  {
    //handle fatal execption
    throw new MyExecption2("Siden er midlertidig nede");
  }
  catch(ExceptionType4 ex)
  {
    //handle fatal execption
    throw new MyExecption2("Siden er midlertidig nede");
  }

  finally
  {
    //clean up the resources
  }

}

---------------------------------------------------
webSide:

try
{
  metode1("Anders");
}
catch(MyExecption1 ex)
{
    //handle non fatal execption
    throw new Execption("Brugernavnet findes allerede")
}
catch(MyExecption2 ex)
{
    //handle fatal execption
    throw new SystemException("Siden er midlertidig nede");
}


-------------------------------------------

Er dette lille eks helt hen i skoven?????

hvis ikke-->
hvad er så rigtigt og hvad er forkert?
hvad er hensigtsmæssigt og hvad det ikke?
Avatar billede anders159 Nybegynder
30. november 2006 - 15:03 #3
ups.....
websiden skulle selvfølgelig være:
try
{
  metode1("Anders");
}
catch(MyExecption1 ex)
{
    //handle non fatal execption
}
catch(MyExecption2 ex)
{
    //handle fatal execption
}
Avatar billede jimgordon Nybegynder
30. november 2006 - 20:40 #4
Jeg syntes det ser fint ud. Bottomline er at du håndtere undtagelser og sender dem op igennem systemet. På websiden skal du nok have en almindelige exception også, hvis der bliver kastet noget du ikke tager hånd om længere nede.

try
{
  metode1("Anders");
}
catch(MyExecption1 ex)
{
    //handle non fatal execption
}
catch(MyExecption2 ex)
{
    //handle fatal execption
}
catch(Exception ex)
{
    //handle unhandled execption
}
Avatar billede arne_v Ekspert
30. november 2006 - 20:54 #5
nogle tommelfinger regler:

1)  brugeren maa aldrig se en exception kun en paen version

    =>

    altid en catch i UI layer

2)  exceptions er en en del af interfacet til et layer

    =>

    1) exceptions skal dokumenteres
    2) exceptions maa ikke vaere implementations specifikke (for alle praktiske
      formaal betyder det specifikke exceptions for det paagaeldende lag)

3)  returner ikke samme exception type bare med forskellig tekst for
    2 forskellige slags exceptions

    =>

    lav en super klasse og et antal sub klasser saa kan den der kalder laget
    selv vaelge om de skal haandteres ens eller ej
Avatar billede anders159 Nybegynder
01. december 2006 - 10:23 #6
tak for svarene..
arne_v: der blev jeg lidt forvirret.

1)må der kun være en catch på UI?

2,2) forstå den ikke helt ;)

3)hvordan håndtere man så forskellige exTyper og hvilke beskder sender man vidre..sender man bare exTypen vidre...og har så kun en catch på UI, der så i en case/if smager på exTypen og udfra det håndtere den?

ville blive glad for et par gode exempler eller links til nogen :)

vil blive meget
Avatar billede arne_v Ekspert
02. december 2006 - 02:41 #7
re 1)

nej

men der skal catches der, så brugerne får en pæn fejl

re 2.2)

eksempel: dit DAL bør ikek smide SqlException, fordi så er dit DAL knyttet
til SQLServer

re 3)

hvis du laver en MyDALException klasse med nogle sub klasser MyDALNotConnect, MyDALInvalidArgs etc.

så skal du altid throwe en af subklasserne

oppe i BLL kan man så vælge om man vil catche de enkelte
sub klasser eller bare MyDALException
Avatar billede anders159 Nybegynder
04. december 2006 - 14:47 #8
så begynder jeg måske at se lidt lys..bare lige et par sidste krampetræk for at sikre at jeg nogenlunde har forstået det ;)

Er ude efter forståelse for hvodan man skal/burde lave 'execption handling' i en n-tier løsning.....

1. Man 'bør' altid lave sin egen myExecptionClass. Hvis man ikke har, bør man håndtere alle execptions på DAL og retunere true/false på BLL forspørgsler(Aldrig sende en system-execption op til BLL)?

1.1 Eller gælder dette kun sqlExecptions?

2. selvom man godt kan have flere catch på UIL, er det så ikke god stil at BLL i de fleste tilfælde grinber de forskellige myExecptions.Subclasses og bare sender disse videre op til DAL, som så altid kun grinber 1 MyExecption.

2.1 hvis ikke, hvad er så god stil mellem Bll og UIL.

3 DAL bør kunne retunere en MyExecption på enhver tænkelig SystemExecption?


håber ikke det er helt hen i skoven ;)
Avatar billede anders159 Nybegynder
04. december 2006 - 14:49 #9
RETTELSE:
2. selvom man godt kan have flere catch på UIL, er det så ikke god stil at BLL i de fleste tilfælde grinber de forskellige myExecptions.Subclasses og bare sender disse videre op til UIL, som så altid kun grinber 1 MyExecption.
Avatar billede arne_v Ekspert
05. december 2006 - 02:10 #10
re 1)

aldrig sende en exception op som er specific for implementationen

og dem som ikke er implementations specifikke er sikkert så generelle at det er
bedre at fange dem og smide en mere sigende exception anyway

re 1.1)

nej - det er bare et godt eksempel på hvad man ikke skal gøre

re 2)

næppe

re 2.1)

igen så specifikke exceptions som muligt

dit BLL hverken skal eller kan vide noget om hvad UIL har som requirement
idag eller om 3 år

re 3)

Næsten.

En NullReferenceException ville jeg pakke ind i noget som kunne fortælle mere om
hvor, hvordan og hvorfor det er gået galt.

Men en OutOfMemoryException kan jeg ikke se noget formål med at pakke ind.
Avatar billede anders159 Nybegynder
06. december 2006 - 09:01 #11
det var næsten 1 ud af 5 mulige....ikke den bedste start på dagen :)

min forvirren er næsten komplet og forstår godt hvis du opgiver her ;)

forståe ikke 1 og 3.

arne_v:(re 1) aldrig sende en exception op som er specific for implementationen.
anders:(re 3) er det ikke det man gør hvis man sender en myExecption op til BLL?


som jeg nu har forstået DAL -> BLL. Når du siger du vil pakke en NullReferenceEx ind, går jeg udfra du mener at lave din egen ExecptionClass.subClass indeholdende dine info om hvor,hvordan, hvorfor og smide den til BLL..... Og kan godt se at der ikke er noget specielt at sige om en OutOfMemory, så denne smides som den er.

Hvad BLL -> UIL angår er jeg stadig rundt på gulvet. Kan godt se at BLL intet ved om UIL og derfor ikke kan tage udgangspunkt i denne, men hvad sender BLL så til UIL. MyExecptions(implementations Specifik) eller SystemExecptions?


håber du orker en sidste runde, da jeg virkelig har et ønske om at forstå og bruge execption handling rigtigt i min kode.

Mvh
Anders
Avatar billede arne_v Ekspert
06. december 2006 - 16:41 #12
nej

en MyException er en del af dit DAL interface, men SQLServer specifikke eller Oracle
specifikke eller XML fil specifikke exceptions er en del af din implementation

der boer ikke smides andree exceptions fordi du skifter fra XML filer til
Oracle eller fra Access til SQLServer
Avatar billede arne_v Ekspert
06. december 2006 - 16:47 #13
UIL-BLL er ligesom BLL-DAL

interface specifikke exceptions ikke implementations specifikke exceptions

og gerne med rigelig brug af subclasses for fleksibilitet
Avatar billede anders159 Nybegynder
07. december 2006 - 02:00 #14
1000 tak for din vedholdenhed :)

Så tror/håber jeg den var der.
Men bliver lige nødt til at spørge i tekstform ;)


1) xExecptions bliver lavet for bedst muligt at beskrive de
funktionsfejl/ImplemtationsExecptions en given komponent kan skabe.

A.dll smider aExecption.SubExecption's
B.dll smider bExecption.SubExecption's
osv osv.

2) En komponent 'bør' derfor altid smide en xExecption.SubExecption og kun i sjældne tilfælde sende en implementrings execption vidre op i systemet.

3) Jo flere subExecptions der er, jo flere konfilkter/konfilktetyper er ordentligt håndteret/beskrevet?

hvis du mener jeg nogenlunde har forstået det, så smid kommentaren som et svar og du ska få dig nogle velfortjente point's :)


----------- Tillægs spørgsmål..........hvis du orker ;) -----------

søger somsagt den  rigtigt/mest hensigtsmæssige/optimale måde at stukturer og skrive kode på....Eller med andre ord, hvordan ville en haj som dig gøre det ;)

....Så angåedne BLL som modtager myDalExecption.SubExecptions.
Du skriver, at så kan BLL selv vælge om den vil gribe myDalExecption eller myDalExecption.SubExecption.

A) Min første tanke var at BLL altid skulle gribe en myDalExecption og så kigge efter subExecptions. På den måde vil der altid kun skulle laves en Catch pr BLL kald??

B) hvis dette er rigtigt. Kan en BLL.class så ikke indeholde en metode som kan smage på alle de myDalExecption.SubExecption den måtte modtage fra DAL og så retunere en myBllExecption.SubExecption.
i retnig af-->
BLL.class.Metode1
try
{
//somthing
}
catch(myDalExecption DalEx)
{
throw getBllExecption(DalEx);
}

getBllExecption(myDalExecption DalEx)
{
if DalEx typeof  DalEx.1 return new myBllExecption.A
if DalEx typeof  DalEx.2 return new myBllExecption.B
if DalEx typeof  DalEx.3 return new myBllExecption.C
}

Eller hvordan strukturerer man det ellers?
Avatar billede arne_v Ekspert
07. december 2006 - 02:13 #15
ikke helt

du har dit IDAL interface

det har en metode GetFoobarData

du har 2 implementer DALSqlServer og DALAccess

koden inde i DALSqlServer kan smide 2 exceptions:
  SqlException("Error connecting")
  SqlException("SQL syntax error")

koden inde i DALAccess kan smide 2 exceptions:
  OleDbException("Error connecting")
  OleDbException("SQL error")

for at undgå at expose de database specifikke exceptions SqlException og OleDbException
laver du en DALException

for at kunne kende forskel på connection og SQL problemer laver du 2 sub klasser:

DALConnectException
DALSQLException

i DALSqlServer catcher og thrower du

  SqlException("Error connecting") -> DALConnectException
  SqlException("SQL syntax error") -> DALSQLException

i DALAccess catcher og thrower du

  OleDbException("Error connecting") -> DALConnectException
  OleDbException("SQL syntax error") -> DALSQLException

i BLL kan programmøren så vælge om han vil catche alt via DALException eller
om han vil catce DALConnectException og DALSQLException separat
Avatar billede arne_v Ekspert
07. december 2006 - 02:14 #16
(lidt forsimplet, men du kan sikkert se pointen)
Avatar billede arne_v Ekspert
07. december 2006 - 02:15 #17
og til tillægs spørgsmål:

nej

enten

try
{
  // kald DAL
}
catch(DALException ex)
{
  // gør noget
}

eller

try
{
  // kald DAL
}
catch(DALConnectException ex)
{
  // gør noget
}
catch(DALSQLException ex)
{
  // gør noget andet
}
Avatar billede anders159 Nybegynder
07. december 2006 - 02:17 #18
Klokke klart :)

så var der lige det med svaret :)
Avatar billede arne_v Ekspert
07. december 2006 - 02:25 #19
svar
Avatar billede anders159 Nybegynder
07. december 2006 - 02:27 #20
Endnu engang tak for hjælpen
vi ses nok en anden gang ;)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester