Java Swing - switch locale dynamically at runtime - java

I understand how to internationalize a java program, but I have a problem.
Language in my program can be switched anytime, but my program can exist in many states, which means that it may or may not have several JLabels, JPanels, JFrames, etc, open. Is there a class or a method which will update the current GUI to the switched language, or does it have to be done manually?
If nothing else works, I'll just require user to restart the program to switch the language, but runtime change would be nice...

The solution generally used is to have a hash of user-facing strings in a central manager class. You make a call into that class whenever you want to populate a field with data:
JLabel label = new JLabel();
label.setText(LocalizationManager.get("MY_LABEL_TEXT"));
Inside the LocalizationManager you will have to fetch the current language of the program, then look up the appropriate string for MY_LABEL_TEXT in the appropriate language. The manager then returns the now 'localized' string, or some default if the language or string isn't available.
Think of the manager as a slightly more complicated Map; it's mapping from a key (ie 'MY_LABEL_TEXT') to what you want to display ("Good day!" or "Bienvenido!") depending on which language you're in. There are a lot of ways to implement this, but you want the manager to be static or a singleton (loaded once) for memory/performance reasons.
For instance: (1)
public class LocalizationManager {
private SupportedLanguage currentLanguage = SupportedLanguage.ENGLISH;//defaults to english
private Map<SupportedLanguage, Map<String, String>> translations;
public LocalizationManager() {
//Initialize the strings.
//This is NOT a good way; don't hardcode it. But it shows how they're set up.
Map<String, String> english = new HashMap<String, String>();
Map<String, String> french = new HashMap<String, String>();
english.set("MY_LABEL_TEXT", "Good day!");
french.set("MY_LABEL_TEXT", "Beinvenido!");//is that actually french?
translations.set(SupportedLanguage.ENGLISH, english);
translations.set(SupportedLanguage.FRENCH, french);
}
public get(String key) {
return this.translations.get(this.currentLanguage).get(key);
}
public setLanguage(SupportedLanguage language) {
this.currentLanguage = language;
}
public enum SupportedLanguage {
ENGLISH, CHINESE, FRENCH, KLINGON, RUSSIAN;
}
}
(1) I haven't tested this, nor is it a singleton, but it's an off the cuff example.

Related

How can my Freemarker ObjectWrapper access a template setting

Use case: system administrator stores a Freemarker template in a database which is used (by Spring Boot REST API) to present information stored by system users (respondents) in a locale-aware way to a different user type (reviewer).
A respondent's response might be stored in this sort of object (or in lists of this sort of object, in the event a question posed to the respondent is expected to have multiple answers):
// snip
import com.fasterxml.jackson.databind.node.ObjectNode;
// more imports snipped
public class LanguageStringMap {
private Map<Language, String> languageStringMap;
public LanguageStringMap(ObjectNode languageMapNode) {
// snip of code instantiating a LanguageStringMap from JSON
}
public void put(Language language, String value) {
if (value.length() == 0)
throw new IllegalArgumentException(String.format(
"value for language '%s' of zero length", language.getCode()));
languageStringMap.put(language, value);
}
public String get(Language language) { return languageStringMap.get(language); }
}
What I think I want to do is write an ObjectWrapper that maps instances of LanguageStringMap to a string (obtained by calling the get() method with a language derived from the Locale requested by the reviewer's browser and set in the template's settings). This presents a cleaner user experience to the system administrator than making the uploaded template contain a bunch of template method calls would.
To do this, my object wrapper needs to access a template setting. I have perused the pertinent Freemarker documentation, but I am still unclear on how to do this or if it is even possible.
I think it would be a mistake to try to implement this with resource bundles uploaded to the database alongside the templates, but that is a consideration.
Typically you simply put the locale specific string into the data-model before the template is processed, along with all the other variables. In that case no ObjectWrapper customization is needed. But if you have to use an ObjectWrapper-based solution, then you can get the locale inside an ObjectWrapper method (like in the override of DefaultObjectWrapper.handleUnknownType) with Environment.getCurrentEnvironment().getLocale().

Design Pattern for dealing with a complex conditional evaluation

I am designed to maintain a system that takes in account the value of three variables to determine which action it will take.
I want to refactor it to use a design pattern, but could not find one suitable for it needs.
To explain the situation, I will use as an example a gym system.
Every gym user has a TYPE_OF_CONTRACT, that could be:
PLATINUM_MEMBERSHIP
GOLD_MEMBERSHIP
SILVER_MEMBERSHIP
The gym has some GYM_CLASSES:
WEIGHT_LIFTING
BODY_BALANCE
STEP
SPINNING
ZUMBA
PERSONAL_TRAINING
Every gym user has a PHYSICAL_CONDITION
NO_RESTRICTIONS
OVER_65
LIMITED_MOBILITY
MEDICAL_CONDITION
BELOW_18
For each combination of these three characteristics, a arbitrary set of actions should be executed. For example:
if PLATINUM_MEMBERSHIP + PERSONAL_TRAINING + OVER_65:
medical approval needed
signed form
if GOLD_MEMBERSHIP + PERSONAL_TRAINING + OVER_65:
medical approval needed
signed form
extra monthly fee
if SILVER_MEMBERSHIP + PERSONAL_TRAINING + OVER_65:
refuse subscription
if (any membership) + STEP + MEDICAL_CONDITION:
medical approval needed
signed form
if PLATINUM_MEMBERSHIP + WEIGHT_LIFTING + LIMITED_MOBILITY:
medical approval needed
signed form
dedicated staff member assist
And so on.
The combination of characteristics can have a set of actions, that are not exclusive and not all of the combinations are ensured.
The legacy code uses nested switches as implementation. Example:
switch (contractType):
case PLATINUM_MEMBERSHIP:
switch (gymClass):
case (PERSONAL_TRAINING):
switch (physicalCondition):
case (OVER_65):
requiresMedicalApproval();
requiresSignedForm();
...
My problem is:
there are 3 conditions that combines to define a set of rules;
these rules are not necessarily unique;
not every combination defines a set;
I refactored a little using extract method technique and cleaning the code a little, but could not get rid of the 3 switches.
I wish to use design patterns to improve the design but so far I was unsuccessful.
I thought about polymorphism and Strategy, but could not figure a way to use any of them.
I also researched in google but haven't found anything that I could use.
What do you suggest?
Thank you.
EDIT:
A solution I reached, while researching #Paul's decision tree approach. After testing with a decision tree, I tried a three dimensional array, to define the conditions of the rules. I also used the Command pattern to define the actions that needed to be performed if the rule is activated.
In brief:
1) Enums to define the variables:
public enum TypeOfContract { ... }
public enum GymClasses { ... }
public enum PhysicalCondition { ... }
Every possible condition would be put in the enums.
2) The Command interface to define the actions
public interface Command {
public void execute(Map<String, Object> parametersMap);
}
Every action would be an implementation of Command. The Map parameter will be used to pass runtime context to the methods.
3) A Procedures class to hold the actions needed for each condition.
public class Procedures {
private List<Command> actionsToExecute = new LinkedList<Command>();
public static final Procedures NO_ACTIONS_TO_EXECUTE = new Procedures();
private Procedures() {}
public Procedures(Command... commandsToExecute) {
if (commandsToExecute == null || commandsToExecute.length == 0) {
throw new IllegalArgumentException("Procedures must have at least a command for execution.");
}
for (Command command : commandsToExecute) {
actionsToExecute.add(command);
}
}
public List<Command> getActionsToExecute() {
return Collections.unmodifiableList(this.actionsToExecute);
}
}
The Procedures class represent the Commands that needed to be executed. It has a LinkedList of Command, to ensure that the Commands are executed in the desired order.
It has the NO_ACTIONS_TO_EXECUTE to be sent instead of a null, in case a combination of the three variables does not exist.
4) A RulesEngine class, to register the rules and its commands
public class RulesEngine {
private static final int NUMBER_OF_FIRST_LEVEL_RULES = TypeOfContract.values().length;
private static final int NUMBER_OF_SECOND_LEVEL_RULES = GymClasses.values().length;
private static final int NUMBER_OF_THIRD_LEVEL_RULES = PhysicalCondition.values().length;
private static final Procedures[][][] RULES =
new Procedures[NUMBER_OF_FIRST_LEVEL_RULES]
[NUMBER_OF_SECOND_LEVEL_RULES]
[NUMBER_OF_THIRD_LEVEL_RULES];
{ //static block
RULES
[TypeOfContract.PLATINUM_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()] =
new Procedures(new RequireMedicalApproval(),
new RequireSignedForm() );
RULES
[TypeOfContract.GOLD_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()] =
new Procedures(new RequireMedicalApproval(),
new RequireSignedForm(),
new AddExtraMonthlyFee() );
...
}
private RulesEngine() {}
public static Procedures loadProcedures(TypeOfContract TypeOfContract,
GymClasses GymClasses, PhysicalCondition PhysicalCondition) {
Procedures procedures = RULES
[TypeOfContract.ordinal()]
[GymClasses.ordinal()]
[PhysicalCondition.ordinal()];
if (procedures == null) {
return Procedures.NO_ACTIONS_TO_EXECUTE;
}
return procedures;
}
}
(Unusual code formatting done for the sake of visualization in this site)
Here the meaningful associations of variables are defined in the RULES three dimensional array.
The rules are defined by employing the corresponding enums.
For the first example I gave, PLATINUM_MEMBERSHIP + PERSONAL_TRAINING + OVER_65, the following would apply:
RULES
[TypeOfContract.PLATINUM_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()]
(the ordinal() is needed to return the int corresponding to the position of the enum)
To represent the actions needed to perform, a Procedures class is associated, wrapping the actions that are to be executed:
new Procedures(new RequireMedicalApproval(), new RequireSignedForm() );
Both RequireMedicalApproval and RequireSignedForm implement the Command interface.
The whole line for defining this combination of variables would be:
RULES
[TypeOfContract.PLATINUM_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()] =
new Procedures(new RequireMedicalApproval(),
new RequireSignedForm() );
To check if a particular combination has actions associated to them, the loadProcedures is called, passing the enums representing that particular combination.
5) Usage
Map<String, Object> context = new HashMap<String, Object>();
context.put("userId", 123);
context.put("contractId", "C45354");
context.put("userDetails", userDetails);
context.put("typeOfContract", TypeOfContract.PLATINUM_MEMBERSHIP);
context.put("GymClasses", GymClasses.PERSONAL_TRAINING);
context.put("PhysicalCondition", PhysicalCondition.OVER_65);
...
Procedures loadedProcedures = RulesEngine.loadProcedures(
TypeOfContract.PLATINUM_MEMBERSHIP,
GymClasses.PERSONAL_TRAINING,
PhysicalCondition.OVER_65);
for (Command action : loadedProcedures.getActionsToExecute()) {
action.equals(context);
}
All information the actions need to execute are now inside a Map.
The conditions, represented by the three enums, are passed to the RulesEngine.
The RulesEngine will evaluate if the combination has associated actions and it will return a Procedures object with the list of these actions that needs to be executed.
If not (the combination has no action associated to it), the RulesEngine will return a valid Procedures object with an empty list.
6) Pros
The usage code is much cleaner
The duplication of code in the switches of the legacy code are now gone
The actions are now standardized and well defined (each one in its own class)
The rules used are now much easier to discern (a developer just needs to look at the RULES array to know which rules are set and what will happen in each one of them)
New rules and actions can be easily added
7) Cons
Easy to make mistakes in the definition of the rules, as the declaration of them is verbose and not semantically analysed - it will accepted repetitions, for example, possibly overwriting previous definitions.
Instead of 3 switches nested inside each other, now I have several classes. The maintenance of the system is a little more complex than before, the learning curve a little steeper.
procedures and rules are not good names - still looking for better ones ;-)
Map as parameter can promote bad coding, cluttering it with a lot of content.
How many options will you have? Let's say you have 8 per category, perhaps you can represent a particular combination as a 24-bit number, with 8 bits per category. When you receive a set of options, convert it over to a bit-pattern than then AND against bit-masks to figure out if a certain action needs to be done.
This still requires you to perform tests, but at least they are not nested, and you simply need to add a new test if/when you add a new feature.
You could use a decision-tree and build it from tuples of values.
This would be a lot simpler and if properly implemented even faster than hard-coded conditions and in addition provides higher maintainability.
In terms of design patterns, if you would like to decrease the complexity, you can use the abstract factory.
You can create three hierarchy of classes.
TYPE_OF_CONTRACT (AbstractProductA)
PLATINUM_MEMBERSHIP (ProductA1)
GOLD_MEMBERSHIP (ProductA2)
SILVER_MEMBERSHIP (ProductA3)
GYM_CLASSES (AbstractProductB)
WEIGHT_LIFTING (ProductB1)
BODY_BALANCE (ProductB2)
STEP (ProductB3)
SPINNING (ProductB4)
ZUMBA (ProductB5)
PERSONAL_TRAINING (ProductB6)
PHYSICAL_CONDITION (AbstractProductC)
NO_RESTRICTIONS (ProductC1)
OVER_65 (ProductC2)
LIMITED_MOBILITY (ProductC3)
MEDICAL_CONDITION (ProductC4)
BELOW_18 (ProductC5)

Multilanguage localizzation in Java

I'm trying to make a program localized in Java.
package javaapplication8;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
public class LanguageController {
private final Map supportedLanguages;
private final ResourceBundle translation;
public LanguageController(String language){
supportedLanguages = new HashMap();
supportedLanguages.put("English",Locale.ENGLISH);
supportedLanguages.put("Italiano",Locale.ITALIAN);
//here I get error
translation = ResourceBundle.getBundle("language", supportedLanguages.get(language));
}
public String getWord(String keyword)
{
return translation.getString(keyword);
}
}
Than in a class I try to print a word in two different languages, italian and english. I have two proprieties file
Language.proprieties
Language_it.proprieties
In the class:
LanguageController langController_it = new LanguageController("Italiano");
System.out.println(langController_it.getWord("Option"));
LanguageController langController_en = new LanguageController("English");
System.out.println(langController_en.getWord("Option"));
EDIT: First problem solution java.util.MissingResourceException: Can't find bundle for base name 'property_file name', locale en_US
I still have error in that line supportedLanguages.get(language)
There are several problems with your application (and with your question for that matter).
First of all, you do not use parametrized collection:
private final Map supportedLanguages;
This map will always return Object, but the getBundle() method has different signature:
public static ResourceBundle getBundle(String baseName, Locale locale);
I am sure that's exactly what Netbeans is complaining about. The ugly way to fix this would be to cast the parameter to Locale:
translation = ResourceBundle.getBundle("language", (Locale) supportedLanguages.get(language));
The better way would be to use type parameters in Map declaration:
private final Map<String, Locale> supportedLanguages = new HashMap<>();
Another possible issue with your application is where you keep properties files with translations. Unfortunately, Java is extremely sensitive where it comes to file location and you have to provide the fully qualified path to a properties file. It changes a bit with Java 8 and ResourceBundle's SPI providers, but that's a different story.
Last, but not least, it seems that you are trying to implement the common anti-pattern, that is language switcher. If you are implementing desktop application, please don't do this mistake!
It is just enough to get user interface default locale:
Locale locale = Locale.getDefault(LocaleCategory.DISPLAY);
Believe it or not, but the ResourceBundle class will try to fall-back to the most appropriate language for the user. If I already have set the UI language in my Operating System preferences, why are you bothering to make a choice again?
Honestly, language switcher make sense for static web sites sometimes, but not for web applications, and definitely not for desktop applications.

Java Registry Class?

I'm fairly new to Java. I'm coming from PHP and I used to create registry classes in php using the magic __get and __set methods. So that other parts of the system can easily do:
registry.foo = new Foo();
I should mention I'm trying to create game engine. Here is my registry in Java atm:
class Registry {
private static Map<String, Object> box = new HashMap<String, Object>();
public static Object get(String key) {
if (Registry.box.get(key) != null) {
return Registry.box.get(key);
}else {
return null;
}
}
public static void set(String key, Object o) {
Registry.box.put(key, o);
}
}
Then for the other parts of the system to access the registry, I currently need this whole thing:
((Object) Registry.get("Object")).doSomething();
Which is really a lot of code. In php this would be accomplished by simply:
Registry.foo.doSomething();
Any way to make this a bit more simpler? I guess I could make public fields, but then the regsitry class would need to implicitly create these fields as the possibility of new objects may need to be added which are unknown to the registry class itself, which is.. annoying :P
Thanks in advance!
This is a two pronged problem:
Java is a statically type language, and does not offer in-language flexibility for defining objects at runtime (you can use a library to synthesize classes at runtime, but, see #2)
A global registry for objects defeats a lot of safeties in a type-safe language. If your entire application centers around getting and putting objects into a global Map, there likely safer and less-coupled designs.
How can this be solved?
Redesign your application structure to not need a global map.
Use a dynamic language subset for Java (such as Groovy).
Use Scala 2.10 (JVM compatible) which features a Dynamic type which does exactly what you want.
First of all this method is too verbose:
public static Object get(String key) {
if (Registry.box.get(key) != null) {
return Registry.box.get(key);
}else {
return null;
}
}
It could be just:
public static Object get(String key) {
return Registry.box.get(key);
}
But second, this is definitely a bad design. Global repository - doesn't sound reasonable. A storage of objects of all types by string key - it's terrible.
Any way to make this a bit more simpler?
Not in any practical way. Java is a statically typed language, and the structure of objects has to be known up front. The very idea of an equivalent of PHP's __get and __set is antithetical to the language.
For what it's worth, your "registry" looks like bad design anyway. (Admittedly making some pretty wild assumptions from the little code you've shown.) You shouldn't need a global repository of what appear to be unrelated objects. You should consider some sort of dependency injection instead.
Based on your comment, instead of structuring your code like this:
class World implements GameSystem {
public void update() {
Registry.get("game").doSomething();
}
}
you should do:
class World implements GameSystem {
Game game;
public World(Game game) { // and other dependencies
this.game = game;
}
public void update() {
this.game.doSomething();
}
}
The idea is that components of your program don't really have any business knowing how to find the other components. It also makes dependencies between the components explicit, and helps you avoid circular dependencies.

Good practice to validate immutable values objects

Suppose a MailConfiguration class specifying settings for sending mails :
public class MailConfiguration {
private AddressesPart addressesPart;
private String subject;
private FilesAttachments filesAttachments;
private String bodyPart;
public MailConfiguration(AddressesPart addressesPart, String subject, FilesAttachments filesAttachements,
String bodyPart) {
Validate.notNull(addressesPart, "addressesPart must not be null");
Validate.notNull(subject, "subject must not be null");
Validate.notNull(filesAttachments, "filesAttachments must not be null");
Validate.notNull(bodyPart, "bodyPart must not be null");
this.addressesPart = addressesPart;
this.subject = subject;
this.filesAttachements = filesAttachements;
this.bodyPart = bodyPart;
}
// ... some useful getters ......
}
So, I'm using two values objects : AddressesPart and FilesAttachment.
Theses two values objects have similar structures so I'm only going to expose here AddressesPart :
public class AddressesPart {
private final String senderAddress;
private final Set recipientToMailAddresses;
private final Set recipientCCMailAdresses;
public AddressesPart(String senderAddress, Set recipientToMailAddresses, Set recipientCCMailAdresses) {
validate(senderAddress, recipientToMailAddresses, recipientCCMailAdresses);
this.senderAddress = senderAddress;
this.recipientToMailAddresses = recipientToMailAddresses;
this.recipientCCMailAdresses = recipientCCMailAdresses;
}
private void validate(String senderAddress, Set recipientToMailAddresses, Set recipientCCMailAdresses) {
AddressValidator addressValidator = new AddressValidator();
addressValidator.validate(senderAddress);
addressValidator.validate(recipientToMailAddresses);
addressValidator.validate(recipientCCMailAdresses);
}
public String getSenderAddress() {
return senderAddress;
}
public Set getRecipientToMailAddresses() {
return recipientToMailAddresses;
}
public Set getRecipientCCMailAdresses() {
return recipientCCMailAdresses;
}
}
And the associated validator : AddressValidator
public class AddressValidator {
private static final String EMAIL_PATTERN
= "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*#[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
public void validate(String address) {
validate(Collections.singleton(address));
}
public void validate(Set addresses) {
Validate.notNull(addresses, "List of mail addresses must not be null");
for (Iterator it = addresses.iterator(); it.hasNext(); ) {
String address = (String) it.next();
Validate.isTrue(address != null && isAddressWellFormed(address), "Invalid Mail address " + address);
}
}
private boolean isAddressWellFormed(String address) {
Pattern emailPattern = Pattern.compile(EMAIL_PATTERN);
Matcher matcher = emailPattern.matcher(address);
return matcher.matches();
}
}
Thus, I have two questions :
1) If for some reasons, later, we want to validate differently an address mail (for instance to include/exclude some aliases matching to existing mailingList), should I expose a kind of IValidator as a constructor parameter ? like the following rather than bringing concrete dependence (like I made):
public AddressValidator(IValidator myValidator) {
this.validator = myValidator;
}
Indeed, this will respect the D principle of SOLID principle : Dependency injection.
However, if we follow this logical, would a majority of Values Objects own an abstract validator or it's just an overkill the most of time (thinking to YAGNI ?) ?
2) I've read in some articles than in respect of DDD, all validations must be present and only present in Aggregate Root, means in this case : MailConfiguration.
Am I right if I consider that immutable objects should never be in an uncohesive state ? Thus, would validation in constructor as I made be preferred in the concerned entity (and so avoiding aggregate to worry about validation of it's "children" ?
There's a basic pattern in DDD that perfectly does the job of checking and assembling objects to create a new one : the Factory.
I've read in some articles than in respect of DDD, all validations
must be present and only present in Aggregate Root
I strongly disagree with that. There can be validation logic in a wide range of places in DDD :
Validation upon creation, performed by a Factory
Enforcement of an aggregate's invariants, usually done in the Aggregate Root
Validation spanning accross several objects can be found in Domain Services.
etc.
Also, I find it funny that you bothered to create an AddressesPart value object -which is a good thing, without considering making EMailAddress a value object in the first place. I think it complicates your code quite a bit because there's no encapsulated notion of what an email address is, so AddressesPart (and any object that will manipulate addresses for that matter) is forced to deal with the AddressValidator to perform validation of its addresses. I think it shouldn't be its responsibility but that of an AddressFactory.
I'm not quite sure if I follow you 100%, but one way to handle ensuring immutable objects are only allowed to be created if they are valid is to use the Essence Pattern.
In a nutshell, the idea is that the parent class contains a static factory that creates immutable instances of itself based on instances of an inner "essence" class. The inner essence is mutable and allows objects to be built up, so you can put the pieces together as you go, and can be validated along the way as well.
The SOLID principals and good DDD is abided by since the parent immutable class is still doing only one thing, but allows others to build it up through it's "essence".
For an example of this, check out the Ldap extension to the Spring Security library.
Some observations first.
Why no generics? J2SE5.0 came out in 2004.
Current version of Java SE has Objects.requiresNonNull as standard. Bit of a mouthful and the capitalisation is wrong. Also returns the passed object so doesn't need a separate line.
this.senderAddress = requiresNonNull(senderAddress);
Your classes are not quite immutable. They are subclassable. Also they don't make a safe copy of their mutable arguments (Sets - shame there aren't immutable collection types in the Java library yet). Note, copy before validation.
this.recipientToMailAddresses = validate(new HashSet<String>(
recipientToMailAddresses
));
The use of ^ and $ in the regex is a little misleading.
If the validation varies, then there's two obvious (sane) choices:
Only do the widest variation in this class. Validate more specifically in the context it is going to be used.
Pass in the validator used and have this as a property. To be useful, client code would have to check and do something reasonable with this information, which is unlikely.
It doesn't make a lot of sense to pass the validator into the constructor and then discard it. That's making the constructor overcomplicated. Put it in a static method, if you must.
The enclosing instance should check that its argument are valid for that particular use, but should not overlap with classes ensuring that they are generally valid. Where would it end?
Although an old question but for anyone stumbling upon the subject matter, please keep it simple with POJOs (Plain Old Java Objects).
As for validations, there is no single truth because for a pure DDD you need to keep the context always in mind.
For example a user with no credit card data can and should be allowed to create an account. But credit card data is needed when checking out on some shopping basket page.
How this is beautifully solved by DDD is by moving the bits and pieces of code to the Entities and Value Objects where it naturally belong.
As a second example, if address should never be empty in the context of a domain level task, then Address value object should force this assertion inside the object instead of using asking a third party library to check if a certain value object is null or not.
Moreover Address as a standalone value object doesn't convey much at its own when compared with ShippingAddress, HomeAddress or CurrentResidentialAddress ... the ubiquitous language, in other words names convey their intent.

Categories

Resources