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

How to check in AngularJS if a service was register or not

There are cases when you need to check in a service or a controller was register in AngularJS.
For example a valid use case is when you have the same implementation running on multiple application. In this case, you may want to intercept the HTTP provider and add a custom step there. This step don’t needs to run on all the application, only in the one where the service exist and register.
A solution for this case would be to have a flag in the configuration that specify this. In the core you would have an IF that would check the value of this flag.
Another solution is to check if a specific service was register in AngularJS or not. If the service was register that you would execute your own logic.
To check if a service was register or not in AngularJS container you need to call the ‘has’ method of ‘inhector’. It will return TRUE if the service was register.
if ($injector.has('httpInterceptorService')) { $httpProvider.interceptors.push('httpInterceptorService&#…

ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded

Today blog post will be started with the following error when running DB tests on the CI machine:
threw exception: System.InvalidOperationException: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information. at System.Data.Entity.Infrastructure.DependencyResolution.ProviderServicesFactory.GetInstance(String providerTypeName, String providerInvariantName) This error happened only on the Continuous Integration machine. On the devs machines, everything has fine. The classic problem – on my machine it’s working. The CI has the following configuration:

TeamCity.NET 4.51EF 6.0.2VS2013
It seems that there …

Run native .NET application in Docker (.NET Framework 4.6.2)

Scope
The main scope of this post is to see how we can run a legacy application written in .NET Framework in Docker.

Context
First of all, let’s define what is a legacy application in our context. By a legacy application we understand an application that runs .NET Framework 3.5 or higher in a production environment where we don’t have any more the people or documentation that would help us to understand what is happening behind the scene.
In this scenarios, you might want to migrate the current solution from a standard environment to Docker. There are many advantages for such a migration, like:

Continuous DeploymentTestingIsolationSecurity at container levelVersioning ControlEnvironment Standardization
Until now, we didn’t had the possibility to run a .NET application in Docker. With .NET Core, there was support for .NET Core in Docker, but migration from a full .NET framework to .NET Core can be costly and even impossible. Not only because of lack of features, but also because once you…