how to properly modelize an object with localized (i18n) properties - oop

I have an Entity which has an id and a title. The id is always the same but the title value change given a locale. I found three way to modelize this :
class Entity
String getId()
String getTitle(Locale)
or
class Entity
String getId()
LocalizedEntity getLocalizedEntity(Locale)
class LocalizedEntity
String getTitle()
or
class Entity
String getId()
class LocalizedEntity extends Entity
Locale getLocale()
String getTitle()
I tend to prefer the first one because it does not corrupt the way you modelize the Entity, it is just a kind of view of your object. The second is the worst case for me.
Which one is better ? Is there another way ?

To my mind, that your data are localised should not impact on your object design, so I would go with your first option.
We built a localisation engine in my day job, a few years ago, and that is the model we used, where the Locale object was specified with three properties (ISO 639-1 α-2 language code, ISO 15924 α-4 script code and ISO 3166 α-2 territory code, together making up an IETF language tag, like en-Latn-GB, zh-Hans-CN, sr-Cyrl-RS and so on).
I hope that helps, though I'm guessing you probably made your decision last year, given the date of your question.

Related

How to structure object: OOP, composition

I have an object, let's call it a Request, that has associations to several other objects like:
Employee submitter;
Employee subjectsManager;
Employee pointOfContact;
And several value properties like strings, dates, and enums.
Now, I also need to keep track of another object, the subject, but this can be one of 3 different types of people. For simplicity let's just talk about 2 types: Employee and Consultant. Their data comes from different repositories and they have different sets of fields, some overlapping. So say an employee has a
String employeeName;
String employeeId;
String socialSecurityNumber;
Whereas a consultant has
String consultantName;
String socialSecurityNumber;
String phoneNumber;
One terrible idea is that the Request has both a Consultant and an Employee, and setSubject(Consultant) assigns one, setSubject(Employee) assigns the other. This sounds awful. One of my primary goals is to avoid "if the subject is this type then do this..." logic.
My thought is that perhaps an EmployeeRequest and a ConsultantRequest should extend Request, but I'm not sure how, say, setSubject would work. I would want it to be an abstract method in the base class but I don't know what the signature would be since I don't know what type the parameter would be.
So then it makes sense to go at it from an interface perspective. One important interface is that these Request objects will be passed to a single webservice that I don't own. I will have to map the object's fields in a somewhat complex manner that partially makes sense. For fields like name and SSN the mapping is straightforward, but many of the fields that don't line up across all types of people are dumped into a concatenated string AdditionalInfo field (wump wump). So they'll all have a getAdditionalInfo method, a getName, etc, and if there's any fields that don't line up they can do something special with that one.
So that makes me feel like the Request itself should not necessarily be subclassed but could contain a reference to an ISubjectable (or whatever) that implements the interface needed to get the values to send across the webservice. This sounds pretty decent and prevents a lot of "if the subject is an employee then do this..."
However, I would still at times need to access the additional fields that only a certain type of subject has, for example on a display or edit page, so that brings me right back to "if subject is instance of an employee then go to the edit employee page..." This may be unavoidable though and if so I'm ok with that.
Just for completeness I'll mention the "union of all possible fields" approach -- don't think I'd care to do that one either.
Is the interface approach the most sensible or am I going about it wrong? Thanks.
A generic solution comes to mind; that is, if the language you're using supports it:
class Request<T extends Subject> {
private T subject;
public void setSubject(T subject) {
this.subject = subject;
}
public T getSubject() {
return subject;
}
}
class EmployeeRequest extends Request<Employee> {
// ...
}
class ConsultantRequest extends Request<Consultant> {
// ...
}
You could similarly make the setSubject method abstract as you've described in your post, and then have separate implementations of it in your subclasses. Or you may not even need to subclass the Request class:
Request<Employee> employeeRequest = new Request<>();
employeeRequest.setSubject(/* ... */);
// ...
int employeeId = employeeRequest.getSubject().getEmployeeId();

Why should I overload a procedure? Why not add a procedurename?

I've been overloading procedures for some time now, but recently asked myself what the actual advantage is in comparison to just adding a procedure with a slightly different name.
So basically, why should I use
Public Void DoSomething(Int FirstParam, String SecondParam)
Public Void DoSomething(String FirstParam, String SecondParam)
in stead of
Public Void DoSomething(Int FirstParam, String SecondParam)
Public Void DoSomething_V2(String FirstParam, String SecondParam)
If anything, a different procedure name actually might make it less confusing to see which procedure is called.
Will you remember, when you're writing code a few months from now, that DoSomething_V2 was the one that took two String parameters? V2 is a spectacularly bad name.
Now if you're asking why not name them sensibly, then you get from new File(...) to File.getInstanceFromParentFileAndChildString(File parent, String child), File.getInstanceFromPathString(String path), File.getInstanceFromParentAndChildStrings(String parent, String child) and File.getInstanceFromURI(URI uri).
This is the way Objective C went, and one of the biggest complaints from newcomers to the language is its amazing verbosity.
That is because you don't have to keep inventing the names. To make the function more easy for others to recognise that it takes two strings, you will have to name the same function like DoSomething_TwoStrings.
If there is another function that takes one string and one int, you will have to name it like DoSomething_String_Int.
What if the order of the elements is to be changed and created into another function? If you choose to name your procedures as V2 and V1 etc., this will create another layer for users to remember. What does V2 take as input, and what about V1. This all creates hundreds of more names than a user really has to remember if you don't use overloading.
Your program will also be clear due to having less vocabulary and smaller function names. Once you know that IDE will clearly give you intellisense as to all the overloads and you can choose what you want, it is a piece of cake to use overload and is lot less cluttery.

when one-to-one relation should I store everything in object or in dedicated storage?

Assume we have class Car which MAIN field is called VIN (Vehicle Identification Number). VIN gives us a lot of information such us:
owner
place of registration
country of production
year of production
color
engine type
etc. etc
I can continue and add more information:
last known GPS coordinates
fine list
is theft (boolean)
etc. etc.
It seems reasonable to store some of information (for example year of production and engine type) right inside Car object. However storing all this information right inside Car object will make it too complicated, "overloaded" and hard to manage. Moreover while application evolves I can add more and more information.
So where is the border? What should be stored inside Car object and what should be stored outside in something like Dictionary<Car, GPSCoordinates>
I think that probably I should store "static" data inside Car object so making it immutable. And store "dynamic" data in special storages.
I would use a class called CarModel for the base attributes shared by every possible car in your application (engine size, color, registration #, etc). You can then extend this class with any number of more specific subclasses like Car, RentalCar, or whatever fits your business logic.
This way you have one clear definition of what all cars share and additional definitions for the different states cars can be in (RentalCar with its unique parameters, for example).
Update:
I guess what you're looking for is something like this (although I would recommend against it):
public class Car
{
// mandatory
protected int engineSize;
protected int color;
// optional
protected Map<String, Object> attributes = new HashMap<String, Object>();
public void set(String name, Object value)
{
attributes.put(name, value);
}
public Object get(String name)
{
return attributes.get(name);
}
}
Why this is not a good solution:
Good luck trying to persist this class to a database or design anything that relies on a well known set of attributes for it.
Nightmare to debug potential problems.
Not a very good use of OOP with regard to type definitions. This can be abused to turn the Car class into something it is not.
Just because your Car class provide a property GPSCoordinates does not mean you need to hold those coordinates internally. Essentially, that's what encapsulation is all about.
And yes, you can then add properties such as "IsInGarageNow", "WasEverDrivedByMadonna" or "RecommendedOil".

Struts 1 ActionForms - What's the convention for dates in the form?

I am about to start with e project that uses Struts 1.2. There is no plan to move to another framework.
I wanted to know what's the convention when handling a date in the form?
Should I create a Date variable and create a setDate(String date) method where the conversion will occur?
Create a Date variable, a setDate(Date date) and register a special converter somewhere in the chain? (don't know if it's possible)
Create a String variable, a setDate(String date) and let the conversion/validation to the validate method in the ActionForm bean?
Or another approach?
Also, if you have any advice to get up to speed with this framework, I would really appreciate it.
Before I respond to your question, let me start by saying this: People don't understand what ActionForm is or what ActionForm does
The ActionForm represents the data that the user filled in the HTML form. Struts reads in the request parameters and matches them by name with the configured ActionForm for the target Action of the submit. It is data inputted by the user, plain and simple.
Data that comes on the request is always of type java.lang.String. But people might have a form field named "age" which is an int in their Model data. Or maybe instead of "age" they have a "birthDate" which off course is java.util.Date in their Model data. So they think it is a good idea to have the type int and Date placed on the ActionForm and allow Struts to convert the Strings that arrive on request into ints and Dates.
Its a very useful conversion and you as a developer don't have to handle it, Struts does. It's a little bit of framework magic.
But this ain't freaking Harry Potter! Conversion can fail on ints and Dates. Why?
int is a primitive type and as such it must always have a value. Default initialization is with zero. When doing the binding (request parameters to ActionForm object properties) Struts sees an int type on the ActionForm and tries to convert the request String value to int.
If user inserted String "5", the field is set to 5. That's fine!
But what if user inserted "bla"? Will we get an exception thrown in our face? Nope! We get back a value of zero because conversion (silently) failed. Ups!
Dates again are an issue. Why? Because their value arrives on request as String. Their format might be something simple like "12/01/2011" which is completely useless as information. Why? Because Dates represented as Strings must go hand in hand with a Locale in order to be transformed to the correct Date instance it represents.
"12/01/2011" + Locale.US = 01 December 2011
"12/01/2011" + Locale.FRENCH = 12 January 2011
Ups!
Ok, so this was the intro! Now let's go to your question.
Should I create a Date variable and create a setDate(String date) method where the conversion will occur.
At some point you will have to send the Date back to the view and the Struts html tags will normally have to go for a getDate() which returns String. The "12/01/2011" you get on user input might be displayed as "Jan. 12, 2011 00:00:00" if the getter returns Date (Struts will do a toString() on the getter value). So you actually need the Date field with both a setter/getter of type Date and a setter/getter of type String. Use type Date in your Action class and use String for interfacing with the view tags.
Question? How do you get handle on the proper Locale value in your ActionForm?
Create a Date variable, a setDate(Date date) and register a special converter somewhere in the chain (don't know if it's possible)
It is possible. You can create and register a custom converter that might take String representations of dates and convert them to Date. If you use the ISO 8601 format I think you will be safe.
Question? Can you accommodate this into the existing application without breaking code that transforms String to dates in their own way by using all sorts of formats or Locales?
Create a String variable, a setDate(String date) and let the conversion/validation to the validate method in the actionForm bean
This won't work. The validate method is called after the parameter bindings on the ActionForm object. When you reach this point is already to late. Struts did the conversion. If you have a field of type int with value zero there is no way to know if the user actually inserted zero and conversion worked or if the user inserted "bla" and the conversion failed and you got back zero as default initialization value. If zero is a valid value for your application than you are in even bigger trouble.
So what's the convention?
There is no convention. Use the above information and apply common sense given your situation.
Ideally you should have all properties in the ActionForm as Strings so that you loose no information during the binding. But this involves manually converting the properties to the proper type in the Action class, before using them. You have full control (Struts no longer does conversions since source and destination values are of type String) but you also have a lot of boiler plate code to write to do it the proper way which at some point can become annoying.
P.S. Before I end this and go to bed (it's 01:00 AM in my Country :D) I just want to mention one thing that people often don't see. The ActionForm is not part of the model, neither should it interact directly with the model.
If you need the data from the ActionForm to be processed in the model, then map it as a one-to-one relationships with a Model DTO (data transfer object). If you don't, then you create a tight coupling between the Model and the Struts framework because your ActionForm objects are not a POJOs. Your class must extend the ActionForm class from Struts that we've been talking about. People don't do this and send the ActionForm straight to the Model. What is even worse is that they also use the validate method to perform business validations instead of basic validation such as "is required", "is value withing range" etc.
ActionForms are just a communication path between the Action (controller) and the view. Treat it as such.

What is a "field"? "Field" vs "Field Value"

In a passport there is a field: First Name, and that field has a value John.
I assert that it is correct to describe the relationship as follows:
Field First Name:
Has a name (First Name).
Has a set of valid values (e.g. defined by regex [A-Za-z. ]{1,30}
Has a description (name that stands first in the person's full name)
And Passport is a set of pairs (field : field value), such that:
passport has a field "First Name"
passport has a value for field "First Name"
Point here is that it is incorrect to say:
"First Name value is John";
The correct way (conceptually/academically) is to say:
"passport has a value 'John' for field 'First Name'".
In practical terms it means (pseudo C#):
struct Passport {
Map<Field, object> fieldValues;
}
struct Field {
string Name;
string Description;
bool IsValidValue(object value);
}
Q: Does this make sense? Any thoughts?
This is pretty subjective and entirely context sensitive, and seems like a silly thing to nitpick over.
Correct or not, if I'm discussing "passport" with a co-worker, I'd throw something at them if they corrected me every time I said "firstName is 'john'", and told me to say it as "passport's firstname field is 'john'". You'd just come across as annoying.
Well..not really in c# see Scott Bellware's answer to my question about C# not being Object Oriented (kinda).
In C# passport is a class so it makes perfect sense to say
"The Passport has a field FirstName"
For a particular instance "FirstName value is John".
Here the first clause describes the class and the next one the object. In a more OO language like ruby I think saying "passport has a value 'John' for field 'First Name'" would be equivalent, you're just describing two objects - the Passport prototype, and the instance of it in the same sentence.
I'm getting pretty confused in it myself though. The question is oddly phrased since there would doubtless be much more to a passport than just its fields, for example a long-standing and persisted identity.
If you are going to model such thing, then you may take a look at reflection API of java or c#. It is pretty similar to what you described. Class has set of fields, field has name, type and other attributes, not value. Object is an instance of class and you can ask object for the value of specified field. Different objects of the same class have values for the same fields, so you may say they share fields. So if you are trying to model class-based OOP then you are probably right.
However this is not the only way to do OOP. There is prototype-based OOP which looks differently, as there are no classes, only objects, so objects contain field with values so there is not much difference if you say that object contain field and field has a value.
So the answer to "Does this make sense?" I think is "yes" because similar thing is in reflection and is used widely. If it is right or wrong - depends on your needs.
UPD: regarding "value = Passport[Field]" vs "value = Passport.Field.Value"
I'd introduce one more passport to make it clear
firstNameField = PassportClass.Fields["FirstName"]
myName = myPassport[firstNameField]
yourName = yourPassport[firstNameField]
assumes that both passport have same fields, that makes sense. Having different passports with different fields may have a sense, just a different one.
No. At least in OOP, it's the field's responsibility to retain the value. Although the object is responsible for ensuring that value is consistent with the other fields or the object's constraints, the actual "containing of the value is the field's job.
Using your example:
Field First Name:
Has a name (First Name).
Has a type (int, string, object)
Has a description (optional)
Has a value
And Passport is a set fields:
May define constraints on such a field as defined by the model, ensuring the value and the object's state as a whole is valid