Thanks Frank and John,

I've been strugling with the enums in Networks.java. A discussion on those
is needed I think. BroadcastDomainType seems to be a hybrid of a stable and
a plugin extendible enum. It breaks my mind and my every change.

regards,
Daan


On Tue, Jul 23, 2013 at 8:37 PM, Frank Zhang <frank.zh...@citrix.com> wrote:

> Speaking of method on enum, I used to think it's very handy feature but
> finally I failed on some scenarios and switched to own defined class.
> The problem is enum is singleton that you can't save stateful data in it.
> For example:
>
> public enum Type {
>         private Object userData;
>
>         private Object getUserData() {...}
>              private void setUserData(Object data) {...}
>         ....
>
>         Type SOME_TYPE;
> }
>
> This kind of thing is somewhat useless, userData here is actually global,
> every call to SOME_TYPE.setUserData() would change its value.
> So for usage perspective the methods you define on enmu are like static
> method on class which has its limitations.
>
> As for methods in enmu body in your example, the only usage I can recall
> now is like what TimeUnit does. For CloudStack, we can do the similar
> thing: SizeUnit that translates storage/memory size in different
> quantities.
>
> public enum SizeUnit {
>     BYTE {
>         public long toKiloByte(long s) {
>             return (s / (k / b));
>         }
>
>         public long toMegaByte(long s) {
>             return (s / (m / b));
>         }
>
>         public long toGigaByte(long s) {
>             return (s / (g / b));
>         }
>
>         public long toTeraByte(long s) {
>             return (s / (t / b));
>         }
>     },
>     KILOBYTE {
>         public long toByte(long s) {
>             return (s * (k / b));
>         }
>
>         public long toMegaByte(long s) {
>             return (s / (m / k));
>         }
>
>         public long toGigaByte(long s) {
>             return (s / (g / k));
>         }
>
>         public long toTeraByte(long s) {
>             return (s / (t / k));
>         }
>     },
>     MEGABYTE {
>         public long toByte(long s) {
>             return (s * (m / b));
>         }
>
>         public long toKiloByte(long s) {
>             return (s * (m / k));
>         }
>
>         public long toGigaByte(long s) {
>             return (s / (g / m));
>         }
>
>         public long toTeraByte(long s) {
>             return (s / (t / m));
>         }
>     },
>     GIGABYTE {
>         public long toByte(long s) {
>             return (s * (g / b));
>         }
>
>         public long toKiloByte(long s) {
>             return (s * (g / k));
>         }
>
>         public long toMegaByte(long s) {
>             return (s * (g / m));
>         }
>
>         public long toTeraByte(long s) {
>             return (s / (t / g));
>         }
>     },
>     TERABYTE {
>         public long toByte(long s) {
>             return (s * (t / b));
>         }
>
>         public long toKiloByte(long s) {
>             return (s * (t / k));
>         }
>
>         public long toMegaByte(long s) {
>             return (s * (t / m));
>         }
>
>         public long toGigaByte(long s) {
>             return (s * (t / g));
>         }
>     };
>
>     private static final long b = 1;
>     private static final long k = b * 1024;
>     private static final long m = k * 1024;
>     private static final long g = m * 1024;
>     private static final long t = g * 1024;
>
>     public long toByte(long s) {
>         throw new AbstractMethodError();
>     }
>     public long toKiloByte(long s) {
>         throw new AbstractMethodError();
>     }
>     public long toMegaByte(long s) {
>         throw new AbstractMethodError();
>     }
>     public long toGigaByte(long s) {
>         throw new AbstractMethodError();
>     }
>     public long toTeraByte(long s) {
>         throw new AbstractMethodError();
>     }
> }
>
> This may explain some of my views on java enum. It does have lots of
> advantages like compiler check, native == operator. Just like
> Alex mentioned, for constants that unlikely to change in future, we can
> stick to enum. But for types that plugin may extend, we'd
> better to use own defined classes.
>
> From: John Burwell [mailto:jburw...@basho.com]
> Sent: Tuesday, July 23, 2013 6:25 AM
> To: dev@cloudstack.apache.org
> Subject: Re: [DESIGN] Why is enum a class...
>
> All,
>
> +1 to Alex's design suggestion.  Another little know feature of
> enumerations is the ability to define abstract methods.  Therefore, Alex's
> example can be expanded as follows:
>
> public enum Type {
>        User(false)
>         {
>                 @Override
>                 public void doWork() {
>                 }
>         },
>        DomainRouter(true)
>         {
>                 @Override
>                 public void doWork() {
>                 }
>         },
>        ConsoleProxy(true)
>         {
>                 @Override
>                 public void doWork(){
>                 {
>         },
>        SecondaryStorageVm(true)
>         {
>                 @Override
>                 public void doWork(){
>                 {
>         },
>        ElasticIpVm(true)
>         {
>                 @Override
>                 public void doWork(){
>                 {
>         },
>        ElasticLoadBalancerVm(true)
>         {
>                 @Override
>                 public void doWork(){
>                 {
>         },
>        InternalLoadBalancerVm(true)
>         {
>                 @Override
>                 public void doWork(){
>                 {
>         }
>
>        /*
>         * UserBareMetal is only used for selecting VirtualMachineGuru,
> there is no
>         * VM with this type. UserBareMetal should treat exactly as User.
>         */
>        UserBareMetal(false);
>
>       private boolean _isSystemVm;
>
>       private Type(Boolean isSystemVm) {
>           _isSystemVm = isSystemVm;
>       }
>
>        public boolean isSystemVM() {
>           return _isSystemVm;
>        }
>
>       public abstract doWork();
>
>    }
>
> Personally, I see using switch statements with Java enumerations as a bad
> code smell.  Java enumerations were specifically designed to allow the
> implementation of behavior on values.  In addition to simplifying code, it
> greatly increases cohesion by defining all of the uses of the value in one
> place and using the compiler to validate coverage.  Finally, it makes unit
> testing of this conditional functionality much more straight forward.
>
> To Frank's point, I don't see the need for another class.  The Java
> compiler properly generates the boilerplate methods and ensures that all
> enumeration values are singletons within a class loader.  Regardless of the
> state added to an enumeration value, User==User will always be true.
>
> Thanks,
> -John
>
> On Jul 23, 2013, at 3:48 AM, Daan Hoogland <daan.hoogl...@gmail.com>
> wrote:
>
>
> +1 I am having a war on the enums in Networks.java that justifies your
> solution, Frank
>
>
> On Tue, Jul 23, 2013 at 2:57 AM, Alex Huang <alex.hu...@citrix.com> wrote:
>
>
> +1 to do this for any enum that was designed to be added to by the plugins.
>
> I actually wrote a class for this before called Constant that did exactly
> this.  The problem I had was that there was no way to guarantee compile
> time enumeration of all of the values like Enum did so it's possible for
> errors to be introduced but certainly we can follow a convention in this
> regard.  Another way would be to use Spring to gather them and inject them
> into a holding class.
>
> --Alex
>
>
> -----Original Message-----
> From: Frank Zhang [mailto:frank.zh...@citrix.com]
> Sent: Monday, July 22, 2013 5:45 PM
> To: dev@cloudstack.apache.org
> Subject: RE: [DESIGN] Why is enum a class...
>
> Frankly speaking, if we are going to change enum, I would suggest not
> using
>
> enmu anymore, instead, defining our own class like:
>
> public class VmType {
>      private static Map<String, VmType > types =
> Collections.synchronizedMap(new HashMap<String, VmType >());
>      private final String typeName;
>
>      public VmType (String typeName) {
>              this.typeName = typeName;
>              types.put(typeName, this);
>      }
>
>      public static VmType valueOf(String typeName) {
>              VmType type = types.get(typeName);
>              if (type == null) {
>                      throw new IllegalArgumentException("VmType type:
> " + typeName + " was not registered by any VmType");
>              }
>              return type;
>      }
>
>      @Override
>      public String toString() {
>              return typeName;
>      }
>
>      @Override
>      public boolean equals(Object t) {
>              if (t == null || !(t instanceof VmType)) {
>                      return false;
>              }
>
>              VmType type = (VmType)t;
>              return type.toString().equals(typeName);
>      }
>
>      @Override
>      public int hashCode() {
>              return typeName.hashCode();
>      }
>
>      public static Set<String> getAllTypeNames() {
>          return types.keySet();
>      }
> }
>
> The only benefit of enum I see is you can use "==" instead of "equals()"
> when comparing variables. However, it makes your code tight, every time
> adding a new type you have to modify the enum.
>
> By above method, when a new plugin wants to extend a new VmType, it
> simply does:
>
> class MagicVmManagerImpl {
>        public static final VmType type = new VmType("MagicVm"); }
>
>
>
> -----Original Message-----
> From: Alex Huang [mailto:alex.hu...@citrix.com]
> Sent: Monday, July 22, 2013 5:23 PM
> To: dev@cloudstack.apache.org
> Subject: RE: [DESIGN] Why is enum a class...
>
> BTW, this code already shows a bug that stems from the static method
> usage.
>
> It says ElasticIpVm is not a system vm (which I don't believe is
> true).  Probably because whoever added elastic ip vm didn't see the
> static method and so didn't add the vm into the method.
>
> --Alex
>
>
> -----Original Message-----
> From: Alex Huang [mailto:alex.hu...@citrix.com]
> Sent: Monday, July 22, 2013 5:14 PM
> To: dev@cloudstack.apache.org
> Subject: [DESIGN] Why is enum a class...
>
> I just went over this code and thought it was related and might be
> interested to other developers.
>
> What's the difference between declaring a enum like this
>
>    public enum Type {
>        User,
>        DomainRouter,
>        ConsoleProxy,
>        SecondaryStorageVm,
>        ElasticIpVm,
>        ElasticLoadBalancerVm,
>        InternalLoadBalancerVm,
>
>        /*
>         * UserBareMetal is only used for selecting
> VirtualMachineGuru, there is no
>         * VM with this type. UserBareMetal should treat exactly as
> User.
>
>         */
>        UserBareMetal;
>
>        public static boolean isSystemVM(VirtualMachine.Type vmtype)
> {
>
>            if (DomainRouter.equals(vmtype)
>                    || ConsoleProxy.equals(vmtype)
>                    || SecondaryStorageVm.equals(vmtype) ||
> InternalLoadBalancerVm.equals(vmtype)) {
>                return true;
>            }
>            return false;
>        }
>    }
>
> Vs
>
>    public enum Type {
>        User(false),
>        DomainRouter(true),
>        ConsoleProxy(true),
>        SecondaryStorageVm(true),
>        ElasticIpVm(true),
>        ElasticLoadBalancerVm(true),
>        InternalLoadBalancerVm(true),
>
>        /*
>         * UserBareMetal is only used for selecting
> VirtualMachineGuru, there is no
>         * VM with this type. UserBareMetal should treat exactly as
> User.
>
>         */
>        UserBareMetal(false);
>
>       private boolean _isSystemVm;
>
>       private Type(Boolean isSystemVm) {
>           _isSystemVm = isSystemVm;
>       }
>
>        public boolean isSystemVM() {
>           return _isSystemVm;
>        }
>    }
>
> The second declaration is more self-descriptive:
>
> - It tells developer when they add more to this enum, they have to
> specify whether it is a system vm.  They may have missed the static
> method in the first declaration and causes failures later.
> - It tells developers using the enum that there's a property that
> let's them know it is a system vm so they can do discovery using a
> context-sensitive editor like Eclipse.
>
> This is the reason why enum is not a simple constant declaration in
> Java (vs C/C++).
> --Alex
>
>
>

Reply via email to