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).
Related
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 design new class, which contains the same function boolean isCellEmpty() at each level of abstraction. I have the Matrix class in the bottom of my class hierarchy. On the top I have GraphMainWindow class.
Where should I do checks (e.g. if (i >= 0, i < xCellsCount, j >= 0 and so...)?
Good question, wondered about it myself many times. Answer: In the lowest level. This way errors will never slip undetected.
You can still check for errors in higher level where an algorithmic process makes sense, but the lowest level is the most important.
There are some exceptions to this. For example, if the error is reported via a message that holds the applicatio and you expect many errors to occur in the lowest level. But these are not so common, and you can bend the above rule if you feel it disturbs you.
The simple answer is: at the most generic level possible. The first inheritable class that declares those variables should perform the checks. Anything below that should just defer to the superclass unless overridden functionality is required. In a class further up the inheritance hierarchy from the one you've chosen to use for the checks, the method handling the checks should probably notify subclasses that haven't implemented an overridden version that they're getting default (and possibly useless) behavior. I often raise an exception in such a case.
So to put it in a nutshell you have this classes diagram:
Matrix ( a
^ ^
| |
... b means : b inherits a)
^
|
GraphMainWindow
You have a method isCellEmpty that is found in the base class and every inherited one.
If the datastruct of data that isCellEmpty use to do its checks do not change since the Matrix class, you do them in the Matrix class which is the most generic one.
If you change the datastructure since the Matrix one you should implement the test in the class that changed the datastructure.
Regards
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
Having the SOLID principles and testability in mind, consider the following case:
You have class A and class B which have some overlapping properties. You want a method that copies and/or converts the common properties from class A to class B. Where does that method go?
Class A as a B GetAsB() ?
Class B as a constructor B(A input)?
Class B as a method void FillWithDataFrom(A input)?
Class C as a static method B ConvertAtoB(A source)?
???
It depends, all make sense in different circumstances; some examples from Java:
String java.lang.StringBuilder.toString()
java.lang.StringBuilder(String source)
void java.util.GregorianCalender.setTime(Date time)
ArrayList<T> java.util.Collections.list(Enumeration<T> e)
Some questions to help you decide:
Which dependency makes more sense? A dependent on B, B dependent on A, neither?
Do you always create a new B from an A, or do you need to fill existing Bs using As?
Are there other classes with similar collaborations, either as data providers for Bs or as targets for As data?
I'd rule out 1. because getter methods should be avoided (tell, don't ask principle).
I'd rule out 2. because it looks like a conversion, and this is not a conversion if A and B are different classes which happens to have something in common. At least, this is what it seems from the description. If that's not the case, 2 would be an option too IMHO.
Does 4. implies that C is aware of inner details of B and/or C? If so, I'd rule out this option too.
I'd vote for 3. then.
Whether this is correct OOP theory or not is up for debate, but depending upon the circumstances, I wouldn't rule C out quite so quickly. While ti DOES create a rather large dependency, it can have it's uses if the specific role of C is to manage the interaction (and copying) from A to B. The dependency is created in C specifically to avoid creating such dependency beteween A and B. Further, C exists specifically to manage the dependency, and can be implemented with that in mind.
Ex. (in vb.Net/Pseudocode):
Public Class C
Public Shared Function BClassFactory(ByVal MyA As A) As B
Dim NewB As New B
With B
.CommonProperty1 = A.CommonProperty1
.CommonProperty2 = A.CommonProperty2
End With
Return B
End Function
End Class
If there is a concrete reason to create, say, a AtoBConverterClass, this approach might be valid.
Again, this might be a specialized case. However I have found it useful on occasion. Especially if there are REALLY IMPORTANT reasons to keep A and B ignorant of eachother.
I'm often running into the same trail of thought when I'm creating private methods, which application is to modify (usually initialize) an existing variable in scope of the class.
I can't decide which of the following two methods I prefer.
Lets say we have a class Test with a field variable x. Let it be an integer. How do you usually modify / initialize x ?
a) Modifying the field directly
private void initX(){
// Do something to determine x. Here its very simple.
x = 60;
}
b) Using a return value
private int initX(){
// Do something to determine x. Here its very simple.
return 60;
}
And in the constructor:
public Test(){
// a)
initX();
// b)
x = initX();
}
I like that its clear in b) which variable we are dealing with. But on the other hand, a) seems sufficient most of the time - the function name implies perfectly well what we are doing!
Which one do you prefer and why?
Thank for your answers guys! I'll make this a community wiki as I realize that there is no correct answer to this.
I usually prefer b), only I pick a different name, like computeX() in this case. A few reasons for why:
if I declare computeX() as protected, there is a simple way for a subclass to influent how it works, yet x itself can remain a private field;
I like to declare fields final if that's what they are; in this case a) is not an option since initialization has to happen in compiler (this is Java-specific, but your examples all look Java as well).
That said, I don't have a strong preference between the two methods. For instance, if I need to initialize several related fields at once, I will usually pick option a). That, though, only if I cannot or don't want for some reason, to initialize directly in constructor.
For initialization I prefer constructor initialization if it's possible,
public Test():x(val){...}, or write initialization code in the constructor body. Constructor is the best place to initialize all the fields (actually, it is the purpose of constructor). I'd use private initX() approach only if initialization code for X is too long (just for readability) and call this function from constructor. private int initX() in my opinion has nothing to do with initialization(unless you implement lazy initialization,but in this case it should return &int or const &int) , it is an accessor.
I would prefer option b), because you can make it a const function in languages that support it.
With option a), there is a temptation for new, lazy or just time-stressed developers to start adding little extra tasks into the initX method, instead of creating a new one.
Also, in b), you can remove initX() from the class definition, so consumers of the object don't even have to know it's there. For example, in C++.
In the header:
class Test {
private: int X;
public: Test();
...
}
In the CPP file:
static int initX() { return 60; }
Test::Test() {
X = initX();
}
Removing the init functions from the header file simplifies the class for the people that have to use it.
Neither?
I prefer to initialize in the constructor and only extract out an initialization method if I need a lot of fields initialized and/or need the ability to re-initialize at another point in the life time of an instance (without going through a destruct/construct).
More importantly, what does 60 mean?
If it is a meaningful value, make it a const with a meaningful name: NUMBER_OF_XXXXX, MINUTES_PER_HOUR, FIVE_DOZEN_APPLES, SPEED_LIMIT, ... regardless of how and where you subsequently use it (constructor, init method or getter function).
Making it a named constant makes the value re-useable in and of itself. And using a const is much more "findable", especially for more ubiquitous values (like 1 or -1) then using the actual value.
Only when you want to tie this const value to a specific class would it make sense to me to create a class const or var, or - it the language does not support those - a getter class function.
Another reason to make it a (virtual) getter function would be if descendant classes need the ability to start with a different initial value.
Edit (in response to comments):
For initializations that involve complex calculations I would also extract out a method to do the calculation. The choice of making that method a procedure that directly modifies the field value (a) or a function that returns the value it should be given (b), would be driven by the question whether or not the calculation would be needed at other times than "just the constructor".
If only needed at initialization in the constructor, I would prefer method (a).
If the calculation needs to be done at other times as well, I would opt for method (b) as it also makes it possible to assign the outcome to some other field or local variable and so can be used by descendants or other users of the class without affecting the inner state of the instance.
Actually only a) method behaves as expected (by analyzing method name). Method b) should be named 'return60' in your example or 'getXValue' in some more complicated one.
Both options are correct in my opinion. It all depeneds what was your intention when certain design was choosen. If your method has to do initialization only I would prefer a) beacuse it is simplier. In case x value is also used for something else somewhere in logic using b) option might lead to more consistent code.
You should also always write method names clearly and make those names corresponding with actual logic. (in this case method b) has confusing name).
#Frederik, if you use option b) and you have a LOT of field variables, the constructor will become a quite unwieldy block of code. Sometimes you just can't help but have lots and lots of member variables in a class (example: it's a domain object and it's data comes straight from a very wide table in the database). The most pragmatic approach would be to modularize the code as you need to.