[C#] gebruiker-gedefinieerde conditie-gebaseerde acties

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Skyaero
  • Registratie: Juli 2005
  • Niet online
Ik heb een class met (nested) data properties. Ik neem als voorbeeld even een auto:

C#: Vehicle.cs
1
2
3
4
5
public class Vehicle
{
    public FuelTank FuelTank { get; set; }
    public IList<Tire> Tires { get; set; }
}


Nu wil ik een set van instructies vastleggen, welke kijkt naar de eigenschappen van de auto en onder bepaalde condities acties onderneemt.

Bijvoorbeeld, stel dat de groefdiepte van de banden < 3 mm is. Ik wil dat de band vervangen wordt en de kosten op een rekening worden geplaatst, ruwweg:

C#:
1
2
3
4
5
6
7
8
foreach (var tire in vehicle.Tires)
{
    if (tire.Tread < 3)
    {
         ReplaceTire(tire);
         AddToBill("New tire", "$99");
     }
}


Ik kan dit geheel in een een mooi klasse plaatsen, bijvoorbeeld als reparatiepakket (ik laat even in het midden op welk moment de methoden worden aangeroepen).

C#: VehicleRepairPackage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class VehicleRepairPackage
 {
    private Vehicle _vehicle;
    private Bill _bill;

    public VehicleRepairPackage(Vehicle vehicle, Bill bill)
    {
        _vehicle = vehicle;
        _bill = bill;
    }

    void CheckFuelTank()
    {
        // Check if the fuel tank is more than 50% full
        if (_vehicle.FuelTank.Fuel < 50)
        {
            _vehicle.FuelTank.Fuel = 100;
            bill.AddCost("Refuelled fuel tank", "$35");
        }
    }

    void CheckTires()
    {
        foreach (var tire in vehicle.Tires)
        {
            if (tire.Tread < 3)
            {
                tire = new Tire();
                _bill.AddCost("New tire", "$99");
            }
        }
    }
}


Nu dan mijn vraag. Ik wil dat de eindgebruiker, welke via de browser deze applicatie beheerd, zelf de voorwaarden en acties kan definiëren. Bijv:
  • De gebruiker creëert een nieuw reparatiepakket
  • De gebruiker kiest een (nested) property van het voertuig
  • De gebruiker stelt een of meerdere condities in
  • De gebruiker definieert 1 of meerdere acties.
Hoe zou de generieke VehicleRepairPackage eruit (kunnen) zien, zodat dit mogelijk wordt? Is hier een design pattern of een veelgebruikte oplossing voor? Ik heb gekeken naar reflectie, maar kreeg het idee dat het bos alleen maar meer bomen ging krijgen.

Beste antwoord (via Skyaero op 27-06-2019 09:30)


  • The_Ghost16
  • Registratie: Januari 2004
  • Laatst online: 19-05 10:05
Ik denk dat het allemaal niet zo veranderlijk is als je denkt. Volgens mij kun je het beste gewoon voorgedefinieerde reparatie opties vastleggen. Hierbij kan de gebruiker dan aangeven welke opties hij wilt.

Als hij dus de brandstof check wilt kan hij deze toevoegen. En als hij bijvoorbeeld de groefdikte wilt kan hij die ook toevoegen.

Eventueel kun je per optie een variabele toestaan. Bijvoorbeeld wat de minimale groef dikte moet zijn of hoeveel brandstof er minimaal moet zijn.

Maar de checks die moeten gebeuren liggen redelijk vast, alleen de gestelde voorwaarden niet. En of alle checks moeten gebeuren ook niet. Dus ik heb het idee dat je het te complex probeert op te lossen.

Alle reacties


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • The_Ghost16
  • Registratie: Januari 2004
  • Laatst online: 19-05 10:05
Ik denk dat het allemaal niet zo veranderlijk is als je denkt. Volgens mij kun je het beste gewoon voorgedefinieerde reparatie opties vastleggen. Hierbij kan de gebruiker dan aangeven welke opties hij wilt.

Als hij dus de brandstof check wilt kan hij deze toevoegen. En als hij bijvoorbeeld de groefdikte wilt kan hij die ook toevoegen.

Eventueel kun je per optie een variabele toestaan. Bijvoorbeeld wat de minimale groef dikte moet zijn of hoeveel brandstof er minimaal moet zijn.

Maar de checks die moeten gebeuren liggen redelijk vast, alleen de gestelde voorwaarden niet. En of alle checks moeten gebeuren ook niet. Dus ik heb het idee dat je het te complex probeert op te lossen.

Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
Reparatiepakketten en eigenschappen van een voertuig zijn onlosmakelijk met elkaar verbonden. Je hebt niks aan een bandenwissel zonder de profieldiepte te kennen.

De eigenschappen van een voertuig zou ik dus niet flexibel maken.

Wil je het per se generiek houden, dan zou je een database met voertuigeigenschappen kunnen bijhouden (meta data).

Maar het aantal standaard onderhoudspakketten op een auto is vrij beperkt (APK, zomer / wintercheck, bandenwissel, kleine / grote beurt). Daarna wordt het toch al gauw maatwerk.

Daarom is een werkbon de beste basis, waar je diverse artikelen en arbeid aan toe kunt voegen (en dus ook samengestelde artikelen).

Maar goed, ik bekijk het vooral vanuit de garage en niet per se de "eindgebruiker".

(ik werk voor een automatiseerder die garagesoftware maakt)

[ Voor 60% gewijzigd door Lethalis op 25-06-2019 11:30 ]

Ask yourself if you are happy and then you cease to be.


Acties:
  • +1 Henk 'm!

  • Solaire
  • Registratie: December 2014
  • Laatst online: 30-09 14:04
Als je écht flexibel wilt zijn moet je uitwijken naar een Rule engine, maar ik denk dat het in jouw geval wel mee zal vallen. Beste oplossing IMO: polymorphie.

Dus je maakt een abstracte klasse, noem het even "Repair", die je een functie meegeeft om de actie uit te voeren en de rekening op te maken. Vervolgens stel je een lijst van "Repair" objecten samen en voer je deze sequentueel uit. Dit kun je op basis van gebruikersinvoer doen, of op basis van een "ServicePackage". Gaat erom dat je uiteindelijk een lijst van reparaties krijgt. Gebruikersinvoer in de vorm van profieldiepte kun je eenvoudig verzamelen en meesturen.

Heb geen C# IDE bij de hand, maar pseudocode ziet er ongeveer zo uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    public abstract class Repair
    {
        public void Perform(Service service)
        {
        }
    }

    public class TireRepair : Repair
    {
        public void Perform(Service service)
        {
            if (service.car.TireTread < service.userPrefs.MinTireTread)
            {
                service.bill.Add("New tire", 100);
            }
        }
    }

    public class Bill
    {
        public void Add(string description, decimal price)
        {
        }
    }

    public class Car
    {
        public int TireTread { get; set; }
    }

    public class UserPreferences
    {
        public int MinTireTread { get; set; }
    }

    public class Service
    {
        public List<Repair> Repairs { get; set; }
        public Bill bill;
        public Car car;
        public UserPreferences userPrefs;

        public void Perform()
        {
            foreach (Repair repair in Repairs)
            {
                repair.Perform(this);
            }
        }
    }

Acties:
  • 0 Henk 'm!

  • Stoelpoot
  • Registratie: September 2012
  • Niet online
Als je gebruikers zelf dat soort acties wilt laten definiëren, dan zal je een flink oerwoud aan bos krijgen. Dat is niet te zeggen dat je er zonder kapmes niet door komt, maar wel dat je heel veel bomen zal planten :+

Condities, daar zal je zelf iets voor moeten uitwerken maar dat is prima mogelijk. Hier zijn vziw ook prima Nugets voor. Wat betreft je package, ik begrijp dat dat eigenlijk een "collectie" wordt van verschillende condities en hun resultaten?

Dan zou ik zeggen, elke "actie" is een product. Dus dan krijg je dus 3 entities: Een conditie, een product, en een package. Aan je conditie is dan een product gekoppeld wat wordt toegevoegd aan een rekening als de conditie geldig is op dat object. In je package plaats je een lijst met condities die voor dat package van toepassing zijn. Logica is puur het loopen over de condities en het toevoegen van producten aan je rekening obv die condities.

Acties:
  • +1 Henk 'm!

  • Skyaero
  • Registratie: Juli 2005
  • Niet online
Dank voor alle waardevolle reacties.

De reactie van @The_Ghost16 bracht mij tot nadenken. Vanzelfsprekend gaat het werkelijke probleem niet over reparaties aan een auto, maar over een domeinspecifiek probleem dat een paar slagen complexer is, waarbij de auto honderden onderdelen heeft die mogelijk gecontroleerd moet worden.

Als ik echter naar de processen van mijn klanten kijk, wil het merendeel slechts een beperkt aantal condities en acties uitvoeren. Iets wat dus prima lijkt te kunnen met een implementatie zoals @Solaire voorstelt. Enige flexibiliteit (bijvoorbeeld de gebruiker keuze geven welke (voorgedefinieerd) acties uitgevoerd moeten worden is vervolgens te realiseren met de oplossing van @Stoelpoot.

Iedereen heeft een stukje bijgedragen aan de oplossing. Dank jullie wel! Hier kan ik verder mee.

Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
@Skyaero
Misschien één ding waar je wellicht niet direct aan gedacht hebt:
Als dit enduser-facing is, is het commercieel gezien nog wel eens zo dat men las bedrijf zijnde op bepaalde service-samenstellingen korting wil gaan kunnen zetten. (Absoluut; procentueel; volgens een staffel bepaald door aantal afgenomen; etc.)

Kortings-regels zijn heel rot om te implementeren als je systeem er niet van begin af aan op ingericht is om contextuele condities af te handelen. Dwz. toepasbaarheid van sommige regels kunnen modeleren a.d.h.v. andere reeds toegepaste - of zelfs omgekeerd: verderop nog mogelijk toe te passen... - regels.

(Geloof me; ik doe werk voor de reisindustrie en een aantal van mijn meer back-office gerichte collega's die integratie met systemen van derden afhandelen kreunen voldoende vaak over wat ze dan weer aan prijsconstructies tegenkomen in back-office systemen.)

Even goed opletten en inventariseren wat je klanten daar nodig gaan hebben, dus. :)

[ Voor 29% gewijzigd door R4gnax op 29-06-2019 01:42 ]

Pagina: 1