Java API design - Pass by Object or Pass By Value - java

I am designing the service layer of my web application. There are some scenario which I need to get the Orders based on the Product.
When I design the API, should I pass by object or value?
Order order = new Order();
String orderId = "1";
order.setId(orderId);
List<Product> products = getProductByOrder(order);
List<Product> products = getProductsByOrderId(orderId)

Well, i think you are making some mistakes with this concepts, in this two ways you are making references to this objects, order and orderId(since String is an object too.)
But the best approach in this case is using getProductsByOrderId(orderId) because your code will be loosely coupled, since your other layer won't have to know about an Order object, and just know about a string object. If we can pass simpler objects as parameters, we do.
Good example from #Pienterekaak posted as comment:
"In many cases its easier to obtain just an orderid, then a whole order object. (for example, you would include an order id in a REST call, not the whole order object)"

From my experience i would go for:
List<Product> products = getProductsByOrderId(orderId)
With the argument, that for the first call, you need an Order object, and for the second call you just need an id, which is probally easier to obtain.

Actually both of these are passing by value. Java only passes by value. In both of these cases you are passing a reference to an Object (String) or (Order). You are passing as a value the location of memory where this object is (pointer). If you are passing a primitive type like int it passes the value like 1 but if you are passing an object it passes the value of the pointer to the object ie. memory location. In any case you are always passing by value.
If you have a Map storing the Order objects it is actually more efficient to pass the Object itself because you are directly passing the pointer for that object. If you pass the String id of 1 you are passing a pointer to that string then you would have to use that string to look up your Order object which is actually adding more processing then just passing a pointer to the object directly.

OrderId belongs to the concept of an order. If you pass the order id, the product has to know, how an order is identified. That's not loosely coupled.
If you put the method into Order, so you can call a property like
List order.Products
only the Order concept knows, how products and orders are connected, which sounds right to me.
Products shouldn't know anything about orders but orders should know about products.
If you use Hibernate, you could configure it to do it for you with an one-to-many, since orderId is a primary key in your order table.

Related

Indexing a simple Java Record

I have a Java Object, Record . It represents a single record as a result of SQL execution. Can CQEngine index collection of Record ?
My class is of the form
public class Record {
private List<String> columnNames;
private List<Object> values;
... Other getters
}
I have looked through some examples, but I have no luck there.
I want to index only specific column(s) with its name and corresponding value. Can this be achived using cqengine or is there any other alternatives to achieve the same.
Thanks.
That seems to be a strange way to model data, but you can use CQEngine with that model if you wish.
(First off, CQEngine will have no use for your column names so you can remove that field.)
To do this, you will need to define a CQEngine virtual attribute for each of the indexes in your list of values.
Each attribute will need to be declared with the data type which will be stored in that column/index, and will need to be able to cast the object at that index in your list of values, to the appropriate data type (String, Double, Integer etc.).
So let's say your Record has a column called 'price', which is of type Double, and is stored at index 5 in the list of values. You could define an attribute which reads it as follows:
public static final Attribute<Record, Double> PRICE =
attribute("PRICE", record -> ((Double) record.values.get(5));
If this sounds complicated, it's because that way of modelling data makes things a bit complicated :) It's usually easier to work with a data model which leverages the Java type system (which your model does not). As such, you will need to keep track of the data types etc. of each field programmatically yourself.
CQEngine itself will work fine with that model though, because at the end of the day CQEngine attributes don't need to read fields, the attributes are just functions which are programmed to fetch values.
There's a bunch of stuff not covered above. For example can your values be null? (if so, you should use the nullable variety of attributes as discussed in the CQEngine docs. Or, might each of your Record objects have different sets of columns? (if so, you can create attributes on-the-fly when you encounter a new column, but you should probably cache the attributes you have created somewhere).
Hope that helps,
Niall (CQEngine author)

4 Key Value HashMap? Array? Best Approach?

I've got loads of the following to implement.
validateParameter(field_name, field_type, field_validationMessage, visibleBoolean);
Instead of having 50-60 of these in a row, is there some form of nested hashmap/4d array I can use to build it up and loop through them?
Whats the best approach for doing something like that?
Thanks!
EDIT: Was 4 items.
What you could do is create a new Class that holds three values. (The type, the boolean, and name, or the fourth value (you didn't list it)). Then, when creating the HashMap, all you have to do is call the method to get your three values. It may seem like more work, but all you would have to do is create a simple loop to go through all of the values you need. Since I don't know exactly what it is that you're trying to do, all I can do is provide an example of what I'm trying to do. Hope it applies to your problem.
Anyways, creating the Class to hold the three(or four) values you need.
For example,
Class Fields{
String field_name;
Integer field_type;
Boolean validationMessageVisible;
Fields(String name, Integer type, Boolean mv) {
// this.field_name = name;
this.field_type = type;
this.validationMessageVisible = mv;
}
Then put them in a HashMap somewhat like this:
HashMap map = new HashMap<String, Triple>();
map.put(LOCAL STRING FOR NAME OF FIELD, new Field(new Integer(YOUR INTEGER),new Boolean(YOUR BOOLEAN)));
NOTE: This is only going to work as long as these three or four values can all be stored together. For example if you need all of the values to be stored separately for whatever reason it may be, then this won't work. Only if they can be grouped together without it affecting the function of the program, that this will work.
This was a quick brainstorm. Not sure if it will work, but think along these lines and I believe it should work out for you.
You may have to make a few edits, but this should get you in the right direction
P.S. Sorry for it being so wordy, just tried to get as many details out as possible.
The other answer is close but you don't need a key in this case.
Just define a class to contain your three fields. Create a List or array of that class. Loop over the list or array calling the method for each combination.
The approach I'd use is to create a POJO (or some POJOs) to store the values as attributes and validate attribute by attribute.
Since many times you're going to have the same validation per attribute type (e.g. dates and numbers can be validated by range, strings can be validated to ensure they´re not null or empty, etc), you could just iterate on these attributes using reflection (or even better, using annotations).
If you need to validate on the POJO level, you can still reuse these attribute-level validators via composition, while you add more specific validations are you´re going up in the abstraction level (going up means basic attributes -> pojos -> pojos that contain other pojos -> etc).
Passing several basic types as parameters of the same method is not good because the parameters themselves don't tell much and you can easily exchange two parameters of the same type by accident in the method call.

PlayFramework get field from model select

Since the play documentation on models is terrible I'll ask here. I have the basic code;
public static void Controller() {
List<Item> item = Item.find("SELECT itemname,id FROM Item WHERE itembool = true ORDER BY itemcreated ASC LIMIT 0,1").fetch();
if ( item == null ) {
notFound();
}
}
What I'm trying to do is get the value for 'itemname' returned for the first value returned from an SQL query (The real query is much more complicated and other things so it can't be replaced with methods). I can get the entire first object with item.get(0) but I can't figure out how to get the value of 'itemname' as a string and it doesn't seem to be documented anywhere.
Edit
Probably should have mentioned in the original question, I need to retrieve by field name, not index. I.E. I can't do items.get(0)[0]; I need to do items.get(0)['itemname'];
The documentation explains this if you read it, in here. Hibernate doesn't use SQL, but JPQL, which has a different syntax as it works with objects, not individual fields.
What you want to do can be achieved in two ways (both in the documentation):
List<Item> item = Item.find("SELECT i FROM Item i WHERE i.itembool = true ORDER BY i.itemcreated ASC").fetch(1);
List<Item> item = Item.find("itembool = true ORDER BY itemcreated ASC").fetch(1);
EDIT:
On the retrieval part, you will get a list of Item, so you can just access the field directly on the object:
item.get(0).getItemName();
Since Play uses Hibernate under the hood, you need to take a look at Hibernate's documentation.
In particular, SELECT itemname,id ... yields Object[] rather than Item, so that you can get itemname as follows:
List<Object[]> items = ...;
String itemname = items.get(0)[0];
well if you have to do a select itemname,id ..., you would not be able to do a items.get(0)["itemname"] because as axtavt and Pere have mentioned, you would get a Object[] back. You can instead create another (perhaps immutable) entity class that can be used in this query. Please refer to hibernate documentation for details. You can then model the entity based on your query requirements and use it to fetch information, thus letting hibernate handle all the magic number game for you. That ways, you would have a bean with filled up values that you can use to map back to your model class if you like.
HTH!

Object Id of an object across the jvms?

I have a question on object ID of an object across JVMs. ie Say suppose i have persisted an object created on JVM1, and now I want to use the same object on JVM2.
So how to do that.
Will the object Id of the object same on both the JVM?
If yes for the above question, then what will be the case if the JVM2 has already an object with the objectID same as the one which is persisted.
thanks.
The object won't exist on JVM2 until you deserialize it. There's no concept of a "universal object ID" in Java - if you need an ID for your objects, you'll have to add it yourself. You could add a UUID field to your object; you'd then want to maintain some sort of cache to allow you to spot duplicates.
Are you really sure you need all of this? It may be worth taking another look at the bigger picture and redesigning.
Check out serialization here or alternatively you could use RMI - check out this link
I'm not really sure what you mean by Object Id, if you mean the reference you get printed out when you print out an object with no toString method then, this is not an object ID this is the memory address reference and will be different on each JVM and different on different invocations of the same program.
You could add a UUID to your object to create an unique id.
UUID javadoc
UUID uuid = UUID.randomUUID();

Domain Driven Design - How to use value object on the UI

I was wondering how you use your ddd model within a web application. Within Eric Evan Cargo application there's the Cargo class which contains the value object Itinerary. Within Itinerary is a collection of Legs, again a value object. All value objects hide the surrogate id to the outside world.
So when using this domain model, how would I create a web app, where you can click on a cargo itinerary, list all legs and then show the details of a leg by redirecting to a new "leg detail" page. Usually I would pass the LegId within the query fields and read it out again on the detail page. But since it has no id, how would you do that?
Using the index of a leg which might change when the collection gets sorted?
Passing all values within the query fields since this is the value object identity?
Sounds like a step backwards to me :)
If the leg has no id, the only way you have to refer to it is through the Cargo, which has an identity, and therefore can be associated with a URI/URL. To refer to a specific leg, you have only the index, which can be a number, or a dictionary key. If you have sorting issues, you can define two lists: one with the canonical ordering for reference purposes, and another with the ordering, mapping order position and canonical index.
As for the reason why the value objects in Evans' example have ids, I think it's for serialization purposes.
Of course, you can also opt for a Itinerary/Leg with identity.

Categories

Resources