Tuesday, July 5, 2016

Inversion Of Control - Unity

Those are the notes on "Inversion Of Control" course on Pluralsight.com by John Somnez related to Unity.
If you want to see the entire course or itself by details, please feel free to go on pluralsight.com

Some vocabulary:

   Dependency Inversion Principle (DIP) - Principle used in software architecture saying you would invert the way how the objects are constructed.

   Inversion Of Control (IoC) - Is a pattern to implement the Dependency Inversion Principle and it is used also for other principles. But it is how to invert interfaces, flow and dependencies.
   Dependency Injection (DI) - Is an implementation of a specific inversion of control pattern. 
   Inversion of Control Container - The framework to be used.

Dependency Inversion





   The high level class should may have some code in it in order to handle the dependencies and differences between low level classes.  
    Because the low level classes are defining the interfaces and high level class should know about how to use it, the high level class is not reusable.
    Consider each interface is different.




   We just moved the interface above the line. So, the interface now is defined by upper layer.
   The main concept is the low level class should conform with the interface.
   Comparing with the previous implementation, we could have many implementation of that interface, but high level class will not care.
   So, initially we had a high level class depending by low level classes and their implicit interfaces. Now, high level classes become reusable.
   According to Bob Martin (which defined this concept) there are some assumptions:
   a. High level modules should not depend by low level modules. Both of them should depend by abstractions.
   b. Abstractions should not depend upon details. Details should depend upon abstractions. With other words, the interfaces should be enough general to keep all information to implement one.
   An interface should be defined externally and both high and low classes to depend of them. 

Layering of an application
   If an application was initially developed as following layers: Policy -> Mechanism -> Utility, a change in layer Utility might affect changes in Mechanism and in Policy. What Bob Martin promoted is: Policy -> Mechanism Interface -> Mechanism interface (implementation ) -> Utility Interface -> Utility interface (implementation).

Inversion of Control
   Many different ideas. But basically is a pattern to apply the principle of dependency injection. It is a very broad concept.
   Long story short:





   Dependecy Inversion is a principle: classes to depend by abstractions. The Dependency Inversion is a principle implemented through a pattern: Inversion of Control. It has 3 flavours:
1. Interface inversion;
2. Flow inversion;
3. Dependency Creation (Binding inversion).
- There are many ways to do that. One of them is called Dependency Injection. That represents the implementation of the pattern of the principle.
   In order to make sense, when you implement an interface, you should have more implementations of that interface. Otherwise... what is the purpose of doing in this way ?

Interface inversion


 Instead to have an implementation for each provider, the consumer will have a single implementation through an abstraction (in this case an interface).

In interface inversion, the interface should be implemented by Provider and not by consumer.



Flow inversion
   It is a simple idea to invert the flow. So, if the application is telling you as user what to do, the flow inversion means to tell you to the application what to do. And that is usually happening via graphic user interfaces.

Dependency Creation / Binding Inversion
   If you create the object inside the class that is using it, then this is not dependency injection.
Inverting the object creation means to create the classes outside of the class where they are used.
   There are many types of Creation Inversion:
      1. Factory Pattern
                   Button button = ButtonFactory.CreateButton();

      2. Service Locator
                   Button button = ServiceLocator.Create (IButton.Class);

      3. Dependency Injection
                   Button button = GetTheRightButton();
                   OurScreen ourScreen = new OurScreen (button);

      4. More...

   What is: Is a type of Inversion of Control that move the creation and binding of a dependency outside of the class that depends on it.
   So, in a way or other, if we have:

 
So, using the dependency inversion principle, the DependencyClass is implementing the IDependency interface and it will be used by MyClass.

But... from somewhere or somehow, we still need the Dependency object. And we can't create it inside MyClass without violating the principle.

The dotted line represents the question: from where the dependency is coming from.





    In this way, the situation becomes:





So, an idea is to use another class known as Injector that is acting as an Injector.

The injector knows about my class, my dependency, interfaces. It is the injector responsibility to bind those things together.

So, when you are using dependency injector you should have something that is doing the injection. Also, that injector is important for all classes in the same situation. 





    There are few ways of injection:

    a) Constructor Injection
        - the most common and simple: it passes the dependency in the constructor of the dependent classes




   In this way, on constructor, the ICreditCard object is passed in. And also it will be kept in that class as a dependency.

    The good think is you are not able to create a class without dependencies.
    b) Setter Injection
        - Use setter instead of constructor. The down side is you could create a class without specifying all required setters (dependencies).
        - It allows us to create and use a class even without dependencies. It gives us flexibility. But in the same way it creates also danger to use a class without knowing if the dependency was set.
        - The example for using a setter injection:


   
    c) Interface Injection
       - Dependent class will implement an interface
       - Injector uses the interface to inject the dependency.
       - It is a little bit uncommon. 


   There is an interface IDependOnCreditCard which has a single method. There is the secret.
       - It is like a setter. The difference is to use an interface which has a method that known how to use it.

Warnings related to Dependency Injection
     1. Leaks the internal implementation details of a class.
          - It violates encapsulation: because it takes the internal implementation and exposes it through constructor of the class.
     2. Prevent deferred creation
          - If the idea of creating an object until needed, cannot be applied here.
          - Theoretically is not possible, because when you pass a dependency to the class, you need to create it first. The passing itself is a usage of that dependency. 
          - Sometimes it is possible to do this with some kind of lazy generation, but in general not.
          - You should be very careful to the large data graphs.
      3. Numbs you from the pain
          - Too many dependencies might be created. 
          - Unit tests are easier.

Building an IoC Container
   What is: - It is just a framework to do the dependency injection. This is the basic.
                - Also it should configure dependencies (give me a concrete type instead of another one)
                - Automatically resolves the configured dependencies.
   So, when you ask for a particular object, it knows by interface or by type what concrete type is, and it goes down that chain and init that object with its references.
   Only IoC Container will know about those objects. The objects will never know about IoC Container. This is the key difference between an IoC Container and a Service Locator.
   In the following figure will be shown an example of IoC container in the shopper example:

   So, in other words, the shopper class requests a dependency which implements ICreditCard in constructor. There are 2 classes which are implementing ICreditCard: MasterCard and Visa. So, depending how IoC Container is configured, it will serve one of: MasterCard or Visa.

   
Using Unity
   Unity in an IoC container from Microsoft. It is part of Enterprise Library. Can be taken also as nuget package. And it is extendable. 

Setting up Unity
   You could do this via NuGet.

Registering types
    You need to create an unity container and register types (optional)
    - What is specific to Unity is that you don't need to register every dependency with Unity.
    - But if many classes implement an interface and we are asking for that interface, then we need to register, to let unity to give us what we need.
    - The basic scenario:
          var container = new UnityContainer();
       container.RegisterType<ICreditCard, MasterCard>();
   - If:
        - you want to register a type and when you will get it back you want to get it with a value:
             container.RegisterType<ICreditCard, MasterCard>( new InjectionProperty ("ChargeCount", 5));
        - you want to register a type with a name:
         container.RegisterType<ICreditCard, MasterCard> ("DefaultCard");
         container.RegisterType<ICreditCard, Visa>("BackupCard");
       - you want to register an Instance and get it back:
         var object = new object();
         container.RegisterInstance

Using container
    - In order to use, your usually command is Resolve:
             var shopper = container.Resolve<Shopper>();

Controlling lifetime of an object
    - With an IoC you could choose between having a singleton or an instance.
    - The default is to create an instance every time when the container resolves a request.
    - For a singleton: 
    container.RegisterType<ICreditCard, MasterCard>(new ContainerControlledLifeTime());




Thursday, March 24, 2016

Understanding ASP.NET CORE


This is the course "Understanding ASP.NET Core" by Roland Gujit.
Those are my notes. It is not the entire course. 
If you are interested, please go on pluralsight.com and learn from there.

ASP.NET Core
     It is still in development, so many things may change. An example could be: ASP.NET 5 is now renamed as ASP.NET Core 1. Also, DNX (Dot Net Executable) is now integrated in DotNet CLI.

     ASP.NET 5 was built from scratch and it is significantly different with the rest of version.
     The dependency injection is now part of ASP.NET 5.

     ASP.NET 5 it is working only on VS 2015 or higher. At the time of this document, ASP.NET 5 is not included automatically with VS2015. So, you need to download the installer from http://get.asp.net . This will install ASP.NET 5 and also the templates in VS 2015.
     
     The new project structure is completely different by the previous versions. 
     You can find there:
      - global.json - this file contains information related to the new DNX (how to build and execute the solution). In this file exists a "sdk" tag what instructs the asp.net to use a particular version of DNX.
      - project.json - it is the file that contains the configurations and other settings for each project in the solution. 

     Packages
      - In ASP.NET 5 are used:
         a. NuGet - in order to manage packages on server side.
         b. Bower - in order to manage packages on client side.
         c. NPM    - in order to build tools and node.js on client/server side. Also here is Grunt.

      - When you'll install packages with Bower for example, the packages will be downloaded and shown in Dependencies folder.
      - But the files are not reachable to the site, as they are not in wwwroot folder. You need to minify and maybe boundling them.

      - In the new ASP.NET 5, there is no way to register and use bundles as it was...
      - In order to do that, you'll use task runners on node js. Now are used plugins to execute tasks. So bundles didn't make it in ASP.NET 5.
      - .csproj is gone. It was replaced by project.json and xproj (xproj is specific VS to be used for its operations)
     - DNX is using the project.json to get what it needs.

     Startup.cs
     - The global.asax file didn't make it in ASP.NET5. Now we have Startup.cs which contains a Main method what will be launch automatically (if exists) by ASP.NET 5. The Startup class it is just a simple class. Not implementing or deriving from anything.
      - Except Main, it might have two another methods: Configure and ConfigureServices.
      - When an application starts it is registering some classes in order to be automatically instantiated. Those classes are called services. And they are injected by an Dependency Injection service. Once registered, other types can ask the container for an instance of registered type. Also during registration you can specify the lifetime of that instance.
      - The lifetime of that registered object is managed by the container (types):
         a. Transient means a new instance is created every time when is asked for.
         b. Scoped means the instance will live until the web request is completely handled.
         c. Singleton means a single instance will be served for all.
      - This dependency service is right now part of ASP.NET 5 and it is invisibly created and filled with ASP.NET 5 services when the application starts. Anyway you still can use old dependency injector frameworks.
      - The concept of adding a service with DI is simple: write a class which implements whaterver interface you want. Add that interface in ConfigureServices with a command like: services.AddSingleton<Ixxxx, xxxx>(); which means when somebody is asking for that interface (Ixxxx) supply that class (xxxx).

     Those services can be injected in Controllers or even in views using @inject.

     The ASP.NET 5 uses also the idea of a pipeline. A request is coming from a browser and nothing will happen, nothing will be sent back.

     When a request is coming, first is catch by IIS (assuming that is the server). The IIS will delegate DNX in order to launch the application. The application will configure the pipeline adding so called middle services: Authorization, MVC, Static Files, etc and also the application will push the request through this configured pipeline. After finishing the pipeline, the request is physically sent back to the server.

      Until now, most of ASP.NET versions are based on System.Web DLL which is tied to IIS. In ASP.NET 5 this is no more there. Because started with version 1.0 it grown for a long period of time, so processing web requests with System.Web is not a solution on today's standards from processing time and memory usage point of view.

     Using the pipeline, you will plug only what you need, resulting to  a more efficient way to answer to the requests. That means also IIS is not required any more. So, it can be hoster by other web servers.
     IIS & IIS Express will still be supported for the beginning. But also there other options like: WebListener - a very light web server used for hosting, Kestrel - is another interesting web server because supports multiple operating systems.


     Pipeline

    When you add a middle ware in pipeline, then that one will be executed. In order to execute another one, the first one should call the second one, otherwise it returns and that's all.
    Instead to use app.Run in Configure method from Startup, you could use Use.
    Base example:

public void Configure (IApplicationBuilder app)   {      app.UseIISPlatformHandler(); // make sure using IIS      app.Use ( async ( context, next ) =>      {         await context.Response.WriteAsync("Hello !");         await next();      }
      app.Use ( async ( context ) =>      {         await context.Response.WriteAsync("Hello AGAIN!");      }   }
     The pipeline will give back control to the previous middle-ware component.

     ASP.NET can be seen as a next version of Katana (Katana is the Microsoft implementation of OWIN).

     WebForms - there will be no web forms in ASP.NET 5.

     MVC 6

     Services are objects that should be injected but first registered. MVC is also a service that should be registered in IoC container. Also it is required to configure a routing for MVC.
     In order to register MVC in ASP.NET you need to use AddMvc() method in ConfigureServices. After adding MVC service, it is required to add Mvc in pipeline.
     You need also to add StaticFileSupport service.
     You may use also a method like UseStatusCodePages() in order to show a friendly error when a page is not found. There are aslo some other methods in order to use this with a custom error page, etc.
     Web.config is not used anymore. It could be used only if you run under iis.
     The yellow error page is now a middleware.
     
     Environments
     
     In a professional development, you could have a development, testing and production servers. The type of the server may be controlled by environment variables. Those variables are staying usually in a file called: launchSettings.json.
     In Startup you could determine for example what environment is by using an MVC service which implements IHostingEnvironment.

     Unified Controllers

     MVC 5 (ASP.NET 4) has a clear distinction between MVC and WEB API. Web API was created using same model that MVC uses. The reason for what MVC and Web API were separately (even they are almost one to one map), it is that MVC is tied to System.Web.dll. Microsoft wanted to untie WEB API from System.Web.dll which gave to WEB API applications to be self hosted.
     Because ASP.NET 5 is not using System.Web.dll, there is no reason to have to sets. So WEB API and MVC are now together and the name Web API has been dropped.

     The new return is now IActionResult instead of ActionResult class. You can now create your ActionResult class, implementing IActionResult without being tied with the ActionResult base abstract class. There is also a benefit for unit testing.

     HTML helper tags
     In the previous version of MVC you could use:
       @Html.EditorFor ( m => m.Name)
     In the new ASP.NET 5 you can use:
       <input asp-for="Name"></input>
     Benefits: more HTML friendly approach. Also you can create your own taghelpers deriving from TagHelper instead to create an extension for Html class.
     There are few more new tags that are supporting the development. For this you need:
     a. Add the reference to the Microsoft.AspNet.Mvc.TagHelpers in the project.
     b. You need to make them visible everywhere: so you need to create a new partial view (eg: _ViewImport) in the root of the Views folder.
     c. Add the following code:
     @addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
     
     In the application, there is a tag called environment which is helping you to include that part of the code when the application has a specific variable environment. So you could load the full css and javascripts when is in development and minifyed versions when you are in production.
     Some tags:
     1. asp-href-include: it is used to add new css files. It can be used with wildcards.
     2. asp-src-include: it is used to add new js files. It can be used with wildcards.
     3. asp-append-version: it is used for images when you add an image, it computes the value based on the content of the image. So, if the image will be changed, it will be loaded and cached again.
     4. In C# 6 if you put $ in front of the string you can construct it with expressions.

     Configuration system
     The configuration system was reviewed. It is still using simple keyvalue pairs in order to keep the information.
     Until version ASP.NET 5 it is common to put settings in web.config or other xml files.
     After this version, web.config is gone. There are new configurations much more flexible like: in memory, JSON, XML, INI and environment variables.
     You could even extend sources by deriving from ConfigurationSource class. What was not possible previous.
     In ASP.NET 5 there is a new set of configuration classes in a different assembly: Microsoft.Extensions.Configuration. Also actual settings are decoupled by the setting system.
     In order to load a set of settings into a class, you need to add a json file with that information. After that you need in Startup to create an instance of ConfigurationBuilder where you should use AddJsonFile. You could add also optional files for different settings using for example an environment variable.
     After you need to call the Build command of that instance of ConfigurationBuilder.
     In order to pass data from json to the class, you should use  services.Configure<xxxx>(configBuilder) and pass it in constructor.

     The Traditional .NET 
     Since the beginning of .NET, things were similar. There is always some kind of Bootstraper which starts the .NET. 
     In the case of console app, this is the executable itself which is started by Windows. In the case of traditional ASP, this is the isapi.dll.
     The app written is compiled in an assembly which contains IL. On the machine IL is compiled in native code by JIT.
     JIT is contained in .NET itself in the part that is called CLR. The other part is named FCL or Framework Class Library. It contains all classes required by Windows Forms, WPF, etc. The advantage of this is the application will contain only what you wrote, not everything. 
     .NET Framework should be installed on the machine where you want to execute the application.
     The CLR is specific designed for Windows. It contains classes specific for Windows.

     Mono
     Mono is an opensource version of .net framework. And it is cross platforms. It is used heavily by Xamarin.

     NuGet
     Ideally, you don't need NuGet in order to run your application. But usually you need in order to download thirdparties from internet.
     Visual Studio has tooling to download, search and install nuget packages. Used to introduce new libraries and even frameworks.
     It is difficult to update, correct or create new versions of .NET in the old way. NuGet fixes this problem.

     .NET Core
     It contains:
         - CoreCLR - what is portable across all platforms
         - CoreFX - a set of classes what are common across platforms (classes like manipulating files, lists, etc. But not WPF for example).
     The entire CLR is distributed via NuGet.
     .NET core has:
         - a small footprint, lightweight
         - it is cloud optimized
         - no machine wide installation
         - it is an open source
     
    DNX
    The primary goal of it is to run the app on the designed framework.
    The command line it is called: DotNet Cli
    DNX runs the app. And DNX hosts the CLR instead of OS.
    DNX will look for Main method.

    Ngnix - is the production server for linux.



 
 

 




Wednesday, March 16, 2016

ASP.NET 5 - first look (Pluralsight)

ASP.NET 5 - First look

   Those are my notes related to pluralsight course. If you want the course, just go on pluralsight.com and see the entire course.

Project structure
   It is here a major change as now, the project is based on file structure. So, if you want to add a new file, just add it in the correct spot of your folder structure and it will be taken automatically.
   The file system is your project and everything in, builds dynamically.
   This is happening because of the new Roslyn compiler which compiles in memory. There are no temporary asp.net folder, because of this.
    Because of that, also the project structure is dramatically changed. The reasons for that big change:
     - it is easier to deploy an application with the new structure, by cloning a repository
     - it is also because of the optimization for cloud
     - it is also because of an unification MVC6 = ASP.NET MVC + WEB API.

   There is a new CLR for this ASP.NET 5 and it is wrapped in NuGet packages. It is significantly small and faster. It is also working on Linux.
   The ASP.NET applications no longer requires System.Web.dll.  Because of this, the earning is the context carried with each request is now 2KB. With the old version, at least 30KB.

   In ASP.NET 5, basic concepts are the same: controllers, views, css and javascript, etc. 
But also there are new concepts that were changed:
   1. The root of the website is no longer the root of the project.
   2. The root of the website is called now wwwroot.
       - this because it is now a clear separation between files and information sent to client and configuration and logic of the application.
       - this will contain the static assets (css, images, js, etc).
       - it is containing also the "bin" folder.

   The project.json configuration file it is telling to asp.net where to find the root folder and other configurations (like dependecies, etc).
   It is json format.
   Now the dependencies are related to NuGet management based on project.json
   There are few reasons for this change:
   1. Dependency management
   2. ASP.NET is moving away from requiring Windows or VS, etc.

   Where packages are stored
     ASP.NET 5 can work on multiple frameworks. The most common ones are ASP.NET 5 (for windows) and ASP.NET Core 5 (for the rest). Of course, those frameworks are specified in project.json config file, so the project will be compiled under both frameworks.
     Because the application can be built on multiple platforms, not all platforms will expose same methods. So, in this situation you can use compiler conditionals like:

#ifdef ASPNET50    // do something#endif#ifdef ASPNETCORE50    // do something else#endif
     The version of ASP.NET 5 was initially named "Project K". For this reason you can find a lot of Ks. Depends what you framework you pick, you could run the application against ASP.NET 5 or CORE.
     The packages are stored now under User's directory, in a folder: .kre (K (the project) - R = runtime, E = environment). Global packages will stay in the same place, but in .kpm folder.
     ASP.NET 5 loves NuGet packages.
     Also, in project.json, where you define what frameworks you would like to use, you can specify for each one a list of specific dependencies. So let all common dependencies in the "dependecies" tag, and the specific ones on "aspnet50" or "aspnetcore50" or so on.
     If you want to add as a reference a project from your solution, you should do this in dependencies tab (from project.json) or in each framework tab (if the project is not supported on the current consumable project).

Build an ASP.NET 5 application from scratch
     There are some new changes in the new ASP.NET 5:
     1. Global.asax file was replaced by Startup.cs
     2. Web.config file was replaced by same file, Startup.cs
     In ASP.NET 5 is a new http pipeline.
     Also ASP.NET 5 tries to find a class called Startup in the root of the application and it is passing an IApplicationBuilder object. In this ASP.NET 5 Linux, this is how the application is configured.

     Adding ASP.NET MVC 6, first you need to go in project.json and add there, in dependencies, Microsoft.ASP.Net.MVC (version 6).
     When you add a reference, usually there is a method that is starting with Use... for each package that you added. You need to use this method in order to activate it.
     Because ASP.NET MVC 6 is in the end a service for application and because it is used dependency injection for that, we need to make some changes in couple of places:

     1. Startup.cs -> update/add ConfigureServices(IServiceCollection services). This IServiceCollection is a dependency injection reference. This method will take place before of application configuration (Configure method). In this way we can have services ready to go by the time of configuring the application. For example, to use Mvc, you need first to add services.UseMvc()
     2. Startup.cs -> update/add Configure (IApplicationBuilder app) with app.UseMvc().

     Routing - in order to perform routing specifications, there are a couple of ways to do that:
     1. In Startup.Configure, when use UseMvc() there is an overload that takes an expression lambda like:
         app.UseMvc (routes => routes.MapRoute("default", 
                          "{controller=Home}/{action=Index}");
     - spre deosebire de MVC anterior, valorile default se baga dupa controller, action, etc.

     2. Using attributes (which was introduced starting with MVC 5), but there are some features refined a little bit in vNext.
     Using attributes you are able to decorate the Controller class with 
       - [Route("/Home"] or [Route("/")] - last one in order to make it default.
       - There is an update: [Route("/[controller]")] in order to take the name of the class.
       - In order to define the default action, you may decorate the action with [Route("[action]")] and/or [Route("/")].

      Views - are very similar with the old MVC.

      Working around controllers is usually managed by a code called Service. Service is available through controllers. In order to have a service, we need to have (generally speaking) followings:
       a. A class that is transporting the message or information - this is the model
       b. An interface of the server (IService...) which is implementing my methods.
       c. The concrete implementation of that class (that is implementing also the IService... interface, in order to add it through DependencyInjection.
          - The dependecy injector can be easily used in constructor. In the previous versions of ASP.NET, it was not possible. But now, in order to use it, you need to go in ConfigureServices and set it there, like:
              i) service.AddInstance<xxx> - equivalent with AddSingleton
             ii) service.AddScope - a new service for each http request

            iii) service.AddTransient - a new instance when someone needs one

Configuration
     Of an ASP.NET 5 was changed. There are no xml files. You can do anything via config.json which should be added in the root of the site.
     If the application is connected to a database, then it requires to read some text from config.json.
     In order to do this, you need to add the text that you want in config.json, like: 
         "messageName" : "text of the message what you want" 
     Also, you need a dependency in order to read this information from there: Microsoft.Framework.ConfigurationModel.Json.
     Usually, you need to add an IConfiguration Configuration {get ; set; } in order to keep your configuration options locally.
      And you need to initialize it, in the constructor of Startup:
        Configuration = new Configuration().AddJsonFile("config.json")
     After that, in the constructor of the service that you are using, just need to add IConfiguration interface. The DI will give you a reference to it. After you have it, you can call it like: _config.Get("message"); 
     You can use here also AddEnvironmentsVariables

WebAPI
     ASP.NET 5 MVC includes also WebAPI.
     WebAPI controllers are derived from the same controllers as the usual MVC Controllers. The difference is WebAPI is returning only data, the MVC controllers are returning a view.

Tools in ASP.NET 5
     KVM - key version manager
     It is allowing you to play with ASP.NET 5 versions, to install, update, etc by command line.
     It installs also the k utility (which is an ASP.NET 5 utility). It is running very well if you are in the path where project.json is located.
     In order to work, you need to add in project.json a new section called "commands" and all commands from there can be executed by k.
     NodeJs and ES6
     NodeJs is installed default with VS2015 
         - it is a simple javascript execution runtime, based on same engine used by Google in Chrome to execute javascript.
         - it can run on server
     Bower 
         - it allows you to install and keep last version of packages that you are using (jquery, etc).
         - its focus is on front end development (comparing with npm's focus what is the nodejs server)
    There are also some build events that can be specified.
     Grunt
         - it allows you to minify, compile, unit testing and so on. Repetitive tasks. 
         - it requires NodeJs
 
     
     
     
     







Friday, November 20, 2015

Observer Pattern

Observer Pattern

    Articolul reprezinta notitele mele cu privire la cursul "Design Patterns Library" din pluralsight, scris de catre by Steve Smith, David Starr, John Sonmez, John Brown, Brian Lagunas, Scott Allen, Robert Horvick, Keith Sparkjoy, Glenn Block, Niraj Bhatt, and Donald Belcham.



    Pattern-ul se recomanda a se aplica in urmatoarele situatii:

    1. Cand un obiect depinde de alt obiect
    2. Cand o schimbare intr-un (sau a unui) obiect necesita schimbarea unui alt obiect
    3. Cand o schimbare a unui obiect trebuie sa notifice alte obiecte fara a stii ca ele sunt acolo (alte clase si instante care monitorizeaza obiectul)

    Ca o prezentare generala a pattern-ului:
     Pe scurt, se foloseste o structura in care subiectul, cel care se schimba, il notifica pe cel care observa cu privire la modificarea facuta. Pentru a notifica, Observer-ul ar trebui sa poata sa se inregistreze si sa se de-inregistreze de la respectivul subiect.
     Deci, Subiectul notifica observer-ul. Acesta, la randul lui va trebui sa fie in stare sa poata sa modifice diverse valori prin subiect (status-uri, etc).
     Astfel daca observer-ul unu face o modificare, atunci observer-ul 2 va primi o notificare.


     Exista mai multe modalitati de implementare a acestui pattern:


     1. Traditional (conform cartii)

     In aceasta abordare:
     Este acela de a crea o clasa subject abstracta care furnizeze metodele necesare pentru inscrierea si de-inscrierea de la notificari, precum si o metoda de notificare. 
     Implementarea abstracta a clasei Observer furnizeaza implementarea goala a unui mecanism de actualizare (Update) si nu furnizeaza nici o implementare concreta a acestei metode (cod).
     De asemenea, GoogleObserver, in acest caz, reprezinta implementarea concreta si a clasei AbstractObserver. In aceasta clasa exista implementarea Update (concreta) precum si o refereinta la sursa de date concreta (la subject).
      Care sunt rezultatele acestei abordari:
      CONs:
        - Subiecti multipli pentru fiecare observator - este necesara pasarea subiectului to observer pentru a stii care din ele este cel care a facut update-ul.
        - Se declanseaza update-ul in mod automat cand diferite proprietati sunt implicate - trebuie putina atentie in momentul in care se efectueaza update-ul atunci cand mai multe proprietati sunt implicate in acelasi timp, avand grija sa nu declansezi update-uri duble cand de exemplu doua proprietati sunt modificate in acelasi timp.

        - Subiectii si observer-ii dispozati pot tine referinte unul la altul - in momentul in care se face dispose la un obiect, deoarece exista referinte de la observeri la subiecti si invers, atunci Garbage Collector-ul va fi impiedicat sa realizeze eliminarea acelor obiecte. Deci trebuie putina atentie aici.
        - Maparea subiectilor catre observer-ii lor - presupune un memory overhead.

        - Update-uri neasteptate - poate aparea cand exista mai multi observeri si o singura schimbare poate implica multiple schimbari peste tot. Mai ales cand sunt implicati foarte multi observeri, o singura schimbare din partea unui observer poate determina schimbari pentru restul observer-ilor ceea ce ar putea impacta negativ sistemul.

        - In cadrul acestei implementari, obiectul este privit in ansamblu.  Este dificil de urmarit schimbarea unei singure proprietati doar. Aceasta se rezolva in .net framework prin evenimente si delegati.


     

    2. Events and Delegates implementation

     In aceasta abordare:

     Aceasta metoda este implementata de .NET Framework prin niste facilitati de limbaj: events si delegates.
Acest pattern poate fi implementat fara abstract classes.
     In principiu evenimenul este creat de subiect si permite inregistrarea observer-ilor printr-un mecanism delegate callback. Observer-ii furnizeaza implementarea metodei delegate, care va fi chemata de subiect cand evenimentul este declansat.
     Imbunatatirea in aceasta abordare este faptul ca se pot avea si evenimente custom, in cazul de mai sus: StockChangeEventArgs (care ia un stock si niste alte date).

     

    3. IObserver <T>  - implementation

     A fost adaugata mai tarziu in .net si suporta cateva feature-uri precum Task Parallel Library. Implementarea arata astfel:

     Are o implementare similara cu varianta traditionala, dar in loc sa aiba o clasa abstracta, are un IObservable<T> si un IObserver<T>.
     In implementarea normala, a clasei concrete, avem o functie Subscribe (care adauga un observer la subject) si o metoda Notify care notifica observerii.
     Insa, la implementarea IObserver, exista trei metode in loc de una:
        - OnNext - ia urmatoarea valoare de la subiect
        - OnError - care este chemata cand este o eroare in procesare
        - OnCompleted - cand nu mai sunt alte schimbari pe subiect.

    IObservable pattern pare ar fi partea cealalta a lui IEnumerable.
    Cand se creeaza clasele de IObserver, nu mai este necesar sa trimiti in constructor subscriber-ul. Aceasta poti sa o faci mult mai tarziu, cand subscrii. Atunci este necesar sa trimiti, ca sa stii unde subscrii.
    

     Aceasta abordare poate sa intoarca si erori, nu numai date.