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(...

How to audit an Azure Cosmos DB

In this post, we will talk about how we can audit an Azure Cosmos DB database. Before jumping into the problem let us define the business requirement: As an Administrator I want to be able to audit all changes that were done to specific collection inside my Azure Cosmos DB. The requirement is simple, but can be a little tricky to implement fully. First of all when you are using Azure Cosmos DB or any other storage solution there are 99% odds that you’ll have more than one system that writes data to it. This means that you have or not have control on the systems that are doing any create/update/delete operations. Solution 1: Diagnostic Logs Cosmos DB allows us activate diagnostics logs and stream the output a storage account for achieving to other systems like Event Hub or Log Analytics. This would allow us to have information related to who, when, what, response code and how the access operation to our Cosmos DB was done. Beside this there is a field that specifies what was th...

Cloud Myths: Cloud is Cheaper (Pill 1 of 5 / Cloud Pills)

Cloud Myths: Cloud is Cheaper (Pill 1 of 5 / Cloud Pills) The idea that moving to the cloud reduces the costs is a common misconception. The cloud infrastructure provides flexibility, scalability, and better CAPEX, but it does not guarantee lower costs without proper optimisation and management of the cloud services and infrastructure. Idle and unused resources, overprovisioning, oversize databases, and unnecessary data transfer can increase running costs. The regional pricing mode, multi-cloud complexity, and cost variety add extra complexity to the cost function. Cloud adoption without a cost governance strategy can result in unexpected expenses. Improper usage, combined with a pay-as-you-go model, can result in a nightmare for business stakeholders who cannot track and manage the monthly costs. Cloud-native services such as AI services, managed databases, and analytics platforms are powerful, provide out-of-the-shelve capabilities, and increase business agility and innovation. H...