"How to questions" regarding OO designs and implementations.

Discussion in 'Mac Programming' started by ajrains, May 13, 2014.

  1. ajrains macrumors newbie

    Joined:
    May 13, 2014
    Location:
    Northern California
    #1
    I'm new to MacRumors

    I'm working my way through Programming in Objective-C (6th Edition) by Kochan. I have "how to questions" regarding OO designs and implementations.

    I understand C and have written a lot of algorithms in C including Digital Differential Analysis, 4x4 matrix multiplication to name a few.

    I have yet to Grok! OO Programming.

    Looking for the right group to ask questions like - How can Object-A become "aware" of Object-B if they are born of separate instantiation trees?

    AJ
     
  2. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #2
    This is probably the right group within the MacRumors site.

    To answer your first question: Normally, you'd tell Object A about Object B by giving A a pointer to B. "Someone" instantiates all these objects, and "someone" would have to tell these objects about each other.
     
  3. Senor Cuete macrumors regular

    Joined:
    Nov 9, 2011
    #3
    Notifications

    In Cocoa objects can communicate by posting or receiving notifications. Typically an object signs up to receive a notification when it's initialized. For example:

    Code:
    - (id) init
    {
    	self = [super init];
    	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    	[nc addObserver: self selector: @selector(someNotification:) name: @"handleSomeNotification" object: nil];
    	return self;
    }
    handleSomeNotification is the name of an instance method that will handle the notification.
     
  4. Dranix macrumors 6502a

    Dranix

    Joined:
    Feb 26, 2011
    Location:
    Gelnhausen, Germany
    #4
    Objects become aware of other objects by getting a pointer/reference to it.

    But what do you mean with instantiation tree? Never in roughly 20 years of oop coding heard that and couldn't find it in the net.
     
  5. whooleytoo macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #5
    I'm guessing he means the sequence/hierarchy in which your objects are created.

    In typical Cocoa applications, some objects are created in code and others are instantiated via xibs, so ensuring the objects are all instantiated at a given point in time, and aware of each other does take some fore-thought on the part of the developer.
     
  6. ajrains thread starter macrumors newbie

    Joined:
    May 13, 2014
    Location:
    Northern California
    #6
    Yep! Fore-thought that's the ticket I assume. Here is an attempt to lay my question out in a mix of prose and code:

    As I mentioned earlier I am new to Objective-C and I can’t seem to find anything that tells me how to call a method in an object that was instantiated in another file of code.

    For example:
    I create a Class A with files A.h and A.m

    In AppDelegate.m I do

    #import “A.h”

    and in the function didFinishLaunching
    I instantiate Class A into Object A

    A * myA = [[A alloc]init];

    Then I use Object myA to record the current Date/Time with a well defined method called storeDate_1;

    [myA storeDate_1:[NSDate date]];

    NOW in the interface there is a button that causes an Action
    where I need to send a message to Object myA to store a new current Date/Time;

    [?? storeDate_2:[NSDate date]];

    So what is the value of ?? -OR- how do I obtain the pointer myA when its not in the scope of the Action function in the interface.

    Another way to ask the question is how do Objects become aware of one another especially in this dynamic environment? All the documentation talks about how you send messages to objects. YEAH! BUT you have to know the id or Pointer or address of the Object to send the message. I have yet to see documentation about how objects learn of the pointers to other instantiated objects. Unless they are instantiated within the same scope.

    AJ
     
  7. ajrains thread starter macrumors newbie

    Joined:
    May 13, 2014
    Location:
    Northern California
    #7
    <smiling> I have no years of OOP coding BUT I do have many years of C coding. An Object is an instance of a Class (or so I have read). When one is unfamiliar with the proper nomenclature or lingo, as I currently am, one can find it difficult to express a question. In my mind I can see instantiations of Classes into Objects within the same scope as a tree. I realize that my use of tree may have been miss leading to others. But what is one to do when seeking knowledge?

    AJ
     
  8. whooleytoo macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #8
    Typically in Cocoa one of two patterns are used (or a combination thereof) :

    - Singleton objects. Create a controller-type class which will only be instantiated once. You use a static method to create/get a reference to this singleton object. The NSApplication class/object is an example of this.

    - IBOutlets. If you're creating lots of objects in Interface Builder/xibs, then you can add outlets to each and connect them visually. When the xib is fully loaded, then the objects are instantiated with the references to each other "pre connected". Not that this is very much a Cocoa pattern, rather than a generic OO approach.
     
  9. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #9
    It's the responsibility of a Controller object to connect View objects that want to initiate actions, with Model objects they may wish to modify. The pattern that combines these three roles and delineates each one's responsibilities is called Model-View-Controller, or MVC.

    https://developer.apple.com/library/mac/documentation/general/conceptual/devpedia-cocoacore/MVC.html

    This is just one way to couple objects. There are others. The book "Design Patterns" lists a bunch of creational, structural, and behavioral patterns. There's another book called "Cocoa Design Patterns".


    The connection between a View and a Controller is usually established by loading a nib file. The connections, target/actions, etc. are defined when the nib file is made. It's basically a specialized list of object-types, names, target/action identifiers, object parameters like position, size, visibility, all archived in a reversible format. You build nib files (xib files) using the Interface Builder component of Xcode.

    The Controller object de-archives the nib, which makes its constituent View objects, and the magic of Cocoa then associates the actions defined for each View objects with the target Controller.

    There's more on this in the other articles of Cocoa Core Competencies (link above). If you want the lowest-level details, see here:
    https://developer.apple.com/library...rence/ObjCRuntimeRef/Reference/reference.html
     
  10. ajrains thread starter macrumors newbie

    Joined:
    May 13, 2014
    Location:
    Northern California
    #10
    Thanks Chown33 for the reminder about MVC designs. Actually I am a newbie to Objective-C and OOP in general. I've been working my way through "Programming in Objective-C" (Sixth Edition) which does not seem to cover the MVC design. I also read a great deal as I plod along. I recently was reading the Apple Document "Object-Oriented Programming with Objective-C" (link: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/OOP_ObjC/OOP_ObjC.pdf).

    ON Page 13 of this document I offer the following quote
    "A program consists of a network of interconnected objects that call upon each other to solve a part of the puzzle (as illustrated in Figure 3-2 (page 13)). Each object has a specific role to play in the overall design of the program and is able to communicate with other objects."

    This quote began to bother me because (well I'm in a state of learning how this "thing" works) from what I have read so far and experimented with it seems that only objects created or instantiated in the same scope can communicate with each other. I mean after all you need the Object-Pointer to send a message to the Object. BUT above the statement is made "Each object ... is able to communicate with other objects." So I'm thinking what have I missed? Hence the example I presented above in the discussion. Was not thinking beyond my wonderment about how objects instantiated in separate scopes communicate.

    AJ
     
  11. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #11
    I think you interpreted the statement too broadly. It doesn't say "with every other object" or even "with any other object". Objects communicate with other objects. The degree to a given object can see other objects, hence its permissible degree of communication, is limited. This is intentional, and is considered good design, be it object-oriented or procedural. It's called encapsulation, or information hiding.
    http://en.wikipedia.org/wiki/Information_hiding

    In plain C, if you declare a function 'static', it's not visible outside its compilation unit. You've restricted the visibility of the function. There's usually a reason for this, and it usually revolves around encapsulation.

    You can use 'static' on variables, too. Again, the purpose is to encapsulate. You can define static structs, typedefs, malloc'ed space, and so on. All without having it be globally visible. This is intentional.

    Objects are the same, but even more so. Encapsulation is builtin to the very structure of classes, objects, methods, and instance-variables. The options for encapsulation in C are fewer. For example, every non-static function-name occupies a single name-space. So if you define a function fread(), it will conflict with the stdio function of that name. Much debugging fun can be had if this is done accidentally.
     
  12. Dranix macrumors 6502a

    Dranix

    Joined:
    Feb 26, 2011
    Location:
    Gelnhausen, Germany
    #12
    Have you experience with event-driven programming? The biggest problem people new to cocoa is from my experience that they don't control all of the code themselves but only a few hooks that get called by the Framework.
     
  13. ajrains thread starter macrumors newbie

    Joined:
    May 13, 2014
    Location:
    Northern California
    #13
    Why yes I do have experience with event-driven programming. And I agree, event-drive computing takes some getting use. You are either in a STATE of Wait-for-event-to-occur OR a STATE where an event has occurred and the event-handler has moved program execution to the appropriate code.

    For this discussion thread that I started, I am focused on the "designs" of how Objects communicate. Well, that's a simple thought, objects are sent messages and the syntax is

    return-value-if-any = [Pointer-to-target-object Method-to-Run:with-any-parameters];

    that's how they communicate.

    The problem is knowing the "Pointer-to-target-object" if the target-object was made "new", or instantiated in a scope the current program execution isn't operating in. I thought there might be a Framework device or an Objective-C feature to resolve this problem, apparently there is not.

    Apple has a doc deep in their references titled "Object-Oriented Programming with Objective-C" in the Section "Structuring Programs" there is discussion on the topics of "Outlet Connections" and "Activating the Object Network".

    Here is the root paragraph of this discussion thread.
    SO. . . is there a "design" for "a service that identifies objects by name"?
     
  14. Dranix macrumors 6502a

    Dranix

    Joined:
    Feb 26, 2011
    Location:
    Gelnhausen, Germany
    #14
    You are overthinking it. There is no other way then giving a pointer to a object that should be able to send messages to another.

    There is no magical web between all objects. It's just like the data-structures in C programs - you as the coder have to create the connections.
     
  15. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #15
    I think stepping away from objective-c and cocoa and learning more about OO would be helpful. It may hurt rather than help, but if you have a very strong imperative background, it may help to think of an object as a struct containing all the data that constitutes the objects member variables, then a bunch of functions that accept a pointer to that struct as their first argument, then the remaining argument list.

    When you want to pass a struct pointer to a function in C, where did the struct come from? What if the struct was declared in another scope? Perhaps you have a struct with a field the is a pointer to the struct you need. Well how did that field get set? Everything has to get strung together eventually, imperative or OO. If you want to call a function the requires a struct pointer, you need to get a hold of that somehow. If you want to pass a message to an object, you need that object somehow. It's really not more complicated than that. Sometimes in C you have a black box library that seems to do some magic. If it's going to act on some data, you'll need to hand it the data. Cocoa may seem like a big black box, and it may be doing a lot of things akin to magic. So maybe stop thinking about that right now. You're going to have to get a handle on an object holding a reference to another so it can pass that object messages, initializing an object with some other objects, setters that accept another object, etc.

    You're overwhelmed. You have to step back. You're trying to learn a language, programming paradigm, a huge framework, and an IDE all at once. It's too much. Have you learned a second language yet? Have you learned a second programming paradigm (imperative, functional, etc.)? Have you worked with multiple huge frameworks? Large libraries? Multiple IDEs?

    If this is the second of anything you're learning of any of these it will be rough. The first time you learn one of these it's hard, but you're unbiased and know you don't know. The second time you're bringing in biases and you're less humble so you expect it to go faster. It gets progressively easier as you learn how to learn new things and can dismiss your biases. You'll learn how to learn without it being in terms of what you already know. Instead of "how do I do this C thing in language X" you'll have more general knowledge. How do you call a function? What is the object model (if OO)? Does this language support tail recursion? You have broader experience and a different lens to look through, rather than the limited view granted by a small amount of experience.

    TL; DR: you've perhaps bitten off more than you can chew. Buy a book or choose a tutorial that assumes you don't know how to program at all and is teaching you Objective-C. Not Cocoa. Not iOS programming. Maybe they get there, but don't get something that assumes OO knowledge.

    -Lee
     
  16. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #16
    Here's the complete section of that document:
    https://developer.apple.com/library...s.html#//apple_ref/doc/uid/TP40005149-CH4-SW2

    The "problem" you perceive doesn't exist. The section you cited is talking about how objects make connections to one another. It specifically discusses intrinsic and extrinsic connections. For an intrinsic connection, the object is usually made by its enclosing object, when the enclosing object needs to do so. Specifically, you write code to call the alloc method of the class, then the init method of the object. You do this for every intrinsic object that the enclosing object needs. There is no unresolved problem here; objects make other objects when they need to.

    For extrinsic connections, getting the "other object" depends entirely on the design of the program. There isn't a universal way to do this, because different programs need different things. The example in the above link is an Appliance object with a connection to a Valve object. One approach is a vendor method (a type of Factory Method) that returns existing Valve objects it knows about. How would the Valve vendor know what Valves to vend (return)? It's presumably designed to know that, as part of what the programmer wrote it to do. In other words, it solves the problem of knowing what Valves to vend, independent of any Appliance object that might request those Valves.

    An example of a kind of "factory method" in procedural programming is the stdio function fopen(). You pass it the name of a file, how you want to access the data in the file, and it "vends" or returns a "file-stream object" of type FILE*. You then work with that file-stream object, and not with the filename.

    How does the caller of fopen() know what filename to pass in, or what access to request? The programmer writes it to do what the programmer wants done. If the filename is builtin, then it's builtin. If it's a command-line arg, then it's a command-line arg. If it's a string received from a network connection, then it's a string from a network connection. The programmer decides what's appropriate, depending on what the program itself is intended to do. If you don't know the intent, or what the program should do, how could you write code to express that intent to the machine?


    You seem to be looking for a universal way to attach names to objects, so they can be retrieved by any other object. There is no such solution. You're reading too much into what the cited paragraph says. It's discussing theoreticals or hypotheticals, in order to illustrate the use of terms like "intrinsic" or "extrinsic" or "outlet". There are no actual Cocoa classes for Valve, Appliance, Building, or Pipe, nor is there a dispenser of arbitrary named objects.

    One specific way that names can be attached to objects is with a global variable holding an NSMutableDictionary. However, objects would have to explicitly be added to this NSMutableDictionary (registration), or explicitly removed. There won't be some magical process whereby every object created will be added to this dictionary along with some generated name. If you don't write code to do this, it won't happen. And unless there's a reason for the program to do this, I don't see why you'd write code to do it.

    To summarize:
    The perceived problem doesn't exist. It's a red herring. There are two distinct cases:
    1. An object directly makes other objects it needs, in which case it has the object pointers because it just made them. It already knows the class, because the programmer writing the code knows which class to instantiate. Hence, there is no problem.
    2. It calls on another object it already knows to supply objects it needs. That other object will return suitable object pointers, which it obtains by applying either #1 or #2. Since the caller receives object pointers from the vending object, there is again no problem.
    One approach to #2 is to have a class with a class method that returns objects. Then the caller needs to know the class-name, but the programmer will already know that, so imparting that knowledge to the caller means writing code that calls the class's method, as distinct from calling the class's alloc method.
     
  17. ajrains thread starter macrumors newbie

    Joined:
    May 13, 2014
    Location:
    Northern California
    #17
    Problem? What problem? Actually in my first post I asked the following "Looking for the right group to ask questions like - How can Object-A become "aware" of Object-B if they are born of separate instantiation trees?" I guess that can be read as a problem. I was looking for a design that might facilitate Object communication when the Objects are "born" or "created" or instantiated in distinct scopes.

    Well yes I have said that many times. And the syntax is SomeThing * myThing = [SomeThing alloc] init];
    AND now you have the Object Pointer myThing, and it can be passed as a method parameter to a future instantiated object in this scope so the newly created object can communicate with myThing, if it needed to.

    Apparently NOT!

    However, the document sort of suggest a design in the notion of a "service object" that might hold an array of object-pointers. Since I have asked my question I have learned of the Singleton design. I has tested this design in an experimental program and it does work. I'm thinking a Singleton acting as a service object with an internal table or array of object pointers. Of course it gets really messy fast in that as objects are released they would also have to tell the Singleton Service Object they have been released. (BLOAT!).

    Yep that is how C and Unix work.


    No not particularly a universal way BUT any way that would allow me to facilitate communication between objects instantiated or born or created in distinct scopes.

    So there is no feature in the Objective-C language that facilitates communication between objects in different scopes. And there is no magical process <smiling> in the environment nor available Frameworks to facilitate communication between objects in different scopes. So if a programmer needs this ability the programmer must build this ability.

    I think the suggestion of a Service Object fits approach #2.

    <smiling>Red herring is a bit harsh in that I have not attempted to mislead or distract BUT to genuinely explore the abilities of Objective-C, BUT I can see why it feels like a Red Herring. I'm always amused the way folks interpret, make assumptions, think and express.

    A problem that often twists Forum Threads into weirdness is the lack of willingness to think outside the box.

    What if the language allowed the following.

    In some scope like the AppDelegate
    SomeThing * myThing = [SomeThing allocWithName:FOO] init ];

    In another scope like the ViewController
    SomeThing * aThing = [SomeThing allocWithName:FOO] init ];

    Now every time I run this line of code in what ever scope I run it in, I get back the address or object pointer if you will that points to the same initial object or initial address in memory.

    myThing and aThing point to the same hunk of memory.


    AJ
     
  18. chown33, May 18, 2014
    Last edited: May 18, 2014

    chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #18
    If you want such a thing, nothing stops you from making it. I simply doubt its general utility. Maybe that's just me, or the kind of programs I write, or even the way I write programs. I can't say I've ever run into a situation where a single unified vending service would be useful.

    Anyway, it appears you've found your solution, so you can move forward.

    EDIT
    Just to clarify, I wasn't accusing you of throwing out red herrings. I was saying that the perceived problem, specifically of a single unified vending service, was a problem I've never seen arise. I've been programming for many years, and while vending services, singletons, etc. do arise, not once have I seen the need to make a single unified service that can handle arbitrary types across multiple use-cases.
     
  19. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #19
    This has to be one of the strangest threads we've had in a while.

    This allocWithName: rigmarole is making a global object registry, and having the key in the alloc would be a weird way to do it anyway. One could certainly create a category on NSObject or a specific class that would be registerWithKey:(NSString *), or any other key type. But you'd want to make sure that the objects were weakly referenced so this didn't become a massive memory leak.

    Generally, you design your program such that truly global, application-scoped objects are modeled as singletons, and otherwise objects are created at the appropriate scope and managed appropriately. There are other patterns like event listeners such that one object may produce notifications, and another may listen. The two are not aware of each other, but are both aware of some third object that facilitates registration and notification. Is that thing a singleton? Maybe. Depends on if it's appropriate. Maybe it's only scoped to a particular feature, so it's life cycle belongs to that feature, so maybe a controller for that feature creates/destroys it, and can pass it around it vend it to objects involved with said feature.

    Anyway... If doing things globally is what you're used to, breaking down ownership and scoping things at the proper level may take time. Right now I'd focus on OO concepts first, then the language, then established patterns. A lot of the involved frameworks are 20 years old, and no one has decided that the god object managing a global registry is necessary, so it hasn't been introduced. If some limited version of this makes sense for your purposes go for it, but it's likely setting up some trouble when it comes to scope and ownership.

    -Lee
     
  20. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #20
    An object is just a C data structure (with added sugar), so you can pass it the same way as you pass an allocated struct, by pointers using some code higher in the tree.

    If the objects are all attached to (instances in) some known higher level object, then, in Objective C, you can use KVC and/or KVO with key paths to get at any object or instance variable in the entire tree, by name.
     
  21. MEJHarrison macrumors 6502a

    Joined:
    Feb 2, 2009
    #21
    While Objective-C and Mac / iDevice programming is new to me (I've been learning for the past few weeks), programming isn't. I've been doing it professionally coming up on 25 years and in a variety of languages (BASIC, C, C++, C# and Java just to name a few). And I concur. I've never had need of such a service or seen a need for such a service. That doesn't mean that pattern isn't useful. But it's also not solving a "common" problem.

    While it seems that you might have stumbled upon a solution, I would urge you to rethink it. It's possible that you're solving the problem in the best way possible, but sorry to say, that doesn't seem likely. And while what you're doing may even work and solve your problem, it just feels like you're going about this in the wrong way. It feels like you're designing an aircraft to go across the street to 7-11 when all you really need to do is open the door and walk.

    It's a problem called over-engineering. You might have a workable solution. But getting things "working" is only a part of being a good programmer. You also need something that is readable, easy to understand, maintainable, etc. One thing I've learned over the years is that the more clever a person gets with their code, the less maintainable it usually turns out to be. That doesn't mean replace clever code with bad code. It just means that "getting it to work" is only a small part of the problem. Especially once you work in a team environment where you're not the only person working with your code.

    There are almost always more than one way to solve a problem. From what I've heard, I think you're doing it wrong. On the other hand, you're also asking questions, reading, learning. The solution you've arrived at is quite impressive for a new person. So trust me when I say I intend no disrespect. I just think you're over-thinking things and most likely not yet grasping a key concept where all this just clicks. If this is the only solution you see at this point, by all means, carry on. Learning how to do something the hard way or wrong way can be as valuable as getting it right. Sometimes it's all about learning what NOT to do. :)
     
  22. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #22
    Congratulations! You have just reinvented global variables.

    Unfortunately, you are well over a half century late with this being an original idea, as global variables were present in the very first computer languages (possibly in Turing machines as well).

    C supports using global variables just dandy. I use lots of them (in small iOS apps that I never intend to extend, reuse the code, or show any hiring managers. :)
     
  23. MEJHarrison macrumors 6502a

    Joined:
    Feb 2, 2009
    #23
    I too thought of the global thing just after posting the other day.

    Also, A can now see B and B can see A. You've fixed that problem. But introduced a new one. The problem is A & B can now also see object F. A & B shouldn't see F. They shouldn't know F even exists. Yet they can see it and every other object in the system.
     
  24. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #24
    Programs don't "know" anything. They are just strings of code bits. The problem is what the programmers knows, then forgets, or the person who has to maintain the program later doesn't know, and thus makes a big buggy mess.

    Otherwise, global variables are just great.
     
  25. MEJHarrison macrumors 6502a

    Joined:
    Feb 2, 2009
    #25
    I'm well aware of that. It's still a bad practice. Otherwise, we'd just make everything global and be done with it.
     

Share This Page