Also, I did a little experiment...the idea here is to highlight the interaction between 'source' and 'destination' without arbitrarily putting the transfer logic in the 'source' role:
var transfer = dci.Roles({
'source->destination': {
$player: function doTransfer() {
transfer.source.withdraw();
transfer.destination.deposit();
}
}
source: {
$player: source,
$contract: Account,
withdraw: function() {
transfer.source.decreaseBalance(transfer.amount);
}
},
destination: {
$player: destination,
$contract: Account,
deposit: function() {
transfer.destination.increaseBalance(transfer.amount);
}
},
amount: {
$player: amount,
$contract: Number
}
});
Add it as a regular function
transfer.interact = function() {transfer.source.withdraw();transfer.destination.withdraw();
};
transfer.interact();
On 04 Jul 2015, at 02:51, Matthew Browne <mbro...@gmail.com> wrote:This proves that it is possible to have an injectionful implementation that does not suffer from the usual "sticky injection" problem and which can handle role method name conflicts as well as injectionless implementations.
var x = 1;(function(){return this;}).call(x) === (function(){return this;}).call(x);
Can I suggest a free autographed copy of “Lean Architecture” to whomever finds the first significant bug (as judged by Matthew.)
Matthew — is it ready for that?
That shouldn't be to surprising to someone that has actually familiarised himself with the specs (which I until recently hadn't as one might see on SO) and it's also only partly true that the expression returns false. If it's called with in at strict environment it returns true. My point is that it doesn't add confusion to coerce the liberals into objects and there's plenty confusion to be found in JS already which we can't remove anyhow --I'm leaning toward agreeing with Rune on this. It certainly is a lot more convenient to set a number or string as a role player and have it just work. I can see Egon's point that the programmer isn't expecting their number or string to be converted to a new Number() or String() object since it happens behind the scenes. Also, the following scenario might be confusing: 'transfer.amount' is assigned a new value, but 'amount' still holds the original value. But now that I think about it, I have a setter method for the roles object already, so I could just add a condition in the setter method to update the original number whenever the Number role-player changes. And role players are supposed to be objects, so I think it's reasonable for the environment to coerce primitives to objects automatically.
Here is a corrected version that works as I intended:
http://jsfiddle.net/mbrowne/uvL1uk5a/4/
On 7/4/15 5:37 PM, Rune Funch Søltoft wrote:
Den 04/07/2015 kl. 20.13 skrev Egon Elbre <egon...@gmail.com>:
I'm leaning toward agreeing with Rune on this. It certainly is a lot more convenient to set a number or string as a role player and have it just work. I can see Egon's point that the programmer isn't expecting their number or string to be converted to a new Number() or String() object since it happens behind the scenes. Also, the following scenario might be confusing: 'transfer.amount' is assigned a new value, but 'amount' still holds the original value. But now that I think about it, I have a setter method for the roles object already, so I could just add a condition in the setter method to update the original number whenever the Number role-player changes. And role players are supposed to be objects, so I think it's reasonable for the environment to coerce primitives to objects automatically.That shouldn't be to surprising to someone that has actually familiarised himself with the specs (which I until recently hadn't as one might see on SO) and it's also only partly true that the expression returns false. If it's called with in at strict environment it returns true. My point is that it doesn't add confusion to coerce the liberals into objects and there's plenty confusion to be found in JS already which we can't remove anyhow --
var x = 1;(function(){return this;}).call(x) === (function(){return this;}).call(x);
But if I were to agree with Egon, then I could have it throw an error instructing the programmer to create their own Number(), String() or Boolean() object.
Now, as to null and undefined...
> Den 05/07/2015 kl. 12.53 skrev Egon Elbre <egon...@gmail.com>:
>
> I would throw an error only if that role definition has methods - i.e. make as much work as possible without implicit wrapping.
>
> The implicit wrapping approach changes the result of "typeof" operator, a lot of code has assertions such as assert(typeof x === "number"), this means that the value playing the role and the actual input value will behave differently in there. It's an easy way to get small bugs.
>
> Inside the context, I don't think the wrapping will be a problem, but I'm seriously concerned when passing those values forward into some library X.
The specifications are pretty clear on how to treat a literal/value when used as an object.
Your suggestion is to not follow those rules. To me that's violating the rule of least surprise after all what we are talking about is simply another case of using a value as an object. I would be surprised if this particular case was inconsistent with all the other cases
On 7/5/15 9:18 AM, Rune Funch Søltoft wrote:
I think Egon meant something like this:Den 05/07/2015 kl. 12.53 skrev Egon Elbre <egon...@gmail.com>: I would throw an error only if that role definition has methods - i.e. make as much work as possible without implicit wrapping. The implicit wrapping approach changes the result of "typeof" operator, a lot of code has assertions such as assert(typeof x === "number"), this means that the value playing the role and the actual input value will behave differently in there. It's an easy way to get small bugs. Inside the context, I don't think the wrapping will be a problem, but I'm seriously concerned when passing those values forward into some library X.The specifications are pretty clear on how to treat a literal/value when used as an object. Your suggestion is to not follow those rules. To me that's violating the rule of least surprise after all what we are talking about is simply another case of using a value as an object. I would be surprised if this particular case was inconsistent with all the other cases
function TransferMoney(sourceAccount, destinationAccount, amount) {
...
test(transfer.amount);
}
function test(amount) {
typeof amount == 'number' //false
}
var amt = 10;
(typeof amt == 'number') //true
TransferMoney(src, dst, amt);
I can of course mention in the docs that all primitives will be coerced into objects, but I do agree with Egon that this could be surprising and introduce subtle bugs in some cases.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.
On 05 Jul 2015, at 00:14, Matthew Browne <mbro...@gmail.com> wrote:I'm leaning toward agreeing with Rune on this. It certainly is a lot more convenient to set a number or string as a role player and have it just work.
On 05 Jul 2015, at 18:38, Rune Funch Søltoft <funchs...@gmail.com> wrote:Eg the example I gave can have both behaviours depending on whether its a strict context or not but again my point is that I think we should do as the specifications whether we agree with them or not. If we can't honour the specs and the DCI semantics then the platform doesn't support DCI and we can't change that fact by not honouring the specs
It depends whether the purpose is research or production.
For research, I agree,
For production, the expense of treating values as objects, and of cloning each one, will provide a very unpleasant surprise for anyone dealing with big data.
If we can't honour the specs and the DCI semantics then the platform doesn't support DCI and we can't change that fact by not honouring the specsWell first of all, we're still formalizing the DCI semantics...but to the extent that we have established them, why is it a violation to say that primitive types must be manually converted into objects in order to play roles? JS includes object versions of every primitive, so it's not like it's that burdensome for the programmer to coerce their own objects.
maybe it would be better to throw an error when attempting to bind a primitive to a role with methods, suggesting that they convert it to an object first.
I think there's a difference between what happens normally in JS and what we're considering here...
Normal JS:
var str = "xyz"
str.substr(1) //treat it as an object
typeof str == 'string' // true
DCI (with automatic coercion):
roles.str = "xyz";
typeof roles.str == 'string' // false