[Long] Modular design and issues
[Long] Modular design and issues
- Subject: [Long] Modular design and issues
- From: Fabio Mancinelli <email@hidden>
- Date: Tue, 13 Mar 2007 10:31:37 +0100
Dear all,
I am developing a Cocoa application and I have some issues at the
design level, so I wanted to ask you what are the "best practices" in
these cases.
My (CoreData) application has 3 Nibs:
1) MainMenu.nib which contains the main window and the
ApplicationController. The main window has a button for managing
"categories" in the data store. (Just for completeness, a Category is
an entity with a name attribute).
2) ManageCategories.nib which contains a window that presents the
list of the currently defined categories and buttons for adding and
removing them. The owner of this Nib file is a
ManageCategoriesController object that subclasses NSWindowController
and implements the application logic.
3) EditCategory.nib which contains a window that has the UI for
creating a new "category", i.e., a "name" text field and two buttons
"OK" and "Cancel". Again, the owner of this Nib file is a
EditCategoryController object that subclasses NSWindowController and
that implements the application logic.
Both ManageCategoriesController and EditCategoryController have the
following designated initializer:
- (id)initWithManagedObjectContext:(NSManagedObjectContext *)moc
This is necessary because both of them need a CoreData context, and
since the objects that will use it (through bindings) reside in
different Nibs I need a way to "propagate" this context from the
ApplicationController instance in the MainMenu.nib to other Nibs.
The ApplicationController code for handling the "manage categories"
action is very simple (and standard):
if(manageCategoriesController == nil) {
manageCategoriesController = [[ManageCategoriesController alloc]
initWithManagedObjectContext:[self managedObjectContext]];
}
[manageCategoriesController showWindow:self];
Everything works fine. The "manage categories" window shows up and
the table is correctly filled with all the information regarding the
available "categories". This design is good because the "manage
categories" functionality is well isolated and loosely coupled (I
might "outsource" completely the development of this part to another
person and "just (re)use it").
So I wanted to apply this design principle to the "edit category"
functionality.
In the "add" action of ManageCategoriesController I do the following:
if(editCategoryController == nil) {
editCategoryController = [[EditCategoryController alloc]
initWithManagedObjectContext:[self managedObjectContext]];
}
[editCategoryController showAddCategorySheetOnWindow:[self window]];
This time, instead of calling showWindow, I call a custom method that
presents the edit category window as a sheet attached to the manage
category window.
Again everything seems to work fine but... When
showAddCategorySheetOnWindow is called, the outlets that are
connected to the Nib elements (mostly to object and array
controllers) are not initialized. In fact, by putting some NSLog in
different methods I get the following trace:
1) addCategory:(id)sender (in ManageCategoriesController)
2) initWithManagedObjectContext:(NSManagedObjectContext *)moc in
EditCategoryController
3) showAddCategorySheetOnWindow:(NSWindow *)window in
EditCategoryController
4) awakeFromNib in EditCategoryController
The code for initWithManagedObjectContext:(NSManagedObjectContext *)
moc in EditCategoryController invokes
[super initWithWindowNibName:@"EditCategory"], but when it returns
the Nib is still not initialized (this is reasonable otherwise the
awakeFromNib would be useless).
I might modify the design, getting rid of EditCategory.nib and
putting all its content in ManageCategories.nib. And this would be
conceptually acceptable.
I can create an instance of EditCategoryController in the Nib file,
and link it to an outlet of ManageCategoriesController. In this way,
the "add" action would call the showAddCategorySheetOnWindow on an
instance that already exists.
But here I would have another problem. By instantianting the
EditCategoryController in the Nib file I cannot call the initializer
that accepts the CoreData context as parameter, and I have to find a
way to communicate this context to the EditCategoryController instance.
I see two ways for doing this:
1) I can create a setManagedObjectContext method in
EditCategoryController and call it from the awakeFromNib method of
ManageCategoriesController. But this is ugly because it implements a
2-step initialization that is error-prone.
2) I can create an outlet in EditCategoryController and link it to
the instance of ManageCategoriesController. So when I need the
CoreData context I just send the managedObjectContext message to this
outlet and retrieve the context. This is also ugly because it
increases the coupling between the two classes.
All the three solutions have "problems" and I cannot identify which
is the "best one" to refine. So the question is: what are the "best
practices" for modularizing Cocoa applications? The example presented
here is quite trivial but it shows some issues that might be relevant
in bigger projects. How do you deal with these issues? Are there
other "design-patterns" that avoid the previously described problems?
Am I missing something?
Thank you for having read such a long post and for your answers.
See you,
Fabio
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden