REST seems to focus most on collections of resources -- lists of things. How should one model something that exists exactly once in a system? And more specifically something very simple. Suppose the modeled system is a classroom, which has students, 1 teacher, and a door that is either open or closed. How would one model the door? I'm thinking it would be something like the following:
GET and POST operations are supported.
GET https://<ipaddress>/classroom/door_status
Returns 200 if successful, with a response containing:
DoorStatus - String - Value of door status, either "Open" or "Closed"
POST https://<ipaddress>/classroom/door_status
Specify the attribute of:
DoorStatus - String - Value of desired door status, "Open" or "Closed"
Returns 201 if the status was successfully modified.
DELETE would always fail.
A classroom could of course have multiple doors, but bear with me for the moment. And of course a building with classrooms often has multiple classrooms. Again bear with me.
Next, we might add a light_status resource for the classroom. Given this is likely, should we start with a "global_properties" resource, which would have DoorStatus and LightStatus properties instead.
Thanks for suggestions, help, or (especially) examples. ...Alan
I don't think there is anything in REST that makes single instance entities illegal or undesirable. That said, in your particular example, you need to evaluate if the door and the light:
Are their own entities related but otherwise independent from the class, OR
Are just attributes or contained objects of the class without their own identity and whose existence depends on the existence of the class
the second option is the one that seems more reasonable to me. If we accept it, then you can return the light and door status as part of the class properties:
GET /class -- Returns the class attributes, including light and door status
PUT /class -- updates class attributes, including light and door status
Related
I am currently learning to create uml diagram, especially class diagram and have some multiple difficulties understanding some concept in the process, here is the question
Does multiplicity always 2 sided? like when i have this classes, PP class is the buyer Class, and Cart is the class to save the buyer order info, i assign 1 - 1 multiplicity because 1 buyer would always have 1 cart vice versa, in Cart it is clearly defined (in my code) that i have a variable with type PP, but inside class PP there is no cart variable at all, so does the multiplicity wrong? should i just assign 1 sided multiplicity in PP and have none in Cart? or does having the variable inside class is not important? i am quite confused on understanding this
About dependency relationship, if i have this PP class which have variable shippingAddress inside the class and using data type ShippingAddress as parameter in some of the function, should i used dependency relationship or association
Thanks a lot
qwerty_so already provided a concise and accurate answer. Nevertheless, I'd like to add some more thoughts to complete the picture.
1
In an association there are always at least 2 sides, and there is a multiplicity on each side: The first diagram says that a PP always has 1 Cart and the Cart always 1 PP. If you meant "sometimes" instead of always, change it to 0..1
There can be more than 2 sides in an n-ary association: Then you'll have n multiplicities.
WHen in a diagram there is no multiplicity indicated on one side, it doesn't mean that there is no multiplicity, but that we don't know what the multipliity is (or that it's not important for what we want to show in the diagram).
Now your question about multiplicity and how to implement it raises another topic:
it is clearly defined (in my code) that i have a variable with type PP, but inside class PP there is no cart variable at all, so does the multiplicity wrong?
It's the question of navigability: If in the implementation of Cart you have a PP variable, this means that you can easily navigate from the a given Cart to the associated PP. If you don't have a Cart variable in the PP implementation, it is difficult to find the corresponding Cart, so it's not navigable. Navigability is shown with an open arrow.
Multiplicity and navigability are two orthogonal concepts.
2
If you have both a dependency and an association, you'd usually show the association. There is no need to also show the dependency, since it is implied by the association. However it's not wrong if you want to show both (but with a dashed line and open arrow) (for example, if you want to add some explanatory comments for each).
Now if in the PP implementation you have a ShippingAddress, it's not only a question of navigability, but it's also a question of ownership of the association end. So you can use the dot notation on the side of the ShippingAddress.
If you don't have an association, but use another class as parameter or return type of an operation, then you may want to show s simpe «use» dependency.
Multiplicity is defined where needed. If it's not given then it's undefined and could be anything from zero to infinity. It depends whether you define that. One reason is simplicity, if you want to just show "it's associated". For a complete model (if that is needed) you have to specify multiplicities at all edges.
Dependency is just a weak relation. If you use some class only in parameters or as pass-through you use a dependency relation. Your 2nd picture would be wrong as you should draw the dependency (dashed line with open arrow) downwards since PP uses/depends on ShippingAddress and not the other way around.
If I have a Cat and Dog class that implement PetBase. And they each hold an object called Owner. And Owner holds an object called Emotion. How would I limit accessing certain properties or functions or function parameters on the Emotion class based on whether it belongs to a Cat or Dog? Like so:
Dog d = new Dog();
d.Owner.Emotion.SetFearLevel(10); // dog owners can have a fear level from 1-10 so let the user decide.
Cat c = new Cat();
c.Owner.Emotion.SetFearLevel(); // all cat owners have the same fear level so I don't want the user to be able to pass in a parameter but still be able to call SetFearLevel(). How do I enforce this?
In this example, I want to restrict the Cat owners from being able to pass in a parameter to SetFearLevel(), but give the Dog owners the flexibility to be as afraid as they want (ie. be able to pass in a parameter to SetFearLevel()).
What do I have to change in the design?
[EDIT]
It was a toss up between Jordao's and DavidFrancis's answers. In the end, I went with DavidFrancis's design due to the tree structure nature of the app.
SetFearLevel is a different signature so you need 2 different subtypes of a base Emotion type.
Then you would need a separate owner subtype for each pet type.
Return types can usually be Covariant (ie a subtype) so each owner subtype can return the specific Emotion subtype that applies to that owner.
You could encapsulate the access to the functionality that you need in the classes themselves:
dog.setOwnerFearLevel(5);
cat.setOwnerFear();
Just be careful with Demeter transmogrifiers.
Your linkages are the wrong way around. You want to start with owner.SetFearLevel(5). Owner owner has to know about his/her own pet and his/her own emotions. Hence the method can check, "Do I own a cat or a dog?" and then set it's emotion instance properly: "I am not afraid dispite that parameter of 5 (because I own a cat)." Or to put it another way, the owner references the pet, not the pet the owner.
To see this more clearly, note that your model easily allows one person to own any number of dogs and cats. You can always create a new pet and make this hapless person the owner. This can be useful, but it makes calculating his/her fear level rather complicated. In a sense, it's almost impossible, because, while for any given pet you know the owner, given any owner you don't know the pet. (An easily fixed problem, I admit.)
So, reference the pet (or pets--maybe use the maximum fear factor) in the Owner class and move the SetFearLevel method to the Owner class from the Emotion class, and everything should fit together nicely.
I have to add a bunch of trivial or seldom used attributes to an object in my business model.
So, imagine class Foo which has a bunch of standard information such as Price, Color, Weight, Length. Now, I need to add a bunch of attributes to Foo that are rarely deviating from the norm and rarely used (in the scope of the entire domain). So, Foo.DisplayWhenConditionIsX is true for 95% of instances; likewise, Foo.ShowPriceWhenConditionIsY is almost always true, and Foo.PriceWhenViewedByZ has the same value as Foo.Price most of the time.
It just smells wrong to me to add a dozen fields like this to both my class and database table. However, I don't know that wrapping these new fields into their own FooDisplayAttributes class makes sense. That feels like adding complexity to my DAL and BLL for little gain other than a smaller object. Any recommendations?
Try setting up a separate storage class/struct for the rarely used fields and hold it as a single field, say "rarelyUsedFields" (for example, it will be a pointer in C++ and a reference in Java - you don't mention your language.)
Have setters/getters for these fields on your class. Setters will check if the value is not the same as default and lazily initialize rarelyUsedFields, then set the respective field value (say, rarelyUsedFields.DisplayWhenConditionIsX = false). Getters they will read the rarelyUsedFields value and return default values (true for DisplayWhenConditionIsX and so on) if it is NULL, otherwise return rarelyUsedFields.DisplayWhenConditionIsX.
This approach is used quite often, see WebKit's Node.h as an example (and its focused() method.)
Abstraction makes your question a bit hard to understand, but I would suggest using custom getters such as Foo.getPrice() and Foo.getSpecialPrice().
The first one would simply return the attribute, while the second would perform operations on it first.
This is only possible if there is a way to calculate the "seldom used version" from the original attribute value, but in most common cases this would be possible, providing you can access data from another object storing parameters, such as FooShop.getCurrentDiscount().
The problem I see is more about the Foo object having side effects.
In your example, I see two features : display and price.
I would build one or many Displayer (who knows how to display) and make the price a component object, with a list of internal price modificators.
Note all this is relevant only if your Foo objects are called by numerous clients.
I am building a package to handle data that arrives with up to 4 different types. Each of these types is a legitimate class in the form of a matrix, data.frame or tree. Depending on the way the data is processed and other experimental factors, some of these data components may be missing, but it is still extremely useful to be able to store this information as an instance of a special class and have methods that recognize the different component data.
Approach 1:
I have experimented with an incremental inheritance structure that looks like a nested tree, where each combination of data types has its own class explicitly defined. This seems difficult to extend for additional data types in the future, and is also challenging for new developers to learn all the class names, however well-organized those names might be.
Approach 2:
A second approach is to create a single "master-class" that includes a slot for all 4 data types. In order to allow the slots to be NULL for the instances of missing data, it appears necessary to first define a virtual class union between the NULL class and the new data type class, and then use the virtual class union as the expected class for the relevant slot in the master-class. Here is an example (assuming each data type class is already defined):
################################################################################
# Use setClassUnion to define the unholy NULL-data union as a virtual class.
################################################################################
setClassUnion("dataClass1OrNULL", c("dataClass1", "NULL"))
setClassUnion("dataClass2OrNULL", c("dataClass2", "NULL"))
setClassUnion("dataClass3OrNULL", c("dataClass3", "NULL"))
setClassUnion("dataClass4OrNULL", c("dataClass4", "NULL"))
################################################################################
# Now define the master class with all 4 slots, and
# also the possibility of empty (NULL) slots and an explicity prototype for
# slots to be set to NULL if they are not provided at instantiation.
################################################################################
setClass(Class="theMasterClass",
representation=representation(
slot1="dataClass1OrNULL",
slot2="dataClass2OrNULL",
slot3="dataClass3OrNULL",
slot4="dataClass4OrNULL"),
prototype=prototype(slot1=NULL, slot2=NULL, slot3=NULL, slot4=NULL)
)
################################################################################
So the question might be rephrased as:
Are there more efficient and/or flexible alternatives to either of these approaches?
This example is modified from an answer to a SO question about setting the default value of slot to NULL. This question differs in that I am interested in knowing the best options in R for creating classes with slots that can be empty if needed, despite requiring a specific complex class in all other non-empty cases.
In my opinion...
Approach 2
It sort of defeats the purpose to adopt a formal class system, and then to create a class that contains ill-defined slots ('A' or NULL). At a minimum I would try to make DataClass1 have a 'NULL'-like default. As a simple example, the default here is a zero-length numeric vector.
setClass("DataClass1", representation=representation(x="numeric"))
DataClass1 <- function(x=numeric(), ...) {
new("DataClass1", x=x, ...)
}
Then
setClass("MasterClass1", representation=representation(dataClass1="DataClass1"))
MasterClass1 <- function(dataClass1=DataClass1(), ...) {
new("MasterClass1", dataClass1=dataClass1, ...)
}
One benefit of this is that methods don't have to test whether the instance in the slot is NULL or 'DataClass1'
setMethod(length, "DataClass1", function(x) length(x#x))
setMethod(length, "MasterClass1", function(x) length(x#dataClass1))
> length(MasterClass1())
[1] 0
> length(MasterClass1(DataClass1(1:5)))
[1] 5
In response to your comment about warning users when they access 'empty' slots, and remembering that users usually want functions to do something rather than tell them they're doing something wrong, I'd probably return the empty object DataClass1() which accurately reflects the state of the object. Maybe a show method would provide an overview that reinforced the status of the slot -- DataClass1: none. This seems particularly appropriate if MasterClass1 represents a way of coordinating several different analyses, of which the user may do only some.
A limitation of this approach (or your Approach 2) is that you don't get method dispatch -- you can't write methods that are appropriate only for an instance with DataClass1 instances that have non-zero length, and are forced to do some sort of manual dispatch (e.g., with if or switch). This might seem like a limitation for the developer, but it also applies to the user -- the user doesn't get a sense of which operations are uniquely appropriate to instances of MasterClass1 that have non-zero length DataClass1 instances.
Approach 1
When you say that the names of the classes in the hierarchy are going to be confusing to your user, it seems like this is maybe pointing to a more fundamental issue -- you're trying too hard to make a comprehensive representation of data types; a user will never be able to keep track of ClassWithMatrixDataFrameAndTree because it doesn't represent the way they view the data. This is maybe an opportunity to scale back your ambitions to really tackle only the most prominent parts of the area you're investigating. Or perhaps an opportunity to re-think how the user might think of and interact with the data they've collected, and to use the separation of interface (what the user sees) from implementation (how you've chosen to represent the data in classes) provided by class systems to more effectively encapsulate what the user is likely to do.
Putting the naming and number of classes aside, when you say "difficult to extend for additional data types in the future" it makes me wonder if perhaps some of the nuances of S4 classes are tripping you up? The short solution is to avoid writing your own initialize methods, and rely on the constructors to do the tricky work, along the lines of
setClass("A", representation(x="numeric"))
setClass("B", representation(y="numeric"), contains="A")
A <- function(x = numeric(), ...) new("A", x=x, ...)
B <- function(a = A(), y = numeric(), ...) new("B", a, y=y, ...)
and then
> B(A(1:5), 10)
An object of class "B"
Slot "y":
[1] 10
Slot "x":
[1] 1 2 3 4 5
Portfolio A → Fund 1
Portfolio A → Fund 2
Portfolio A → Fund 3
I couldn't frame my sentence without not using is/has. But between 1 & 2,
1) has a:
class PortfolioA
{
List<Fund> obj;
}
2) is a:
class PortfolioA : List<Fund>
{
}
which one do you think is better from the point of extensibility, usability? I can still access my funds either way, albeit with a small syntactical change.
I vote with the other folks who say HAS-A is better in this case. You ask in a comment:
when I say that a Portfolio is just a
collection of funds, with a few
attributes of its own like
TotalPortfolio etc, does that
fundamentally not become an "is-a"?
I don't think so. If you say Portfolio IS-A List<Fund>, what about other properties of the Portfolio? Of course you can add properties to this class, but is it accurate to model those properties as properties of the List? Because that's basically what you're doing.
Also what if a Portfolio is required to support more than one List<Fund>? For instance, you might have one List that shows the current balance of investments, but another List that shows how new contributions are invested. And what about when funds are discontinued, and a new set of funds is used to succeed them? Historical information is useful to track, as well as the current fund allocation.
The point is that all these properties are not correctly properties of a List, though they may be properties of the Portfolio.
do not 'always' favor composition or inheritance or vice-versa; they have different semantics (meanings); look carefully at the meanings, then decide - it doesn't matter if one is 'easier' than the other, for longevity it matters that you get the semantics right
remember: is-a = type, has-a = containment
so in this case, a portfolio logically is a collection of funds; a portfolio itself is not a type of fund, so composition is the correct relationship
EDIT: I misread the question originally, but the answer is still the same. A Portfolio is not a type of list, it is a distinct entity with its own properties. For example, a portfolio is an aggregate of financial instruments with an initial investment cost, a total current value, a history of values over time, etc., while a List is a simple collection of objects. A portfolio is a 'type of list' only in the most abstract sense.
EDIT 2: think about the definition of portfolio - it is, without exception, characterized as a collection of things. An artist's portfolio is a collection of their artwork, a web designer's portfolio is a collection of their web sites, an investor's portfolio consists of all of the financial instruments that they own, and so on. So clearly we need a list (or some kind) to represent a portfolio, but that in no way implies that a portfolio is a type of list!
suppose we decide to let Portfolio inherit from List. This works until we add a Stock or Bond or Precious Metal to the Portfolio, and then suddenly the incorrect inheritance no longer works. Or suppose we are asked to model, say, Bill Gates' portfolio, and find that List will run out of memory ;-) More realistically, after future refactoring we will probably find that we should inherit from a base class like Asset, but if we've already inherited from List then we can't.
Summary: distinguish between the data structures we choose to represent a concept, and the semantics (type hierarchy) of the concept itself.
The first one, because you should try to favour composition over inheritance when you can.
It depends whether the business defines a Portfolio as a group (and only a group) of funds. If there is even the remote possibility of that it could contain other objects, say "property", then go with option 1. Go with option 2 if there is a strong link between a group of funds and the concept of Portfolio.
As far as extensibility and usefullness 1 has the slight advantage over 2. I really disagree with the concept that you should always favour one over the other. It really depends on what the actual real life concepts are. Remember, you can always^ refactor.
^ For most instances of always. If it is exposed publicly, then obviously not.
I would go with option (1) - composition, since you may eventually have attributes specific to the portfolio, rather than the funds.
The first one, because it is "consists of". => Composition
I will differ with what appears to be the common opinion. In this case I think a portfolio is very little more than a collection of funds... By using inheritance you allow the use of multiple constructors, as in
public Portfolio(CLient client) {};
public Portfolio(Branch branch, bool Active, decimal valueThreshold)
{
// code to populate collection with all active portfolios at the specified branch whose total vlaue exceeds specified threshold
}
and indexers as in:
public Fund this[int fundId] { get { return this.fundList[fundId]; } }
etc. etc.
if you want to be able to treat variables of type Portfolio as a collection of funds, with the associated syntax, then this is the better approach.
Portfolio BobsPortfolio = new Portfolio(Bob);
foreach (Fund fund in BobsPortfolio)
{
fund.SendStatement();
}
or stuff like that
IS-A relation ship represents inheritances and HAS-A relation ship represents composition. For above mentioned scenario we prefer composition as PortfolioA has a List and it is not the List type. Inheritances use when Portfolio A is a type of List but here it is not. Hence for this scenario we should prefer Composition.