Mvc – When to create an in-memory object to manage repository records

design-patternsmvcobject-oriented-designrepositorysingle-responsibility

Suppose I have a conceptual Ledger that is populated with Line Items. Assume that Line Items themselves are stored in some type of persistent storage. The ledger is shown to the user who can add/remove Line Items, or update variables inside a particular Line Item, such as price/quantity/description.

To handle this, for example, I could write a single class using Repository layer, call it something like LineItemRepository, and have it have functions like loadLineItems(), addLineItem(), removeLineItem(), changeQuantityX(), etc

To do its operations the class will need to be aware of things like

  • ledger_id to load all the line items pertaining to that id, or to add a line item to the ledger
  • line_item.id to remove/update a Line Item

enter image description here

It looks like with an aid of a Controller class, this will be all I need to trigger business domain events like "Add new Line Item", "Update Line Item Price", "Delete Line Item", etc. I can also do things like "Find Sum of all Line Items with Description 'x' inside Ledger Y".

My Repository can essentially be a Ledger

Question

1) Is it okay to keep the concept of Ledger and Line Item Repository in a single class conceptually with respect to SRP and SOC? If so how do I call this class? ItemRepositoryLedger?

2) When do I need, why might I need, or do I ever need a separate Ledger object (in-memory representation of what is in the database, tasked with business functionality) from the Repository (tasked with actual database retrieval and storage functionality, presumably unaware of business functionality) ?

I think that I could use such in-memory Ledger class for things like

  • Load all line items at once into it and then not touch the database for a while until I really need to
  • Add, edit update delete Line Items in the in-memory Legder as much as I need to before flushing them all into the database. While I do so the database may become out of sync if it is updated by someone else (although in my specific case such cases will be rare…)
  • Perform various many math operations on the Line Items without touching or stressing the database with each new way I want to sum things for example.

But the problems I see is that such Ledger will temporarily contain duplicate information of what is in the database. That strikes me as "BAD". But maybe not. What if I want to load records and then do several various item pricing additions without hitting the database for each new one?

Goal

My goal for this question is to get a clearer understanding of here concepts of Repository, and in-memory structure such as Ledger fit in the MVC universe.

Current understanding is that Repository is only used to store/retrieve data and is not used to, for example, compute total price of LineItems. A Ledger class would do that, after first using Repository to load the Line Items into memory.

But then I could also use Repository to sum the line items for me using SQL. So I am a bit confused here…

Further Thoughts

I can take it a step further and ask .. Do I need an in memory Line Item object to represent the one in the database? I guess I will need some object variable to store the data received from the database, to be able to show it in the View layer. Without it, I have to call repository from my View.

Thus I probably need some structure/object/collection of variables to represent Line Item, until it is ready to be displayed in the View.

Should Ledger object follow the same logic?

Is Ledger essentially a Controller object, a manager of Repository in this case and not a separate domain-only entity?

Best Answer

As your question is definitely more about high level design than about implementation, I would go back to the literal definition of a ledger (one of them, anyway), to get semantic hints :

"Ledger, n.: an account book of final entry, in which business transactions are recorded".

Whether it's about tracking and/or querying monetary unit transactions or about inventories of tangible (or not) items, I understand the essence of a ledger mostly as one of the interfaces / contracts implemented by (or delegated to) actual persistent stores of the domain's transactions (i.e., repositories).

IWO, the ledger(s) is/are interfaces that domain services will consume somewhere between themselves and the repositories (or implemented at either ends).

Theoretically speaking, I suppose a ledger interface could expose a set of pure functions, say, parameterized by start date / end date, transaction, item / account types, and whether one wants to see double-entry-based balances, etc -- but of course one may end up needing to break that purity, if computing such summaries on-demand just isn't feasible because they'd involve crunching data over too large datasets, etc.

'HTH,

Related Topic