Is on_delete=models.CASCADE representing composition and models.PROTECT aggregation?
Since one of the main differences between aggregation and composition is that with composition if the composed class is deleted, all the objects of the componing classes are delated by consequence, and since this doesn't happen with aggregation, is the statement above correct?
Both CASCADE and PROTECT represent composition, since both imply that the child object cannot exist if the parent object is deleted. PROTECT prevents you from deleting the parent if a child object exists and as you said CASCADE will delete all child objects
SET_NULL, SET_DEFAULT and SET represent aggregation since in each case the "child" model object can continue existing when the parent is deleted
Related
Consider two EObjects, both created through some factory method
EObject parent = instantiateAParent();
EObject child = instantiateAChild();
I want child's parent to be parent. Is this possible to do this without relying on the exact type of child and parent? If yes, how?
Yes this is possible. What you want to do is the following:
Retrieve the type (in the Ecore sense) of the parent (parent.eClass())
Find all its EReferences with isContainment to true (eClass.getEAllContainments())
Among these containment references, you want to find at least one whose type is compatible with the type of child (eReference.getEReferenceType().isInstance(child))
Since you may have several containment references at this point, you may use any algorithm to select one (maybe asking the user, etc.)
Set the value of the reference you chose (parent.eSet(eReference, child)). Note that if the containment reference you chose is single-valued, this may have a significant impact on your model.
Is there any way to convert a parent object to one of its child objects such that the object retains the same old information (including the old key). I have implemented concrete inheritance. Thanks.
Definitions
SOFT DELETE - does not remove an object from the database, but appears to do so
HARD DELETE - removes the object completely from the database
Question
What is the best way to implement soft deletion in a codebase (specifically, a Django project)?
The simplest method I think would be to simply add:
is_deleted = models.BooleanField(default=False)
to a superclass which implements a softDeleteObject, and then override delete() to set the appropriate flags on the objects in question. Related objects would also need to inherit from the same superclass.
An alternative would be instead to delete the original, and have what amounts to an Archive object which is a representation of the deleted objects.
Analysis
The first appears to have a greater degree of simplicity, but does require some wide-ranging overrides - for example, User would have to be overridden to ensure that the foreign key relations of all deleted objects still held, and that deleting a User then didn't hard delete all their soft-deleted objects.
The second could be implemented with pre_delete signals which trigger creation of the surrogate objects. This again has some advantages (don't need to override all the delete() methods), but does require the implementation of archived versions of the models used in the project.
Which is preferable, and are there other alternatives?
Why not to use active/deleted/status flags on the specific models where it is needed and do it this way? Or check the app django-reversion, there is probably everything you will need ;)
If a class contains pointer to a singleton class, can it beaggregation?
To my understanding it cannot be a has-a relationship since the class does not make an instance of the singleton class, it is just using it like association relationship.
The title doesn't make 100% complete sense as written. There are singleton classes, but there aren't really singleton relationships. Any relationship can be assigned a multiplicity at either end, so if you mean one-to-one relationships, all you do is assign multiplicity 1 at both ends.
Classes can also have multiplicities. You don't often see this used, except in one case: singletons.
When it comes to A having or containing or referencing B, there are basically three levels of tightness in UML.
Aggregation (unfilled rhomboid arrow head) implies that the containment is not exclusive and that the contained object does not share any aspect of its lifecycle with the containing object. In implementation, this is typically a pointer.
Composition (filled rhomboid arrow head) implies that the contained object gets destroyed when the containing object does. Getting this to work usually means that the containment is exclusive. In implementation, this is often a pointer whose destructor is called in the destructor of the containing class (although it may not be created in the constructor of the containing class).
Directed association or member attribute (same thing in UML) implies that the contained object is part of the state, or a constituent if you will, of the containing object. In implementation, this typically means that the reference is not a pointer, or if it is that the contained object is co-created and -destroyed with the containing object.
Aggregation of a singleton is perfectly permissible (even from several different classes), because aggregation is by definition non-exclusive.
Composition is a bit iffy, unless the containing class is also a singleton.
Attribute / directed association is most likely wrong. If the containing class is a singleton, it doesn't make any sense to make the contained class a singleton as well since that's implied. And if the contained class is used as a member in two different classes, it cannot be a singleton.
In addition to the above, you can also of course add as many Usage relationships as you wish. This is common in all design, and implies that the class at the source end of the relationship calls methods in the class at the target end.
I would say, technically, yes, you can have a member variable that is a pointer to a singleton object and call it aggregation; using the aggregation term doesn't have much meaning once you write the code though. For all intents and purposes, it is just an association.
However, the use of an aggregation association in a diagram may or may not help a viewer of the diagram to comprehend it. That probably depends on who you are going to show it to and what they might understand aggregation to mean.
To actually answer the question in the title (using info from The UML User Guide (2nd Edition):
______________________ ______________________
| | | 1|
| AggregatingClass | | SingletonClass |
|____________________| 0..1|____________________|
| |<>--------| |
|____________________| |____________________|
| | | |
|____________________| |____________________|
(Note the 1 in the upper right hand corner of the singleton class box indicating cardinality.)
There is also an aggregation with an open square instead of a filled.
The open means the first instance does not make the other (but still has a has-a relationship).
You could pretend that it is aggregation, but truth of it is this: singletons have nothing to do with object oriented code. They are a form of global state (just like global variables are).
You might want to consider a different approach to the problem.
P.S some materials that could help:
Global State and Singletons
Don't Look For Things!
When I use multi-table inheritance, Django creates two tables - one for the base class, and one for the derived one, pointing to the first. Is there a way to keep the base table entry while deleting the derived one, and create another entry for another model?
To put it simpler: I have models: A, B(derived from A), C(derived from A). I want to convert an object of type B to type C. Copying is not a good solution because A serves as a set of items, so items point to it with a ForeignKey.
There is no built-in way to do this. If you need to preserve the entry in the base table because FKs are pointing to it, you'll have to write some manager methods to manipulate the B and C tables using raw SQL.
If you're using an RDBMS that doesn't support referential integrity, you might be able to just copy the data, delete the B instance, and create the C instance with the PK manually set to B's PK.
If there's no built-in way, then I think doing it manually is not so bad - make c a copy of b, then do b.items.update(itemset=c).