Sharing data between model & view of an app - actionscript-3

I'm currently trying to find a "definitive" solution (meaning : finding a solution that seems efficient a complying with OOP precepts) to a recurring problem I've been experiencing for some time : the problem of shared data in different parts of my code.
Take note that I'm not using any MVC framework anywhere here. I'm just refering to my data class as a Model and to the display class as a View (because its the proper names and have nothing to do with the MVC pattern, people made views & models way before the MVC pattern was "created").
Here's my problem :
Whenever I make an application that uses some quite expanded data (for example a game), I try to separate logic (movements, collisions, etc...) and display in two classes. But then, I stumble upon the problem : how to "bind" the data stored in my logic class with the corresponding display objects in my view class, without duplicating data, references, or other things between the different classes ?
Lets take a basic example :
I have a MyLogicClass, holding a Vector of "EntityData" objects (each with position, sizes, various states, everything to handle the logic of my items)
And I have a MyViewClass, creating and displaying Sprites for each EntityData that are in the MyLogicClass, and make them move after them being updated in the game loop.
The first thing that would come to my mind would be to store inside each data element its corresponding view, thus allowing me to loop throught my Vector to update the items logic then update the views accordingly. But that forces me to hold a MyLogicClass reference inside the MyViewClass, to be sure that I can target the entities data, forcing me to couple the two classes (things that I would prefer not to do).
On the other hand, there's the solution of each Entity having an ID, both in my data model (MyLogicClass's EntityData objects having an ID parameter) and in my View class (Sprites holding a reference to its original entity data ID). But when I want to target a specific entity that forces me to loop for it in my data model, then loop for it again to find the related Sprite in my View. This solution allows me to have loose coupling between my data and my view, but looping through hundreds of elements twice every frame (can happen !) really sounds not performance optimized for me.
I may be giving the whole problem a lot more importance that it should deserve, but I've been stumbling upon that more than one time, and I'd love to have some other views than mine about that.
Do you guys have any advice / solution for such an issue ?
Are there some other data formats / hierarchy that I may not be aware of for such case ?

What I've done is 'link' them together using events and event listeners. I have my "model parts" throw specific events that the "display parts" catch and render/update.
I've found this does let me structure some of my tests by writing testing code that would listener for certain events and error checks it that way. My code is still separated and testable on it's own: I can test my "model" by triggering and making sure the right events with the right values are being thrown. Like-wise, I can write some testing code to throw preset events that can be caught by the "display" to see if it has any issues.
Then once it is all working, I just reuse those same event listeners and link to 'each other'.
Later my "controller" (user input) would manipulate the "model" parts, which would cause events to be thrown to the "display" thus be rendered/updated.
I don't know if this is "correct" or not in terms of following the mvc pattern nor do I really have any formal knowledge on these sorts of things. I'd be interested in someone else's more knowledgeable opinion as well.

I think maybe you have over thought the problem. I do this sometimes.
Your view class has to have some type of link to the model obviously and an event is a great way to do it. Something bare bones here to give you an idea.
// Model class
package
{
class MyModel extends EventDispatcher
{
// you can make them public but that would
// be against some oop practices. so private it is
private var m_position:Vector2D;
MyModel(){}
// one way of doing getters/getters
// example: theModel.SetPosition(something);
public function GetPosition():Vector2D { return m_position; }
public function SetPosition(value:Vector2D):void
{
m_position = value;
ModelChanged();
}
// the other way
// sample: theModel.position = something;
public function get position():Vector2D {return m_position; }
public function set position(value:Vector2D):void
{
m_position = value;
ModelChanged();
}
private function ModelChanged():void
{
dispatchEvent(new Event(Event.CHANGE));
}
}
}
// now for our view.
package
{
class MyView extends Sprite // or whatever
{
private var model:MyModel;
MyView(model:MyModel)
{
this.model = model;
model.addEventListener(Event.CHANGE, handleModelChanged);
// fire off an event to set the initial position.
handleModelChanged(NULL);
}
private function handleModelChanged(evt:Event):void
{
x = model.position.x;
y = model.position.y;
// etc etc etc.
}
}
}
Anyhow you don't need the setters if your going to have the logic in the model file also obviously if nothing outside of the model needs to change it no reason for setters. But you do need the getters.
This decouples the model from the view and you can write any view any way you want and all you have to provide is a handler for when the model has changed. Just expose whatever data your views will need with getters.
You now only have to loop through the models and if one changes it will fire off an event and the views that are listening in will update.
hope I didn't miss anything and that explains what you were wanting.
Edit: I forgot to add, you don't have to have "ModelChanged()" all over the place if your using something like an update function. Just update and when your finished fire off the event.

Related

How would Object.defineProperty be in AS3?

I'm an architect from a strong JavaScript background, but I did some .NET and Java in the past.
However, I wanted to put a hand on ActionScript3, which I was promised that is very related to JavaScript.
As a startup project I took on myself to try port to ActionScript3 one of my favorite assertion utils - should.js - that makes your test codes really pleasant to read.
Updated: 2013-02-19
I saw I confuse with my abstract speaking, so I replaced some of the post with the concrete question in mind.
Here's the full picture:
Consider the following JavaScript code:
Object.defineProperty(Object.prototype, 'should'
, { set: function(){}
, get:
function(){
return new Assertion(Object(this).valueOf());
}
, configurable: true
, enumerable : false
}
);
That is part of the implementation of the JavaScript module Should. The other part is a definition of a the class Assertion, that is constructed with a value, and implements a wide and nice set of assertion methods, against that value. Methods like like
var o = Assertion(actualValue)
o.equals(expectedValue1)
o.moreThan(expectedValue2)
o.contains(expectedValue3)
and aliases to keep english grammer
var o = Assertion(actualValue)
o.equal(expectedValue1)
o.contain(expectedValue3)
and aliases for the lazy sharpshooters, like
o.eql(expectedValue)
o.gt(expectedValue) //greater then
o.gte(...) //greater then or equal
//and so on...
and some connectors that just return this, (which is the instance of Assertion constructed with the test value) like
o.be
o.and
What does it give you?
A test code that looks like this:
var person = getPerson();
Should.exist(person); //that's a static call, and that's easy
//but these are a member calls:
person.should.have("name","age","address","friends");
person.name.should.equal("John");
person.age
.should
.be.number()
.and.be.between(20,30);
person.address
.should
.be.string().and
.startWith("\d").and
.endWith(" st.")
//or even
.and.match(/^[0-9]{1,9}\s+[A-Z][a-z0-9 ]* st\.$/);
person.friends
.should
.be.array().and
.be.between(3,5).and
.containOnlyType(String);
Isn't that wonderful? it's plain English!
You could argue about aesthetics of indentation, where to put the and, and if they are at all necessary, but besides that - anybody can read or write it:
Once you took the 'should' attribute that exists on every object but does not spoil map iterations - you can go on chaining whatever you have to claim regarding the value you started from.
It could have more nifty iteration tools, reflection utilities, be augmented with test functions relevant for your object model, and so on and so forth, but lets just get over the first step :)
But for that, you need every object in the system to feature a non-enumerable smart property called should that in it's getter function returns an Assertion object constructed with the this as the tested value.
(you ain't seen nothing yet - wait to see the beautiful rejection messages it gives! Yummie!!
So yea - I would happily sacrifice the option to call an attribute "should"... and will happily give up intelisense as well - at least as long as it's plain English)
So, in comments, bfavaretto gave us the first step - we know how to prevent enumeration of an attribute - great & thanks!!
Now, can we make it a getter-attribute who's function can access the this?
When I'm done I'm going to put it in some public repo licensed under MIT, for all of us to have fun with :)
Help anybody?
You example is actually 90% correct - but define it like actionscript, not like javascript!
You can still define prototypes in AS3 and they will still work just like prototypes in AS2. The only difference in AS3 is the compiler. AVM2 for some reason does not cast prototypes to native classes (although I didn't test custom classes).
The Prototype Trick: Cast the class as an object.
Eg: if you create:
Array.prototype.random = function():void{}
Then create the object:
var myProtoArray:Array = new Array;
2 things will happen:
myProtoArray.random() //ERROR - this will fail, AVM2 did not map the prototype to Array
but
Object(myProtoArray).random() //WORKS
random() was cast to the Object class, then mapped to Array - I have no idea why!
Hope this helps, cheers.
I confess I'm not keenly familiar with how Javascript works, but if I'm understanding defineProperties purpose correctly, it is a runtime dictation of not just what a property should be, but also the associated namespace to which it belongs (or at least what AS3 considers a namespace).
Class properties are either predefined & only modifiable via custom get() set() functions, or dynamic. Once compiled, their namespace cannot be changed (to my knowledge), so any non-private property is implicitly enumerable, and modifiable whether or not you've written getter/setters (ie: foo.a = value). According to Adobe...
Properties that you create are enumerable, but built-in properties are
generally not enumerable.
That said, you can get a complete list of properties from a class by using describeType. Quite an exhaustive amount of info can be gleaned this way, and I suspect should suit your needs if you wanted to port Mozilla's recreated defineProperties example. Below is an example printing out only property values.
function showProps(obj:*):void {
var desc:XML= describeType(obj);
// public vars
for each (var n:XML in desc.variable){
trace(n.#name + ": " + obj[n.#name]);
}
// getters
for each (n in desc.accessor){
try {
trace(n.#name + ": " + obj[n.#name]);
} catch (error:Error) {
trace("Unable to read write-only property.");
}
}
}
I hope this helps, but I'm certain I don't fully understand what you're trying to accomplish. If you could elaborate, that'd be appreciated.
Ok, guys, thanks for all the help, 22+
I'll give a summary for the people that are interested in the original question, and after that - I'll show you the outcome of my efforts.
The challange was made of two parts:
1 - prevent the augmented (=added on runtime) property from being enumerated
To the first part - thanks to #bfavaretto, commented on the question level - Object.setPropertyIsEnumerable - did the trick great.
2 - make the augmented property operate a getter function with access to the this so it can use it on the constructor of the returned value.
About this second part - Basically - I could not find a way to augment (=add) a property getter to a prototype, and have it operate on instances that enjoy it's API through the inheritance tree.
Anyway, within these limits - here's the outcome:
https://github.com/osher/should.as
Not exact porting because of the platform differences,
and I still have some methods to catch up with the original should.js (like the HTTP testing methods)
but close enough.
The main difference is that instead
var o:Object =
{ name : "Radagast"
, color: "Brown"
}
o.should.have.properties("name","color")
.and.have.property("name","Radagast");
o.name.should.not.equal("Palandoo");
o.color.should.equal("Brown");
you have to go
o.should().have.properties("name","color")
and.have.property("name","Radagast");
o.name.should().not.equal("Palandoo");
o.color.should().equal("Brown");
(the brackets - no getter possible - so the should attribute is a method, and you have to invoke it yourself)
Now if you get stuck and need help from the intellisense, you have to do this:
var should:tdd.Should = o.color.should();
should. <ctrl+space>
which kind'a takes the sting out, but for a peek in the intelisense - it helps
Important
One more thing - you have to force the static constructor of Should as soon in execution as you can,
for example, I do it here:
[Suite]
[RunWith("org.flexunit.runners.Suite")]
public class my_awsome_test_suite
{
//forces the static constructor of tdd.Should
import tdd.Should;
private static var s:Should = new Should();
public var c1:testCase1;
public var c2:testCase2;
public var c3:testCase3;
public var c4:testCase4;
}
I'll probably add some propper README.md later, and more awsome member functions to tdd.Should
Have fun

How much information should one pass through events?

Say, I have a datagrid with checkboxes, and each time a checkbox is marked I store the object in the data property of flex ResultEvent
public class MyItemRenderer extends ItemRenderer{
public static var CLICK:String = "CheckBoxClick";
protected function itemRendererClickListener(data:Object):void{
dispatchEvent(new ResultEvent(MyItemRenderer.CLICK, data))
}
}
I handle the result here.
protected function checkbox_clicked(event:ResultEvent):void{
//Here I do everything I want with the data.
Alert.show(event.result.toString());
}
This is what I've been using for months, but I never wondererd if this was a bad practice.
Or let alone bad practice, what is the optimal way to do this?
it's not really 'bad'. But it does create an additional reference to an object that can potentially keep that object in memory longer (or indefinitely if not managed well).
Generally speaking, you should only store data related to the event itself in the event instance. You can use the event.target and event.currentTarget properties to reference back to the object that dispatched the event and get data that way.
In your case, your event is a check box state change. The event itself (being checked) doesn't need any data associated with it besides the item being checked (which you can get with 'target' or 'currentTarget'). So it would be more appropriate in my opinion to do the following:
Alert.show(MyItemRenderer(event.currentTarget).data.toString());
This keeps your events more reusable
Best practice for Events with data is to use a custom event (see http://cookbooks.adobe.com/post_AS3__Creating_and_dispatching_Custom_Events-17609.html) for explanation
btw, another 'best practice' is to avoid the generic Object class in your code - instead, create a value object class

Access of undefined property data flex

I'm learning flex/flash and I'm lost on this one. I have used the "data" in a bunch of views and it works fine. For some reason it isn't working here.
I set a field to a string here:
function LoginLoaded (e:Event):void {
trace(e.target.data);
var ServerReturn:String;
ServerReturn = new String(e.target.data);
data.UserCommonReturnData = ServerReturn;
navigator.pushView(CommonPlaces, data);
}
and here in the common places view I try to load it back:
var CommonPlacesData:String = new String();
var CurrentSelect:String = new String();
CommonPlacesData = new String(data.UserCommonReturnData);
This gives the error "Access of undefined property data" I don't get it because calling on something like data.PickUpTime (also a string) works fine in other views.
The data begins in the first view like this:
[Bindable] public var User:ObjectProxy = new ObjectProxy();
User.ID = "2314084";
navigator.pushView(TaxiNowOrLaterView, User);
then in later views I call on it like this: (works fine)
var PickUpString:String = new String(data.ID);
Any help would be great!! Thanks!!!
There are few things about your code. First, you really should make it a habit to name the identifiers as appropriate to the language. Identifiers that start with the capital letter and subsequently use minuscule letters for the rest of the logical part of the word (system alternatively known as PascalCase) is employed to only name classes. The rest of identifiers should use camelCase (similar to PascalCase, but the first letter isn't capitalized)**. This greatly reduces the effort at understanding your code. A seasoned AS3 programmer would interpret your code as follows:
// Static constant (!) ID of the class User is assigned (?) a value of "2314084"
User.ID = "2314084";
// invoke a method pushView of a local variable navigator with arguments
// of which first is the class TaxiNowOrLater, the second is the class User
navigator.pushView(TaxiNowOrLaterView, User);
while, perhaps, you didn't mean it.
new String();
In the context of AS3 makes no sense at all. Strings are never references, are immutable and have literal syntax the majority of programmers agreed upon. The code above is identical to "". In the similar way, new String(anotherString) has exact same effect as anotherString.
Your question: event.target may be many different things, some of them may have property called "data" and some may not. The general approach to this problem is that you need to cast the value of event.currentTarget or event.target to the type you expect to dispatch the event. Suppose you are expecting an event from an instance of a Button class, then:
private function clickHandler(event:MouseEvent):void {
if (Button(event.currentTarget).enabled) // do things
}
This will not protect you from an error, if the same event was dispatched by an object, which is not a button, but will make the error reporting more conscious, because it would tell you what class was it trying to cast to what other class, when it failed.
If your program logic requires that the handler be aware of events it shouldn't handle (why?) you could then write it like this:
private function clickHandler(event:MouseEvent):void {
var button:Button = event.currentTarget as Button;
if (button && button.enabled) // do things
}
event.target vs event.currentTarget - very-very rarely you would need the event.target, most of the time you need the currentTarget. I'm not saying it is wrong, but, it looks like it might be the problem. target is the object that was the first cause of the event. Events may bubble, which means they may travel the display list hierarchy up and down, first from the parent to child, then in reverse direction. In the example below, suppose there was a label on the button, which was clicked once the event was generated - in such case, even if you added a listener to the button, event.target would be the button label, not the button. currentTarget is, on the contrary, the immediate object which dispatched the event into the handler.
Few more things: ObjectProxy is an idiotic class, you probably shouldn't use at any event. It serves no purpose and, perhaps, buggy, but very few cared to discover its bugs so far. In a nutshell, what it does is as follows: it creates an object, which "watches" dynamic creation, assignment and removal of its properties and dispatches events when these events happen. This behavior is prone to a lot of errors and implicit bugs. For example, is foo.bar = "baz"; foo.bar = "baz"; a reassignment of the same property or not? Is foo.bar.baz = "fizzbuzz"; a modification of foo.bar? What if property name is not a sting? And so on.
Why you shouldn't use it: there is always a better way to treat your data. A more transparent, easier to debug, more efficient. This class is a prototype, which had never really worked. Besides having the behavior described above, it is huge in terms of lines of code that were used to write it. Debugging the errors that happen inside of it requires a lot of time and patience, which are certainly not worth it.
If you need an object to represent a user, define a class, with properties you expect the user to have and just use that class - this will make debugging and understanding your code much easier.
[Bindable] metadata is evil. I can't tell you you should avoid it, because it is used too often, but, I will. You should avoid it as much as possible. I didn't yet encounter an instance of when the use of this meta would be justified. Much in the similar spirit as ObjectProxy it is a prototype, something designed for lazy programmers w/o much consideration for either performance or corner cases. This is, again, a source of a lot of implicit bugs, typically difficult to spot due to the code generated around this meta "swallowing" the errors. The alternative to this meta is plain addEventListener(...) code with custom events.
Unfortunately, a lot of tutorial will use this kind of code to have you quickly started with the language + framework...
** there are some exceptions to this rule: constants are all upper-case and namespace names use underscores to separate the logical part of the word, but never use uppercase letters.

Function Parameter best practice

I have question regarding the use of function parameters.
In the past I have always written my code such that all information needed by a function is passed in as a parameter. I.e. global parameters are not used.
However through looking over other peoples code, functions without parameters seem to be the norm. I should note that these are for private functions of a class and that the values that would have been passed in as paramaters are in fact private member variables for that class.
This leads to neater looking code and im starting to lean towards this for private functions but would like other peoples views.
E.g.
Start();
Process();
Stop();
is neater and more readable than:
ParamD = Start(paramA, ParamB, ParamC);
Process(ParamA, ParamD);
Stop(ParamC);
It does break encapsulation from a method point of view but not from a class point of view.
There's nothing wrong in principle with having functions access object fields, but the particular example you give scares me, because the price of simplifying your function calls is that you're obfuscating the life cycle of your data.
To translate your args example into fields, you'd have something like:
void Start() {
// read FieldA, FieldB, and FieldC
// set the value of FieldD
}
void Process() {
// read FieldA and do something
// read FieldD and do something
}
void Stop() {
// read the value of FieldC
}
Start() sets FieldD by side effect. This means that it's probably not valid to call Process() until after you've called Start(). But the code doesn't tell you that. You only find out by searching to see where FieldD is initialized. This is asking for bugs.
My rule of thumb is that functions should only access an object field if it's always safe to access that field. Best if it's a field that's initialized at construction time, but a field that stores a reference to a collaborator object or something, which could change over time, is okay too.
But if it's not valid to call one function except after another function has produced some output, that output should be passed in, not stored in the state. If you treat each function as independent, and avoid side effects, your code will be more maintainable and easier to understand.
As you mentioned, there's a trade-off between them. There's no hard rule for always preferring one to another. Minimizing the scope of variables will keep their side effect local, the code more modular and reusable and debugging easier. However, it can be an overkill in some cases. If you keep your classes small (which you should do) then the shared variable would generally make sense. However, there can be other issues such as thread safety that might affect your choice.
Not passing the object's own member attributes as parameters to its methods is the normal practice: effectively when you call myobject.someMethod() you are implicitly passing the whole object (with all its attributes) as a parameter to the method code.
I generally agree with both of Mehrdad and Mufasa's comments. There's no hard and fast rule for what is best. You should use the approach that suits the specific scenarios you work on bearing in mind:
readability of code
cleanliness of code (can get messy if you pass a million and one parameters into a method - especially if they are class level variables. Alternative is to encapsulate parameters into groups, and create e.g. a struct to whole multiple values, in one object)
testability of code. This is important in my opinion. I have occassionally refactored code to add parameters to a method purely for the purpose of improving testability as it can allow for better unit testing
This is something you need to measure on a case by case basis.
For example ask yourself if you were to use parameter in a private method is it ever going to be reasonable to pass a value that is anything other than that of a specific property in the object? If not then you may as well access the property/field directly in the method.
OTH you may ask yourself does this method mutate the state of the object? If not then perhaps it may be better as a Static and have all its required values passed as parameters.
There are all sorts of considerations, the upper most has to be "What is most understandable to other developers".
In an object-oriented language it is common to pass in dependencies (classes that this class will communicate with) and configuration values in the constructor and only the values to actually be operated on in the function call.
This can actually be more readable. Consider code where you have a service that generates and publishes an invoice. There can be a variety of ways to do the publication - via a web-service that sends it to some sort of centralized server, or via an email sent to someone in the warehouse, or maybe just by sending it to the default printer. However, it is usually simpler for the method calling Publish() to not know the specifics of how the publication is happening - it just needs to know that the publication went off without a hitch. This allows you to think of less things at a time and concentrate on the problem better. Then you are simply making use of an interface to a service (in C#):
// Notice the consuming class needs only know what it does, not how it does it
public interface IInvoicePublisher {
pubic void Publish(Invoice anInvoice);
}
This could be implemented in a variety of ways, for example:
public class DefaultPrinterInvoicePublisher
DefaultPrinterInvoicePublisher _printer;
public DefaultPrinterInvoicePublisher(DefaultPrinterFacade printer) {
_printer = printer
}
public void Publish(Invoice anInvoice) {
printableObject = //Generate crystal report, or something else that can be printed
_printer.Print(printableObject);
}
The code that uses it would then take an IInvoicePublisher as a constructor parameter too so that functionality is available to be used throughout.
Generally, it's better to use parameters. Greatly increases the ability to use patterns like dependency injection and test-driven design.
If it is an internal only method though, that's not as important.
I don't pass the object's state to the private methods because the method can access the state just like that.
I pass parameters to a private method when the private method is invoked from a public method and the public method gets a parameter which it then sends to the private method.
Public DoTask( string jobid, object T)
{
DoTask1(jobid, t);
DoTask2(jobid, t);
}
private DoTask1( string jobid, object T)
{
}
private DoTask2( string jobid, object T)
{
}

Which design is better for a class that simply runs a self-contained computation?

I'm currently working on a class that calculates the difference between two objects. I'm trying to decide what the best design for this class would be. I see two options:
1) Single-use class instance. Takes the objects to diff in the constructor and calculates the diff for that.
public class MyObjDiffer {
public MyObjDiffer(MyObj o1, MyObj o2) {
// Calculate diff here and store results in member variables
}
public boolean areObjectsDifferent() {
// ...
}
public Vector getOnlyInObj1() {
// ...
}
public Vector getOnlyInObj2() {
// ...
}
// ...
}
2) Re-usable class instance. Constructor takes no arguments. Has a "calculateDiff()" method that takes the objects to diff, and returns the results.
public class MyObjDiffer {
public MyObjDiffer() { }
public DiffResults getResults(MyObj o1, MyObj o2) {
// calculate and return the results. Nothing is stored in this class's members.
}
}
public class DiffResults {
public boolean areObjectsDifferent() {
// ...
}
public Vector getOnlyInObj1() {
// ...
}
public Vector getOnlyInObj2() {
// ...
}
}
The diffing will be fairly complex (details don't matter for the question), so there will need to be a number of helper functions. If I take solution 1 then I can store the data in member variables and don't have to pass everything around. It's slightly more compact, as everything is handled within a single class.
However, conceptually, it seems weird that a "Differ" would be specific to a certain set of results. Option 2 splits the results from the logic that actually calculates them.
EDIT: Option 2 also provides the ability to make the "MyObjDiffer" class static. Thanks kitsune, I forgot to mention that.
I'm having trouble seeing any significant pro or con to either option. I figure this kind of thing (a class that just handles some one-shot calculation) has to come up fairly often, and maybe I'm missing something. So, I figured I'd pose the question to the cloud. Are there significant pros or cons to one or the other option here? Is one inherently better? Does it matter?
I am doing this in Java, so there might be some restrictions on the possibilities, but the overall question of design is probably language-agnostic.
Use Object-Oriented Programming
Use option 2, but do not make it static.
The Strategy Pattern
This way, an instance MyObjDiffer can be passed to anyone that needs a Strategy for computing the difference between objects.
If, down the road, you find that different rules are used for computation in different contexts, you can create a new strategy to suit. With your code as it stands, you'd extend MyObjDiffer and override its methods, which is certainly workable. A better approach would be to define an interface, and have MyObjDiffer as one implementation.
Any decent refactoring tool will be able to "extract an interface" from MyObjDiffer and replace references to that type with the interface type at some later time if you want to delay the decision. Using "Option 2" with instance methods, rather than class procedures, gives you that flexibility.
Configure an Instance
Even if you never need to write a new comparison method, you might find that specifying options to tailor the behavior of your basic method is useful. If you think about using the "diff" command to compare text files, you'll remember how many different options there are: whitespace- and case-sensitivity, output options, etc. The best analog to this in OO programming is to consider each diff process as an object, with options set as properties on that object.
You want solution #2 for a number of reasons. And you don't want it to be static.
While static seems like fun, it's a maintenance nightmare when you come up with either (a) a new algorithm with the same requirements, or (b) new requirements.
A first-class object (without much internal state) allows you to evolve into a class hierarchy of different differs -- some slower, some faster, some with more memory, some with less memory, some for old requirements, some for new requirements.
Some of your differs may wind up with complicated internal state or memory, or incremental diffing or hash-code-based diffing. All kinds of possibilities might exist.
A reusable object allows you to pick your differ at application start-up time using a properties file.
In the long run, you want to minimize the number of new operations that are scattered throughout your application. You'd like to have your new operations focused in places where you can find and control them. To change from old differ algorithm to new differ algorithm, you'd like to do the following.
Write the new subclass.
Update a properties file to start using the new subclass.
And be completely confident that there wasn't some hidden d= new MyObjDiffer( x, y ) tucked away that you didn't know about.
You want to use d= theDiffer.getResults( x, y ) everywhere.
What the Java libraries do is they have a DifferFactory that's static. The factor checks the properties and emits the correct Differ.
DifferFactory df= new DifferFactory();
MyObjDiffer mod= df.getDiffer();
mod.getResults( x, y );
The Factory typically caches the single copy -- it doesn't have to physically read the properties every time getDiffer is called.
This design gives you ultimate flexibility in the future. At it looks like other parts of the Java libraries.
I can't really say I have firm reasons why it's the 'best' approach, but I usually write classes for objects that you can have a 'conversation' with. So it would be like your 'single use' option 1, except that by calling a setter, you would 'reset' it for another use.
Rather than supplying the implementation (which is pretty obvious), here's a sample invocation:
MyComparer cmp = new MyComparer(obj1, obj2);
boolean match = cmp.isMatch();
cmp.setSubjects(obj3,obj4);
List uniques1 = cmp.getOnlyIn(MyComparer.FIRST);
cmd.setSubject(MyComparer.SECOND,obj5);
List uniques = cmp.getOnlyIn(MyComparer.SECOND);
... and so on.
This way, the caller gets to decide whether they want to instantiate lots of objects, or keep reusing the one.
It's particularly useful if the object needs a lot of setup. Lets say your comparer takes options. There could be many. Set it up once, then use it many times.
// set up cmp with options and the master object
MyComparer cmp = new MyComparer();
cmp.setIgnoreCase(true);
cmp.setIgnoreTrailingWhitespace(false);
cmp.setSubject(MyComparer.FIRST,canonicalSubject);
// find items that are in the testSubjects objects,
// but not in the master.
List extraItems = new ArrayList();
for (Iterator it=testSubjects.iterator(); it.hasNext(); ) {
cmp.setSubject(MyComparer.SECOND,it.next());
extraItems.append(cmp.getOnlyIn(MyComparer.SECOND);
}
Edit: BTW I called it MyComparer rather than MyDiffer because it seemed more natural to have an isMatch() method than an isDifferent() method.
I'd take numero 2 and reflect on whether I should make this static.
Why are you writing a class whose only purpose is to calculate the difference between two objects? That sounds like a task either for a static function or a member function of the class.
I would go for a static constructor method, something like.
Diffs diffs = Diffs.calculateDifferences(foo, bar);
In this way, it's clear when you're calculating the differences, and there is no way to misuse the object's interface.
I like the idea of explicitly starting the work rather than having it occur on instantiation. Also, I think the results are substantial enough to warrant their own class. Your first design isn't as clean to me. Someone using this class would have to understand that after performing the calculation some other class members are now holding the results. Option 2 is more clear about what is happening.
It depends on how you're going to use diffs. In my mind, it makes sense to treat diffs as a logical entity because it needs to support some operations like 'getDiffString()', or 'numHunks()', or 'apply()'. I might take your first one and do it more like this:
public class Diff
{
public Diff(String path1, String path2)
{
// get diff
if (same)
throw new EmptyDiffException();
}
public String getDiffString()
{
}
public int numHunks()
{
}
public bool apply(String path1)
{
// try to apply diff as patch to file at path1. Return
// whether the patch applied successfully or not.
}
public bool merge(Diff diff)
{
// similar to apply(), but do merge yourself with another diff
}
}
Using a diff object like this also might lend itself to things like keeping a stack of patches, or serializing to a compressed archive, maybe an "undo" queue, and so on.