How to extend the Java API to be able to introduce new annotations [closed] - annotations

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Can you explain me how I can extend or change the JAVA-API to using two new Annotations #any and #option to allow Multiplicies in Java?
The main idea for the Multiplicities is the follow:
Multiplicities help to solve many maintenance problems, when we change a to-many-relationship into a to-one-relationship or vice-versa.
I would like to use the above annotations for "fields", "parameter methods" and "return parameters".
For example:
class MyClass {
String #any name; // instead of using List<String>, i would like to use #any
public String setFullname(String #option name) { // #option is another multiplicity
...
}
}
To allow this definition, i have to change the JAVA-API and extends it with these two annotations, but I don't know how to do this.
Can you tell me how to change the API, and which steps I must follow to achieve my requirements?
Please look at this paper to understand the issue.
As explained in that paper, using multiplicities for building to-many relationship causes number of problems:
"It makes maintenance tedious and error-prone."
<< If the maintenance of a program requires a change of a relationship from to-one to to-many (or vice versa), nearly every occurrence of the variable representing this relationship in the program needs to be touched. In a language with static type checking, these occurrences
will be identified by the compiler (as type errors) after the declaration of the field has been changed so that at least, no use is forgotten; in a language without it, the change is extremely error-prone>>
"It changes conditions of subtyping"
<< If S is a subtype of T, an expression of type S can be assigned to a variable (representing a to-one relationship) of type T. When the relationship is upgraded to to-many and the types of the expression and variable are changed to Collection and Collection to reflect this, the assignment is no longer well-typed [18]. To fix this, the use of a (former to-one and now tomany) variable must be restricted to retrieving elements of its collection, which may require substantial further code changes. We consider this dependency of
subtyping on multiplicity to be awkward.>>
"It changes call semantics"
Yet another manifestation of the discontinuity is that when a variable holding a related object is used as an actual parameter of a method
call with call-by-value semantics, the method cannot change the value of the variable (i.e., to which object the variable points), and thus cannot change which object
the variable’s owner is related to. By contrast, when the variable holds a collection of related objects, passing this variable by-value to a method allows the
method to add and remove from the collection, and thus to change which objects the variable’s owner is related to, effectively giving the call by-reference semantics.
We consider this dependency of semantics on multiplicity to be awkward. Surely, there is an easy fix to all problems stemming from the noted discontinuity:
implement to-one relationships using containers also. For instance, the Option class in Scala has two subclasses, Some and None, where Some wraps an object of type
E with an object of type Option, which can be substituted by None, so that the object and no object have a uniform access protocol (namely that of Option). By making Option
implement the protocol of Collection, the above noted discontinuity will mostly disappear. However, doing so generalizes the problems of collections that stem from
putting the content over the container. Specifically:
"Related objects have to be unwrapped before they can be used".
Using containers for keeping related objects, the operations executable on a variable representing the relationship are the operations of the container and not of the related objects. For instance, if cookies have the operation beNibbled(), the same operation can
typically not be expected from a collection of cookies (since Collection is a general
purpose class).
"It subjects substitutability to the rules of subtyping of generics". While the difference in subtyping between to-one and to-many variables (item 2 above) has been
removed, the wrong version has survived: now, a to-one relationship with target type T, implemented as a field having type Option, cannot relate to an object of T’s subtype S (using Option, unless restrictions regarding replacement of the object are accepted).
"It introduces an aliasing problem".
While aliasing is a general problem of objectoriented programming (see, e.g., [11, 19]), the use of container objects to implement relationships introduces the special problem of aliasing the container: when two objects share the same container, the relationship of one object cannot evolve differently from that of the other. This may however not model the domain correctly, and can lead to subtle programming errors.
"Expressive poverty".
More generally, given only collections it is not possible to
express the difference between “object a has a collection, which contains objects b1 through bn” and “object a has objects b1 through bn”. While one might maintain that the former is merely the object-oriented way of representing the latter, and that the used collection is merely an implementation object, it could be the case that the collection is actually a domain object (as which it could even have aliases; cf. above). In object-oriented modelling, by contrast, collections serving as implementation classes are abstracted from by specifying multiplicities larger than 1 (possibly complemented by constraints on the type of the collection, i.e., whether it is ordered, has duplicates, etc.). A collection class in a domain model is therefore always a domain class.
The following figure highlights these problems using a sample program from the internet service provider domain.
http://infochrist.net/coumcoum/Multiplicities.png
Initially, a customer can have a single email account which, according to the price plan selected, is either a POP3 or an IMAP account. Accounts are created by a factory (static method Account.make, Figure 1 left, beginning in line 4) and, for reasons of symmetry, are also deleted by a static method (Account.delete; line 19); due to Java’s lack of support for calling by reference (or out parameters), however, delete does not work as expected. Therefore, resetting of the field account to null has been replicated in the method Customer.transferAccount (line 40). When the program is upgraded to support multiple accounts per customer, the first change is to alter the type of account to List (Figure 1 right, line 30). As suggested by above Problem 1, this entails a number of changes. In class Customer it requires the introduction of an iteration over all accounts (line 35), and the replacement of the receiver of the method set, account, with the iteration variable a (Problem 4). In class Account, make must be changed to return a list of accounts (line 4), and the construction of accounts (lines 7 and 12) must be replaced by the construction of lists that contain a single account of the appropriate type. Admittedly, making the Account factory return a list seems awkward; yet, as we will see, it only demonstrates Problem 7. Also, it brings about a change in the conditions of subtyping (Problem 2): for make to be well-typed (which it is not in Figure 1, right), its return type would either have to be changed to List (requiring a corresponding change of the type of Customer.account, thus limiting account’s use to read access; Problem 5), or the created lists would need to be changed to element type Account. The parameter type of Account.delete needs to be changed to List also; replacing the assignment
of null with clearing the list (line 20) to better reflect the absence of an account (cf. the above discussions on the different meanings of null) makes delete work as intended, which may however change the semantics of a program actually calling delete (Problem 3). An analogous change from assigning null to calling clear() in class Account, line 40, introduces a logical error, since the transferred account is accidentally cleared as well (Problem 6).
The solution is to use multiplicities, as followed (look at the comment below for the image):
The question is now, how can I implement multiplicities in Java?

You are confused about what API means. To implement this idea, you would need to edit the source code of the Java compiler, and what you would end up with would no longer be Java, it would be a forked version of Java, which you would have to call something else.
I do not think this idea has much merit, to be honest.

It's unclear why you think this would solve your problem, and using a non-standard JDK will -- in fact -- give you an even greater maintenance burden. For example, when there are new versions of the JDK, you will need to apply your updates to the new version as well when you upgrade. Not to mention the fact that new employees you hire will not be familiar with your language that deviates from Java.
Java does allow one to define custom annotations:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/annotations.html
... and one can use reflection or annotation processors to do cool things with them. However, annotations cannot be used to so drastically change the program semantics (like magically making a String mean a List of strings, instead) without forking your own version of the JDK, which is a bad idea.

Related

Polymorphism in sysml

currently i am trying to design an executable activity where a logical component send a request to several other logical components to start initialization. The usual way in activity diagram is to create for each block a swimline. But, as the number of LCs are high in this case the diagram will be extremely big and also later its modification will be a hurdle.
In programming, the solution to this problem is polymorphism where the objects are casted as the mother class and pushed into a vector and then within the loop the abstract function of the mother class is called.
I wonder if there is any similar solution to this problem in sysml or not?
I tried to assign one swimline to the all the LCs which recevie the request but it seems each swimline can only be assigned to a block.
Yes, there is a similar solution. Actually, it is even easier. Just let the ActivtyPartition represent a property with a multiplicity greater than 1. Any InvocationAction in this partition will then mean a concurrent invocation on all instances held in this property.
The UML specification says about this:
section 15.6.3.1 Activity Partitions
If the Property holds more than one value, the
invocations are treated as if they were made concurrently on each
value and the invocation does not complete until all the concurrent
instances of it complete.
Typical InvocationActions are CallActions and SendSignalActions. So, you could call the initialize() operation in a partition representing the property myLogicalComponents:LC[1..*].
If you don't already have defined such a property, you can derive it, by making it a derived union and then define all existing properties with components to be initialized as subsets of it:
/myLogicalComponents:LC[1..*]{union}
LC1:LC {subsets myLogicalComponents}
LC2:LC {subsets myLogicalComponents}
Of course, this assumes, that all your logical components are specializing LC, so that they all inherit and redefine the initialize() operation.
In SysML you also have AllocateActivityPartitions. No clear semantics is described for it, so I think you are better served with the UML ActivityPartitions, which are also included in SysML.

DDD can event handler construct value object for aggregate

Can I construct a value object in the event handler or should I pass the parameters to the aggregate to construct the value object itself? Seller is the aggregate and offer is the value object. Will it be better for the aggregate to pass the value object in the event?
public async Task HandleAsync(OfferCreatedEvent domainEvent)
{
var seller = await this.sellerRepository.GetByIdAsync(domainEvent.SellerId);
var offer = new Offer(domainEvent.BuyerId, domainEvent.ProductId, seller.Id);
seller.AddOffer(offer);
}
should I pass the parameters to the aggregate to construct the value object itself?
You should probably default to passing the assembled value object to the domain entity / root entity.
The supporting argument is that we want to avoid polluting our domain logic with plumbing concerns. Expressed another way, new is not a domain concept, so we'd like that expression to live "somewhere else".
Note: that by passing the value to the domain logic, you protect that logic from changes to the construction of the values; for instance, how much code has to change if you later discover that there should be a fourth constructor argument?
That said, I'd consider this to be a guideline - in cases where you discover that violating the guideline offers significant benefits, you should violate the guideline without guilt.
Will it be better for the aggregate to pass the value object in the event?
Maybe? Let's try a little bit of refactoring....
// WARNING: untested code ahead
public async Task HandleAsync(OfferCreatedEvent domainEvent)
{
var seller = await this.sellerRepository.GetByIdAsync(domainEvent.SellerId);
Handle(domainEvent, seller);
}
static Handle(OfferCreatedEvent domainEvent, Seller seller)
{
var offer = new Offer(domainEvent.BuyerId, domainEvent.ProductId, seller.Id);
seller.AddOffer(offer);
}
Note the shift - where HandleAsync needs to be aware of async/await constructs, Handle is just a single threaded procedure that manipulates two local memory references. What that procedure does is copy information from the OfferCreatedEvent to the Seller entity.
The fact that Handle here can be static, and has no dependencies on the async shell, suggests that it could be moved to another place; another hint being that the implementation of Handle requires a dependency (Offer) that is absent from HandleAsync.
Now, within Handle, what we are "really" doing is copying information from OfferCreatedEvent to Seller. We might reasonably choose:
seller.AddOffer(domainEvent);
seller.AddOffer(domainEvent.offer());
seller.AddOffer(new Offer(domainEvent));
seller.AddOffer(new Offer(domainEvent.BuyerId, domainEvent.ProductId, seller.Id));
seller.AddOffer(domainEvent.BuyerId, domainEvent.ProductId, seller.Id);
These are all "fine" in the sense that we can get the machine to do the right thing using any of them. The tradeoffs are largely related to where we want to work with the information in detail, and where we prefer to work with the information as an abstraction.
In the common case, I would expect that we'd use abstractions for our domain logic (therefore: Seller.AddOffer(Offer)) and keep the details of how the information is copied "somewhere else".
The OfferCreatedEvent -> Offer function can sensibly live in a number of different places, depending on which parts of the design we think are most stable, how much generality we can justify, and so on.
Sometimes, you have to do a bit of war gaming: which design is going to be easiest to adapt if the most likely requirements change happens?
I would also advocate for passing an already assembled value object to the aggregate in this situation. In addition to the reasons already mentioned by #VoiceOfUnreason, this also fits more naturally with the domain language. Also, when reading code and method APIs you can then focus on domain concepts (like an offer) without being distracted by details until you really need to know them.
This becomes even more important if you would need to pass in more then one value object (or entity). Rather passing in all the values required for construction as parameters not only makes the API more resilient to refactoring but also burdens the reader with more details.
The seller is receiving an offer.
Assuming this is what is meant here, fits better than something like the following:
The seller receives some buyer id, product id, etc.
This most probably would not be found in conversations using the ubiquitous language. In my opinion code should be as readable as possible and express the behaviour and business logic as close to human language as possible. Because you compile code for machines to execute it but the way you write it is for humans to easily understand it.
Note: I would even consider using factory methods on value objects in certain cases to unburden the client code of knowing what else might be needed to assemble a valid value object, for instance, if there are different valid constellations and ways of constructing the same value objects where some values need reasonable default values or values are chosen by the value object itself. In more complex situations a separate factory might even make sense.

working around type erasure -- recommended way?

After Scala-2.10 the situation has changed, since there is now a dedicated reflection system.
What is the recommended, best-practice, standard way the community has settled down on in order to amend the deficiencies created by type erasure?
The situation
We all know that the underlying runtime system (JVM / bytecode) is lacking the ability to fully represent parametrised types in a persistent way. This means that the Scala type system can express elaborate type relationships, which lack an unambiguous representation in plain JVM byte code.
Thus, when creating a concrete data instance, the context of the creation contains specific knowledge about the fine points of the embedded data. As long as the creation context is connected to the usage context in a statical fashion, i.e. as long as both are connected directly within a single compilation process, everything is fine, since we stay in "scala realm" where any specific type knowledge can be passed within the compiler.
But as soon as our data instance (object instance) passes a zone where only JVM bytecode properties are guaranteed, this link is lost. This might happen e.g. when
sending the data element as message to another Actor
passing it through subsystems written in other JVM languages (e.g. an OR-Mapper and RDBMS storage)
feeding the data through JVM Serialisation and any marshalling techniques built on top
and even just within Scala, passing through any function signature which discards specific type parameter information and retains only some type bound (e.g. Seq[AnyRef]) or an existential type (Seq[_])
Thus we need a way to marshal the additional specific type information.
An Example
Let's assume we use a type Document[Format]. Documents are sent and retrieved through a family of external service APIs, which mostly talk in JSON format (and are typically not confined to usage from Java alone). Obviously, for some specific kinds of Format, we can write type classes to hold the knowledge how to parse that JSON and convert it into explicit Scala types. But clearly there is no hope for one coherent type hierarchy to cover any kind of Document[Format] (beyond the mere fact that it is a formatted document and can be converted). It figures that we can handle all the generic concerns elegantly (distributing load, handling timeouts and availability of some API / service, keeping a persistent record of data). But for any actual "business" functionality, we need to switch over to specific types eventually.
The Quest
Since the JVM bytecode can not represent the type information we need, without any doubt we need to allocate some additional metadata field within our Document[Format] to represent the information "this document has Format XYZ". So, by looking at that piece of metadata, we can re-gain the fully typed context later on.
My question is about the preferred, most adequate, most elegant, most idiomatic way of solving this problem. That is, in current Scala (>= Scala-2.10).
how to represent the additional type information (i.e. the Format in the example above)? Storing Format.class in the document object? or using a type tag? or would you rather recommend a symbolic representation, e.g. 'Format or "my.package.Format"
or would you rather recommend to store the full type information, e.g. Document[Format], and which representation is recommended?
what is the most concise, most clear, most clean, most readable and self-explanatory solution in code to re-establish the full type context? Using some kind of pattern match? Using some implicit? Using a type class or view bound?
What have people found out to work well in this situation?
Scala documentation: http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html
From the article:
Like scala.reflect.Manifest, TypeTags can be thought of as objects
which carry along all type information available at compile time, to
runtime. For example, TypeTag[T] encapsulates the runtime type
representation of some compile-time type T. Note however, that
TypeTags should be considered to be a richer replacement of the
pre-2.10 notion of a Manifest, that are additionally fully integrated
with Scala reflection.
You should also look at Manifests.

Why does Optional not extend Supplier

I used Supplier quite often and I'm looking at new Guava 10 Optional now.
In contrast to a Supplier an Optional guarantees never to return null but will throw an IllegalStateException instead. In addition it is immutable and thus it has a fixed known value once it is created. In contrast to that a Supplier may be used to create different or lazy values triggered by calling get() (but it is not imposed to do so).
I followed the discussion about why an Optional should not extend a Supplier and I found:
...it would not be a well-behaved Supplier
But I can't see why, as Supplier explicitly states:
No guarantees are implied by this interface.
For me it would fit, but it seems I used to employ Suppliers in a different way as it was originally intended. Can someone please explain to me why an Optional should NOT be used as a Supplier?
Yes: it is quite easy to convert an Optional into a Supplier (and in addition you may choose if the adapted Supplier.get() will return Optional.get() or Optional.orNull())
but you need some additional transformation and have to create new objects for each :-(
Seems there is some mismatch between the intended use of a Supplier and my understanding of its documentation.
Dieter.
Consider the case of
Supplier<String> s = Optional.absent();
Think about this. You have a type containing one method, that takes no arguments, but for which it's a programmer error to ever invoke that method! Does that really make sense?
You'd only want Supplierness for "present" optionals, but then, just use Suppliers.ofInstance.
A Supplier is generally expected to be capable of returning objects (assuming no unexpected errors occur). An Optional is something that explicitly may not be capable of returning objects.
I think "no guarantees are implied by this interface" generally means that there are no guarantees about how it retrieves an object, not that the interface need not imply the ability to retrieve an object at all. Even if you feel it is OK for a Supplier instance to throw an exception every time you call get() on it, the Guava authors do not feel that way and choose to only provide suppliers that can be expected to be generally well-behaved.

Immutability and shared references - how to reconcile?

Consider this simplified application domain:
Criminal Investigative database
Person is anyone involved in an investigation
Report is a bit of info that is part of an investigation
A Report references a primary Person (the subject of an investigation)
A Report has accomplices who are secondarily related (and could certainly be primary in other investigations or reports
These classes have ids that are used to store them in a database, since their info can change over time (e.g. we might find new aliases for a person, or add persons of interest to a report)
Domain http://yuml.me/13fc6da0
If these are stored in some sort of database and I wish to use immutable objects, there seems to be an issue regarding state and referencing.
Supposing that I change some meta-data about a Person. Since my Person objects immutable, I might have some code like:
class Person(
val id:UUID,
val aliases:List[String],
val reports:List[Report]) {
def addAlias(name:String) = new Person(id,name :: aliases,reports)
}
So that my Person with a new alias becomes a new object, also immutable. If a Report refers to that person, but the alias was changed elsewhere in the system, my Report now refers to the "old" person, i.e. the person without the new alias.
Similarly, I might have:
class Report(val id:UUID, val content:String) {
/** Adding more info to our report */
def updateContent(newContent:String) = new Report(id,newContent)
}
Since these objects don't know who refers to them, it's not clear to me how to let all the "referrers" know that there is a new object available representing the most recent state.
This could be done by having all objects "refresh" from a central data store and all operations that create new, updated, objects store to the central data store, but this feels like a cheesy reimplementation of the underlying language's referencing. i.e. it would be more clear to just make these "secondary storable objects" mutable. So, if I add an alias to a Person, all referrers see the new value without doing anything.
How is this dealt with when we want to avoid mutability, or is this a case where immutability is not helpful?
If X refers to Y, both are immutable, and Y changes (i.e. you replace it with an updated copy), then you have no choice but to replace X also (because it has changed, since the new X points to the new Y, not the old one).
This rapidly becomes a headache to maintain in highly interconnected data structures. You have three general approaches.
Forget immutability in general. Make the links mutable. Fix them as needed. Be sure you really do fix them, or you might get a memory leak (X refers to old Y, which refers to old X, which refers to older Y, etc.).
Don't store direct links, but rather ID codes that you can look up (e.g. a key into a hash map). You then need to handle the lookup failure case, but otherwise things are pretty robust. This is a little slower than the direct link, of course.
Change the entire world. If something is changed, everything that links to it must also be changed (and performing this operation simultaneously across a complex data set is tricky, but theoretically possible, or at least the mutable aspects of it can be hidden e.g. with lots of lazy vals).
Which is preferable depends on your rate of lookups and updates, I expect.
I suggest you to read how they people deal with the problem in clojure and Akka. Read about Software transactional memory. And some of my thoughts...
The immutability exists not for the sake of itself. Immutability is abstraction. It does not "exist" in nature. World is mutable, world is permanently changing. So it's quite natural for data structures to be mutable - they describe the state of the real or simulated object at a given moment in time. And it looks like OOP rulez here. At conceptual level the problem with this attitude is that object in RAM != real object - the data can be inaccurate, it comes with delay etc
So in case of most trivial requirements you can go with everything mutable - persons, reports etc Practical problems will arise when:
data structures are modified from concurrent threads
users provide conficting changes for the same objects
a user provide an invalid data and it should be rolled back
With naive mutable model you will quickly end up with inconsistent data and crushing system. Mutability is error prone, immutability is impossible. What you need is transactional view of the world. Within transaction program sees immutable world. And STM manages changes to be applied in consistent and thread-safe way.
I think you are trying to square the circle. Person is immutable, the list of Reports on a Person is part of the Person, and the list of Reports can change.
Would it be possible for an immutable Person have a reference to a mutable PersonRecord that keeps things like Reports and Aliases?