On 3 December 2010 12:53,  <presid...@basnetworks.net> wrote:
>> On 2 December 2010 13:51,  <presid...@basnetworks.net> wrote:
>>>> 2010/12/1 Richard Quadling <rquadl...@gmail.com>
>>>>
>>>>> On 1 December 2010 09:22, Stas Malyshev <smalys...@sugarcrm.com>
>>>>> wrote:
>>> ...
>>>
>>>> Why change the expected behavior of isset? If a property has not been
>>>> set
>>>> then isset must return false, and that includes $foo->name = NULL.
>>>
>>>
>>> Thats simple then, when isset is invoked, call the get method, and if it
>>> returns null then isset() returns false, but otherwise returns true.
>>> That
>>> was likely just a small oversight on Richard's part.
>>
>> No, it was not an oversight.
>>
>> Calling the getter() in response to isset() will probably result in a
>> change to the value of the property. For a property, isset() can and
>> only be interested in the last value of the property, not the next
>> value.
>>
>> As I understand things, isset() performs 2 tests. First a check to see
>> if the variable exists and then to see if it has a value assigned.
>>
>> For a property, the first part of that equation is fairly simple - the
>> property has to exist or not.
>>
>> The second part though is not easy. A variable will not change value
>> in response to isset(), but, if isset() calls the getter(), then it
>> could and probably would. Calling isset() shouldn't alter anything.
>
> Agreed, isset should not alter anything.
>
>> Having isset() call the getter() and unset() call the setter() is fine
>> as long as the getter() and setter() know why they are being called.
>>
>> If the developer needs to supply the last value - their choice - then
>> this could be implemented by caching the last value in a local scope
>> static. Completely encapsulated.
>>
>> get($isset = false){
>>  static $lastValue;
>>
>>  if (!$isset) {
>>   // Generate the new value and assign it to $lastValue
>>  }
>>
>>  return $lastValue;
>> }
>
> The major issue I see here, is that a property should not be generating a
> value in an unpredictable way.  In the example above, you indicate that
> the value could change just by calling the get method.  While it is
> possible to write a property that does such a thing, this is completely
> incorrect and should not be actively supported by the language in any way.
>  The value of a property (as viewed from the outside of the class) should
> never, ever change solely by a call to a getter method.
>
> Basically what this means, is that two subsequent calls to a get method of
> a property should ALWAYS return the same value.  I think this is the only
> scenario that we should care to support, and if the user is changing
> values in a getter method, then they need to understand that isset may not
> work as desired.
>
> If you need to generate and return a random or similar value, that should
> be done as a method.  See the MSDN article "Choosing Between Properties
> and Methods" for more details:
>
> http://msdn.microsoft.com/en-us/library/ms229054.aspx
>
> Isset should be a direct reflection of the value that is/will be returned
> by the getter method.  If you call isset() on a property, you are asking
> "if this property exists, and I access it, will I get a non-null value?".
>
> Not only that, an $isset parameter is ugly and cumbersome, and complicates
> a feature that is meant to simplify a programmers life.
>
> Having isset and unset methods alongside the get/set methods seems
> reasonable to me, for the situations that you do need to handle those
> operations explicitly, but I do not think an isset/unset implementation
> should be required in every case (meaning there must be a default way of
> handling that functionality), or else properties will be avoided by
> programmers due to being to complicated to create.
>
> - Dennis
>
>


In a multiuser environment (where I do all my work), the current
instance of an object may (and will probably will) contain stale data.

Take something simple, say, a sales order processing system (SOP).

Amongst all the data held in the system, there are 3 important
properties to consider which cannot be altered by the sales order
processing system.

1 - Credit Limit - can only be altered by the Sales Ledger (SL) system
- in an SOP scenario, the credit limit is read-only.
2 - Account Balance - depending upon the process in the SOP, _this_
instance may or may not be able to alter this value. Order entry -
readonly. Raising invoices for despatched orders (assuming no middle
land "posting" mechanism between SOP and SL), then writable.
3 - On Order Total (the value of all outstanding orders) - Like the
Account Balance, _this_ instance will not be the only entity capable
of altering this value - many users in SOP will be creating new orders
in real time. Invoice production for despatched orders will also alter
this value.

A fourth important value in this equation is ...

4 - Current Order Value - for the sake of argument, only _this_
instance can alter this value. Implemented as a getter() to a private
variable fed by order details and order calculations - order discount,
Tax/VAT, etc.

The first 3 are retrieved from a cached, low TTL database request.

The fourth could simply be a cached value with a write-through to the
DB. This would allow the work in progress to be seen live, even though
the order isn't yet finalised. This is extremely useful in realtime
for features like realtime stock allocation.



An important attribute of an account is the available balance. This is
the normally the value that would be available if all outstanding
orders were fulfilled, combined with their current balance and
compared against their credit limit.

In a multi-user system, any of these values could be different from
one moment to the next.

class Account{
 public property $AvailableBalance{
  get{
   return $this->CreditLimit - ($this->AccountBalance - $this->OnOrder);
  }
 }
}

This hides the mechanics away and tells any user that the account for
this order has a realtime $CreditLimit, $AccountBalance, $OnOrder and
an accurate $AvailableBalance. At the beginning and end of the order
entry and maybe as each line is being entered, the AvailableBalance is
accessed to see if it the current order can be met financially.

The Account's properties are all read-only in this scenario (I'd have
2 Account classes, one for the Sales Ledger and a subclass for
everywhere else. The ability to essentially remove the setter() in a
subclass would turn a read/write property into a readonly property).


So, based upon this fairly simple scenario, isset() would clearly
alter the value of the account's properties if it had to call the
getter()s.

And, in this example, no great harm would be caused by doing so. But
it would certainly be an unnecessary overhead to do so.



You say "While it is possible to write a property that does such a
thing, this is completely incorrect and should not be actively
supported by the language in any way.".

How are you going to stop me from writing code that DOES generate a
new and appropriate value in response to a getter() request.

Surely that's the exact job of a getter()? To generate and supply a
potentially new and accurate value. Not to supply some pre-hashed
value which is accessible via __get() or by directly accessing a
public variable (as seen in the EmployeeRecord on the MSDN link you
gave - completely pointless).


You may come back and say the mechanics should be ...

public function getAvailableBalance() {
  return $this->getCreditLimit() - ($this->getAccountBalance() -
$this->getOnOrder()) - $this->getOrderValue();
}

with each property being retrieved by an appropriate method (as
suggested in the MSDN article - computationally expensive for a
property).

But the nett effect is the same. The DB (probably via a cache with a
low TTL) would still be hit - in fact it would need to hit as we need
live data for the calculations.

The end-user would have to type a few more letters and think in terms
of "behaviour" rather than "attribute" in terms of accessing the
value.

This is the current way you'd have to write the code.


If that is what you say I _should_ do, then I ask what are the
benefits of using properties for me?

At best, it seems like a way to allow separate docblocks and
readonly/writeonly. If the getter can't return a different value then
it really doesn't seem that useful.

I'd expect a property to provide the value of an attribute of the
object. Properties would also allow the developer to respond to
requests to supply or alter the attribute and limit/allow that
request. The value of a property/attribute can be different.  A Clock
object can have a time attribute. You can't change time (Einstein and
Hawking may argue differently). So I have think in terms of retrieving
the time from my clock rather than thinking in terms of a clock has a
time property.


The response to isset/unset can only sensibly be handed by the
designer of the property. Either as additional isset()/unset()
functions in the property, or as a flag to the get()/set() functions
(my favourite).



Richard.
-- 
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to