I'm trying to gain insight into the least overhead solution to tracking model object changes in Cocoa.
As I see it there are 3 options:
Use Core Data – lot's of functionality exists for monitoring model object changes (Core Data NSManagedObject - tracking if attribute was changed). I don't know what the overhead of Core Data's management infrastructure is compared to other approaches but it's well established architecture for multi-threading support is a plus. For cross-platform devs there is some downside in not having a readily accessible schema but there are ways around that issue.
Write custom accessors that mark the object as dirty when updating a field with a new value. I've been using this technique with mixed success for quite some time. There are some sticky issues to deal with when sharing objects across threads. You also don't get the benefits of enhancements to automatic synthesis of attributes, etc. You do, however, have greater control of your data store than when using Core Data which can be of benefit (eg. certain operations can be done in a SQL store across many objects in a much more efficient way). Note: There could be a lot of variation here depending on how you write the accessors. For the sake of conversation let's assume setters make a check of the new value against the old one, make appropriate calls to KVO (willChange / didChange), and set a boolean flag (all within synchronization of course).
Use KVO to monitor object fields (ala keyPathsForValuesAffectingValueForKey:) and mark the object as dirty in the KVO callout. I have yet to use this method but it seems like a decent approach. The obvious downside would be the callout every time a setter is called.
I am inclined to think that option 2 has the lowest overhead (in terms of raw processing requirements) given that Core Data and KVO both have some additional overhead either in the generated accessors or in the KVO callouts. The question is, how substantial is the overhead?
And lastly, did I miss an option?
Thanks.
Related
This is similar to a question I asked before, but now that I've come much further along I still have a question about "proper" subclassing of NSManagedObject as I was told last night that it's a "bad idea" to put lots of non-persisted properties and ivars inside one. Currently I have TONS of code inside my NSManagedObject, and Apple's docs don't really address the "rightness" of that. FYI: the code works, but I'm asking if there are pitfalls ahead, or if there are obvious improvements to doing it another way.
My "object" is a continuously growing array of incoming data, the properties/ivars that track the progress of the analysis of that data, and the processed data (output). All of this is stored in memory because it grows huge, very quickly, and would not be possible to re-generate/re-analyze continuously. The NSManagedObject properties that are actually persisted are just the raw data (regularly saved, as Core Data doesn't support NSMutableData), a few basic properties and 2 relationships to other NSManagedObjects (1 being a user, the other being a set of snapshots of the data). Only one object is being recorded to at any one time, although dozens can be opened for viewing (which may involve further processing at any time).
It's not possible to have the object that inserts the entity (data manager that manages Core Data) have all of the processing logic/variables inside it, as each object necessitates at least a handful of arrays/properties that are used as intermediaries and tracking values for the analysis. And I, personally, think that it sounds silly to create two objects for each object that is being used (the NSManagedObject that is the store, and another object that is the processing/temp store).
Basically, all of the examples I can find using NSManagedObjects have super simple objects that are things like coordinates, address book entries, pictures: stuff that is basically static. In that case I can see having all of the logic that creates/modifies them outside the object. However, my case is not that simple and I have yet to come up with an alternative that doesn't involve duplication.
Any suggestions would be appreciated.
You might use a 'wrapper', that is to say a class with a reference to one of your managed object instances, this wrapper would contain your algorithms and your non persisted algorithms.
I often get confused with when to use DataSource Pattern and when to use the Properties for providing configuration information to objects.
I have two ways to do this,
Generally I keep a lot of properties in the Object's class that has to be configured and a method that resets the object and continues with the new properties.
And the for the Object which is configuring the other object, I keep a method that with the name configureXYZ:WithValues: , which resets the properties and calls the reset method of the object to be configured.
This I have seen with MPMoviePlayerController, that we have to set properties.
and Other way is how tableView works, all the configuration information comes from datasource methods.
Can anyone throw more light on which way is preferred in which scenario.
Because Its often I feel tempted to use design patterns and make the code look stylish but I wanted to know when do we actually need these.
I am absolutely clear with delegate pattern and have to use it on regular basis.
DataSource was one thing I was never clear with.
When designing a class, the key factor you should consider when deciding between using a delegate or properties is how often the values can change. Properties work best if you will set the values one time and they should never change again. Delegates (of which datasource is just an example) work best if the values might change over time or change due to conditions.
For example, in UITableView, the number of rows is highly dynamic. It could change for many reasons outside of the control of the table view. What the rows even represent is highly dynamic. They might be data; they might be menu options; they might be pieces in a game. UITableView doesn't try to guess or control any of that. It moves it to a delegate (datasource) where potentially very complex decisions could be made.
MPMoviePlayerController has a few controls that mean very specific things and should almost never change (particularly once the movie starts playing). Basically you set the thing up, hit play and walk away. In that case, a delegate would likely be overkill.
There are many cases that are in the middle, and either way may be ok. I would encourage developers to consider delegation first, and then if it doesn't make sense go with properties. This isn't because delegation is always the right answer, but more because most C++- or Java-educated developers don't think in terms of delegation, so should make a conscious effort to do so.
Some other thoughts along these lines:
When using properties, it is ideal if they are configured at initialization time and are thereafter immutable. This solves a great number of problems.
If you find yourself needing a lot of properties, delegation is probably better and often simpler.
Delegate notification methods (somethingDidHappen:) are often better implemented as blocks. (Blocks are relatively new in ObjC. Many delegate-based Apple interfaces are moving to blocks, but you'll see a real mix out there for historical reasons.)
The difference between "delegate" and "datasource" is that a delegate manages behavior, while a datasource provides data. They are typically implemented identically.
It mostly depends on the dynamics of the class. UITableView is a very dynamic interface element. Its data comes and go. You can add/remove/edit/sort. You can interact with it. IF you assign properties to a tableView, it loses some of the properties that makes it as robust as it is. MPMoviePlayerController, on the other hand, has a different purpose. I have never used this class but by the looks of it, it reads one video file and provides playback. There is not many changes to it, so properties makes a lot of sense.
If you are writing a class, and you need that class to be as flexible as possible(UIPickerView, UITableView), having delegates allows you to do so. If your class only works with limited configuration after initialization, you could be better by taking the property approach.
So this seems like a fairly simple answer to a common problem: Infinite loop detected in Jackosn. If, when serializing an object tree, Jackson comes upon an object it has already serialized why doesn't it just ignore it? Is there a way to do this in Jackson, or has someone created something similar?
Why all this mucking around with JsonManagedReference/JsonBackReference, which is completely insufficent if you start serializing child objects (which need a reference to the parent) some of the time and you are serializing parent objects some of the time (which obviously doesn't want the child to refer back to itself)?
It seems like now I have to create custom views that take into account every type of circular reference and use case possible which in any non-trivial ORM is a huge task.
EDIT (October 2012)
Jackson 2.x actual now DOES support identity information handling with #JsonIdentityInfo annotation! So the original answer is bit out of date...
OBSOLETE
Jackson does not support handling of object identity: this is a non-trivial task not so because of identifying shared objects which can be done by traversing object graph (incurring some overhead), but rather in figuring out how to include identity information; which ids to use and how. This in turn is somewhat similar to inclusion of type information, but now adds second dimension of extra wrapping to handle.
Doing this has been requested before, and some thought has gone into figuring out how to do it, but ratio of effort to benefit (i.e. number of requests, how badly it is needed) has been higher than adding other features.
So your best bet is to use wrapper objects and implement this manually, or have a look at XStream which can solve this (when enabled; it adds significant overhead in time) and also has JSON output mode using Jettison.
Implementing this manually for your use case is bit easier than solving the general case: you could start with BeanSerializerModifier to add wrapper handler that can keep track of object identities, and know what to serialize instead as object id.
I am creating a simple application using the MVC design pattern where my model accesses data off the web and makes it available to my controllers for subsequent display.
After a little research I have decided that one method would be to implement my model as a singleton so that I can access it as a shared instance from any of my controllers.
Having said that the more I read about singletons the more I notice people saying there are few situations where a better solution is not possible.
If I don't use a singleton I am confused as to where I might create my model class. I am not over happy about doing it via the appDelegate and it does not seem viable to put it in any of the viewControllers.
any comments or pointers would be much appreciated.
EDIT_001:
TechZen, very much appreciated (fantastic answer as always) can I add one further bit to the question before making it accepted. What are your thoughts on deallocating the singleton when the app exits? I am not sure how important this is as I know quite often that object deallocs are not called on app teardown as they will be cleared when the app exits anyway. Apparently I could register the shared instance with NSApplicationWillTerminateNotification, is that worth doing, just curious?
gary
There is a lot of push back on the use of singletons because they are often abused. Lazy coders either (1) don't put enough functionality in the singleton which results in having logic spread out in other objects like spaghetti or (2) they put in to much functionality such that the singleton becomes the entire program. Lazy coders way to often use singletons instead of doing data validation, object testing and object tracking. People get sick of trying to untangle and maintain lazy singleton use so they try to suppress the use of singletons.
I thoroughly understand the impulse and I myself ritualistically warn against singleton abuse.
However, a data model is one of the few legitimate uses for a singleton. This is especially true in small apps like those which run on mobiles. In the end, you will either use a singleton for your data model or you will attach it to a singleton.
For example, suppose you decide to park your non-singleton data model object in the app delegate. Well, you've done this: dataModel-->appDelegate-->application(singleton). To access it, you would call:
[[[UIApplication sharedApplication (a singleton)] delegate] theDataModelObj];
Even if you pass it around like a token from object to object you will still have to have the dataModel obj begin as the property of a singleton.
When an object really does have to meet the "Highlander" pattern ("There can be only one!") then a singleton is the best choice. In addition to the application object, you have user defaults as a singleton as well as the file manager. Clearly, in all three cases, you want one and only one instance in existence for the entire app. For example, if you had more than one user defaults object, your app would be a train wreck trying to track all the preference settings. If you have more than one file manager, file operations could step on one another.
A properly designed user data model is just a larger version of user defaults. It should be the only object that directly manipulates the user's data. No other object in the app should have that task in the least. That makes the singleton design pattern the best one to use in this particular case.
Singletons are a very powerful tool but just as with a physical tools, the more power they give you, the more opportunities they create for you to cut you head off if you use them carelessly. For this reason, a singleton should seldom be your first choice. There are usually better design patterns to employ.
However, when you really need a singleton, you shouldn't shy away from using them just because the laziness of others has given them a bad rep.
Knowing when and when not to use a powerful and dangerous tool is part of the programmers intuition you develop with experience. You can't go by formula. It is one of those factors that makes good coding an art and the programmer a craftsman.
Should entities have behavior? or not?
Why or why not?
If not, does that violate Encapsulation?
If your entities do not have behavior, then you are not writing object-oriented code. If everything is done with getters and setters and no other behavior, you're writing procedural code.
A lot of shops say they're practicing SOA when they keep their entities dumb. Their justification is that the data structure rarely changes, but the business logic does. This is a fallacy. There are plenty of patterns to deal with this problem, and they don't involve reducing everything to bags of getters and setters.
Entities should not have behavior. They represent data and data itself is passive.
I am currently working on a legacy project that has included behavior in entities and it is a nightmare, code that no one wants to touch.
You can read more on my blog post: Object-Oriented Anti-Pattern - Data Objects with Behavior .
[Preview] Object-Oriented Anti-Pattern - Data Objects with Behavior:
Attributes and Behavior
Objects are made up of attributes and behavior but Data Objects by definition represent only data and hence can have only attributes. Books, Movies, Files, even IO Streams do not have behavior. A book has a title but it does not know how to read. A movie has actors but it does not know how to play. A file has content but it does not know how to delete. A stream has content but it does not know how to open/close or stop. These are all examples of Data Objects that have attributes but do not have behavior. As such, they should be treated as dumb data objects and we as software engineers should not force behavior upon them.
Passing Around Data Instead of Behavior
Data Objects are moved around through different execution environments but behavior should be encapsulated and is usually pertinent only to one environment. In any application data is passed around, parsed, manipulated, persisted, retrieved, serialized, deserialized, and so on. An entity for example usually passes from the hibernate layer, to the service layer, to the frontend layer, and back again. In a distributed system it might pass through several pipes, queues, caches and end up in a new execution context. Attributes can apply to all three layers, but particular behavior such as save, parse, serialize only make sense in individual layers. Therefore, adding behavior to data objects violates encapsulation, modularization and even security principles.
Code written like this:
book.Write();
book.Print();
book.Publish();
book.Buy();
book.Open();
book.Read();
book.Highlight();
book.Bookmark();
book.GetRelatedBooks();
can be refactored like so:
Book book = author.WriteBook();
printer.Print(book);
publisher.Publish(book);
customer.Buy(book);
reader = new BookReader();
reader.Open(Book);
reader.Read();
reader.Highlight();
reader.Bookmark();
librarian.GetRelatedBooks(book);
What a difference natural object-oriented modeling can make! We went from a single monstrous Book class to six separate classes, each of them responsible for their own individual behavior.
This makes the code:
easier to read and understand because it is more natural
easier to update because the functionality is contained in smaller encapsulated classes
more flexible because we can easily substitute one or more of the six individual classes with overridden versions.
easier to test because the functionality is separated, and easier to mock
It depends on what kind of entity they are -- but the term "entity" implies, to me at least, business entities, in which case they should have behavior.
A "Business Entity" is a modeling of a real world object, and it should encapsulate all of the business logic (behavior) and properties/data that the object representation has in the context of your software.
If you're strictly following MVC, your model (entities) won't have any inherent behavior. I do however include whatever helper methods allow the easiest management of the entities persistence, including methods that help with maintaining its relationship to other entities.
If you plan on exposing your entities to the world, you're better off (generally) keeping behavior off of the entity. If you want to centralize your business operations (i.e. ValidateVendorOrder) you wouldn't want the Order to have an IsValid() method that runs some logic to validate itself. You don't want that code running on a client (what if they fudge it. i.e. akin to not providing any client UI to set the price on an item being placed in a shopping cart, but posting a a bogus price on the URL. If you don't have server-side validation, that's not good! And duplicating that validation is...redundant...DRY (Don't Repeat Yourself).
Another example of when having behaviors on an entity just doesn't work is the notion of lazy loading. Alot of ORMs today will allow you to lazy load data when a property is accessed on an entities. If you're building a 3-tier app, this just doesn't work as your client will ultimately inadvertantly try to make database calls when accessing properties.
These are my off-the-top-of-my-head arguments for keeping behavior off of entities.