I’m building an ordering system. And here I have an Order class, which has a property named OrderNumber. As you know, OrderNumber can only be assigned once, so I don’t want to make it public (so I made it private).
However, the order number is generated according to a sequencial value stored in database.
For example, the value in database is 10, now I genearte an order number, the order number will be “Year-Month-10“, and the value will increase to 11. The value will be reset every month.
You see, the order number generation has a dependency to database. If I make OrderNumber private, I can only call the generate order number method in the Order class (maybe in the constructor), that’s not good and hard to do unit testing. And, I don’t want to use any ServiceLocator in the Order class, I think it’s bad too.
If I make the order number public, the problems above can be resolved. But the order number might be changed by some coders’ mistake now, it’s not safe.
So, can I make the OrderNumber property public? And your reasons?
Updates:
Thanks to Yahia for giving me a hint.
Now I consider making OrderNumber property readonly, and pass the generator (e.g. IOrderNumberGenerator) to the constructor of the Order class.
But there’s another problem:
In my senario, the order number is not assigned when the Order object is created. The customer can create and save an order without passing the order to the order verifier.
So before the order is passed to the order verifier, the order number is not assigned. OrderNumber is assigned only when the customer click the “Request Order Verification” button, and then the OrderNumber cannot be changed again. And the workflow moves to the next step (Order Verification).
I’ve created a new question, please look here: Design Decision: Generate OrderNumber which depends on a database value
BTW: I’m using C#
Thanks!
I would recommend having a public readonly property
OrderNumber(i.e. makesetprivate) based on a private field… this gives you the benefits of both without any negative aspects.Something you should consider:
Cases like the ones you describe are usually solved by implementing the Factory pattern…
EDIT – regarding the update of the OP:
Make a class
OrderNumberand put it as a public property into yourOrderclass.The
OrderNumber classhas only private constructor and is only created via Factory pattern.Thus your
Orderhas initiallynullassigned to theOrderNumberproperty… this property has aprivate setmethod which only allows assignment when the internal field isnull… to assign anOrderNumberyou have for example aStatusproperty which when changed toOrder Verificationcalls the saved reference toIOrderNumberGenerator(from the constructor) and set theOrderNumberonce…