How does High Cohesion help us reduce Coupling? - oop

Assume methods M1 and M2 have strongly related responsibilities
First example:
If
• M1 and M2 are defined within class A ( thus class A is highly cohesive )
• class B uses A.M1 and class C uses A.M2
then
• A is coupled with both B and C classes
• changing the signature of M1 will require changes only in B, but not in C
Second example:
If
• M1 is defined within class A1 ( thus B is coupled with A1 )
• M2 is defined withing class A2 ( thus C is coupled with A2 )
then
• changing the signature of M1 will require changes only in B, but not in C
a) To my understanding, classes in last example are no more coupled than classes in first example! Or am I missing something?
b) As far as I can tell, classes in first example are more loosely coupled than those in second example only if:
we assume that changing the signature of M1 will also require us to change the signature of M2, but I don't see that happening very often?!
or if both M1 and M2 operate on the data of same type T1, then replacing T1 with T2 will require changes in both M1 and M2?!
or if we assume that due to M1 and M2 having closely related responsibilities, that the chances are that much greater that changing M1 will often require M2 also to be changed (even if M1 doesn't directly or indirectly call M2)?!
or if we assume that due to M1 and M2 having closely related responsibilities, the chances are much greater that some class will require both M1 and M2 ( as such having M1 and M2 in single class reduces coupling )?!
c) Are there any other reasons why defining M1 and M2 within A ( instead of defining M1 within A1 and M2 within A2 ) will reduce coupling?
Note - I'm aware that we should have higly cohesive modules due to easier maintenance and reusability
Thank you

Yes it does. What you are missing that is if ClassA is cohesive, changing M1 will cause ClassB to access some other method in ClassA. It increases maintenance because you won't have to modify other modules (method and variables) in ClassA itself.
When we call a class cohesive (say ClassA) , we mean that we can easily use the purpose(s) of the class without have to make our caller class (ClassB) according to the requirements of ClassA. Hence, ClassB is not dependent on ClassA and thereby cohesion is reduced.
Don't think of think of cohesion in terms of methods. Methods are not called cohesive, classes are.

Related

Which objects own the method? Translating from discrete math

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)

When can a reference's type differ from the type of its object?

Yesterday I was asked a question in an interview:
Suppose class A is a base class, and class B is derived class.
Is it possible to create object of:
class B = new class A?
class A = new class B?
If yes, then what happen?
Objects of type B are guaranteed to also be objects of type A. This type of relationship is called "Is-a," or inheritance, and in OOP it's a standard way of getting polymorphism. For example, if objects of type A have a method foo(), objects of type B must also provide it, but its behavior is allowed to differ.
The reverse is not necessarily true: an object of type A (the base class) won't always be an object of type B (the derived class). Even if it is, this can't be guaranteed at compile-time, so what happens for your first line is that the code will fail to compile.
What the second line does depends on the language, but generally
Using a reference with the base type will restrict you to only accessing only members which the base type is guaranteed to have.
In Java, if member names are "hidden" (A.x exists and so does B.x, but they have different values), when you try to access the member you will get the value which corresponds to the type of the reference rather than the type of the object.
The code in your second example is standard practice when you are more interested in an API than its implementation, and want to make your code as generic as possible. For instance, often in Java one writes things like List<Integer> list = new ArrayList<Integer>(). If you decide to use a linked list implementation later, you will not have to change any code which uses list.
Take a look at this related question: What does Base b2 = new Child(); signify?
Normally, automatic conversions are allowed down the hierarchy, but not up. That is, you can automatically convert a derived class to its base class, but not the reverse. So only your second example is possible. class A = new class B should be ok since the derived class B can be converted to the base class A. But class B = new class A will not work automatically, but may be implemented by supplying an explicit conversion (overloading the constructor).
A is super class and B is a SubClass/Derived Class
the Statement
class A = new class B is always possible and it is called Upcasting because you are going Up in terms of more specific to more General
Example:
Fruit class is a Base Class and Apple Class is Derived
we can that Apple is more specific and must possess all the quality of an Fruit
so you can always do UPcasting where as
DownCasting is not always possible because Apple a=new Fruit();
A fruit can be a Apple or may it is not

Designing operation (a,b) -> (c,d)

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).

At what level should i do checks?

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

OO design: Copying data from class A to B

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.