When I generate code from StructureDefinitions, it would be obvious to use the class for the resource referenced in base as superclass.
A resource that is based on another resource can change the the type of a property of the base resource (for example from String to List<String> if max="0" is overridden by max="*").
This would break in strongly typed languages because a subclass has to conform to the interface of the super class (can only specialize but not generalize).
What would be the correct strategy to deal with that?
I can use snapshot instead of differential and not extend the class of the base resource.
Should I still extend one of the more general super classes like Element, BackboneElement, Resource, DomainResource?
Are there any flaws in my reasoning?
Resources can't "extend" other resources. If the base resource has a cardinality for an element of 1..1, the derived model can't change the lower cardinality below 1, nor the upper cardinality above 1.
The primary way of "extending" a resource is to make use of the "extension" element which is defined as being 0..* pretty much everywhere in the base resources. So technically when you're creating a profile, you're always constraining - either tightening down core elements or constraining expectations for at least some of the repetitions of the "extension" element.
You can find more information about allowed cardinality changes here
Related
As updating business network could break your APIs and You may not able to fetch old data. We are looking for generic guidelines about what we should take care before updating business network and deploying using composer.
We will include this into the docs for the release next week...
Model Compatability
Introduction
Composer models are expected to change and evolve over time. However some care and discipline must be applied when making model changes to ensure that existing instances are still valid with respect to the new model.
A model M' is compatible with model M if instances created with model M are valid with respect to model M'. If the instances are valid, then they may be deserialized using the Serializer.
Terminology
The following terms are used throughout this document:
Class : the declaration of the structure of an asset, participant, transaction, concept or event
Instance : an instance of a class, for example if org.example.Vehicle is an asset (class), then org.example.Vehicle#ABC123 is an instance of an org.acme.Vehicle
Property : a member (or field) defined by a class, including a relationship. For example the class org.example.Vehicle may have a property called model of type string.
A class (the asset SampleAsset):
```
namespace org.acme.sample
asset SampleAsset identified by assetId {
o String assetId
--> SampleParticipant owner
o String value
}
```
An instance of the class:
{
"$class": "org.acme.sample.SampleAsset",
"assetId": "assetId:6463",
"owner": "resource:org.acme.sample.SampleParticipant#participantId:8091",
"value": "secret plant frequently ruler"
}
Evolution of Namespaces
A new class may be added to a namespace without breaking compatibility with pre-existing instances.
Evolution of Classes
This section describes the effects of changes to the declaration of a class and its properties on pre-existing instances.
Renaming
Renaming a class will break compatability with any pre-existing instances of the class, or relationships to the class.
abstract Classes
If a class that was not declared abstract is changed to be declared abstract, then attempts to create new instances of that class will throw an error at runtime; such a change is therefore not recommended for widely distributed classes.
Changing a class that is declared abstract to no longer be declared abstract does not break compatibility with pre-existing instances.
Superclasses
An error is thrown at load time if a class would be a superclass of itself. Changes to the class hierarchy that could result in such a circularity when instances are loaded are not recommended for widely distributed classes.
Changing the direct superclass of a class type will not break compatibility with pre-existing instances, provided that the total set of superclasses of the class type loses no properties.
If a change to the direct superclass results in any class no longer being a superclass respectively, then errors may result if pre-existing instances have relationships to the modified class. Such changes are not recommended for widely distributed classes.
Class Properties
No incompatibility with pre-existing instances is caused by adding a property to a class if the property is either declared as optional or is assigned a default value. Adding new properties that are neither optional nor have a default will break compatability with any pre-existing instances of the class.
Changing the cardinality of a property (changing an array [] to a non-array or vice-a-versa) will break compatability with any pre-existing instances of the class.
Deleting a property from a class will break compatibility with any pre-existing instances that reference this field.
Changing the type of a property may cause an error if the property is used by a pre-existing instance.
Changing the validation expression of a property may cause an error if the property is used by a pre-existing instance.
Properties that are relationships follow the same rules as for other types.
Evolution of Enums
Adding or reordering constants in an enum type will not break compatibility with pre-existing instances.
If a pre-existing instance attempts to access an enum constant that no longer exists, an error will occur. Therefore such a change is not recommended for widely distributed enums.
In all other respects, the model evolutions rules for enums are identical to those for classes.
Problem:
We know that Java doesn’t allow to extend multiple classes because it would result in the Diamond Problem where the compiler could’t decide which superclass method to use. With interface default methods the Diamond Problem were introduction in Java 8. That is, because if a class implements two interfaces, each defining the same default method, and the implementing class doesn’t override the common default method, the compiler couldn’t decide which implementation to chose.
Solution:
Java 8 requires to provide an implementation for default methods implemented by more than one interface. So if a class would implement both interfaces mentioned above, it would have to provide an implementation for the common default method. Otherwise the compiler would throw a compile time error.
Question:
Why is this solution not applicable for multiple class inheritance, by overriding common methods introduced by child class?
You didn’t understand the Diamond Problem correctly (and granted, the current state of the Wikipedia article doesn’t explain it sufficiently). As shown in this graphic,
the diamond problem occurs, when the same class is inherited multiple times through different inheritance paths. This isn’t a problem for interfaces (and never was), as they only define a contract and specifying the same contract multiple times makes no difference.
The main problem is not associated with the methods but the data of that super type. Should the instance state of A exist once or twice in that case? If once, C and B can have different, conflicting constraints on A’s instance state. Both classes might also assume to have full control over A’s state, i.e. not consider that other class having the same access level. If having two different A states, a widening conversion of a D reference to an A reference becomes ambiguous, as either A could be meant.
Interfaces don’t have these problems, as they do not carry instance data at all. They also have (almost) no accessibility issues as their methods are always public. Allowing default methods, doesn’t change this, as default methods still don’t access instance variables but operate with the interface methods only.
Of course, there is the possibility that B and C declared default methods with identical signature, causing an ambiguity that has to be resolved in D. But this is even the case, when there is no A, i.e. no “diamond” at all. So this scenario is not a correct example of the “Diamond Problem”.
Methods introduced by interfaces may always be overriden, while methods introduced by classes could be final. This is one reason why you potentially couldn't apply the same strategy for classes as you could for interfaces.
The conflict described as "diamond problem" can best be illustrated using a polymorphic call to method A.m() where the runtime type of the receiver has type D: Imagine D inherits two different methods both claiming to play the role of A.m() (one of them could be the original method A.m(), at least one of them is an override). Now, dynamic dispatch cannot decide which of the conflicting methods to invoke.
Aside: the distinction betwee the "diamond problem" and regular name clashes is particularly relevant in languages like Eiffel, where the conflict could be locally resolved for the perspective of type D, e.g., by renaming one method. This would avoid the name clash for invocations with static type D, but not for invocations with static type A.
Now, with default methods in Java 8, JLS was amended with rules that detect any such conflicts, requiring D to resolve the conflict (many different cases exist, depending on whether or not some of the types involved are classes). I.e., the diamond problem is not "solved" in Java 8, it is just avoided by rejecting any programs that would produce it.
In theory, similar rules could have been defined in Java 1 to admit multiple inheritance for classes. It's just a decision that was made early on, that the designers of Java did not want to support multiple inheritance.
The choice to admit multiple (implementation) inheritance for default methods but not for class methods is a purely pragmatic choice, not necessitated by any theory.
Is both term override and rewrite are same in Magento. I have searched alot for this but not found any answer.
Thanks
Short answer: yes, though it depends on who you talk to.
All rewrites are overrides, but not all overrides are rewrites. A rewrite in Magento should only refer to a configuration-based class overrides. Factory methods are used by the framework to instantiate the MVC types:
Mage_Core_Model_Layout->createBlock()
Mage::helper()
Mage::getModel()
Mage::getResourceModel()
etc....
These methods generally match a class group (e.g. catalog) to a class prefix (e.g. Mage_Catalog_Model) in order to instantiate a particular class (e.g. Mage::getModel('catalog/product') yields Mage_Catalog_Model_Product). This mapping allows for developers to specify a certain xpath associated with the class argument (e.g. 'catalog/product' & global/models/catalog/rewrite/product) to specify an alternate class to instantiate. From there it's the responsibility of the developer to use inheritance as appropriate to achieve the proper overriding & extending behavior.
There are other mechanisms for achieving overrides, the most common of which is the so-called "include path hack", which allows for classes from "lower" autoload directories to be (re)defined in higher-level directories in the following order of precedence (note that app/code/local/):
app/code/community/
app/code/core/
lib/
This style of override should be considered a last-case means of changing core code. It has legitimate use cases (especially for obeying DRY), but may be non-obvious in an upgrade.
In the book The Well Grounded Rubyist (excerpt), David Black talks about the "Class/Object Chicken-and-Egg Paradox". I'm having a tough time understanding the entire concept.
Can someone explain it in better/easier/analogical/other terms?
Quote (emphasis mine):
The class Class is an instance of itself; that is, it’s a Class
object. And there’s more. Remember the class Object? Well, Object
is a class... but classes are objects. So, Object is an object. And
Class is a class. And Object is a class, and Class is an object.
Which came first? How can the class Class be created unless the
class Object already exists? But how can there be a class Object
(or any other class) until there’s a class Class of which there can
be instances?
The best way to deal with this paradox, at least for now, is to ignore
it. Ruby has to do some of this chicken-or-egg stuff in order to get
the class and object system up and running—and then, the circularity
and paradoxes don’t matter. In the course of programming, you just
need to know that classes are objects, instances of the class called
Class.
(If you want to know in brief how it works, it’s like this: every
object has an internal record of what class it’s an instance of, and
the internal record inside the object Class points back to Class.)
You can see the problem in this diagram:
(source: phrogz.net)
All object instances inherit from Object. All classes are objects, and Class is a class, therefore Class is an object. However, object instances inherit from their class, and Object is an instance of the Class class, therefore Object itself gets methods from Class.
As you can see in the diagram, however, there isn't a circular lookup loop, because there are two different inheritance 'parts' to every class: the instance methods and the 'class' methods. In the end, the lookup path is sane.
N.B.: This diagram reflects Ruby 1.8, and thus does not include the core BasicObject class introduced in Ruby 1.9.
In practical terms, all you need to understand is that Object is the mother of all classes. All classes extend Object. It is this relationship that you will use in programming, understanding inheritance and so forth.
Eg; You can call hash() on any instance of any object at any time? Why? Because that function appears in the Object class, and all classes inherit that function, because all classes extend Object.
As far as the idea of Class goes, this comes up much less frequently. An object of class Class is like a blueprint, it's like having the class in your hands, without creating an instance of it. There's a little more to it, but it's a difficult one to describe without a lengthy example. Rest assured, when (if ever) the time comes to use it, you'll see it's purpose.
All this excerpt is saying is that Object has a class of type Class and Class is an object, so must extend Object. Its cyclic, but it's irrelevant. The answer is buried somewhere in the compiler.
Regarding the which-came-first criterion, there are two kinds of Ruby objects:
Built-in objects. They exist at the start of a Ruby program and can be considered to have zero creation time.
User created objects. They are created after the program starts via object creation methods (new/clone/dup, class-definition, module-definition, literal-constructs, ...). Such objects are linearly ordered by their time of creation. This order happens to inversely correspond to class-inheritance and instance-of relations.
A detailed explanation of the Ruby object model is available at www.atalon.cz.
I know that my answer comes at least 3 years late, but I have learned about Ruby quite recently and I must admit that the literature sometimes presents (in my opinion) misleading explanations, even though one is handling a very simple problem. Moreover, I am (and was) surprised by such appalling phrases as:
"The best way to deal with this paradox, at least for now, is to ignore it."
stated by the author D. Black, and quoted in the question, but this attitude seems to be pervasive. I have experienced this tendency within the physics community but I have not suspected it had also spread through the programming one. I am not stating that nobody understands what is lurking behind, but it seems at least intriguing why not providing the (indeed) very simple and precise answer, as in this case there is one, without invoking any obscure words such as "paradox" within the explanation.
This so-called "paradox" (even though it is definitely NOT such thing) comes from the (at least misleading) belief that "being an instance of (a subclass of)" should be something as "being an element of" (in, say, naive set theory), or in other terms, a class (in Ruby) is the set containing all the objects sharing some common property (for instance, under this naive interpretation the class String includes all the string objects). Even though this naive point of view (which I may call the "membership interpretation") may help understanding isolated (and rather easy) classes such as String or Symbol, it indeed PRODUCES A CLEAR CONTRADICTION with our naive understanding (and also the axiomatic one, for it contradicts Von Neumann's regularity axiom of set theory, if someone knows what I am talking about) of the membership relationship, for an object could not be an element of itself, as the previous interpretation implies when regarding the object Class.
The previously stated problem is easily avoided if one gets rid of such misleading membership interpretation with a very simply minded model as follows.
I would have guess that my following explanation is well-known by the experts, so I claim no originality at all, but perhaps it was not rephrased in the (simple) terms I am going to present it: in some sense I am completely astonished that (apparently) nobody stated in these terms from the very beginning, and my intention is just to highlight what I believe is the basic underlying structure.
Let us consider a set O of (basic) objects, which consists of all the (basic) objects Ruby has, provided with a mapping f from O to O (which is more or less the .class method), satisfying that the image of the composition of f with itself has only one element.
This latter element (or object) is denoted Class (indeed, what you know to be the class Class).
I would be tempted to write this post using LaTeX code but I am not quite sure if it will be parsed and converted into typical math expressions.
The image of the mapping f is (by definition) the set of Ruby classes (e.g. String, Object, Symbol, Class, etc).
Ruby programmers (even though if they do not know it) interpret the previous construction as follows: we say that an object "x is an instance of y" if and only if y = f(x). By the way this tells us you exactly that Class is an instance of Class (i.e. of itself).
Now, we would need much more decorations to this simple model in order to get the full Ruby hierarchy of classes and functionality (imposing the existence of some fixed members on the image of the map f, a partial order on the image of the map f in order to define subclasses to get afterwards inheritance, etc), and in particular to get the nice picture that was interestingly upvoted, but I suppose that everybody can figure this out from the primitive model I gave (I have written some pages explaining this for myself, after having read several Ruby manuals. I may provide a copy if anybody finds it useful).
Which came first: The class Class or the class Object?
Every class is an instance of the class Class. It follows that the class Object is an instance of the class Class. So you need the class Class to create the class Object. Therefore:
The class Class exists before the class Object.
The class Class is a subclass of the class Object. So you need the class Object from which the class Class can be created. Therefore:
The class Object exists before the class Class.
So statement-2 conflicts with statement-1 and so we have our chicken & egg dilemma. Or you can just accept it as a circular definition!
I have done a dig into the source code of Ruby and created this post on how to make sense of it.
If a method takes a class/struct as an input parameter, what is the best way to name it?
Example:
class Person{}
class Address{}
class Utility{
//name **style 1** - use method overloading
public void Save(Person p){}
public void Save(Address a){}
*//name **style 2** - use unique names that define what they are doing
//or public void SavePerson(Person p){}
//and public void SaveAddress(Address a){}*
}
I personally like style 1 (Use the languages features - in this case overloading).
If you like style 1, can you point me to any "official" documentation, that states this to be a standard?
I would say your challenge is not in the field of method naming, but rather type design. A type that is responsible for saving both Person objects and Address objects seems like a type with more than one responsibility. Such a type will tend to grow and grow and grow and will eventually get hard to maintain. If you instead create more specialized types, method naming may automatically become a simpler task.
If you would still want to collect these methods in the same type, it's mostly a matter of style. One thing to perhaps think about is whether this type may be consumed by code written in another language, and that does not support method overloading. In such cases the longer names is the way to go. Otherwise just stick to what feels best (or whatever is the ruling convention at your workplace).
It is a matter of style.
If you don't like long method names, go with 1.
If you don't like long overload lists, go with 2.
The important bit is to keep consistent, so do not mix the two styles in one project.
If you are seeing that you have many such methods, you may need to rethink your design - perhaps a solution involving inheritance would be more appropriate.
Distinct names avoid entirely any problems associated with method overloading. For example:
Ambiguity is avoided if an argument's type matches more than one of the candidates.
In C++, overloaded methods can hide those of the same name in a superclass.
In Java, type erasure prevents overloaded methods differing only by type parameterization.
It would also be worthwhile to ask whether polymorphism could be used instead of overloading.