Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Enums: Properties vs. Methods

Reply
Thread Tools

Enums: Properties vs. Methods

 
 
Daniele Futtorovic
Guest
Posts: n/a
 
      03-29-2011
On 29/03/2011 23:08, Lew allegedly wrote:
> Daniele Futtorovic wrote:
>> Wat? Which job? Which hammer? There's no difference between the
>> alternatives
>> with respects to what their methods are like. Leaving convenience and
>> maintenance aside, the only difference between both is that in the
>> first one
>> (without fields), the instructions are probably easier to inline.

>
> That's confusing. The first example presented was with fields, and the
> second one was without fields.


****, sorry. s/first/second/

> Regardless, the instructions are just as easy to inline either way. One
> returns a constant, the other a constant variable.


For all purposes, yeah. I would however expect the one with the constant
to be marginally easier, as it requires no analysis of the field.

--
DF.
An escaped convict once said to me:
"Alcatraz is the place to be"
 
Reply With Quote
 
 
 
 
Lew
Guest
Posts: n/a
 
      03-29-2011
Daniele Futtorovic wrote:
> For all purposes, yeah. I would however expect the one with the constant to be
> marginally easier, as it requires no analysis of the field.


Which of the two are you calling "the one with the constant"?

--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedi.../c/cf/Friz.jpg
 
Reply With Quote
 
 
 
 
Lew
Guest
Posts: n/a
 
      03-29-2011
Lew wrote:
> Daniele Futtorovic wrote:
>> For all purposes, yeah. I would however expect the one with the constant to be
>> marginally easier, as it requires no analysis of the field.


> Which of the two are you calling "the one with the constant"?


The reason for my confusion:

From the JLS, §17.5.3:
"If a final field is initialized to a compile-time constant ... uses of that
final field are replaced at compile time with the compile-time constant."

Details in §15.28:
"A compile-time constant expression is an expression denoting a value of
primitive type or a String that does not complete abruptly and is composed
using only the following:
. . .

o Simple names that refer to constant variables (§4.12.4).

§4.12.4:
"We call a variable, of primitive type or type String, that is final and
initialized with a compile-time constant expression (§15.2 a /constant
variable/."

<sscce type="com.lewscanon.eegee.Finality">

package com.lewscanon.eegee;

import java.util.Random;

/**
* Finality.
*/
public class Finality implements Runnable
{
final Random randy = new Random();

final int kount = 3;

@Override
public void run()
{
int value = randy.nextInt( kount + 1 );
System.out.print( " value = "+ value +": " );

switch ( value )
{
default:
System.out.println( "MISS" );
break;

case kount:
System.out.println( "HIT!" );
break;
}
}

/**
* main.
* @param args String [].
*/
public static void main( String [] args )
{
Finality fina = new Finality();

for ( int ix = 0; ix < 10; ++ix )
{
System.out.print( ix + "." );
fina.run();
}
}
}
</sscce>

--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedi.../c/cf/Friz.jpg
 
Reply With Quote
 
Daniele Futtorovic
Guest
Posts: n/a
 
      03-30-2011
On 30/03/2011 01:05, Lew allegedly wrote:
> Daniele Futtorovic wrote:
>> For all purposes, yeah. I would however expect the one with the
>> constant to be
>> marginally easier, as it requires no analysis of the field.

>
> Which of the two are you calling "the one with the constant"?


The same as you when you said:
"One returns a constant, the other a constant variable"

That is to say, the solution in which the OP overrode the methods in the
enum instances.

Apologies for not making myself sufficiently clear.

--
DF.
An escaped convict once said to me:
"Alcatraz is the place to be"
 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      03-30-2011
On Mar 30, 12:40*pm, Daniele Futtorovic <da.futt.n...@laposte-dot-
net.invalid> wrote:
> On 30/03/2011 01:05, Lew allegedly wrote:
>
> > Daniele Futtorovic wrote:
> >> For all purposes, yeah. I would however expect the one with the
> >> constant to be
> >> marginally easier, as it requires no analysis of the field.

>
> > Which of the two are you calling "the one with the constant"?

>
> The same as you when you said:
> "One returns a constant, the other a constant variable"
>


You completely missed my point, which is that BOTH are constants.

> That is to say, the solution in which the OP overrode the methods in the
> enum instances.
>


How would that one be easier for anything? Please elucidate.

Both approaches have constants in the compiled code.

--
Lew
 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      03-30-2011
On 29.03.2011 17:47, Lew wrote:
> On 03/29/2011 11:18 AM, Robert Klemme wrote:
>> All,
>>
>> I am just musing about the pros and cons of using boolean properties
>> in enum classes vs. custom methods. So far I found
>>
>> pro Properties:
>> - less classes

>
> How is that a pro?


The reasoning was that then less space in Perm is needed.

>> - when adding enum values to an enum you cannot forget to define
>> properties

>
>> pro Methods:
>> - smaller memory footprint per instance

>
> You actually don't know what the footprint will be once Hotspot takes
> over. With your "toy" example, those booleans might all optimize away
> and both cases take the same memory at runtime.


Just so I understand it properly: are you saying that with hotspot the
compiler might remove members of the instances? I am not sure how that
would work since then hotspot would need to create several different
versions of the property getter methods (one per instance). I believe
this is not what hotspot can do.

>> Considering that there are always only so many instances it seems the
>> properties approach wins. It seems, custom methods in enum instances
>> are most useful if enums do actually do something. Then different
>> enums can have differing implementations of the method and we have an
>> instance of Strategy / State pattern.
>>
>> Do you have more items for the lists? Did I overlook something?

>
> Your example didn't make a good case for why you'd want do do such a thing.


Right.

> Your "methods" example is confusing and the purpose behind the logic
> deeply obscured by the idioms. That alone is enough to kill it. Your
> "properties" example was clear and concise and easy to follow.
>
> No-brainer.


Well, roughly speaking the idea was this:
https://gist.github.com/892503#file_valve.java

Here there are boolean properties which derive from the enum, i.e.
whether there is traffic allowed or not and whether the traffic can flow
unlimited.

Now code which uses this enum need not create switches based on concrete
enum instances but can use boolean properties in control flow (e.g.
print a warning if no traffic at all is allowed). One might later want
to add another enum value BROKEN(false, false) which is used to describe
the state of a broken medium. If this is done the code that uses those
properties to make decisions does not need to be extended.

Cheers

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      03-30-2011
On 29.03.2011 18:26, markspace wrote:
> On 3/29/2011 8:18 AM, Robert Klemme wrote:
>> /** We use custom methods. */
>> public enum Meth {

>
> I agree with Lew that this second example was pretty confusing and hard
> to follow. I also think that it's difficult to predict memory usage
> without careful analysis.
>
> I'd like to see a "motivating" example. What do you actually intend to
> use this for? I can't see that a general case is too interesting, except
> to disqualify the method pattern.


See https://gist.github.com/892503#file_valve.java

>> Then different
>> enums can have differing implementations of the method and we have an
>> instance of Strategy / State pattern.

>
> I don't think State works this way. Strategy ... maybe, but the use of
> enums for Strategy seems confining. I'd just use regular inheritance and
> classes. The "method pattern" for Strategy would be fine I think if it
> weren't shoe-horned into an enum.


Actually I always have a hard time distinguishing those two patterns:
IMHO they are pretty much identical at the core, the main feature is
that I delegate functionality to another instance which might be from
different classes related via inheritance (at least implementing the
same interface). The only real difference that I can spot is the point
in time when the delegate is changed: in one case it might be never
changed during the lifetime of an instance (strateg) and in the other
case it is changed whenever a state change occurs (state). I find that
only a marginal difference between the two compared to the crucial point
that those patterns both use an exchangeable delegate.

http://en.wikipedia.org/wiki/State_pattern
http://en.wikipedia.org/wiki/Strategy_pattern

>> Full toy class https://gist.github.com/892503#file_prop_vs_meth.java

>
> I'll check it out.


Thanks.

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
Reply With Quote
 
Daniele Futtorovic
Guest
Posts: n/a
 
      03-30-2011
On 30/03/2011 19:33, Lew allegedly wrote:
> On Mar 30, 12:40 pm, Daniele Futtorovic<da.futt.n...@laposte-dot-
> net.invalid> wrote:
>> On 30/03/2011 01:05, Lew allegedly wrote:
>>
>>> Daniele Futtorovic wrote:
>>>> For all purposes, yeah. I would however expect the one with the
>>>> constant to be
>>>> marginally easier, as it requires no analysis of the field.

>>
>>> Which of the two are you calling "the one with the constant"?

>>
>> The same as you when you said:
>> "One returns a constant, the other a constant variable"
>>

>
> You completely missed my point, which is that BOTH are constants.


If I were so inclined, I would argue that no, in the first case
"constant" is a noun, in the second an adjective, and that in the
clear-cut language of the JLS the noun 'constant' has a stringent
definition and the adjective 'constant', in the context of variables,
too, but that these definitions don't match.

But I won't, because I consider this whole issue a complete waste of
time, and only had responded to correct my inaccuracies, not to drive
any point.

--
DF.
An escaped convict once said to me:
"Alcatraz is the place to be"
 
Reply With Quote
 
markspace
Guest
Posts: n/a
 
      03-30-2011
On 3/30/2011 11:06 AM, Robert Klemme wrote:

> Actually I always have a hard time distinguishing those two patterns:
> IMHO they are pretty much identical at the core,



They're very different. State is for implementing state machines.
Strategy is for extensibility.

The biggest difference, to me, is that if I were implementing a State
pattern, I'd treat the State class as an implementation detail and keep
it and its children private. Whereas for Strategy having a public
Strategy interface/class is the whole point.


> See https://gist.github.com/892503#file_valve.java



This really isn't either State or Strategy. It's just an enum with some
properties. I think you mean it to be a State, so let's start there.

State has defined transitions from one state to another. That each
state also might have a defined properties is almost incidental. Let me
try to find a better example, something that's a well known state
machine: opening up my TCP book (Comer) I see that he defines a TCP
connection to have the following states:

LISTEN, SYNSENT, SYNRCVD, ESTABLISHED, FINWAIT1, FINWAIT2, LASTACK,
CLOSEWAIT, TIMEWAIT, CLOSING, CLOSED, and FREE. These state transition
depending on whether an SYN, RESET or FIN has been received, whether the
user calls close(), and some internal timers.

I don't want to do the whole state machine (it's complicated) so let's
just try part of it. The first bit is that the internal state of a TCP
connection is an implementation detail and should not be public. This
is very different from Strategy!

So starting from ESTABLISHED, if a fin is recieved, it goes to the
CLOSEWAIT state. If a syn is received, it's an error and we send a
reset and abort the connection. If a reset is received, we abort the
connection. Here I'm just going straight to the CLOSED state after
aborting the connection, although Comer doesn't mention this.

From CLOSEWAIT, we wait for the application to close the connection,
then send a fin and go to LASTACK. Normally I think there's some
sending of final data here too.

From LASTACK, if we get a syn, we send a reset and abort the
connection. If we get a reset, we abort the connection. It seems to me
we should be waiting for an ack to our fin, but Comer doesn't mention it.

From CLOSED, we are quiescent, although if we get any actual data on a
closed channel we should sent a reset (not shown).

Note that Comer doesn't always explicitly define each state transition.
Those that I couldn't find I just let them throw an error. This might
be wrong, but I felt was safest.

Note also that the State pattern "Context" here is called TcpConnectionTest.

Each state is discreet and does its own thing. It's not affected by
other states, the code is nicely encapsulated, and it's easy to extend
by adding more states and more transitions. Each state here has a
reference to its context (TcpConnectionTest). The state drives the
processing on the context, and also sets the next state when a
transition is called for. The context itself doesn't really know how
states progress, but it does provide methods for the states to call when
they need something done. This is normal for the State pattern, afaik.

Also, I'm using inner classes here, but that's only for a usenet
example. I could have used an implicit point to the enclosing class
(TcpConnectionTest) but that's not part of the State pattern. So I use
static inner classes and I pass a reference to the context via each
constructor, which is part of the State pattern.

I'd suggest you get a good introductory book to design patterns, such as
Head First Design Patterns.

/*
Copyright 2011 Brenden Towey. All rights reserved.
*/

package test;

/**
*
* @author Brenden Towey
*/
public class TcpConnectionTest {

private TcpState state;

public TcpConnectionTest() {
state = new Established( this );
}

public void reset() {
state.reset();
}

public void close() {
state.close();
}

public void fin() {
state.fin();
}

private void sendReset() {
System.out.println("Reset");
}

private void doAbort() {
System.out.println("Abort");
}

private void sendFin() {
System.out.println("Fin");
}

private static abstract class TcpState {
final TcpConnectionTest connection;

public TcpState(TcpConnectionTest connection) {
this.connection = connection;
}
abstract void fin();
abstract void syn();
abstract void close();
abstract void reset();
}

private static class Established extends TcpState {

public Established( TcpConnectionTest con ) {
super( con );
}


@Override
void fin() {
connection.state = new CloseWait( connection );
}

@Override
void syn() {
connection.sendReset();
connection.doAbort();
connection.state = new Closed( connection );
}

@Override
void close() {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
void reset() {
connection.doAbort();
connection.state = new Closed( connection );
}
}

private static class CloseWait extends TcpState {

public CloseWait(TcpConnectionTest connection) {
super( connection );
}

@Override
void fin() {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
void syn() {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
void close() {
connection.sendFin();
connection.state = new LastAck( connection );
}

@Override
void reset() {
throw new UnsupportedOperationException("Not supported yet.");
}

}

private static class LastAck extends TcpState {

public LastAck(TcpConnectionTest connection) {
super( connection );
}

@Override
void fin() {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
void syn() {
connection.sendReset();
connection.doAbort();
connection.state = new Closed( connection );
}

@Override
void close() {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
void reset() {
connection.doAbort();
connection.state = new Closed( connection );
}

}

private static class Closed extends TcpState {

public Closed(TcpConnectionTest connection) {
super(connection);
}

@Override
void fin() {
}

@Override
void syn() {
}

@Override
void close() {
}

@Override
void reset() {
}
}
}


 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      03-30-2011
Robert Klemme wrote:
> Lew wrote:
> > You actually don't know what the footprint will be once Hotspot takes
> > over. With your "toy" example, those booleans might all optimize away
> > and both cases take the same memory at runtime.

>
> Just so I understand it properly: are you saying that with hotspot the
> compiler might remove members of the instances? *I am not sure how that
>


More the other way around: if it sees an opportunity to enregister
members it will remove the instance from the members.

> would work since then hotspot would need to create several different
> versions of the property getter methods (one per instance). *I believe
> this is not what hotspot can do.
>


Yes. So? that's what HotSpot does, except it's not one per instance,
it's N >= 1 per instance, potentially. HotSpot optimizes for
individual hot spots in the code, hence the name.

> >> Considering that there are always only so many instances it seems the
> >> properties approach wins. It seems, custom methods in enum instances


Yes, it wins, but that has nothing to do with memory or performance in
the JVM.

For the toy example given I would expect no difference, since the
final variables ocmpile to constants anyway.

>> Your "methods" example is confusing and the purpose behind the logic
>> deeply obscured by the idioms. That alone is enough to kill it. Your
>> "properties" example was clear and concise and easy to follow.
>>
>> No-brainer.


> Well, roughly speaking the idea was this:https://gist.github.com/892503#file_valve.java
>


Side channel should not be necessary to make the point.

> Here there are boolean properties which derive from the enum, i.e.
> whether there is traffic allowed or not and whether the traffic can flow
> unlimited.
>
> Now code which uses this enum need not create switches based on concrete
> enum instances but can use boolean properties in control flow (e.g.
> print a warning if no traffic at all is allowed). *One might later want
>


THe use of values in a 'switch' doesn't seem relevant to the decision
between your approaches at all.

> to add another enum value BROKEN(false, false) which is used to describe
> the state of a broken medium. *If this is done the code that uses those
> properties to make decisions does not need to be extended.
>


Enums are not the most amenable to that kind of refactoring
regardless. But the so-called "properties" approach sure is easier
for that situation than the so-called "methods" approach, and for the
same reason I like it in the first place.

As for JVM effects, I would expect the two approaches to be
indistinguishable. Constant variables are compiled into constants in
the code, so they get treated identically with constants (being, after
all, constants in truth) at run time.

--
Lew

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is there a way to find the class methods of a class, just like'methods' finds the instance methods? Kenneth McDonald Ruby 5 09-26-2008 03:09 PM
CompositeControls: ViewState properties w/ Mapped properties probl =?Utf-8?B?Q2hyaXN0b3BoZSBQZWlsbGV0?= ASP .Net 1 01-19-2006 09:19 AM
Making Custom Control Properties Visible in Visual Studio's Properties Palette Nathan Sokalski ASP .Net 0 10-17-2005 02:05 AM
Re: C++ properties Library Created (was Binding together Properties of Objects) Victor Porton C++ 1 08-29-2004 08:02 PM
Problems parsing when Properties.dtd.properties Kent Lichty Java 0 04-16-2004 03:08 PM



Advertisments