I'm not really sure about how to distinguish whether I should define a relationship as dependency or association for certain cases.
For example,
class AttendanceSheet {
Map<String> students;
boolean[] attend;
public void addStudent(Student s)
{
students.add(s.getName(),s.getStudentNumber());
}
public void checkAttendance(String name) { //... }
}
class Student {
private String name;
private int staffNumber;
//more information such as address, age, etc..
Student(String n, int sn)
{
name = n;
studentNumber = sn;
}
public String getName()
{
return name.clone();
}
public String getStudentNumber()
{
return studentNumber;
}
}
For this case, would Student and Association have association or dependency?
This is because I'm not sure whether the association must have the actual reference of the object or it suffice to just have certain information that can reach the object (since student id and number is far more enough to know find out which student object it is directing to).
In your case the <<uses>> is sufficient, because you don't have actual properties of type Student in AttendanceSheet.
As a side note: not using object references and instead just having the studentNumber is - to say the least - an odd design. But I don't know the context.
On the business level those objects are related, but there is no single preferred method of diagramming this relationship.
Please see Section 9.5.4 of UML specification for more details on the topic, especially Figure 9.12
To be specific those two notations are semantically equivalent (I'm ignoring irrelevant details):
In the first one to keep a traceability you can use an explicit Dependency pretty much the way you did.
One can also consider students as a Shared Aggregation, however it might be also considered an overkill. Not necessary, just showing a possibility for an answer completeness.
You may also consider Qulified associations to indicate a reference to the Student is based on their specific properties. This is pretty much closest to your need. Sorry, I don't know how to achieve such notation in my tool, but you can find more details in Figure 11.37 in Section 11.5 of the aforementioned specification.
Related
In my DDD attempt I've defined the following ubiquitous language:
A product can have multiple drawings. A drawing consists of a drawing number, a revision number* and multiple attachments**. A drawing can be revised by a new drawing with a different revision number.
Invariants:
for every drawing number a product has, there can only be one current revision.
there can be no drawings with the same drawing number and revision
*sometimes initially empty
**the attachments are the actual product drawings, can be .jpg, .pdf, .stp, etc.
Is there a mismatch in the language? These attachments can also be called the actual drawings where the above properties are merely metadata to programmatically distinguish them.
Some context, the application should help the business with the development of products. The drawings are concepts that after discussion and revisions will form a sample that must be approved by the customer. For this context, I've chosen an event-sourcing architecture because of the business value to evaluate the incremental development of products.
The problem I'm having is whether to put these past revisions in the model. This could be done by adding a boolean property to the drawings that indicate if they are the currently used drawing. This however goes against my gut-feeling to model drawings as immutable value objects (now the drawing has a mutable property). In my mind I've supported this gut-feeling with the argument that once a drawing is changed this results in a new drawing with a different revision number.
Another gut-feeling I have though, is that I should put the past revisions in the model as they have business value. Is it a good solution to let a product have a list of current drawings and past drawings?
How should I think about when a user wants to correct a drawing? For example, when someone didn't attach all correct files to the drawing and you later want to correct this by adding more files, or removing some?
Code example
To give a brief example with some code, this is one of the things I came up with, the drawing as an value-object that uses the drawing number and revision in the equals method:
public class Product {
private Set<Drawing> currentDrawings;
private Set<Drawing> oldDrawings;
}
public class Drawing {
private String drawingNumber;
private String revision;
private Set<URL> files;
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Drawing)) return false;
Drawing other = (Drawing ) o;
if (this.drawingNumber != other.drawingNumber) return false;
if (this.revision != other.revision) return false;
return true;
}
//getters and constructor omitted for brevity
}
Not enough reputation to answer Luiz E's comment, so I'll put it here instead: in some cases a product consists of different parts, materials, and so forth. Sometimes there's a clear parent drawing that referenced other subdrawings, other times there are just a bunch of drawings of parts that will be assembled later.
I tend to adhere to the "KISS" principle, instead of modeling all these different relations between the drawings that will only confuse the users (they are not the creators of the drawings).
For future references, when designing an aggregate according to DDD
principles, one should keep the aggregate clean and not pollute the
model with earlier versions of (parts of) the aggregate. Keep in mind
that you want the model to represent the current state of the
aggregate.
If earlier states of (parts of) the aggregate have some sort of
business value, you should consider event-sourcing or other patterns
that allow an audit log or version control.
For this specific question, the Product aggregate and the Drawing value-object might look like this:
public class Product {
private Map<String, Drawing> drawings;
}
public class Drawing {
private String drawingNumber;
private String revision;
private Set<URL> files;
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Drawing)) return false;
Drawing other = (Drawing ) o;
if (this.drawingNumber != other.drawingNumber) return false;
if (this.revision != other.revision) return false;
return true;
}
//getters and constructor omitted for brevity
}
The reason I would prefer Map over Set here is that you want to have only one revision per drawing number and every Drawing must have an unique drawing number. This is easy to achieve if you use the drawing number as the Key value in a Map and simply put the revised Drawing on the drawing number Key, as this will replace the old Value object.
As a drawing should be considered equal by comparing their drawing number and revision, it would be harder (not impossible) to check if there are no duplicate drawing numbers. You can solve this by only comparing Drawings to their drawing number, but this would undermine the definition of a revision (an correction to the Drawing, which makes it a different Drawing).
Assume the classic Order/OrderLine scenario.
public class Order {
...
public void AddOrderLine(OrderLine ol) {
this.OrderLines.Add(ol);
UpdateTaxes();
}
private void UpdateTaxes() {
//Traverse the order lines
//Collect the VAT amounts etc
//Update totals
var newTaxes = Orderlines.SelectMany(ol => ol.GetTaxes());
Taxes.Clear();
Taxes.Add(newTaxes);
}
}
Now, we figure that we need to handle taxes better, with different ways for customers in various countries etc, where some require VAT to be collected and others not.
In short, the tax rules will depend on the customer's location, items purchased etc. How would we do this? Should we put a lot of code into UpdateTaxes? Could we use tax calculator factory and reference it in UpdateTaxes?
private void UpdateTaxes() {
var taxRules = TaxRulesFactory.Get(this);
var taxes = taxRuleCalc.Apply(this);
Taxes.Clear();
Taxes.Add(taxes);
}
Considering your broader question regarding complex behaviour in ARs the preferred way to handle this would be to use double-dispatch. Bear in mind that complex behaviour certainly can be included in the AR if that behaviour is cohesive.
However, for functionality that varies to the degree of tax or even discount calculation, where one would implement various strategies, you could opt for the double dispatch:
public class Order
{
public void ApplyTax(ITaxService taxService)
{
_totalTax = taxService.Calculate(TotalCost());
}
public void ApplyDiscount(IDiscountService discountService)
{
_discount = discountService.GetDiscount(_orderLines.Count, TotalCost());
}
public Money TotalCost()
{
// return sum of Cost() of order lines
}
}
These services also should not be injected into the AR but rather passed into the relevant method.
May be you could extract UpdateTaxes into a separate class which would be responsible for tax calculation against a particular order. And itself would chose an appropriate strategy (a separate strategy class) depending on customer, order, etc. I feel that tax calculation is a separate responsibility here.
You might also have a think about whether the concept of Tax and the concept of Orders need to be located within the same bounded context. It perhaps seems logical or at least implicit that when you're in the process of creating an Order you will want to know Tax due, but does this necessarily apply in your domain?
I'm not saying it does or it doesn't, by the way -- I'm simply saying think about it for your particular domain. Very often when the model seems awkward to represent it's because it mixes concerns that don't belong together.
There may be situations where we need to return a list of tuple rows from the associated data model i.e not a fully qualified entity but a part of it, specifically a list of selected columns from the associated data-source (may be a database).
I know of some of ways to return a list of tuple rows from the database using JPA like the following
There is no need to look closely into the code from the JPA criteria API, if you were to dislike criteria queries. The question is not directly related to JPA criteria. I prefer JPA criteria to JPQL for no precise reason - just because I like criteria queries very much.
Using a list of object arrays - List<Object[]> :
public List<Object[]> object(int first, int pageSize) {
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]>criteriaQuery=criteriaBuilder.createQuery(Object[].class);
Root<Product> root = criteriaQuery.from(entityManager.getMetamodel().entity(Product.class));
List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Product_.prodId));
selections.add(root.get(Product_.prodName));
selections.add(root.get(Product_.prodCode));
selections.add(root.get(Product_.prodDesc));
selections.add(root.get(Product_.marketPrice));
selections.add(root.get(Product_.salePrice));
criteriaQuery.select(criteriaBuilder.array(selections.toArray(new Selection[0])));
//Or criteriaQuery.multiselect(selections.toArray(new Selection[0]));
return entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize).getResultList();
}
Using a list of tuples - List<Tuple> :
public List<Tuple> tuple(int first, int pageSize) {
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple>criteriaQuery=criteriaBuilder.createTupleQuery();
Root<Product> root = criteriaQuery.from(entityManager.getMetamodel().entity(Product.class));
List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Product_.prodId));
selections.add(root.get(Product_.prodName));
selections.add(root.get(Product_.prodCode));
selections.add(root.get(Product_.prodDesc));
selections.add(root.get(Product_.marketPrice));
selections.add(root.get(Product_.salePrice));
criteriaQuery.select(criteriaBuilder.tuple(selections.toArray(new Selection[0])));
//Or criteriaQuery.multiselect(selections.toArray(new Selection[0]));
return entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize).getResultList();
}
Using a list of rows mapped a class of objects - List<MappedClass> :
public List<ProductUtils> constructor(int first, int pageSize) {
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<ProductUtils>criteriaQuery=criteriaBuilder.createQuery(ProductUtils.class);
Root<Product> root = criteriaQuery.from(entityManager.getMetamodel().entity(Product.class));
List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Product_.prodId));
selections.add(root.get(Product_.prodName));
selections.add(root.get(Product_.prodCode));
selections.add(root.get(Product_.prodDesc));
selections.add(root.get(Product_.marketPrice));
selections.add(root.get(Product_.salePrice));
criteriaQuery.select(criteriaBuilder.construct(ProductUtils.class, selections.toArray(new Selection[0])));
//Or criteriaQuery.multiselect(selections.toArray(new Selection[0]));
return entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize).getResultList();
}
Again the same thing can be rewritten using JPQL.
The first two of them are ugly and require accessing properties using indices in EL on XHTML pages. Maintaining them is difficult, if the order in which the fields appear is changed at a later time (of course, aliases can be used with Tuple). Also, use of Tuple is always avoidable, since it requires an additional dependency in JSF from the javax.persistence package increasing coupling between modules.
Using a constructor query to map the result list to a class may suffice. It can be used along with PrimeFaces LazyDataModel as follows.
#Named
#ViewScoped
public class TestManagedBean extends LazyDataModel<ProductUtils> implements Serializable {
#Inject
private Service service;
private static final long serialVersionUID=1L;
public TestManagedBean() {}
#Override
public List<ProductUtils> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, Object> filters) {
// Put some logic here like setting total rows for LazyDataModel - setRowCount(10)
return service.constructor(first, pageSize); //Use filters and sort meta whenever necessary.
}
}
But this is also too unmaintainable, if I need to access more or less fields from the database at some later time at a different place that requires creating a new class or adding a new constructor (constructor overloading in the existing class) to the existing class which in turn requires to check carefully the actual and formal parameters of the constructor method to see, if they match in number, order and type precisely that often makes me blind.
I hope, there should be some better ways that allow us to tackle such situations in a precise way.
Parameterized constructor(s) in the existing entity classes, if used instead (without creating a new class like ProductUtils, in this case) may cause problems while implementing web services (JAX-WS) in the application (if needed). Therefore, I never tend to use parameterized constructors of entity classes anywhere.
I'm supposed to declare a class field for a federal tax rate, which is a constant, with a value .07. How can I achieve this?
Since you didn't specify a language, I'll throw in a Java solution
public class YourClass {
public static final double TAX_RATE = 0.07;
}
In Java naming convention, you name your constants with all upper casing and use _ to separate words instead of the normal camel casing.
the final keyword, is to make it, well, final - meaning unchangeable
Anything not withing a block like a constructor or a method is considered a field.
I have an application that requires mappings between string values, so essentially a container that can hold key values pairs. Instead of using a dictionary or a name-value collection I used a resource file that I access programmatically in my code. I understand resource files are used in localization scenarios for multi-language implementations and the likes. However I like their strongly typed nature which ensures that if the value is changed the application does not compile.
However I would like to know if there are any important cons of using a *.resx file for simple key-value pair storage instead of using a more traditional programmatic type.
There are two cons which I can think of out of the blue:
it requires I/O operation to read key/value pair, which may result in significant performance decrease,
if you let standard .Net logic to resolve loading resources, it will always try to find the file corresponding to CultureInfo.CurrentUICulture property; this could be problematic if you decide that you actually want to have multiple resx-es (i.e. one per language); this could result in even further performance degradation.
BTW. Couldn't you just create helper class or structure containing properties, like that:
public static class GlobalConstants
{
private const int _SomeInt = 42;
private const string _SomeString = "Ultimate answer";
public static int SomeInt
{
get
{
return _SomeInt;
}
}
public static string SomeString
{
get
{
return _SomeString;
}
}
}
You can then access these properties exactly the same way, as resource files (I am assuming that you're used to this style):
textBox1.Text = GlobalConstants.SomeString;
textBox1.Top = GlobalConstants.SomeInt;
Maybe it is not the best thing to do, but I firmly believe this is still better than using resource file for that...