Organizing and naming different closely related Dtos
My current setup is as follows (I name my Dtos as 'Models'):
The order can be of different types (such as draft or receipt, and there's more but I'm keeping it simple).
But we also need a way to fetch multiple types at once (hence why a basic Order exists).
There is reason that there's a difference between all of them (some relationship constraints when orders are being transformed).
My main problem is the mess that is happening between the models.
The DraftOrderModel should expose a
List<ReceiptOrderModel>
. However when you receive the draft order, you don't want the -full- details of the receipt order (since they contain all the order items etc which is not needed).
You want a slimmer model of the receipt order that contains basic stuff such as its id, it's title and maybe its price...
But I'm not sure how to make this..? Should I make a new DraftOrderReceiptOrderShortModel
? That sounds obnoxious....
Should I make a nested class ReceiptOrderShortModel
inside DraftOrderModel
?
Should I make a general OrderShortModel
and reuse it whenever I want ?
I'm not sure how to continue without making it more of a mess:)22 Replies
Use interfaces instead of base classes for this
Hm, can you give me an example?
or you could just have List<ReceiptOrderId> in the DraftOrderModel and if you need the specific order you go and fetch it?
We currently have this and it works actually really good. We have a Transaction that can have subsequent transactions and instead of having the full Transaction object in a list we just have list of IDs... The Transaction model is like "oh, you want my children? sure, here you go"... "what? you want its details? I dunno, go fetch yourself, I don't really care bro"
We typically need some stuff for display, so it would always end up in 2 calls
That's why I want a short variant of it inside the model
is it going to be a system with a lot of users and a lot of records in the DB? (like 500 000 users and over 1M records)
Nope, it's a LAN system with no more than 1-2 computers online
so is it even worth it to you to care for the 100-200ms for second call?
I'll probably do make a general OrderShortModel and reuse it
Hm...
I think it's easier to have everything at one go instead of back-n-forth calling
if I would have to care about that I would probably use the interfaces
IMO the solution with the model just knowing the appropriate IDs is used more in practice (I could be wrong tho)
it depends on REST APIs I've seen in the world..
a) 90% of the cases you need it ? I'll embed it
b) 90% of the cases you don't need it ? Here's the id if you need it
It's the same concept as order items... Most of the times you need them, so when you fetch an order they come by default you don't go to a separate endpoint
yeah, but you can implement multiple interfaces
you cannot inherit multiple base classes
Yeah I'll probably do an
IOrder
interface however my only painpoint is
having a List<IOrder> GetOrders
which should return a list of all of them, no matter the type
but it's not a big dealso you want a specific order? or list of orders with only some items?
Both will be needed
There's a place where all orders can be shown (with filters etc)
and theres a place where you only receive draft orders
and a separate place for only receipt orders
I basically have every usecase, that's why it makes it annoying
are you building an API and a UI? Both are internal for your company/personal only?
It's a desktop app that will likely need to expose an API at some point in the near future
The API will be ""public"" for other apps inside the same PC to be used
We have a library that contains all this stuff that is shared between API and Desktop
Desktop just does the native call, API exposes the call through a controller
i see
So all the "services" are the core part of the app... The UI is just glue code to visuals
and the controllers are also glue code...
It's as separated as it should be
or "abstracted" in better terms
maybe you could build the API exactly for the needs of your UI?
Eh no approach is wrong. Although I wanted to be closer to APIs since it's a good way of thinking
And minimizing RAM usage (since you don't load everything at once)
at work we have an API for a service, the service is public but we're the only one using the API and we're distributing the client apps... and let me tell you, the API is done exactly as REST API should be... but oh boy, it has so many endpoints and it's so fucking complex to do the simplest things... I wish the API was tailored to the applications... To get an account that owns a device, I have to get account id from the device detail, to get the device detail i have to fetch it via device id and then fetch the owning account... Why? because that's how the rest api should be... We have 3 applications, no client ever can call the API itself (we won'T give them the crypto protocol documentation so they couldn't authorize :D) but no, there cannot be an endpoint that would give the app exactly what the app needs, that would go against the api design
what I want to say is, consider building the API for the needs of the UI, it can save you a lot of work and it could actually also save you some troubleshooting
Oh yeah that sounds like a bit of a microservice hell
Maybe you could have the
expand
pattern like stripe implements
basically dynamic include
/orders?expand=items
and you can ask which relationships to load
I'm not sure how this can be implemented in C# but I bet it can be done