I have a class X and class Y which is basically a collection of Xs. I want to write a method to add an X to a specific collection Y. this method will change some state on X and of course on Y. My question is where is it best to have this method, in X class (so the method will be x.addToY(y)) or should it go on the Y class (y.addX(x))? what are the considerations I should make?
In your case it is very simple, but imagine that Y can hold other elements different of X, say elements of types A, B and C. Are these types supposed to know how to be added to a collection Y? The answer is no, but if so, you would have to implement a AddToY method for each of these types, which is not good at all. The collection Y is the one who knows how to add items to itself, regardless of what types are those items. This is known as Separation of Concerns and it mainly states that every type or entity should have the functionalities that are of its concern. In this case, you can see that a collection should be able to add items to itself, but a certain type X may have nothing to do with a collection, thus, it shouldn't have the functionality of adding itself to a certain collection. Hope this help you understand.
Consider that if you put the method in X to add itself to Y while Y contains a collection of X, then X would have to know about Y and Y would have to know about X; whereas if you put the method in Y then Y would need to know X, but X would not need to know about Y. You avoid circular dependency.
Besides the common sense association of such a method with the Y class, another consideration is concurrency: while this may at first be a single threaded app, you (or someone else) may extend class Y in the future to enable synchronized multithreaded collection access, in that case, it would certainly be more convenient to have addX in Y so that the multithreaded subclass can override that method with its concurrency support.
Related
So, suppose I'm working in the world of discrete mathematics and I have some function
f: A x B x C -> D.
With this function I can make computations like f(a,b,c) = d. (I'm being vague here on purpose).
Now suppose I want to implement this computation explicitly in some modern OO programming language. So I initialize a variable called a of class ClassA and so on with b and c. Then what? Which object should own the computation? Or could it be an initializer. Could it be a static function?
I could have:
d = a.f_1(b,c),
d = b.f_2(a,c),
d = c.f_3(a,b),
d = new ObjD(a,b,c),
d = ZStatic.f_4(a,b,c)
all as plausible options, couldn't I?
Given the situation, should symmetry demand I implement all of these options?
I'd prefer to avoid the constructor approach completely, but beyond that I don't know what progress could be made other than the assumption of essentially arbitrary information.
So, what object should own the function $f$, if any?
To give the best answer, it is important to know what kind of variables you use.
A very important metric in oop is to achieve high cohesion. Cohesion is the degree to which the elements of a module belong together. If your variables a,b and c belong together in a specific context, then it should be the best solution to put them in exactly one class. And if they are in one class you should not worry about, which class should own the computation (your fourth solution).
Your last suggestion, to use a static function is also conceivable. This approach is often used in mathematic librarys in different kind of languages (e.g. Java: Math class)
Is it possible in OWL to add a property onto a single class? So far, I see properties joining a pair of classes (like defining whether or not properties are symmetric, etc.). For example, what kind of property would I use to tag whether or not an animal is a pest. If it matters, I'm using Protégé to construct the ontology.
If your question is whether or not a property can have same domain and range, then yes, it is possible.
If X is a class and p is a property, it is possible to have
p range X
p domain X
and an assertion would look like:
i type X // an instance of X
i p i // a self assertion
I'm not sure how this fits your example though: how are you modeling 'being a pest'? It looks to me like you could model this as
i type Pest
e.g., as a class assertion not a property.
I have an operation that I need to design. That operation takes two objects of a certain class X, and returns two new objects of the same class (I may need the originals later). The logic that dictates the selection of this object is contained in class Y. On one hand, I don't want class Y to know details about class X implementation; on the other, I don't want class X to know details about selecting the different objects to perform this operation on.
If that was all the problem, I'd just create a static method on class A. However, the methods in language I'm working on return only one object. Also, the operation needs to be robust, and calling operation two times to get C and D respectively isn't possible, as both C & D both rely on a single random number.
How should I design such operation?
Update: I'm using Obejctive C.
I decided to just modify given objects A & B with a static method. I'll have to make copies of them before calling this method, but I think it'll be not slower than creating new ones; most of the information in objects C & D is derived from A & B anyway.
(I still think it's an ugly solution, and will welcome a more qualified answer).
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
I have a class that has several properties. Some properties can be changed by other classes but some properties are dependent on other properties. For example assume that my class has three properties: A, B and C. A and B can be changed by other classes in system and C is equal to A + B. The class generate property change notification So I want when A or B changed, a notification generate for both the changed property (A or B) and a notification is generated for C too.
I have three options (any other?)
1- Create a normal C property (with backing field) and add code in setter of A and B to change C.
2- Create a normal C property and listen to property change notification of my class inside of my class and change C when A or B changes.
3- Create a calculating property for C no setter but getter is A+B, in setter of A (and B), I fire property change for both A (or B) and C.
Which one is a better design pattern (in C#)? I personally like design number 2.
Sounds like an Observer pattern might be useful here. See for example http://www.oodesign.com/observer-pattern.html. Although a search for Observer pattern will yield many results and other examples, some much simpler, and language specific.
I would probably go with a variation on 2 and 3.
You could have a calculated property (getter only) for C so that the C = A + B calculation is only in one place.
Then, as per your option 2, you could listen to property changed events within the same class... but instead of updating C when you detect a PropertyChanged event for A and B, you only need to raise a PropertyChanged event for C at that time.
2 is the purest since it keeps A,B and C separate, but it does involve a bit of overhead qith the string parsing in the property notification.
If it was a simple set of properties I'd be tempted with 1, since they are still reasonably separate but the update is much simpler. 3 is the worst IMO, since A+B are replicating code which should be separate anyway (C notifications).
The problem here is that you are trying to mix the way that things should be done with the way Microsoft forces you to do things... :)
But my rantings aside it think that option 3 sounds cleanest. Certainly not 1, that is the worst by far, and I think that subscribing to your own property change events could lead to some funky problems that would be hard to debug when some poor sap tries to maintain the code in the future...
If you think about it at a high level, what you are suggesting in 3 perfectly describes what is happening in the class:
Any time that property A is changed observers of the class should be notified that property C has also changed (because it has).