Association names on ends without navigability? - associations

I have a question regarding UML Class diagrams.
I know I can just use one name which refers to both sides but my question is:
Is it necessary to show association names at both sides of an association when it is uni directional?

Association ends are properties (i.e., "variables"). When a class owns a property and the property is unnamed, that could be a problem. In contrast, when an association owns an unnamed property, that's not really a problem. You don't need to specify a name for association-owned properties.
Here's an example. I've made MagicDraw show association-end properties as attributes as well, just to make a point:
Notice how theB shows up as a property in class A and at the end of the association with class B. That's because they are two different ways of showing the same property. (It's a special way of showing association-end properties that we normally don't turn on in the tool.) Also notice how class C has an unnamed property inside the box and at the end of the association with class A. Again, that's two different ways to show the same property. How would you implement that unnamed property in a programming language? That could be a problem, right?
Another thing to notice is that class B does not have an attribute called theA, and class A does not have an attribute called theC. That's because those properties are non-navigable and the associations own those properties.
Conflating navigability and property ownership has become deprecated in UML. Recently, the UML spec introduced "association dot notation" to indicate property ownership. (A dot at the end means the class owns the property.) Personally, I never had a problem with the conflation, and I hate the new dot notation. Many tools do not support it, and I think it's downright ugly. Moreover, a diagram that has no dots on it is ambiguous. You can't tell whether it was drawn before or after dots were introduced to the spec!

Related

Write OCL restrictions related to associations with other classes

How do you model the following restriction?
A place is popular if it has been bookmarked by 2 or more than 2 users.
Here the corresponding uml diagram:
uml
I tried several ways, for example:
context place inv: place.popular = (self.user.place.popular>=2)
but nothing worked well...
The constraint that you expressed is an interesting start but does not work because self.user in the place context is a collection. Your expression moreover attempts to use popular as if it were an integer.
If there would be an unambiguous user, you’d just need to check its size():
context place inv:
place.popular = (self.user->size()>1)
Unfortunately, there are two associations with User: one for the favorites (bookmarks) and for for historic (past visits whether they appreciated or not). This makes that expression ambiguous. To disambiguate, in absence of a role name (name at the association end), you’ll need to qualify the user with the association name:
context place inv:
place.popular = (self.favorites::user->size()>1)
(Btw, in case of absence of association name, you'd need to use the default name A_place_user instead of favorites).
See also section 7.5.3 of the OCL specifications for more information about navigating associations.
Edit: more complex navigations**:
You could also navigate to properties of associated classes. It works like the navigation above, but with the help of the collect() operation. You can then perform collection oprations such as sum()
context route inv:
self.totalDistance = self.step->collect(distanceFromPreviousStep)->sum()
Navigating to a specific object in a collection of linked objects is more delicate. In the case of the steps, we see that the association is ordered (by the way, it should be {ordered} and not «ordered»). This allows to use last() to get the last element in the given order:
context route inv:
self.destination::place = self.step->last().place

Symfony: adding a block-prefix for an abstract custom type

I have a custom type that is abstract.
As it seems that leads to it not getting its own block_prefix in the hierarchy.
So I thought I would put that into configureOptions.
But in the deriving classes I do occassionally also have to define configureOptions which then again leads to either overwriting the parent method which defeats the purpose. Or if I call it explicitly
with parent::configureOptions the system will put the custom prefix above (in the sense of "higher priority") the automatically generated prefix of the implementing class which I obviously do not want.
Is there a solution to this problem that is not "make the parent class not abstract"?
I say that because if possible I don't want to loose the enforcement of the contract given by the abstract parent-class.
EDIT: I realized that it was a false assumption I made that making the base class non-abstract would lead to the addition of the class name as block-prefix.

What are differences between PageList, ValueList and Code-Pega-List?

I run into a question about differences between PageList/ValueList and Code-Pega-List.
I know that
1) ValueList is a group of elementary type elements, which has unique index.
2) PageList is an indexed group of complex elements.
But what about class Code-Pega-List? Where I am allowed to utilize it?
When I was researching that question, I found out, that PageList or ValueList property cannot be passed as parameter where is awaited Code-Pega-List type property.
Thank you.
Firstly, Page List and ValueList is property types such as for example Page, Single Property, Page Group, etc. You can create property any type applies to any class, for example #baseclass.
Code-Pega-List is class. Class consist of several properties any types (Page, Page List, etc.). You can open class Code-Pega-List in application explorer and see it.
Code-Pega-List is a core class for Pega Platform. Many rules used it, such as methods in activity rule (Obj-Browse), report definition rule, etc. This class contains standard logic, for example count of elements in page-list contain in property .pxResults. I think that my answer help you understand difference.

Multiple "default" properties/methods in a VB6 class?

I am trying to make a replacement VB6 class for the Scripting.Dictionary class from SCRRUN.DLL. Scripting.Dictionary has (among other things) a "Keys" method that returns an array of keys, and a read/write "Item" property that returns the item associated with a key. I am confused about this, because both of them seem to be defaults for the class. That is:
For Each X In MyDict
Is equivalent to:
For Each X In MyDict.Keys
Which to me implies that "Keys" is the default operation for the class, but:
MyDict("MyKey") = "MyValue"
MsgBox MyDict("MyKey")
Is equivalent to:
MyDict.Item("MyKey") = "MyValue"
MsgBox MyDict.Item("MyKey")
Which to me implies that "Item" is the default operation for the class.
I've never before created a VB6 class that had a default operation, so upon realizing this, I thought perhaps I could define multiple default operations as long as they all have different signatures, which they do: Keys is nullary, the Item getter takes a Variant, and the Item setter takes two Variants. But this doesn't seem to be allowed: When I use "Tools/Procedure Attributes" to set the Keys function to be the default, and then I use it to set the Item property to be the default, the IDE complains that a default has already been set.
So I think I'm misunderstanding something fundamental here. What is going on in the Scripting.Dictionary object that makes it able to act as if "Keys" is the default in some contexts, but as if "Item" is the default in others? And whatever it is, can I accomplish the same thing in VB6?
OK, answering my own question: I haven't tried this yet, but I gather that "Item" should be made the default, and that I should add an entirely new function called "NewEnum" that looks something like the following (slightly modified from an example in Francesco Balena's "Programming Microsoft Visual Basic 6.0" book):
Public Function NewEnum() As IUnknown
Set NewEnum = m_Keys.[_NewEnum]
End Function
(where "m_Keys" is a Collection containing the keys), and then use Tools/Procedure Attributes to hide NewEnum and to set its ProcID to -4.
What you are observing is the difference between the default member and a collection enumerator. A COM object (including VB6 classes) can have both.
You can identify the default property of a class by looking in the Object Browser for the tiny blue globe or the words "default member of" in the description (see Contents of the Object Browser). The Object Browser will not identify an enumerator method, but if you look at the class's interface definition using OLE View or TypeLib Browser (free but registration required) it's DispId will be 0xfffffffc or -4.
In your own class, you can mark the default property by setting the Procedure ID to "(default)" in the Procedure Attributes dialog (see Making a Property or Method the Default). You already listed the steps for setting up the collection enumerator in your own answer, but you can find this listed as well in the Programmer's Guide topic Creating Your Own Collection Class: The House of Bricks.
Scripting.Dictionary has a dirty secret:
It does not handle enumeration at all, it returns big ugly Variant arrays and your For Each loops iterate over those.
This is one of the reasons why a Dictionary can actually be far less efficient than a standard VB6 Collection.

Understanding the use of Interfaces and Base Classes

I know there are a number of post out there on Interfaces and Base classes, but I'm having a hard time getting the correct design pattern understanding.
If I were to write a reporting class, my initial though would be to create an interface with the core properties, methods, etc. that all reports will implement.
For example:
Public Interface IReportSales
Property Sales() As List(Of Sales)
Property ItemTotalSales() As Decimal
End Interface
Public Interface IReportProducts
Property Productss() As List(Of Inventory)
Property ProductsTotal() As Decimal
End Interface
Then I assume I would have a class to implement the interface:
Public Class MyReport
Implements IReportSales
Public Property Sales() As System.Collections.Generic.List(Of Decimal) Implements IReportItem.Sales
Get
Return Sales
End Get
Set(ByVal value As System.Collections.Generic.List(Of Decimal))
Items = value
End Set
End Property
Public Function ItemTotalSales() As Decimal Implements IReport.ItemTotalSales
Dim total As Decimal = 0.0
For Each item In Me.Sales
total = total + item
Next
End Function
End Class
My thought was that it should be an interface because other reports may not use "Items", this way I can implement the objects that are used for a given report class.
Am I way off? should I have still have just created a base class? My logic behind not creating a base class was that not all report classes may use "Items" so I didn't want to define them where they are not being used.
To attempt to answer you question, abstract classes are used to provide a common ancestor for related classes. An example of this in the .Net API is TextWriter. This class provides a common ancestor all various classes whose purpose is to write text in some fashion.
Interfaces are more properly used to act as adapters for different objects that don't belong in the same "family" of objects but have similar capabilities. A good example of this can be seen with the various collections in the .Net API.
For example, the List and Dictionary classes provide the ability for you to manage a collection of objects. They do not share a common ancestor by inheritance, this wouldn't make sense. In order to allow easy interop between them though, they implement some of the same interfaces.
Both classes implement IEnumerable. This cleanly allows you use objects of either type List or Dictionary as an operand for anything that requires an IEnumerable. How wonderful!
So now in your case in designing new software you want to think about how this would fit into your problem space. If you give these classes a common ancestor via inheritance of an abstract class you have to be sure that all the items that inherit from it are truly of the base type. (A StreamWriter is a TextWriter, for example). Inappropriate use of class inheritance can make your API very difficult to build and modify in the future.
Let's say you make an abstract class, ReportBase, for your repots. It may contain a few very generic methods that all reports simply must have. Perhaps it simply specifies the method Run()
You then only have one type of report you want to make so you define a concrete Report class that inherits from ReportBase. Everything is great. Then you find out you need to add several more types of reports, XReport, YReport, and ZReport for sake of example. It doesn't really matter what they are, but they work differently and have different requirements. All of the reports generate pretty HTML output and everyone is happy.
Next week your client says they want XReport and YReport to be able to output PDF documents as well. Now there are many ways to solve this, but obviously adding an OutputPdf method to your abstract class is a poor idea, as some of those reports shouldn't or can't support this behavior!
Now this is where interfaces could be useful to you. Let's say you define a few interfaces IHtmlReport and IPdfReport. Now the report classes that are supposed to support these various output types can implement those interfaces. This will then let you create a function such as CreatePdfReports(IEnumerable<IPdfReport> reports) that can take all reports that implement IPdfReport and do whatever it needs to do with them without caring what the appropriate base type is.
Hopefully this helps, I was kind of shooting from the hip here as I'm not familiar with the problem you're trying to solve.
Yes, if you don't know how many reports are not going to use Items , you can go for Abastract class.
Another good thought follows:
You can also create both Interface and Abstract class
Define Sales in Interface , create two abstract classes , one for Reports that implement both and another for Report not implementing Sales. Implement interface for both
define both method (implement sales) in first and only implement sales in second.
Give appropriate names to both Abstract classes e.g. ReportWithItemsBase or ReportWithoutItemsBase.
This way you can also achieve self explaining named base classes on deriving Report classes as well.

Resources