OOP Newbie: Accessing Fields Directly vs. Passing Objects as Parameters - oop

Suppose Object1 needs information from Object2. I'll say it's in an Object2 property, but the info could as easily be the return value from an Object2 function. When I look at others' code I see sometimes they will have a method in Object1 directly accessing the property. Other times I see people pass Object2 as a parameter in a method, and then access the property from the passed Object2.
These scenarios seem almost the same to me. Directly accessing the property seems simpler. As a newbie, what do you think I should think about when deciding how Object1 should get information from Object2? (When would I want to have an object parameter rather than directly accessing the property?)
Thanks -- Al C.

One problem with passing Object2 to Object1 is that you create a dependency between Object2 and Object1. The only way that Object1 can obtain the data it needs is to have a reference to Object2.
Now, sometimes you want that, but most of the time you don't. So you're most likely better off simply passing the value you need as a parameter to the method, rather than passing the instance of Object2.

If the method only needs the one property value from Object2, it would be best to pass that property value directly. If the method needs access to many properties or other features of Object2, passing a reference to Object2 would be appropriate.
There are exceptions - if you need to protect the signature of the method (i.e. it is public) and you foresee additional use of Object2 within the method in the future, passing the object reference may be appropriate.
The previous answers also make valid points - you should consider the coupling of Object1 and Object 2 when you make this decision.

Usually the goal is to minimize coupling between objects.
Let's use a simple example where I have three objects; an AppController, which holds a reference to a DataController and a MainWindowController. You need to pass DataController.Data to the MainWindowController, so you can display the values in a table in the main window. You could pass DataController to MainWindowController as a method parameter, or make DataController an instance variable in MainWindowController. To minimize coupling through, the cleanest way is for AppController to pass Data directly to MainWindowController, so it doesn't need to know anything about DataController.

It's all about whether or not Object1 knows about Object2. In OOP, part of good design is to have objects store as LITTLE information as possible that still allows them to behave properly. So the problem fundamentally comes down to: does Object1 need to know about Object2's existence (that is, does it need an instance of Object2 to exist) or can it be told about the existence of an Object2 instance? Usually, in OOP, you want to lean more towards the latter than the former.
However, that said, in a situation where Object1 can operate on data which comes from Object2, the best way would probably to have Object1 have a method which operates on the data type of the property on Object2; that way, you decouple Object1 and Object2, in that Object1 does not have a dependency on Object2 to provide a given property in a given way; the calling code can connect the two.

Yes, what Randolpho says is true.
Remember, with OOP you are aiming to create separate identities that can function as a whole in the system. When you start creating objects that rely heavily on each other, not only do you increase your chances of bugs, but also the chance that your program won't work anymore at all.
Now your example is a minor, but imagine 5, 10, 100 objects calling each other through parameters, that's nasty work.

Take a look at Encapsulation on wikipedia.
Encapsulation [..] protects the integrity of the component, by preventing users from setting the internal data of the component into an invalid or inconsistent state.

Related

I am STUCK! creating OOP data-structure dynamically, I think

I am close to pulling my hair out on this. I have the need to create a type of object such that when a new object is instantiated it associates itself with every other object of that class via an array property. That is object1 gets created and has an array with no other objects. Object 2 gets created and has an array with object1. Object 3 gets created and has an array with object1 and object2. Also object1 and object2 now have object 3 in their arrays.
This has proved more difficult that I had prejudged by simply using conditional logic and for-in looping.
I have attempted to create an object manager class to keep a list of all objects created and use those references to loop through its owned objects and "cross-pollinate" them with each other. Check for ![object1.name isEqualToStringName:thisObject.name] in each for-in loop.
I imagine this may be somewhat opaque and needlessly confusing to some. The essence of what I want to do is dynamically associate every object with every object via an array property.
The app creates object8 and object8 is added to the arrays of object1...object7.
This is something I am attempting to do in a larger context of an app where the objects must maintain situational awareness of each other and having an array of each other will help to facilitate that. If there is a design pattern, methodology, principle or something I am missing here please.. please inform me.

How to receive notifications from an NSMutableArray subclass

I have subclassed NSMutableArray to allow for a datasource. This is called BaseObjectArray. The array actually only holds a list of rowids (as uint64_t), and when asking for objectAtIndex it asks the datasource delegate for the object with that rowid (to allow for lazy DB queries).
The internal list of rowids is a class in it's own right (a RowIDSet, or the OrderedRowIDSet subclass, which is just a subclass of NSObject), that maintains just the list of unique rowids.
What I need is to somehow listen for changes to the BaseObjectArray (which is actually listening to changes on it's RowIDSet object, perhaps through a similar method).
As objects may be added/removed from the BaseObjectArray not using the standard addObject:, but instead with addRowID:, the object that owns the BaseObjectArray will probably not get standard KVO notifications.
Possible solutions I have considered:
The BaseObjectArray has owner and ownerKey properties, and the BaseObjectArray triggers [owner willChangeForKey:ownerKey]; whenever anything changes.
Use will/didChangeNotificationBlocks - listeners can simply add a block to the BaseObjectArray (retaining these blocks in an NSMutableArray), and all the blocks in this array are triggered when something in the BaseObjectArray changes. I am uncertain about the possible retain-cycle nightmare that may ensue.
KVO on a 'contents' property of the BaseObjectArray. Anyone wanting to observe the BaseObjectArray actually observes the keyPath 'contents', and inside the BOArray it calls [self willChangeForKeyPath:#"contents"]. The contents property just returns self.
... something obvious that i have missed ...
Please let me know if any of these make the most (or any) sense, or if there is a better solution out there.
Thanks :)
Unless you know what you are doing, you should not subclass NSMutableArray. NSMutableArray is a class cluster and requires special treatment.
Why not just create a custom object that uses a plain NSMutableArray as its storage class? There seems to be no good reason to subclass NSMutableArray in your case, but maybe I'm misunderstanding your question.
I don't know if this will work, but if it does, it's probably the best way.
Make sure your NSMutableArray subclass is KVC compliant for the key self (if this doesn't work for self add a new property e.g rows which returns self or a copy of self). To make self (or whatever new property you use) KVC compliant you need to follow the Indexed To-Many Relationship Compliance rules for mutable ordered collections:
Implement a method named - that returns an array.
Or have an array instance variable named or _.
Or implement the method -countOf and one or both of -objectInAtIndex: or -AtIndexes:.
Optionally, you can also implement -get:range: to improve performance.
self ticks the box on the first of these. Also:
Implement one or both of the methods -insertObject:inAtIndex: or -insert:atIndexes:.
Implement one or both of the methods -removeObjectFromAtIndex: or -removeAtIndexes:.
ptionally, you can also implement -replaceObjectInAtIndex:withObject: or -replaceAtIndexes:with: to improve performance
So you'll need e.g. -insertObject:inSelfAtIndex: and -removeObjectFrom<Key>AtIndex:
Then you can use manual KVO notifications wherever you want to notify obeservers of the self property on that object. So you might use
NSIndexSet* indexes = // index set containing the index or indexes of objects to remove
[self willChange: NSKeyValueChangeRemoval valuesAtIndexes: indexes forKey:#"self"];
when removing objects.

Is there a way to tell when KVO starts/ends for a particular value?

I have some values that are computed over collections, and may or may not be displayed (and thus may or may not have an observer) at any given time. I would rather not have to track all the members of the collection if nobody is observing my computed values.
Can I tell if anyone is currently observing a value, and can I tell when they start observing?
I know for a given object foo I can use [foo observationInfo] to get a list of observers with key paths registered with a root at foo, but that doesn't automatically get all paths TO foo (in fact it only gets ones registered to observe foo's self key).
That’s not a good idea from the design point of view. If you really insist on not updating the contents when nobody needs them (which could be a legitimate case, for example if the updates are expensive), you can introduce methods to start/stop the updates:
- (void) beginUpdatingContents;
- (void) endUpdatingContents;
These should be tied to a counter inside the class and if the counter is > 0, you know somebody wants to keep the contents updated. This solution is explicit and therefore better than silent magic with KVO.
If you want more magic, how about overriding addObserver:forKeyPath:options:context: and removeObserver:forKeyPath: and tracking what is still observing you?
The way I've actually done this in the past is by making wrapper objects (I called them bindings) which set up KVO and also register themselves with the target. So, a user would call MyBinding *binding = [targetObject bindKeyPath:#"foo" ...] and then later [binding detach]. You then have the binding use KVO under the hood and keep a list of themselves so you know when it's empty.

Should I use == or [NSManagedObject isEqual:] to compare managed objects in the same context?

Let's say variable A and B hold instances of managed objects in the same managed object context. I need to make sure that they are associated with the same "record" in the persistent store. The section on Faulting and Uniquing in the Core Data Programming Guide says that:
Core Data ensures that—in a given managed object context—an entry in a persistent store is associated with only one managed object.
From this, it seems that a pointer comparison is sufficient for my purpose. Or does it ever make sense to use isEqual: to compare managed objects in the same context?
Use == to determine if two pointers point to the same object. Use -isEqual to determine if two objects are "equal", where the notion of equality depends on the objects being compared. -isEqual: normally compares the values returned by the -hash method. I wrote previously that it seemed possible that -isEqual: might return true if two managed objects contain the same values. That's clearly not right. There are some caveats in the docs about making sure that the hash value for a mutable object doesn't change while it's in a collection, and that knowing whether a given object is in a collection can be difficult. It seems certain that the hash for a managed object doesn't depend on the data that that object contains, and much more likely that it's connected to something immutable about the object; the object's -objectID value seems a likely candidate.
Given all that, I'm changing my opinion ;-). Each record is only represented once in a given context, so == is probably safe, but -isEqual: seems to better express your intention.
Pointer comparison is fine for objects retrieved from a single managed object context, the documentation on uniquing you quote promises as much.
ObjectID should be used for testing object equality across managed object contexts.
isEqual does not do attribute tests, because it is documented to not fault the object. In fact, looking at the disassembled function it is definitely just a pointer compare.
So the semantics of the equality test for managed objects are simply "points to the same object (record) in the managed object context" and will compare false for objects in different contexts.
Warning: Since NSManagedObject isEqual compares objectIDs, a comparison can fail if one instance is using the temporary objectID and the other instance is using the permanent objectID.
Background: When an NSManagedObject is created, it is assigned a temporary objectID. It is converted into a permanent objectID when the NSManagedObject is actually persisted into the store. You can see the difference if you print the objectID:
x-coredata:///MyEntity/t03BF9735-A005-4ED9-96BA-462BD65FA25F118 (temporary ID)
x-coredata://EB8922D9-DC06-4256-A21B-DFFD47D7E6DA/MyEntity/p3 (permanent ID)
When an objectID is converted to permanent, instances of the NSManagedObject in other threads and collections are not updated. So if you put an NSManagedObject into an NSArray when it has a temporary objectID, using methods like containsObject will fail if you try to find the object with the permanent objectID. Remember containsObject uses isEqual.
Finally, a couple of useful methods are NSManagedObjectID isTemporaryID and NSManagedObjectContext obtainPermanentIDsForObjects:error:.

Passing copy of object to method -- who does the copying?

I have an object that I'm passing in a method call. Say I'm using a language that only allows you to pass objects by reference, like Java or PHP. If the method makes changes to the object, it will affect the caller. I don't want this to happen. So it seems like I need to make a copy of the object.
My question is: whose responsibility is it to clone the object? The caller, before it calls the method? Or the callee, before it changes the object?
EDIT: Just to clarify, I want this to be part of the contract of this method -- that it never modifies the original object. So it seems like it should be up to the method to make the copy. But then the caller has no protection from a method that doesn't do this properly. I guess that's acceptable -- the only other alternative seems to be to have this built into the language.
Generally, the caller should make the copy if it is concerned about changes. If the caller doesn't care, the method should make the copy if it needs to do something that it knows shouldn't persist.
So you want to do something like
MyObject m = new MyObject();
MyObject n = MyObjectProcessor.process(m);?
It seems simpler to me to do something like
MyObject n = MyObjectProcessor.alter(m.clone());
where it's clear who's doing what to who. You could make the argument that the processor class function should be free of side effects, i.e. it should return a new object any time it's going to change state, but (AFAIK) that's not so consistently followed in OO as opposed to functional programming.
Something like the above is probably harmless, as long as it's clearly named and documented.
We could look at ruby for guidance. They use a ! symbol to indicate that an object is modified in-place. So, salary.add(10000) returns a new object but salary.add!(10000) returns the original object but modified. You could use the same idea in Java or PHP by using a local naming convention.
The caller. Because, sometimes you want to make changes to the objects themselves and other times to a copy.
Although, I consider it a bad practice for callee to modify passed objects (at least in object oriented languages). This can cause many unwanted side effects.
(after your) EDIT: In that case it is callee's responsibility to enforce the contract, so there are two options:
The callee simply does not modify the object
or the callee copies the object and works with the copy afterwards
Depends, is there any reason that the method could be called in the future where you want the change to be seen by the caller? If so then the caller should make the copy. Otherwise the callee should make it. I would say that the second case is probably more common.
If you have the caller clone the object, it gives you the flexibility to not use a copy (by not cloning it first), and also means you don't have to return a new object, you can just operate on the reference passed in.
My first reaction would be that it is the caller's responsibility, but I think it actually depends.
It depends on the contract defined between the two methods. The method that is making changes should explicitly identify that fact and let the caller make the decision. OR, The method that is making the changes should explicitly identify that it will NOT make any changes to the passed object and then it would be responsible for making the copy.
I would say the callee: it simplifies calls and caller won't have to worry for the integrity of the given objects. It is the responsibility of the callee to preserve the integrity.
I assume you would have something like const declaration. This would be compiler enforced and would be more efficient than creating copies of your objects.
I think the caller should make the clone, just to make the naming easier. You can name your method Foo() instead of CloneBarAndFooClone().
Compare:
void RemoveZeroDollarPayments(Order order)
vs.
Order CloneOrderAndRemoveZeroDollarPaymentsFromClone(Order order)
If not changing the object is part of the method contract, the only possibility is having the copy made inside the method. Otherwise you are lying to your client.
The fact that you actually need to modify an object exactly like the one given to you is just an implementation detail that should not put a burden on the caller. In fact, he does not even need to have visibility of that.