Deel 2 - HeinPauwelyn/IoTShop GitHub Wiki

Uitwerking

Stap 1: GenericRepository<T>

Voeg de GenericRepository<T> toe zoals gezien in de theorie. Welke repositories kunnen we vervangen door de GenercirRepository<T>? Verwijder de repositories voor ProgrammingFramework en DeviceOperating system. Wijzig de code zodat het project terug compileert.

Stap 2: DeviceRepository wijzigen

DeviceRepository moet nu erven van GenericRepository<T>, vergeet niet de IGenericRepository interface te implementeren. We gaan ook een interface genereren voor DeviceRepository. U kan dit doen via rechtermuis klik → "Refactor" → "Extract Interface". We doen dit om de componenten "loosely coupled" te maken zodat ze niet afhankelijk zijn van elkaar.

image

Pas ook de interface IDeviceRepository als volgt aan:

public class DeviceRepository : GenericRepository<Device>, IDeviceRepository 
{
    // uw code
}

Zorg ervoor dat de code terug compileert en test uit.

public interface IDeviceRepository : IGenericRepository<Device>
{
    // uw code
}

Stap 3: Service Layer

Nu gaan we de service layer toevoegen. Deze laag bevat business regels en zal het centrale aanspreekpunt zijn vanuit onze controller. Voeg een map "Services" toe aan je project. In deze map maken we de ProductService klasse aan.

image

Vanuit de ProductService is het de bedoeling de verschillende repositories aan te spreken. We gaan deze injecteren via de constructor. Dit ziet er als volgt uit:

private IGenericRepository<DeviceOperatingSystem> repoOS = null;
private IGenericRepository<ProgrammingFramework> repoFramework = null;
private DeviceRepository repoDevice = null;

public ProductService(IGenericRepository<DeviceOperatingSystem> repoOS, IGenericRepository<ProgrammingFramework> repoFramework, DeviceRepository repoDevice)
{
    this.repoOS = repoOS;
    this.repoFramework = repoFramework;
    this.repoDevice = repoDevice;
}

Pas nu eerst de controller aan zodat deze GEEN repositories meer aanmaakt en gebruikt. We mogen ze enkel nog doorgeven aan de service. In de controller ziet dit er als volgt uit:

private ProductService ps;

public CataloogController()
{
    IGenericRepository<DeviceOperatingSystem> repoOS = new GenericRepository<DeviceOperatingSystem>();
    IGenericRepository<ProgrammingFramework> repoFramework = new GenericRepository<ProgrammingFramework>();
    IDeviceRepository repoDevice = new DeviceRepository();
    
    ps = new ProductService(repoOS, repoFramework, repoDevice);
}

Wijzig nu de controller zodat deze overal gebruik maakt van de service en niet meer van de repositories individueel. U zal ook de nodige methodes moeten toevoegen aan de service layer. Wijzig de code en zorg dat alles compileert en terug werkt. Als laatste stap genereren we een interface uit de service laag “ProductService”. Vergeet deze interface niet publiek te plaatsen.

image

Stap 4: Ioc container Unity

Als we kijken naar de constructor code van onze controller dan zien we daar heel wat code staat voor het aanmaken van de repositories. Hoe meer repositories en extra functionaliteit de service laag nodig heeft, hoe complexer deze code zal worden. Een oplossing hiervoor is het gebruik van een IoC container (Inversion of control).

Deze container zorgt voor de aanmaak van objecten indien nodig en niet wij. We draaien de verantwoordelijkheid om naar de software zelf om de nodig objecten aan te maken (Inversion of control). Lees: Het is deze container die er voor zal zorgen zorg dat alle defaultcontructors, copyconstructors of baseconstructors aangemaakt worden voor zowel de Dbcontext, de repositories en de services. Er zijn verschillende IoC containers op de markt.

Wij kiezen voor Unity. We voegen Unity toe via Nuget door te zoeken op Unity.Mvc5.

image

Na de installatie van de container moeten we Unity registreren in Global.asax.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace IoTShop.Server.WebApp
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            UnityConfig.RegisterComponents();        // <-- deze lijn toevoegen
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}

Unity zal voor ons de nodig objecten aanmaken als ze nodig zijn. We moeten dus alle objecten registeren in de Unity container: de UnityConfig.cs file in de App_Start map.

image

public static class UnityConfig
{
    public static void RegisterComponents() 
    {
        var container = new UnityContainer();

        container.RegisterType<IGenericRepository<ProgrammingFramework>, GenericRepository<ProgrammingFramework>>();
        container.RegisterType<IGenericRepository<DeviceOperatingSystem>,GenericRepository<DeviceOperatingSystem>>();
        container.RegisterType<IDeviceRepository, DeviceRepository>();
        container.RegisterType<IProductService, ProductService>();

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }
}

Stap 5: Controller(s) met service depedency

De laatste stap is het aanpassen van de controller waarin we de ProductService gebruiken. Hier kunnen we de constructor opruimen zoals hieronder.

private IProductService ps;

public CataloogController(IProductService ps)
{
    this.ps = ps;
}

Vanaf nu zou Unity verantwoordelijk moeten zijn voor de aanmaak van de objecten. Uiteindelijk beschik je nu over een applicatie die opgebouwd is uit verschillende ontkoppelde onderdelen (classes), die strict opgebouwd worden volgens een opgelegde interface. De volledige structuur zou er als volgt kunnen uitzien:

  | Controller  | Service | Repository

----- | ------- | -------| ---------- Klasse | CatalogController | ProductService | DeviceRepository Interface of inheritance | Controller | IProductService | GenericRepository<Device> en IDeviceRepository copy en base constructors | Via IoC container met Unity.MVC5 | Via IoC container met Unity.MVC5 | Via IoC container met Unity.MVC5 Met dependancy | IProductService | IGenericRepository<DeviceOperatingSystem>, IGenericRepository<ProgrammingFramework> en IDeviceRepository | Methodes | User methods (Index() en Info(int deviceId)) en admin methodes (New() en UploadPictures() | GetDevices(), GetDevice(int deviceId), GetDeviceOperatingSystems(int deviceId), GetDeviceFrameWorks(int deviceId), AddDevice(Device device), UpdatePicture(Device device), GetProgrammingFrameworks() en GetDeviceOperatingSystems() | AddDevice(Device device) en UpdatePicture(Device device)

Wanneer je nog niet alle gewenste methodes uitwerkte, dan zou je nu eerst een testmethode kunnen schrijven voor deze ontbrekende methodes (= testdriven development).

Stap 6: Uitbreidingen

  • Zorg ervoor dat gewone bezoekers een bestelling kunnen plaatsen
    • Orders moeten worden opgeslagen
    • Klanten moeten niet registeren maar kunnen gewoon een basket vullen en op het einde uitchecken en de verzendgegevens opgeven
    • Klant moet een e-mail ontvangen met zijn bestelling
      • Opgepast: zorg ervoor dat we vlot van e-mailsysteem kunnen switchen
    • Betaling van het order is fictief maar voorzie volgende keuzes:
      • VISA
      • Paypal
      • Overschrijving
    • Verzending
      • Afhaling (gratis)
      • DPD (3 euro)
      • DHL (5 euro)
  • Zorg ervoor dat administrators een overzicht van de bestellingen kunnen zien
⚠️ **GitHub.com Fallback** ⚠️