Saturday, July 31, 2010

Agile Data modeling, de-normalization, and other important factors

This subject probably deserves an entire book, but in the essence of keeping this blog post short, I've tried to highlight some of the more important data modeling tasks related to conceptual, logical, and physical data model design. Please note, this is not meant to be exhaustive. Relational models, object-relational models, and object models are not always the right solution for the problem. There are many great solutions available in the NoSQL area, and there is nothing wrong with a hybrid solution.

Software applications that are compiled on specific machine architectures often store and retrieve information from database software systems. Web server platforms often interpret machine-independent script that stores and retrieves information from database software systems. Java bytecode is executed by a Java Virtual Machine, and data is stored and retrieved from database software systems.

Efficient storage and retrieval of information from database software systems are certainly dependent on underlying hardware and operating system software characteristics. However, efficient storage and retrieval of information is also dependent on the structure and efficient execution of query statements that are used to store and retrieve the information. In a purely academic world, data is modeled and normalized in 3NF, 4NF, and 5NF forms. However, higher-order normalized forms do not always promote the creation of optimal query statements. Therefore, certain parts of a data model are often denormalized to improve the read performance of the database software system.

At a high level, joins between multiple, large relations are generally expensive, so denormalization reduces this cost. Reducing the cost of something typically results in inconsistencies or redundancies in the data, so the developer(s) are left with the job of minimizing the amount of redundant data. A formal process typically alleviates this strain.

Defining the I/O characteristics of a database is an important precursor to data modeling. Often times, the I/O characteristics of the database are not defined before modeling the data. Nevertheless, there are a few basic tasks and questions that can help define the I/O characteristics of the database. What is the purpose of the database and what types of problem(s) does the database solve? What types of operations (read, write) will be performed on the database? How many users will the database support? Define user stories - short, succinct 1-3 sentence action statements. Define as many as needed from both the developer perspective and the user perspective. The user stories will help define the conceptual data model for the domain from which the logical data model can be created. A clear definition of the purpose of the system will aid in defining the read/write (I/O) characteristics of the database software system, thus forming a picture of the system. For instance, OLTP databases typically support short transactions, so it is important that write latency is minimized. The answers to the questions above will also help determine the type of hardware storage configuration needed. Another important question when determining the type of hardware configuration is the following. How much downtime can be afforded, and how much failover is needed?

At this point, the types of queries can be seen that will be run on the database with heavy consideration given to the I/O characteristics of the database and the types of joins and scans preferred for the query optimizer to ideally use.

Agile data modeling can be defined as continual iterative feedback with the ability to add entities and relationships, or slice off sections of a data model in various sizes, at any point in the project. This may seem difficult but can be accomplished. Whether the database architecture adheres to the relational model, object-relational model, or object model, the proper classification of entities and attributes, in conjunction with a balance of normalized and de-normalized groups of data, will allow the addition and subtraction of small and large chunks of relations from the data model throughout the development process; for a specific domain. Formal algorithms can be used to map entity relationship models to relations.

And how is this done? Continually modeling entities within the real world. Abstracting classes, re-factoring, keeping the hierarchy semi-flat, avoiding deep polymorphic behavior, and always embracing changes to the data model while never generalizing with a one size fits all approach.

It's important to note that data modeling is a crucial step in designing a database software system that efficiently stores and retrieves information. This process involves defining the I/O characteristics of the database, understanding the purpose of the system, and creating a conceptual data model for the domain. From there, a logical data model can be created, followed by a physical data model that considers the hardware storage configuration needed. Agile data modeling allows for continual iterative feedback, and the proper classification of entities and attributes, in conjunction with a balance of normalized and de-normalized groups of data, will allow for the addition and subtraction of small and large chunks of relations from the data model throughout the development process. Overall, data modeling is a critical aspect of creating an efficient and effective database software system.

Close to Optimal Data Modeling

Agile Data modeling, de-normalization, and other important factors

This subject probably deserves an entire book but in the essence of keeping this blog post short, I've tried to highlight some of the more important data modeling tasks related to conceptual, logical, and physical data model design. Please note, this is not meant to be exhaustive. Relational models, object relational models, and object models are not always the right solution for the problem. There are many great solutions available in the noSQL area and there is nothing wrong with a hybrid solution.

Software applications that are compiled on specific machine architectures often store and retrieve information from database software systems. Web server platforms often interpret machine independent script that stores and retrieves information from database software systems. Java byte code is executed by a Java Virtual Machine and data is stored and retrieved from database software systems.

Efficient storage and retrieval of information from database software systems is certainly dependent on underlying hardware and operating system software characteristics. However; efficient storage and retrieval of information is also dependent on the structure and efficient execution of query statements that are used to store and retrieve the information. In a purely academic world, data is modeled and normalized in 3NF, 4NF, and 5NF forms. However; higher order normalized forms do not always promote the creation of optimal query statements. Therefore, certain parts of a data model are often de-normalized to improve the read performance of the database software system. At a high level, joins between multiple, large relations are generally expensive so de-normalization reduces this cost. Rreducing the cost of something typically results in inconsistencies or redundancies in the data so the developer(s) is left with the job of minimizing the amount of redundant data. Formal process typically alleviates this strain.

Defining the I/O characteristics of a database is an important precursor to data modeling. Often times, the I/O characteristics of the database are not defined before modeling the data. Nevertheless, there are a few basic tasks and questions that can help define the I/O characteristics of the database. What is the purpose of the database and what types of problem(s) does the database solve? What types of operations (read, write) will you be performing on the database? How many users will the database support? Define user stories - short, succinct 1-3 sentence action statements. Define as many as you need from both the developer perspective and the user perspective. The user stories will help define the conceptual data model for the domain from which the logical data model can be created. A clear definition of the purpose of the system will aid in defining the read/write (I/O) characteristics of the database software system. Thus forming a picture of the system. For instance, OLTP databases typically support short transactions so it is important that write latency is minimized. The answers to the questions above will also help determine the type of hardware storage configuration needed. Another important question when determining the type of hardware configuration is the following. How much downtime can we afford and how much failover do we need?

At this point, we can begin to see the types of queries that will be run on the database with heavy consideration given to the I/O characteristics of the database and the types of joins and scans that we would like for the query optimizer to ideally use.

Agile data modeling - Continual, iterative feedback. The ability to add entities and relationships, or slice off sections of a data model in various sizes, at any point in the project. This may seem difficult but can be accomplished. Whether the database architecture adheres to the relational model, object-relational model, or object model, the proper classification of entities and attributes, in conjunction with a balance of normalized and de-normalized groups of data, will allow the addition and subtraction of small and large chunks of relations from the data model throughout the development process; for a specific domain.

Formal algorithms can be used to map entity relationship models to relations.

And how is this done? Continually modeling entities within the real world. Abstracting classes, re-factoring, keeping the hierarchy semi-flat, avoiding deep polymorphic behavior, and always embracing changes to the data model while never generalizing with a one size fits all approach.

Saturday, July 24, 2010

High Performance Database Development

Fast, High performance, database driven, application architectures that support true rapid development are little talked about. AOLServer, OpenACS, PostgreSQL, and TCL are such a combination.

I was introduced to AOLServer and OpenACS in 2002 by a close friend who I grew up with. We built a very robust application architecture over the course of the following 6 years.

PostgreSQL was sitting behind the AOLServer/OpenACS instance and AOLServer nicely managed the database connection pools. AOLServer is multi-threaded and internally handles TCL interpretation and execution. TCL makes heavy use of lists (implementation notes aside), so many LISP programmers have enjoyed working with it.

The OpenACS developer toolbar is a tool that provides developers with access to various debugging and profiling information about their OpenACS application. It is a feature that is built into the OpenACS application framework and can be enabled or disabled depending on the needs of the developer.

Once enabled, the developer toolbar is accessible via a web browser and provides a range of information about the current page, including SQL queries, response times, and server resources. This information can be used to optimize and debug an OpenACS application, allowing developers to quickly identify and fix performance issues.

The OpenACS developer toolbar is just one of the many tools available to developers using the AOLServer, OpenACS, PostgreSQL, and TCL stack. Together, these technologies provide a fast, high-performance, database-driven application architecture that supports rapid development.

Monday, July 19, 2010

Dtrace on FreeBSD 8

 Dtrace on FreeBSD 8 - new server with no load

# uname -msri
FreeBSD 8.0-RELEASE-p3 amd64 DEV_A64_KERNEL

From the OpenSolaris DTrace Toolkit

# /usr/local/share/DTTraceToolkit/syscallbypid.d
Tracing... Hit Ctrl-C to end.
  77913 perl                     sigprocmask                    48
  1267 svscan                   stat                           51
 45001 httpd                    read                           52
 26063 python2.4                recvfrom                       61
 26922 sshd                     ioctl                          69
 27104 more                     read                           69
 26888 postgres                 getppid                        78
 26888 postgres                 gettimeofday                   78
 26888 postgres                 select                         78
 26889 postgres                 getppid                        78
 26889 postgres                 select                         78
 45001 httpd                    poll                           81
 27102 postgres                 read                           82
 27103 postgres                 read                           82
 27105 postgres                 read                           82
 27101 dtrace                   clock_gettime                  97
 26063 python2.4                select                        102
 45001 httpd                    writev                        118
 44966 python2.4                read                          121
 26890 postgres                 read                          162
 26063 python2.4                read                          179
 26063 python2.4                _umtx_op                      186
 27104 more                     write                         205
 26063 python2.4                write                         208
 26891 postgres                 write                         300
 27101 dtrace                   ioctl                         301
 26922 sshd                     write                         304
 26922 sshd                     read                          306
 27054 psql                     poll                          378
 27054 psql                     recvfrom                      378
 27055 postgres                 sendto                        379
 26922 sshd                     select                        609
 26922 sshd                     sigprocmask                  1218
 27054 psql                     write                        3203

 

# /usr/local/share/DTTraceToolkit/rwbypid.d
78168  sshd                        R       39
 97062 squid                       R       58
 45164 httpd                       W       81
 97062 squid                       W       95
 97474 python2.4                   R       98
   555 pflogd                      R      132
 45164 httpd                       R      186

 

# dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'

CPU     ID                    FUNCTION:NAME
  0  25202                       open:entry svscan .
  0  25202                       open:entry imapd ./cur
  0  25202                       open:entry imapd ./new
  0  25202                       open:entry imapd ./courierimapkeywords/:list
  0  25202                       open:entry imapd ./courierimapkeywords
  0  25202                       open:entry svscan .
  2  25202                       open:entry postgres pg_stat_tmp/pgstat.tmp
  7  25202                       open:entry postgres global/pg_database
  7  25202                       open:entry postgres pg_stat_tmp/pgstat.stat
  7  25202                       open:entry postgres pg_stat_tmp/pgstat.stat
  7  25202                       open:entry postgres pg_stat_tmp/pgstat.stat
  4  25202                       open:entry tinydns data.cdb
  5  25202                       open:entry tinydns data.cdb
  0  25202                       open:entry svscan .
  0  25202                       open:entry svscan .
  0  25202                       open:entry svscan .
Syscalls count by process

# dtrace -n 'syscall:::entry { @num[pid,execname] = count(); }'
 28820  qmailmrtg7                                                      158
    28825  qmailmrtg7                                                      158
    27504  postgres                                                        159
    28776  cron                                                            234
    28853  bash                                                            245
    28861  bash                                                            245
    28869  bash                                                            245
    28877  bash                                                            245
    28798  qmailmrtg7                                                      264
    28777  newsyslog                                                       293
    28772  dtrace                                                          322
    28778  sh                                                              327
    28281  httpd                                                           542
    28900  svn                                                             691
    28903  svn                                                             740
    28902  svn                                                             748
    28904  svn                                                             748
    28901  svn                                                             758
    28780  perl                                                           3023

 

# Files opened by process
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
CPU     ID                    FUNCTION:NAME
  4  25202                       open:entry svscan .
  0  25202                       open:entry squid /usr/local/plone/<domain-name>-dev.com/var/squidstorage/08/0C
  4  25202                       open:entry svscan .
  4  25202                       open:entry svscan .
  4  25202                       open:entry svscan .
  0  25202                       open:entry imapd ./.Spam/tmp/1279591336.M11620P234573_courierlock.dev.<domain-name>.com
0 25202 open:entry imapd ./.Spam/tmp/1279591336.M11620P234573_courierlock.dev.<domain-name>.com
0 25202 open:entry imapd ./.Spam/tmp 0 25202 open:entry imapd ./.Spam/tmp/1279591336.M11867P28573_imapuid_15.dev.<domain-name>.com
0 25202 open:entry imapd ./.Spam/courierimapuiddb 0 25202 open:entry imapd ./.Spam/tmp/1279591336.M113467P28573_imapuid_15.dev.<domain-name>.com 0 25202 open:entry imapd ./.Spam/cur 0 25202 open:entry imapd ./.Spam/new 0 25202 open:entry imapd ./.Spam/courierimapkeywords/:list 0 25202 open:entry imapd ./.Spam/courierimapkeywords 0 25202 open:entry squid /usr/local/plone/abcdexcrfdsf-dev.com/var/squidstorage/09/0C 4 25202 open:entry svscan .

Thursday, May 27, 2010

bsdtalk186 - Soft Updates w/ Journaling & ULE Sched

FreeBSD Soft Updates with Journaling, ULE Scheduler

Very good short interview with Jeff Roberson, FreeBSD Committer.Discussion on the addition of journaling to soft updates and the development of the ULE scheduler.

BSD Talk Blog - Jeff Roberson (February 05, 2010)

You can also listen on your Android device. Just download Google Listen from the marketplace. After you setup Google Listen on your Android Device, search for bsdtalk or FreeBSD from within Google Listen.

Tuesday, May 4, 2010

Single Thread Object Communication

When objects in a single thread are loosely coupled and need to communicate with each other, Notifications allow you to broadcast messages on a synchronous or asynchronous basis and still retain object independence.

When you implement Store Kit in your application, it is most likely a reasonable assumption that you want to re-use your in-app store in a future iPhone application without rewriting the object(s) that implement the SKPaymentTransactionObserver and SKProductsRequestDelegate protocols. We know that these objects receive asynchronous notifications via the delegate protocol(s) that they implement. So in a nutshell, the object that implements the SKProductsRequestDelegate protocol will receive a response asynchronously when the product identifier request that it previously sent is successfully processed. The payment transaction observer object, which is added as an observer to the payment queue upon application launch, again receives asynchronous notifications when there's stuff to do in the payment queue.

When your transaction observer receives notifications from the payment queue that there are updated transactions, completed transactions, or failures, it is most likely the responsibility of the observer object to process these notifications. The processing of these notifications most likely entails application specific logic. So rather than loading up your transaction observer with application specific logic, the NSNotification center provides a clean way of synchronously or asynchronously(via Notification Queues) notifying other objects within the same thread. There is also an NSDistributedNotificationCenter for broadcasting messages to objects in other threads.

By using the NSNotification center, you can separate the application-specific logic from the observer object that receives notifications from the payment queue. This allows for a cleaner and more modular design, as each object can focus on its specific responsibilities without being tightly coupled to other objects. In addition, the NSNotification center provides a flexible way to communicate between objects within the same thread or across different threads using the NSDistributedNotificationCenter. This makes it easier to reuse and refactor code, which can save time and effort in the long run.

Monday, May 3, 2010

Creating a Mobile App for the iPhone

In the coming weeks, I plan on covering the development process from start to finish. I will be talking about code organization, memory management, useful xcode features, core data, performance optimization, debugging, iterative development, and any other useful topics that I come across.

iLogMiles was approved by Apple for sale on the App store, on April 6, 2010. iLogMiles is free to download. The app quickly hit the #2 spot on the top free business apps list. The user can upgrade to the full version and purchase themes from within the free application. We utilized the Apple Store Kit framework to provide the in-app store. The Store Kit framework provides the necessary means to securely process payments from within the application. Products are identified via product identifiers. Apple clearly defines the types of products that may be sold via the Store Kit framework. More on this later but keep in mind that it is very important to read through all of the documentation.

Over the next few weeks, we will be talking about the mobile application development process. To give you some background on me, I started with C++ in 1997. At the time, I mostly used the GNU compilers on FreeBSD and Linux and Sun workshop on a SPARCstation. And for the C++ courses I was taking, Borland in a Win environment. To get up to speed on iPhone OS, I purchased the WWDC 2009 sessions and watched them all (at the gym on my iPhone). I attended the iPhone tech talk tour in San Jose and I listened to any and all of the available iPhone development podcasts (at the gym) that I could find. I poured through all of the books that I could get my hands on. I read the iPhone OS programming guides on the iPhone OS developer connection. XCode also has integrated documentation for the Apple API's. I've always used vi/vim with ctags, so I had to force myself to watch the xcode screencasts (available via third-party on the Internet). There are lots of great xcode tips out there and you can print out a summary page with all of the cute shortcuts - if you are so inclined to do so. I found it quite helpful to print the shortcuts page.  Design patterns are at the core of how the Cocoa frameworks interact. Apple provides solid documentation on Cocoa design patterns in the iPhone OS Reference Library and these patterns can be understood at a high-level without delving into any code. This is my suggested approach. If you are not familiar with design patterns, the gang of four book (the GOF book as most often termed in the software world) - Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, is the official source for design patterns. The theory behind Cocoa's design patterns can be found in this book and for that matter, the use of design patterns in any modern object-oriented software system can be found in this book. The GOF book describes design patterns in a language independent manner. Familiarizing yourself with Cocoa's design patterns from a language independent perspective is a key starting point for building an iPhone application.

Continuing on the topic of cocoa design patterns, Apple's frameworks are designed for re-use. There are folks out there who are very experienced with design patterns and are able to layer design patterns on top of the cocoa frameworks. These individuals understand all of the memory implications. They understand MVC backward and forward and they understand the Cocoa design patterns backward and forward. If you do not fall into this category, then keep it simple. If there is one problem that I have seen across forums and code samples on the Internet, it is that of "fighting the apis". It is very important to not fight the apis. The apple documentation describes the proper use of the iPhone OS frameworks and associated API's. The Apple developer connection provides plenty of sample code so it is important to read through this code to understand the proper use of the iPhone OS APIs.

From inception to app store approval, we spent 5 months developing iLogMiles. While this may seem longer than the standard "2 month" development lifecycle, I can assure you that iLogMiles uses a wide variety of the iPhone OS frameworks. In the coming weeks, we plan on covering the development process from start to finish. I will be talking about code organization, memory management, xcode features, core data, performance optimization, debugging, iterative development, and any other topics that we see useful.

Apple, the Apple logo, iPhone, iPod touch, and iTunes are trademarks of Apple Inc., registered in the U.S. and other countries. iPad is a trademark of Apple Inc. App Store is a service mark of Apple Inc.

Monday, February 1, 2010

Objective-C Categories

Categories are a powerful tool for extending the functionality of existing classes in Objective-C. However, it's important to follow Apple's guidelines when using them to avoid any undefined behavior.

Categories allow you to extend the functionality of an existing class without subclassing. Before I get into an example, here are a few guidelines to follow when using categories. Apple recommends to not use categories to override methods in other classes, inherited classes, or other categories. Categories are not meant to add instance variables to classes either. If used in such contexts, the behavior of a program is undefined. Apple recommends using categories for adding functionality to large, existing classes and then grouping that functionality accordingly. Overriding existing Cocoa methods that are inherited from within the Cocoa hierarchy is a no-no as is extending methods that are already part of a category within the Cocoa hierarchy. Categories allow the addition of methods to existing classes while retaining the scope of class instance variables. So here's an example. Categories are quite simple to create and very powerful.

myCategory.h
@interface UIViewController(myCategory)
- (void)messageName:(double)arga keywordA:(double)argb keywordB:(NSString *)argc;
myCategory.m
#import "myController.h"

@implementation UIViewController(myCategory)
- (void)messageName:(double)arga keywordA:(double)argb keywordB:(NSString *)argc {
// process arguments
// do something with ivar
// ...
}
myController.h
#import "myCategory.h"
@interface myController : UIViewController {

   someType ivar;
}

- (void) someMessage;
...
@end
myController.m
#import "myController.h"

@implementation

- (void)someMessage {

   [self messageName];  // send message to self - i.e. call method defined by category
}

@end

Sunday, January 24, 2010

Core Data

I was fortunate to attend the iPhone Tech Talk conference, hosted by Apple Inc. in San Jose last October, 2009. One of the sessions I attended was on Core Data. At a very high level, Core Data is an Apple™ software framework for storing data on the computer - namely, the iPhone and the Mac. Please note that I don't plan on covering database design theory in this post so I'm assuming a familiarity with it.

Core data is an Object graph management and persistence framework. Core data maintains a graph of objects (otherwise known as a managed object graph or managed object context). References to managed objects are stored in the object graph. Core Data serializes these objects and persists them to a data store. Core data can use several different underlying data stores - xml, binary, sqlite. The managed object context is a key concept in Core Data, as it provides a proxy between the application objects and the underlying data store(s). The persistent store coordinator is responsible for managing the relationship between the managed object context and the persistent store(s). A managed object context wraps a collection of managed objects and sits on top of a persistent store coordinator which houses one or more persistent stores. A managed object context is created via an instance of the NSManagedObjectContext class.

It's important to note that the Core Data sqlite file should not be accessed directly from within code, as the schema may change and it's not intended for direct manipulation.

In Summary, a managed object context is a collection of managed objects. Managed objects are instances of the entities that are defined in the data model. A managed object represents a row of data in a table. The managed objects context sits on top of a persistent store coordinator. The managed object context is a proxy between the objects in the application and the underlying data store(s). A persistent object store is represented by a xml, binary, or sqlite file. The persistent store coordinator sits between the managed object context and the persistent store(s). The persistent store coordinator in turn abstracts one or more persistent object stores as a single aggregate. Please note, a persistent store coordinator can only be associated with one managed object context. But a persistent store coordinator can have many persistent object stores. The managed object context talks directly to the persistent store coordinator. The managed object context is a scratchpad of managed objects.
After working with Core Data, it is a worthwhile exercise to open the core data sqlite file and dig through the tables. A quick look through the tables will explain how Apple is handling referential integrity. The Core Data sqlite file is "not meant" to be accessed directly from within code. Do not modify it or attempt to write queries against it. There is no guarantee that the schema will not change. Core Data is meant to abstract implementation dependent details (i.e. the implementation may change upon any future releases).

The following notes were derived from three sources: Apple WWDC 2009, the iPhone Core Data session in San Jose last October, and my experience working with object/relational databases.

Creating a Core Data Stack

  1. Load the Data Model
  2. Create the persistent store coordinator and set the model
  3. Add the data store
  4. Create a managed object context and set the persistent store coordinator

Core Data Model

  1. A Core Data model does not need to be normalized. Define data contracts early on. Don't over tighten the data model - design with usage patterns in mind. Define entities or tables with Xcode's visual editor. (core data objects represent rows in these tables). In other words, a Core Data object (row of data) of type PERSON is an instance of the PERSON entity in the Core Data model. Of course, a person object will have relationships with other objects in the database. A Core Data Managed object context manages these objects, their relationships, and persists them to the underlying data store (via the persistent store coordinator). Core Data is simple to setup. Don't complicate it.
  2. NSManagedObjectContext defines the verbs (CRUD or fetch/insert/delete/save) that act on managed objects (nouns)
  3. NSManagedObjectContext tracks changes to properties in the data model
  4. Core Data fits very well in the MVC architecture.
  5. An NSPersistentStoreCoordinator can have multiple persistent stores(NSPersistentStore) and multiple Managed Object Contexts can use a single NSPersistentStoreCoordinator
  6. It is possible to delete the sqlite store file if the stored data needs to be deleted. This file is stored in $HOME/Library/Application Support/iPhone Simulator/User/Applications/SOMEAPPLICATIONGUID/Documents
  7. Use Core Data migration or built-in versioning for model changes. easy to use. zero code.

Multithreading

  1. Core data assigns one managed object context per thread; use notifcations for changes made to managed objects within a managed object context.
  2. never pass managed objects between threads, pass object IDs (actually the primary key)
  3. within a thread, create a new Managed object context and then tell the new Managed object context what objects IDs to fetch

Fetching

    Use NSFetchedResultsController (break up fetches into sections) - it is fast, efficient, and easy.
  1. Create an NSFetchedResultsController
  2. Set the fetch request, predicate, and sort descriptors. fetch request provides predicate and sort descriptors). fetch request and predicate are immutable.
  3. the keypath returns the section name (section information is cached)
  4. set yourself as its delegate and implement your tableview methods
  5. Create separate controllers for different data sets

NSFetchRequest

  1. set the entity that you want to fetch against
  2. create NSEntityDescription - provide managed object context and entity you want to work with
  3. set the predicate (if applicable)
  4. Fetch - pass in fetch and error

Batching

  1. setup fetch request (only need some of the objects at a time so setBatchSize:)
  2. set batch size
  3. you get back an NSArray of results

Prefetching

  1. use setRelationshipKeyPathsForPrefetching:

Managed Object Interaction

    NSManagedObject
  1. Use accessors
  2. Objective-C properties
  3. To Many relationships are sets
  4. NSManagedObjects provides Key value coding/observing out of the box
  1. Managed Object Context observes object changes. Leverage change tracking notifcations
  2. Register for Object Level Changes (KVO)
  3. Register for Graph Level Changes (NSNotifications)


Iterate over Custom UITableViews

UITableViews on the iPhone often contain a variable number of cells. The following code snippet should be helpful for those who need to iterate over a variable length table and subsequently read or set data model and cell state.
   //loop through cells in each section and make sure the data model is in sync 
   NSInteger numSections = [self numberOfSectionsInTableView:someTable];
   for (NSInteger s = 0; s < numSections; s++) { 
      NSLog(@"Section %d of %d", s, numSections); 
      NSInteger numRowsInSection = [self tableView:someTable numberOfRowsInSection:s]; 
      for (NSInteger r = 0; r < numRowsInSection; r++) {
         NSLog(@"Row %d of %d", r, numRowsInSection); 
         MyCell *cell = (MyCell *)[someTable cellForRowAtIndexPath: 
                                  [NSIndexPath indexPathForRow:r inSection:s]]; 
         DataModelObject *theObject = (DataModelObject *)[fetchedResultsController objectAtIndexPath:
                                                         [NSIndexPath indexPathForRow:r inSection:s]]; 
         [theObject setValue:[NSNumber numberWithBool:MyCell.someProperty] forKey:@"someEntityKey"]; 
      } 
   }