ordercloud-api / ordercloud-dotnet-catalyst

A foundational library for OrderCloud integrations and server-side projects in .NET
Apache License 2.0
9 stars 15 forks source link

Simple framework for XP definitions #113

Closed oliverheywood451 closed 1 year ago

oliverheywood451 commented 1 year ago

Intro

This is a potential opinion on how strongly-typed XP should be defined in a C# project. It would include adding code to the catalyst library and creating a guide for solutions. The goals are

The framework

Currently, strongly-typed xp requires code like below for every resource.

// Boilerplate
public class OrderCalculateResponseWithXp : OrderCalculateResponse<OrderCalculateResponseXp, LineItemOverrideWithXp> { }
public class LineItemOverrideWithXp : LineItemOverride<AdHocProductWithXp> { }
public class AdHocProductWithXp : AdHocProduct<AdHocProductXp> { }

// boilerplate if empty, but still required
public class  OrderCalculateResponseXp { }

// Not Boilerplate
public class AdHocProductXp
{
     // put xp here
}
  1. The first suggestion is to put all the boilerplate code above into a library like Catalyst so that the meaningful code - definitions of XP - are clear and unobstructed. Classes like AdHocProductXp would be defined in the library as empty partials, with the solution also defining them as partials and including the xp details.

  2. The second suggestion is to define a convention of putting all the partial <Resource>Xp classes in a single file called Xp.cs. Putting them all in one file makes it easy to be confident there are no other xp definitions hiding in other parts of the project. It also means that source control will produce merge conflicts if two people edit xp simultaneously. This is actually a benefit because it means changes in xp are considered in the context of all existing xp. This reduces the likelihood of conflicting or duplicated definitions. It would look something like this

https://github.com/ordercloud-api/dotnet-middleware/blob/dev/Customer.OrderCloud.Common/Models/Xp.cs

New library code

ModelWithXp.cs

public class OrderCalculateResponseWithXp : OrderCalculateResponse<OrderCalculateResponseXp, LineItemOverrideWithXp> { }
public class LineItemOverrideWithXp : LineItemOverride<AdHocProductWithXp> { }
public class AdHocProductWithXp : AdHocProduct<AdHocProductXp> { }
...

Xp.cs

public partial class OrderCalculateResponseXp { }
public partial class AdHocProductXp { }
...

New client project code

Xp.cs

public partial class AdHocProductXp 
{
    public string MyProperty { get; set; }
}
...

MyServerSideCommand.cs

// same as before, but dev needs to understand the connection between AdHocProductXp and AdHocProductWithXp.
AdHocProductWithXp product = await _oc.AdHocProduct.GetAsync<AdHocProductWithXp>(myID);

Gotchas

oliverheywood451 commented 1 year ago

This was resolved here -> https://github.com/ordercloud-api/dotnet-middleware/blob/dev/Customer.OrderCloud.Common/Models/Xp/XpBoilerplate.cs

Decided to not make it part of the library