Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am working on an application where I want the user to be able to enter notes associated to any input field. For example, a user may type in a value for a field named Price, and add a note next to it to specify that it is negotiable under certain conditions.
The solutions I have considered are:
Creating two attributes for each field (e.g. Price and PriceNote)
Creating a new class (e.g. Field) containing a Value and a Note, then changing all model properties to that Field type.
There are downsides to both of these solutions, though. Creating additional attributes would bloat the code and make modifications awkward, while creating an extra class would require typecasting field values constantly and handling editors/displays manually in the views.
Is there a better, more elegant solution?
Not sure what the backend looks like, but you could create a object that looks like this:
{ProductId: 123,
ProductName:'Widget',
Price:200.00,
minQuantity: 10,
Comments:[
Price: "can be reduced blah blah",
minQuantity: "N/A on orders > 1000"
]
}
This way - you can access price/minQuantity the same way you always would, and Comments are stored in a simple string/string dictionary.
You could also cache those comments in a totally different call ... So you pull them separately from the actual object definition.
Data Storage
Again, depending on your db, you could store comments as json in a text field, or you could store them normalized in a table that has ObjectType,EntityId,FieldName,Comment in it. Up to you, but I'm guessing you don't need them in "every" table -- just occasionally want to add label/comments to fields.
Let me know the middle tier (eg - c#) and maybe we can turn that json into an actual class in your middle tier.
public interface IProduct {
string ProductId {get; set; }
string ProductName {get; set; }
Double Price {get; set; }
int minQuantity {get; set; }
Dictionary<string,string> Comments {get; set; }
}
As a simple example.
Finally, in Angular/Controller
For the front end, you could create a simple property that returns the correct comment:
HTML:
<input ng-model="Price" /><p>{{getComments("Price")}}</p>
Controller:
$scope.getComments = function(fieldNm) {
if($scope.product==undefined
|| $scope.product.Comments.length==0) {
|| $scope.product.Comments.hasOwnProperty(fieldNm)==false) {
return '';
}
return $scope.product.Comments[fieldNm];
}
Or, you could create a directive to accomplish the same thing universally (so you don't have to repeat code in several controllers.
You could try a class structure like this
public class Field
{
private string Value;
private string Comment;
}
public class ViewModel
{
private Field Price { get; set; }
private Field SomeOtherFiled { get; set; }
}
One downside will be to access the value you'll have to do Price.Value or for comment Price.Comment (but it makes sense logically anyway)
The best solution I found is to create a Dictionary<string, string> in the model to store notes, with keys set using nameof(MyAttribute). Notes will have to be retrieved with TryGetValue(), but it is less awkward than constantly typecasting or duplicating fields, and it is easily accessible from views.
Model:
public virtual IDictionary<string, string> Notes { get; set; }
View:
#Html.EditorFor(model => model.Notes[nameof(model.MyAttribute)], new { htmlAttributes = new { #class = "form-control" } })
If I need to manipulate the note:
string myNote;
if (MyModel.Notes.TryGetValue(nameof(MyModel.MyAttribute), out myNote))
{
// Do something with the note
}
else
{
// There is no note for the given attribute
}
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 11 months ago.
Improve this question
What is the best practice respecting the encapsulation?
I am using code first strategy with Entity Framework in .NET 6.
public class Employee
{
[Required]
public string Name { get; private set; }
public void SetName(string value)
{
this.Name = value;
}
}
or
public class Employee
{
private string _name;
[Required]
public string Name {
get { return _name; }
set { _name = value; }
}
}
or
public class Employee
{
[Required]
public string Name {get;set;}
}
Or is there a better way?
Thanks!
It is entirely personal preference and working through the scenarios you expect to encounter and how you want to safeguard or streamline them.
As a general rule I personally advocate for simplicity. A simple domain that is easy to understand is easy for other developers and consumers to pick up or otherwise be instructed. Often these decisions are made to try and restrict developers so-as to silo the domain so that UI developers for example either cannot directly modify data, or try and tightly control access. This may be necessary in very large projects/teams and can work provided your "gate keepers" can keep updates regular and consistent so that everyone can do what needs to be done, but often due to time constraints or responsibilities changing hands (gatekeepers leave and get backfilled by others that don't understand or agree) then bypasses inevitably leak into the model just leading to a confusing and unnecessarily complicated mess.
When it comes to the domain, I generally follow a more DDD-based approach similar to your first example, except I only use methods where I expect that there is a validation or specific combination of state that the entity can enforce itself. The responsibility for mutator methods like this either fall on the entity or the repository. (As I typically use a repository pattern)
For a value that can just change and might have simple validation or none at all, I will just use public setters. For no validation:
public string SomeValue { get; set; }
for basic validation that the entity can validate itself, using either attributes or validation logic inside the setter:
private string _someValue;
public string SomeValue
{
get { return _someValue; }
set
{
if (string.IsNullOrEmpty(value)) throw new ArgumentException("SomeValue is not optional.");
_someValue = value;
}
}
Often, Updates to state involve changing more than one thing where the combination of data should be validated together against the current remainder of the entity state. We don't want to set values one at a time because this means that the entity state could be left in an invalid state, or there is no guarantee that a caller will not simply set one value, ignoring the fact that the other values are technically invalid. As a very rough example of the concept, without getting into validation, it would be updating an address. Sure, it is possible that we may want to make a correction to a single address field, but typically if we are changing one address field we will most likely be invalidating the rest. For example, if I have an address that contains a Street Name, Number, City, PostCode, and Country, changing just the city or just the country would most often make the address completely invalid. In these cases I would use a Setter method to encapsulate updating an address:
public string Country { get; internal set; }
public string City { get; internal set; }
public string PostCode { get; internal set; }
public string StreetName { get; internal set; }
public string StreetNumber { get; set; }
public void UpdateAddress(string country, string city, string postCode, string streetName, string streetNumber)
{ // ...
}
It might be fine to allow them to just change the street number on it's own, or possibly even the street name without calling UpdateAddress so these might have public setters. City and Country might be FK values (CityId/CountryId) so there would be even less need to update these independenty. Simply having this method gate-keep the setting of the value should send a clear message to developers that they should be ensuring the complete and valid address details are sent at once, not relying on them correctly chaining piecemeal updates.
Where I might want to validate changes against existing data state, I would use an Internal setter, and have the update method as part of the Repository. For example if I want to allow them to update a Name, but ensure the name is unique. The repository has access to the domain, so I find it's a good location for this responsibility:
public void UpdateUserName(User user, string newName)
{
if (user == null) throw new ArgumentNullException("user");
if (string.IsNullOrEmpty(newName)) throw new ArgumentNullException("newName");
if (user.Name == newName) return; // Nothing to do.
var nameExists = _context.Users.Any(x => x.Name == newName && x.UserId != user.UserId);
if (nameExists) throw new ArgumentException("The name is not unique.");
user.Name = newName; // Allowed via the internal Setter.
}
It would be expected that if this was talking to a UI that the UI would validate that the name was unique prior to saving, but persistence should validate in case this can be called by other avenues like APIs, where things like unique constraints on the DB serve as the final guard.
Similarly, when it comes to creating entities, I will use factory methods much like the above in the Repository classes to do things like CreateAddress(...) which ensure that address entities are not simply newed up and filled adhoc. This ensures that when an entity is created, all required fields & relationships are provided and filled. The objective of this approach is to help ensure that from the point an entity is created and at every point through its mutation it is in a valid and complete state.
Hopefully that gives you some food for thought on the subject. Ultimately though you should look at what is important for your particular scenario and what real and actual problems you want to address. Don't get too caught up on trying to ward off hypothetical worst-case scenarios and ending up with something so rigid that it negatively impacts your coding responsiveness.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I'm using a web service with this request format:
{
"type":"LogonReq",
"id":"b43b301c-5216-4254-b3fc-cc863d4d6652",
"date":"Wed, 16 Aug 2017 17:35:34 UTC",
"parameters":[
{
"userName":"user",
"password":"password"
}
]
}
Even though every message in the API requires only 1 set of parameters, the API still requires "parameters" to be an array.
Is it better practice to have the caller create the list or to create the list in the MessageBase constructor, or something altogether different ?
Which way would satisfy an OOP purist code reviewer?
public class MessageBase<T>
{
public MessageBase() { this.parameters = new List<T>(); }
public string type { get; set; }
public string id { get; set; }
public string date { get; set; }
public List<T> parameters { get; set; }
}
public class LogonMessage{
public string userName { get; set; }
public string password { get; set; }
}
var logon = new MessageBase<LogonMessage>()
{
date = DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss UTC"),
id = Guid.NewGuid().ToString(),
type = "LogonReq",
};
logon.parameters.Add(new LogonMessage() { userName = "user", password = "password" });
or
public class MessageBase<T>
{
public string type { get; set; }
public string id { get; set; }
public string date { get; set; }
public List<T> parameters { get; set; }
}
public class LogonMessage{
public string userName { get; set; }
public string password { get; set; }
}
var logon = new MessageBase<LogonMessage>()
{
date = DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss UTC"),
id = Guid.NewGuid().ToString(),
type = "LogonReq",
parameters = new List<LogonMessage>() { new LogonMessage() { userName = "user", password = "password" } }
};
You will probably find many interesting opinions and answers to this. I can only give you mine based on my experience.
I myself would probably initialize the list within the constructor
However, since you are trying to get a good idea around the phylosophy of coding, here are some things to consider :
1) Does the MessageBase object make sense or is it useful with a NULL list? Is there any scenario where I want this list as null?
2) Actually, I would expect an OOP purist to say that you should not expose the "parameters" as a List. By exposing the object as a property, someone can do this:
login.parameters.Add()
Or this
logon.parameters = anotherListOfMine
In a way it does break encapsulation. You could make the list property read only (ie, with a protected/private setter) but "clients" of this class will still be able to access all properties and methods of the List and modify/handle them.
Now, you have to expose this in some way as you will be serializing/deserializing into JSON, so that poses a problem! Maybe you can have a private/protected List field and expose the values through a readonly property that exposes an IEnumerable and behind the scenes, you are doing:
get { return myPrivateList.ToArray(); }
3) But again, do you really win that much? Your next question should be "Who is my client?" If you are exposing this class to other developers, or is part of a framework, you might want to apply something like my point number 2, and limit the exposure. If this is internal to your application and your team maybe you should be pragmatic and simply expose the List as you are doing right now.
4) Alternatively, while still making it open, you could instead have a property of type IEnumerable so you can pass in any type.
5) Another option is to expose your list because you need to serialize it, but make it readonly. Have instead different methods, or non-serializable properties, of username and password. If these parameters are always the same that is. I am thinking this might not be your case.
I think I could go on and on this. I will stop here before you hit the downvote button :).
What's the best way to design a class (or classes) that can hold the potential values of item, as well as the one the user actually selected? I've come across this problem before and always feel like I'm missing a core class design feature.
Right now I usually do something like the following
class MultiChoice
Name (I.e. Box Size)
Default Value ("22x15")
PotentialValues ({"10x10","20x20","22x15"})
But that doesn't handle the actual value the user selected, so I add that in.
class MultiChoice
Name (I.e. Box Size)
Default Value ("22x15")
PotentialValues ({"10x10","20x20","22x15"})
SelectedValue
That doesn't feel right though, because when I construct a drop-down I'm filling in stuff with SelectedValue = null. Then when I store the data, I'm storing all the options too, which I don't need.
Is there a better way to handle this with an interface or other language construct? I always feel like I'm missing something blatantly obvious here.
You really have two separate entities here:
MultiChoiceQuestion
MultiChoiceAnswer
Create two separate classes to represent these two separate concepts.
ASP.NET MVC has the SelectList class. While you might not actually be working in ASP.NET MVC, it seems clear that Microsoft felt that the concept of "backing class for a dropdown" was universal enough to warrant its own class.
In whatever you consider the "Model" (that part of your program containing the business domain classes and business logic), there will always exist database tables that serve as lookups for these dropdowns.
tblCountries
CountryID PK
CountryCode string
FullName string
In your ViewModel, there will be a corresponding list of countries from which you can populate the dropdown:
public class InvoiceViewModel
{
...
public int CountryID { get; set; }
public SelectList Countries { get; set; }
// or
public List<Country> Countries { get; set; }
...
}
Of course, by the time you get to the UI, the actual dropdown contains enough plumbing to hold both the select list and the selected value.
You really only need a single Value field. Set it to whatever you want in the constructor (so it's defaulted when the object is created). You can also change your 'potential values' to be static, so it's the same for the entire class.
public class Box
{
public string Value { get; set; }
public static List<string> AllowedValues { get; private set; }
public Box()
{
AllowedValues.AddRange(new string[]{"10x10","20x20","22x15"});
Value = AllowedValues.First();
}
}
Then when a user changes the value, simply update it.
Box thisBox = new Box();
string val = "22x15";
if (Box.AllowedValues.Contains(val))
thisBox.Value = val;
I am using ASP.Net MVC 3 and I need to create a single drop down list which contains items that relate to multiple database tables.
Normally, if I need to do a drop down list for a single data type I can easily use the ID as the "value" for each drop down option and would do something like this:
#Html.DropDownListFor(x => x.SelectedID, Model.GetMyList())
But now I want to mix up multiple data types. So lets say for this example I want to create a single list to represent something like "Owner" and this can be either a "User" or a "Customer". In this example, both User and Customer are separate database tables and therefore the ID value alone is not enough to identify them correctly.
So what are the best ways to achieve such functionality?
Straight off the top of my head, my first thoughts are to create a "custom" value string which could then be parsed server side to work out the ID and data type, something like...
"USER|1"
"CUSTOMER|1"
I know I can make this work, but am I making this more complicated than it needs to be? Is there a built-in or advised way of doing this?
In your Model can you not do something like this:-
public class Model
{
public string Owner { get; set; }
public List<MyList> ListCollection { get; set; }
public class MyList
{
public int Id { get; set; }
public string Value { get; set; }
}
}
So then when you are checking which list item is selected you also have access to the "Owner" field which will tell you what table it belongs to ?
As nobody has come up with anything better, I can confirm that my original idea (as unwanted as it was) did the job.
When setting the value of the select options, a custom string should be created that can easily be parsed server side, this was achieved using a pipe separating the TYPE of entity, and the ID, for example:
"USER|1"
"USER|2"
"CUSTOMER|1"
"CUSTOMER|2"
Once the selected value is passed to the server, it can then be parsed something like the following:
string option = "USER|1";
string[] values = option.Split('|');
string entityType = values[0];
int entityId = Int.Parse(values[1]);
which can then be used something like this:
if(entityType == "USER")
UpdateUser(entityId);
else//CUSTOMER
UpdateCustomer(entityId);
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
EDIT:
For clarity, this question is related to DDD, which has a concept called Value Objects, these are not Value Types, they are a way of building objects in such a way that the contents make up the identity, I was trying to understand how far these concepts should apply (From Comments it seems they should not seep outside domain). This question may look odd for people not familiar with DDD but to be clear it is about a very specific mechanism for creating objects NOT creating value types.
Consider the following sample code, which has two Value Objects:
public class SqlServerConnectionSettings
{
public string DatabaseName { get; set; }
public string ServerName { get; set; }
public SqlServerCredentials Credentials { get; private set; }
public SqlServerConnectionSettings(SqlServerCredentials credentials)
{
Credentials = credentials;
}
public string AsConnectionString()
{
//Snip
}
}
public class SqlServerCredentials
{
public string Username { get; private set; }
public string Password { get; private set; }
public bool UseIntegratedSecurity { get; private set; }
public SqlServerCredentials(string username = "", string password = "", bool useIntegratedSecurity = true)
{
Username = username;
Password = password;
UseIntegratedSecurity = useIntegratedSecurity;
}
public string AsConnectionStringCredentials()
{
//Snip
}
}
Rather than have distinct params for Username, Password, UseIntegratedSecurity I have created a value object to hold them. My question is, Is this taking the concept too far, have I misunderstood the point value objects have been designed for?
Looks good to me. You group items which belong together into cohesive units, what could be wrong about that?
It depends on your context.
If you define SqlServerCredentials as an Entity, yes, you're going too far :
"An entity is an object that is not defined by its attributes, but rather by a thread of continuity and its identity."
If you define SqlServerCredentials as a Value Object, you're right (don't forget that it should be immutable !):
"A value object is an object that contains attributes but has no conceptual identity. They should be treated as immutable."
If you define SqlServerCredentials as an Aggregate, you're right, too :
A n aggregate is a collection of objects that are bound together by a root entity, otherwise known as an aggregate root. The aggregate root guarantees the consistency of changes being made within the aggregate by forbidding external objects from holding references to its members.
In conclusion, in a DDD way, if you're not considering SqlServerCredentials as an entity, it's ok. But it's all about context.