I am looking at the Backbone.js documentation and I notice that many methods accept options that you can provide, but they aren't specified.
For example, if you look at the remove() method, you will see this:
remove collection.remove(models, [options])
Remove a model (or an array of models) from the collection, and return them. Each model can be a Model instance, an id string or a JS object, any value acceptable as the id argument of collection.get. Fires a "remove" event for each model, and a single "update" event afterwards. The model's index before removal is available to listeners as options.index.
It doesnt't mention what sort of options it accepts. Many methods in the Backbone.js documentation don't specify the options they accept.
How do I figure out which options a backbone.js method accepts?
remove collection.remove(models, [options])
Remove a model (or an array of models) from the collection, and return
them. Each model can be a Model instance, an id string or a JS object,
any value acceptable as the id argument of collection.get. Fires a
"remove" event for each model, and a single "update" event afterwards,
unless {silent: true} is passed. The model's index before removal is
available to listeners as options.index.
The latest Backbone documentation lists at least one option, and it's one of the common ones applicable to any Backbone method which fires an event: silent. If set to true this option will cause the method not to trigger the event it normally would.
So why not clarify that silent (or whatever options might apply to a method) are the only ones in the documentation? Why leave it an ambiguous options?
options is a generic mechanism Backbone provides for taking any sort of auxiliary information, so the options could also be used beyond just the documented options in a few ways ...
the method might take options which are undocumented because they are only applicable to a limited number of people, or simply because they are new and the Backbone team hasn't bothered to add the documentation for them. If you want to "figure out" that these options exist you have to either read about them in the GitHub issue that triggered their addition, or read through the Backbone source code yourself. I strongly recommend the latter option: Backbone's source code is extremely readable, and you can learn a lot from it.
you might want to override the native methods, in which case you might want to take your own options through that same options object
options are passed through to the trigger call made by remove (or any event-triggering method), which means you can use them to pass information through to event handlers as your own custom "options"
Related
I'm adding a GUI to an existing command line app. The properties used by the app are held in class(es) and I'm creating a dialog that binds to those options objects. However, if I want to cancel out of that dialog I then have reset the values of my options objects, which is where I'm running into probs.
I could take an internal copy of the option objects and use that to re-populate the original object to allow the cancel/rollback but that seems cumbersome.
I can (somehow) implement an undo function on each class - is there a pattern for that?
I use the GUI controls standalone to hold values and only update the options objects when the dialog has been confirmed.
What's best practise?
You should consider creating a new class to be used just by the GUI.
GUIs have their own needs.
Make sure to take care of multi thread issues if you have more than one thread accessing the options object.
The design patterns that address undo functionality are called Command and Memento.
I think Memento would fit better on this case.
Take a look on this question on SO: Design Pattern for Undo Engine.
The following links are of interest (and many more):
http://www.coderanch.com/t/100676/patterns/Memento-Vs-Command-pattern
http://www.developer.com/design/article.php/3720566/Working-With-Design-Patterns-Memento.htm
http://www.colourcoding.net/blog/archive/2009/07/23/reversibility-patterns-memento-and-command.aspx
After writing a few lesser programs when learning Java the way I've designed the programs is with Model-View-Control. With using MVC I have a plethora of getter methods in the model for the view to use.
It feels that while I gain on using MVC, for every new value added I have to add two new methods in the model which quickly get all cluttered with getter & setters.
So I was thinking, maybe I should use the notifyObserver method that takes an argument. But wouldn't feel very smart to send every value by itself either so I figured, maybe if I send a kind of container with all the values, preferably only those that actually changed.
What this would accomplish would be that instead of having a whole lot of getter methods I could just have one method in the model which put all relevant values in the container.
Then in the view I would have a method called from the update which extracted the values from the container and assigning them to the correct fields.
I have two questions concerning this.
First: is this actually a viable way to do this. Would you recommend me doing something along these lines?
Secondly: if I do use this plan and I don't want to keep sending fields that didn't actually change. How would I handle that without having to have if statements to check if the value is not null for every single value?
I've more familiar with the MVP paradigm, but hopefully they're similar enough to comment. While getters (and setters) in and of themselves are not necessarily evil, they are sometimes a sign that your subsystems are too strongly coupled. One really great way to decouple this is to use an event bus: see Best practices for architecting GWT apps. This allows the view to just shoot off events for the controller to listen for whenever something important happens, and the view can listen for events whenever something changes in the model that corresponds to updating the view. Ideally you wouldn't even need to ever pass the model to the view, if you can break up any changes into incremental pieces and just tell the view to change this part and then this other part.
If you feel you have too many getters (and setters) in your model class, maybe you have too many fields altogether. Is it possible that there are several distinct classes hiding within your model? If you extract these into separate classes, it may make your model more manageable.
OTOH the associated container you are thinking about could also be viable - but then why duplicate all data? You could instead use the associated container directly in the model to store all properties you can think of. And you can also pass this around for observers to get updates (preferably wrapped into an unmodifiable container, of course) - although in this setup you wouldn't need to.
In general, Java is a verbose language which expects you to put all those getters and setters (and a lot more) in place. However, any decent IDE can generate those for you with a few keypresses. Note also that you need to write them only once, and you will read and call them many many more times. Verbose also means easily readable.
If you have too many getter it's ok. But you shouldn't need the setter. The view is supposed to only read/query the model.
The MVC pattern should promote something that is asymmetric: the control update the model by calling methods in the model that embed the logic and update the sate accordingly; this respects encapsulation. The view reads/queries the model via the getters. This goes a bit against information hiding, but that's how MVC works.
I wouldn't personally pass all information in the events. It sounds complicated to me: either you end up with something that is not statically typed (e.g. you pass hashmaps), or with a plethora of typed events. I would stick with something simple, and have (possibly many) getter in the model.
There is signal in QStandardItemModel which is emitted when data of an item is changed.
Usually we connect a handler for this signal and do all the work in the handler routine.
Such handle routine only gets pointer to the item.
Using this pointer it is possible to access the data of the item.
However, we do not know what exactly has changed... we only have updated value.
If item data has several roles I want to be able to get exactly which role (data) has been changed and what was the previous value.
In general, QStandardItemModel is for very simple data modeling. If you want to get into more advanced things like you desribe, you should look into subclassing QAbstractItemModel or one of it's abstract derivatives: Model/View classes
It may seem like a lot of work, but use the examples and refernce guides: Model/View programming, Model subclassing and the rewards will be great.
This is not possible with the standard signals of Qt. I suggest to add another signal for that.
For my own models, I usually use this approach: I have a root instance which contains pointers to all parts of my data model. Items in my model use this root instance to send signals like
itemChanged(item, attribute, oldValue, newValue)
for simple properties. The same goes for lists and the like; only here, I have several signals depending on the action, for example:
itemAdded(list, item, index)
[EDIT] The QT signal handling is very basic. Usually, it will only tell "something has changed". There is no support for "what exactly has changed?" since you don't need it most of the time. So if you need that information, you must do it yourself. You can't use a role alone, because roles must be backed by something in your item. What you can do is add change information to your items and read that when the role is requested. But this is not something that is supported "out of the box".
I have an object that implements the indexed accessor methods for a key called contents. In those accessors, I call willChange:valuesAtIndexes:forKey: and didChange:valuesAtIndexes:forKey: when I modify the underlying array.
I also have a custom view object that is bound to contents via an NSArrayController. In observeValueForKeyPath:ofObject:change:context: the only value in the change dictionary for the NSKeyValueChangeKindKey I ever see is NSKeyValueChangeSetting. When I'm adding objects to the array, I expect to see NSKeyValueChangeInsertion.
Recreating my view's internal representation of the objects it observes every time I insert a single item -- particularly when I'm bulk loading hundreds of items -- presents quite a performance problem, as you'd imagine. What am I doing wrong that Cocoa seems to think I'm setting a completely new array each time I add or remove a single item?
(Note to all readers: I hate using answers for this, too, but this discussion is too long for comments. The downside, of course, is that it ends up not sorted chronologically. If you don't like it, I suggest you complain to the Stack Overflow admins about comments being length-limited and plain-text-only.)
I don't understand what you mean by implementing array accessors in the view.
Implement accessors, including indexed accessors, for the mutable array property that you've exposed as a binding.
Bindings is built on top of KVO.
And KVC.
All bindings are implemented using observeValueForKeyPath:
Overriding that is one way, sure. The other way is to implement accessors in the object with the bindable property (the view).
My custom view provides a binding that the app binds to an array -- or in this case, an array controller. Accessor methods apply to KVC, not KVO.
Cocoa Bindings will call your view's accessors for you (presumably using KVC). You don't need to implement the KVO observe method (unless, of course, you're using KVO directly).
I know this because I've done it that way. See PRHGradientView in CPU Usage.
Curiously, the documentation doesn't mention this. I'm going to file a documentation bug about it—either I'm doing something fragile or they forgot to mention this very nice feature in the docs.
It absolutely matters that I'm getting a set message on every array update. I wouldn't have posted it as a question if it didn't matter.
There are quite a large number of people who engage in something called “premature optimization”. I have no way of knowing who is one of them without asking.
I have an object that implements the indexed accessor methods for a key called contents. In those accessors, I call willChange:valuesAtIndexes:forKey: and didChange:valuesAtIndexes:forKey: when I modify the underlying array.
Don't do that. KVO posts the notifications for you when you receive a message to one of those accessors.
I also have a custom view object that is bound to contents via an NSArrayController. In observeValueForKeyPath:ofObject:change:context: the only value in the change dictionary for the NSKeyValueChangeKindKey I ever see is NSKeyValueChangeSetting. When I'm adding objects to the array, I expect to see NSKeyValueChangeInsertion.
For one thing, why are you using KVO directly? Use bind:toObject:withKeyPath:options: to bind the view's property to the array controller's arrangedObjects (I assume) property, and implement array accessors (including indexed accessors, if you like) in the view.
For another, remember that arrangedObjects is a derived property. The array controller will filter and sort its content array; the result is arrangedObjects. You could argue that permuting the indexes from the original insertion into a new insertion would be a more accurate translation of the first change into the second, but setting the entire arrangedObjects array was probably simpler to implement (something like [self _setArrangedObjects:[[newArray filteredArrayUsingPredicate:self.filterPredicate] sortedArrayUsingDescriptors:self.sortDescriptors]]).
Does it really matter? Have you profiled and found that your app is slow with wholesale array replacement?
If so, you may need to bind the view directly to the array's content property or to the original array on the underlying object, and suffer the loss of free filtering and sorting.
I call the KVO methods manually for reasons outside the scope of this issue. I have disabled automatic observing for this property. I know what I'm doing there.
I don't understand what you mean by implementing array accessors in the view. Bindings is built on top of KVO. All bindings are implemented using observeValueForKeyPath: My custom view provides a binding that the app binds to an array -- or in this case, an array controller. Accessor methods apply to KVC, not KVO.
It absolutely matters that I'm getting a set message on every array update. I wouldn't have posted it as a question if it didn't matter. I call something like
[[modelObject mutableArrayValueForKey:#"contents"] addObjectsFromArray:hundredsOfObjects];
On every insertion, my view observes a whole new array. Since I'm potentially adding hundreds of objects, that's O(N^2) when it should to be O(N). That is completely unacceptable, performance issues aside. But, since you mention it, the view does have to do a fair amount of work to observe a whole new array, which significantly slows down the program.
I can't give up using an array controller because I need the filtering and sorting, and because there's an NSTableView bound to the same controller. I rely on it to keep the sorting and selections in sync.
I solved my problem with a complete hack. I wrote a separate method that calls the KVO methods manually so that only one KVO message is sent. It's a hack, I don't like it, and it still makes my view reread the entire array -- although only once, now -- but it works for now until I figure out a better solution.
I have two classes that each need an instance of each other to function. Ordinarily if an object needs another object to run, I like to pass it in the constructor. But I can't do that in this case, because one object has to be instantiated before the other, and so therefore the second object does not exist to be passed to the first object's constructor.
I can resolve this by passing the first object to the second object's constructor, then calling a setter on the first object to pass the second object to it, but that seems a little clunky, and I'm wondering if there's a better way:
backend = new Backend();
panel = new Panel(backend);
backend.setPanel();
I've never put any study into MVC; I suppose I'm dealing with a model here (the Backend), and a view or a controller (the Panel). Any insights here I can gain from MVC?
It's time to take a look at MVC. :-) When you have a model-view-controller situation, the consensus is that the model shouldn't be aware of the view-controller (MVC often plays out as M-VC), but the view is invariably aware of the model.
If the model needs to tell the view something, it does so by notifying its listeners, of which it may have multiples. Your view should be one of them.
In a circular construction scenario I'd use a factory class/factory method. I would normally make the construction logic private to the factory (using friend construct, package level protection or similar), to en sure that no-one could construct instances without using the factory.
The use of setter/constructor is really a part of the contract between the two classes and the factory, so I'd just use whichever's convenient.
As has been pointed out, you really should try to find a non-circular solution.
First of all, contrary to what others has said here, there's no inherent problem with circular references. For example, an Order object would be expected to have a reference to the Customer object of the person who placed the Order. Similarly, it would be natural for the Customer object to have a list of Orders he has placed.
In a refernce-based language (like Java or C#) there's no problem, at all. In a value-based language (like C++), you have to take care in designing them.
That said, you design of:
backend = new Backend();
panel = new Panel(backend);
backend.setPanel(panel);
It pretty much the only way to do it.
It's better to avoid circular references. I would personally try to rethink my objects.
panel = new Panel(backend);
You do this in this routine something like
Public Sub Panel(ByVal BackEnd as BackEnd)
Me.MyBackEnd = BackEnd
BackEnd.MyPanel = Me
End Sub
You don't need BackEnd.SetPanel
It is better to use Proxies. A proxy links one object to another through raising a Event. The parent hands the child a proxy. When the child needs the parent it calls a GetRef method on the proxy. The proxy then raises a event which the parent uses to return itself to the proxy which then hands it to the child.
The use of the Event/Delegate mechanism avoids any circular reference problems.
So you have (assuming that the backend is the 'parent' here)
Public Sub Panel(ByVal BackEnd as BackEnd)
Me.MyBackEnd = BackEnd.Proxy
BackEnd.MyPanel = Me
End Sub
Public Property MyBackEnd() as BackEnd
Set (ByVal Value as BackEnd)
priBackEndProxy = BackEnd.Proxy
End Set
Get
Return priBackEndProxy.GetRef
End Get
End Property
Here is a fuller discussion on the problem of circular references. Although it is focused on fixing it in Visual Basic 6.0.
Dynamic Memory Allocation
Also another solution is aggregating Panel and BackEnd into another object. This is common if both elements are UI Controls and need to behave in a coordinated manner.
Finally as far as MVC goes I recommend using a a Model View Presenter approach instead.
Basically you have your Form Implement a IPanelForm interface. It registers itself with a class called Panel which does all the UI logic. BackEnd should have events that Panel can hook into for when the model changes. Panel handles the event and updates the form through the IPanelForm interface.
User clicks a button
The form passes to Panel that the user clicked a button
Panel handles the button and retrieves the data from the backend
Panel formats the data.
Panel uses IPanelForm Interface to show the data on the Form.
I've been delaying implementing the lessons learned here, giving me plenty of time to think about the exact right way to do it. As other people said, having a clear separation where the backend objects have listeners for when their properties change is definitely the way to go. Not only will it resolve the specific issue I was asking about in this question, it is going to make a lot of other bad design smells in this code look better. There are actually a lot of different Backend classes (going by the generic class names I used in my example), each with their own corresponding Panel class. And there's even a couple of places where some things can be moved around to separate other pairs of classes into Backend/Panel pairs following the same pattern and reducing a lot of passing junk around as parameters.
The rest of this answer is going to get language specific, as I am using Java.
I've not worried a whole lot about "JavaBeans," but I have found that following basic JavaBean conventions has been very helpful for me in the past: basically, using standard getters and setters for properties. Turns out there's a JavaBean convention I was unaware of which is really going to help here: bound properties. Bound properties are properties available through standard getters and setters which fire PropertyChangeEvents when they change. [I don't know for sure, but the JavaBeans standard may specify that all properties are supposed to be "bound properties." Not relevant to me, at this point. Be aware also that "standard" getters and setters can be very non-standard through the use of BeanInfo classes to define a JavaBean's exact interface, but I never use that, either.] (The main other JavaBean convention that I choose to follow or not as appropriate in each situation is a no-argument constructor; I'm already following it in this project because each of these Backend objects has to be serializable.)
I've found this blog entry, which was very helpful in cluing me into the bound properties/PropertyChangeEvents issue and helping me construct a plan for how I'm going to rework this code.
Right now all of my backend objects inherit from a common class called Model, which provides a couple of things every backend in this system needs including serialization support. I'm going to create an additional class JavaBean as a superclass of Model which will provide the PropertyChangeEvent support that I need, inherited by every Model. I'll update the setters in each Model to fire a PropertyChangeEvent when called. I may also have JavaBean inherited by a couple of classes which aren't technically Models in the same sense as these but which could also benefit from having other classes registered as listeners for them. The JavaBean class may not fully implement the JavaBean spec; as I've said, there are several details I don't care about. But it's good enough for this project. It sounds like I could get all this by inheriting from java.awt.Component, but these aren't components in any sense that I can justify, so I don't want to do that. (I also don't know what overhead it might entail.)
Once every Model is a JavaBean, complete with PropertyChangeEvent support, I'll do a lot of code cleanup: Models that are currently keeping references to Panels will be updated and the Panels will register themselves as listeners. So much cleaner! The Model won't have to know (and shouldn't have known in the first place) what methods the Panel should call on itself when the property updates.