Skip to main content

What to use? Event or delegate?

Un eveniment este de fapt un delegate mai special. Comportamentul este destul de asemanator a unui eveniment in interiorul clasei unde este declarat, dar in afara acestei clase singurul lucru care se poate face este subscribed si unsubscribed. In momentul cand cineva face (un)subscribed, putem sa executam actiuni specifice prin definirea explicita a actiunilor de "Add" si "Remove"( per event).
Chiar daca pentru un eveniment putem sa specificam nivelul de acces( public, protected, private, internal), asta nu inseamna ca oricine poate sa faca raise la eveniment. Doar clasa care contine evenimentul poate sa faca raise la eveniment.
In mod normal evenimentele nu trebuie sa execute o actiune pe obiectul care contine acest eveniment, ele trebuie doar sa notifice abonatii ca ceva s-a intamplat. Din aceasta cauza evenimentele trebuie privite ca ceva optional. Aruncarea evenimentului este ceva optional, iar orice exceptie aparuta in momentul respectiv nu ar trebuii sa afecteze logica blocului de cod care face raise la eveniment.
Din punctul meu de vedere evenimentele trebuie folosite cand vrem sa notificam 1 sau mai multi abonati ca ceva s-a intamplat. In cazul in care vrem ca abonatul sa faca o actiune care poate afecta clasa care a facut raise la eveniment, atunci este necesar sa folosim delegates.


Pentru mai multe informatii despre events si delegates:


Comments

  1. Legat de
    "Aruncarea evenimentului este ceva optional, iar orice exceptie aparuta in momentul respectiv nu ar trebuii sa afecteze logica blocului de cod care face raise la eveniment"
    adevarat, raise la evenimente ar trebui facut doar la sfarsit, dupa ce actiunea a fost terminata cu success..

    Insa daca un event handler arunca totusi o exceptie (desi nu prea e frumos asta :) ), cine implementeaza componenta respectiva nu prea are ce face decat sa o arunce mai departe..

    ReplyDelete
  2. Dar mecanismul prin care facem raise trebuie sa fie a.i. in momentul in care apare o eroare pe Invoke, logica clasei noastre sa nu fie afectata.
    Depinde cred si de tipul de clasa. Daca suntem pe UI, atunci e normal sa aruncam exceptia mai departe, dar daca este o clasa ce proceseaza date( ceva pe back-end) atunci logica din spate nu trebuie sa fie afectata daca un eveniment arunca o exceptie. Nu cred ca este problema acestei clase daca un client arunca o exceptie. Poate sa scrie intr-un log, sau sa arunce exceptia mai departe( printr-un alt thread de exemplu), dar logica clasei de baza trebuie sa ramana la fel.

    ReplyDelete
  3. Adevarul e ca n-am prea intalnit folosite Events in .NET decat folosite in contexte de UI (WinForms, WPF, ASP.NET), dat fiind ca observer pattern e folosit mai ales in contextul asta..
    Altfel, ai dreptate:
    http://c2.com/cgi/wiki?ObserversShouldNeverThrowExceptions

    ReplyDelete
  4. Eu am folosit evenimente si in back-end. Spre exemplu daca am un fir de executie care proceseaza date, arunc evenimente periodic ca sa anunt progresul (in procente). La eveniment se poate abona controllerul care, la randul lui modifica un progress bar pe ui.

    In cazul exemplului de mai sus, intr-adevar nu as vrea ca o exceptie aruncata de controller sa intrerupa procesarea datelor din back-end. Pt asta eu am folosit pana acum un try-catch. (astept pareri pro-contra daca aveti)

    try
    {
    OnProgressChanged(new ProgressChangedEventArgs(i));
    }
    catch {}

    In felul asta eu anunt progresul, dar nu opresc procesarea datelor daca vr-unul dintre abonati arunca exceptie. (Anuntarea progresului e ceva optional, nu e vital pt procesarea datelor.)

    Obs! Pe catch, exceptia poate fi scrisa intr-un log file.

    ReplyDelete
  5. E o chestei de preferinte - eu prefer principiul "fail fast" (http://martinfowler.com/ieeeSoftware/failFast.pdf ; http://c2.com/cgi/wiki?FailFast) - daca apare o exceptie in aplicatie, din orice sursa, care nu stiu/nu pot sa o tratez, prefer sa o loghez, sa afisez un mesaj user-friendly la user, eventual sa incerc sa salvez starea aplicatiei (si/sau sa eliberez resursele alocate, eventual) dupa care sa las thread-ul curent sa moara.

    Chiar daca e logata, o exceptie unhandled poate insemna doua lucruri:
    - un bug in aplicatie (si deseori asta poate inseman ca aplicatia e intr-un state "unexpected" in care daca executia se continua rezultatele pot fi cel putin eronate)
    - o exceptie dupa care executia nu mai poate continua oricum in conditii normale (gen stack overflow, out of memory etc.)

    Normal, sunt si dezavantaje la abordarea asta: se prea poate ca o exceptie "expected" sa apara si sa nu fie prinsa, desi ar fi trebuit, mai mult efort trebuie alocat pentru a trata corespunzator toate tipurile de erori etc.
    E oarecum similara cu dilema legate de checked exceptions din Java vs. C#..

    ReplyDelete

Post a Comment

Popular posts from this blog

Windows Docker Containers can make WIN32 API calls, use COM and ASP.NET WebForms

After the last post , I received two interesting questions related to Docker and Windows. People were interested if we do Win32 API calls from a Docker container and if there is support for COM. WIN32 Support To test calls to WIN32 API, let’s try to populate SYSTEM_INFO class. [StructLayout(LayoutKind.Sequential)] public struct SYSTEM_INFO { public uint dwOemId; public uint dwPageSize; public uint lpMinimumApplicationAddress; public uint lpMaximumApplicationAddress; public uint dwActiveProcessorMask; public uint dwNumberOfProcessors; public uint dwProcessorType; public uint dwAllocationGranularity; public uint dwProcessorLevel; public uint dwProcessorRevision; } ... [DllImport("kernel32")] static extern void GetSystemInfo(ref SYSTEM_INFO pSI); ... SYSTEM_INFO pSI = new SYSTEM_INFO(

Azure AD and AWS Cognito side-by-side

In the last few weeks, I was involved in multiple opportunities on Microsoft Azure and Amazon, where we had to analyse AWS Cognito, Azure AD and other solutions that are available on the market. I decided to consolidate in one post all features and differences that I identified for both of them that we should need to take into account. Take into account that Azure AD is an identity and access management services well integrated with Microsoft stack. In comparison, AWS Cognito is just a user sign-up, sign-in and access control and nothing more. The focus is not on the main features, is more on small things that can make a difference when you want to decide where we want to store and manage our users.  This information might be useful in the future when we need to decide where we want to keep and manage our users.  Feature Azure AD (B2C, B2C) AWS Cognito Access token lifetime Default 1h – the value is configurable 1h – cannot be modified

What to do when you hit the throughput limits of Azure Storage (Blobs)

In this post we will talk about how we can detect when we hit a throughput limit of Azure Storage and what we can do in that moment. Context If we take a look on Scalability Targets of Azure Storage ( https://azure.microsoft.com/en-us/documentation/articles/storage-scalability-targets/ ) we will observe that the limits are prety high. But, based on our business logic we can end up at this limits. If you create a system that is hitted by a high number of device, you can hit easily the total number of requests rate that can be done on a Storage Account. This limits on Azure is 20.000 IOPS (entities or messages per second) where (and this is very important) the size of the request is 1KB. Normally, if you make a load tests where 20.000 clients will hit different blobs storages from the same Azure Storage Account, this limits can be reached. How we can detect this problem? From client, we can detect that this limits was reached based on the HTTP error code that is returned by HTTP