<?xml version="1.0" encoding="windows-1252"?>
<node id="1016982" title="Re: RFC on how I'm doing when it comes to writing objects?" created="2013-02-04 12:20:17" updated="2013-02-04 12:20:17">
<type id="11">
note</type>
<author id="982107">
jmlynesjr</author>
<data>
<field name="doctext">
&lt;p&gt;I am working on learning to write objects myself. The following is a draft document I am writing to document what I am finding in the documentation and in posts and emails. It's related to wxPerl, but maybe it will be of use to you as well. Also,take a look at my [wxPerl LCD Clock] post to see the direction I am going at the moment.&lt;/p&gt;

&lt;p&gt;Update: Added link to clock post.&lt;/p&gt;

&lt;readmore&gt;&lt;code&gt;A Bridge to a Real wxPerl Application(Draft)
--------------------------------------------
Compiled and/or written by:
James M. Lynes Jr.
Last Modified: February 4, 2013

Introduction
------------

In my process of learning Perl and wxPerl over the past two years, I have noticed that there
is quite a gap between the way things are done in the "hello world" type of example and
the way things are done in a real application. In many cases, the examples available to learn
from are nicely packaged into large applications since there are so many modules to be
presented. Unfortunately this packaging adds complexity over and above that needed by the
module itself. In addition these examples are written by very experienced developers
using all of the "obscure" Perl syntax. The available documentation is 2200+ pages
of the wxWidgets C++ usage and many of the examples are sparsely commented. Fortunately,
over time, the C++ usage gets easier to read and the documentation becomes easier
to use. It's a steep hill for a new learner to climb.

In order to assist in my learning, I ported many of the "wxBook" C++ examples to wxPerl. I
tried to use the most stripped down program structure that I could that would illustrate
only the function being demonstrated, focusing on readability over efficiency.

Now I am looking to start combining these elements into a "real" application. And even though
I tend to lean towards readability, it's time for some of the "obscure" Perl syntax to
begin to be blended in. I'm sure my coding style will evolve as more of these idioms
are included in my applications. I intend to document my findings in this document.
Maybe it will speed up your learning curve too.

Basic Application Structure
---------------------------

The following is a basic structure for a wxPerl application. Some programmers
like to reverse the order of the packages shown.

      package main;						# Program initialization
      use strict;
      use warnings;
      my $app = App-&gt;new();					# Create the application object
      $app-&gt;MainLoop;						# Start event processing

      package App;						# Application initialization
      use strict;
      use warnings;
      use base 'Wx::App';					# Inherit from Wx::App object
      sub OnInit {						# Called from $app automatically
          my $frame = Frame-&gt;new();				# Create the top level window
          $frame-&gt;Show(1);					# Display the top level window
      }

      package Frame;						# Create the top level window
      use strict;
      use warnings;
      use Wx qw(:everything);					# Lazy way to pull in references
      use base qw(Wx::Frame);					# Inherit from Wx::Frame object
      use Wx::Event(EVT_A EVT_B EVT_3 etc);			# List required events

      # use other modules as needed by your application - Core, CPAN, or custom
      
      sub new {
          my ($self) = @_;

          # Create top level window- (SUPER refers to Wx::Frame)
          $self = $self-&gt;SUPER::new(undef, wxID_ANY, "Window Title", wxDefaultPosition, wxDefaultSize);

          # Attach required events(listed above) to an event handler - simple format - see below
          EVT_A($self, \&amp;onAhandler);				# $self is the window/subwindow
          EVT_B($self, \&amp;onBhandler);				# that is to receive this event
          EVT_C($self, \&amp;onChandler);

          # Create subwindows, controls, sizers, etc. as needed by the application

          return $self;						# Return the top level window object
      }
      1;							# True, so App continues processing

      sub onAhandler {						# One handler per event above
          my ($self, $event) = @_;
          # Process the event here
      }
      sub onBhandler {						# One handler per event above
          my ($self, $event) = @_;
          # Process the event here
      }
      sub onChandler {						# One handler per event above
          my ($self, $event) = @_;
          # Process the event here
      }
      # Other subroutines as needed by the application

Alternate Event Handler - can be overridden in a derived class(from a Mark Dootson email) 
-----------------------------------------------------------------------------------------

      EVT_A($self, sub{shift-&gt;_evt_on_Ahandler(@_);})

      _evt_on_Ahandler {
          my($self, $event) = @_;
          $self-&gt;SUPER::_evt_on_Ahandler($event);
          # Extra code here for a derived class
      }

Application Flow
----------------

The flow of an application is as follows:

      1. main creates the application object($app) by calling App-&gt;new()
      2. The application object($app) automatically calls App::OnInit()
      3. OnInit calls Frame-&gt;new() to create the top level window
      4. Frame-&gt;new() creates the top level window, subwindows, controls,
          sizers, event handlers, etc. as needed by the application
      5. Frame returns the top level window object, $self, to OnInit
      6. OnInit displays the top level window($self) by calling $frame-&gt;Show(1)
      7. OnInit returns to main
      8. main starts the MainLoop(which processes events) by calling $app-&gt;MainLoop 
         (it's all event processing from here on out, steps 1-8 aren't called again)    


Object Creation - Basic to Actual Practice
------------------------------------------

C Structure Emulation(from Perltoot)
------------------------------------

       By far the most common mechanism used in Perl to represent a Pascal
       record, a C struct, or a C++ class is an anonymous hash.  That's
       because a hash has an arbitrary number of data fields, each
       conveniently accessed by an arbitrary name of your own devising.

       If you were just doing a simple struct-like emulation, you would likely
       go about it something like this:

           $rec = {
               name  =&gt; "Jason",
               age   =&gt; 23,
               peers =&gt; [ "Norbert", "Rhys", "Phineas"],
           };

       If you felt like it, you could add a bit of visual distinction by up-
       casing the hash keys:

           $rec = {
               NAME  =&gt; "Jason",
               AGE   =&gt; 23,
               PEERS =&gt; [ "Norbert", "Rhys", "Phineas"],
           };

       And so you could get at "$rec-&gt;{NAME}" to find "Jason", or
       "@{$rec-&gt;{PEERS} }" to get at "Norbert", "Rhys", and "Phineas".

Basic Class Structure/Creation(from Perltoot) - This version does not support Inheritance
----------------------------------------------------------------------------------------

       Still, someone has to know what's in the object.  And that someone is
       the class.  It implements methods that the programmer uses to access
       the object.  Here's how to implement the Person class using the
       standard hash-ref-as-an-object idiom.  We'll make a class method called
       new() to act as the constructor, and three object methods called
       name(), age(), and peers() to get at per-object data hidden away in our
       anonymous hash.

           package Person;
           use strict;

           ##################################################
           ## the object constructor (simplistic version)  ##
           ##################################################
           sub new {
               my $self  = {};
               $self-&gt;{NAME}   = undef;
               $self-&gt;{AGE}    = undef;
               $self-&gt;{PEERS}  = [];
               bless($self);           		# See below
               return $self;
           }

           ##############################################
           ## methods to access per-object data        ##
           ##  (hand coded Accessors)                  ##
           ## With args, they set the value.  Without  ##
           ## args, they retrieve the value.           ##
           ##############################################

           sub name {
               my $self = shift;
               if (@_) { $self-&gt;{NAME} = shift }
               return $self-&gt;{NAME};
           }

           sub age {
               my $self = shift;
               if (@_) { $self-&gt;{AGE} = shift }
               return $self-&gt;{AGE};
           }

           sub peers {
               my $self = shift;
               if (@_) { @{ $self-&gt;{PEERS} } = @_ }
               return @{ $self-&gt;{PEERS} };
           }

           1;  # True, so the require or use succeeds

Basic Class with support for inheritance(from Perltoot)
-------------------------------------------------------

       Even though at this point you may not even know what it means, someday
       you're going to worry about inheritance.  (You can safely ignore this
       for now and worry about it later if you'd like.)  To ensure that this
       all works out smoothly, you must use the double-argument form of
       bless().  The second argument is the class into which the referent will
       be blessed.  By not assuming our own class as the default second
       argument and instead using the class passed into us, we make our
       constructor inheritable.

           sub new {
               my $class = shift;
               my $self  = {};
               $self-&gt;{NAME}   = undef;
               $self-&gt;{AGE}    = undef;
               $self-&gt;{PEERS}  = [];
               bless ($self, $class);
               return $self;
           }

       That's about all there is for constructors.  These methods bring
       objects to life, returning neat little opaque bundles to the user to be
       used in subsequent method calls.


Automagically generate accessors/mutators for your class(from Class::Accessor)
------------------------------------------------------------------------------

       Most of the time, writing accessors is an exercise in cutting and pasting.
       You usually wind up with a series of methods like this:

           sub name {
               my $self = shift;
               if(@_) {
                   $self-&gt;{name} = $_[0];
               }
               return $self-&gt;{name};
           }

           sub salary {
               my $self = shift;
               if(@_) {
                   $self-&gt;{salary} = $_[0];
               }
               return $self-&gt;{salary};
           }

         # etc...

       One for each piece of data in your object.  While some will be unique,
       doing value checks and special storage tricks, most will simply be exercises
       in repetition.  Not only is it Bad Style to have a bunch of repetitious code,
       but it's also simply not lazy, which is the real tragedy.

       If you make your module a subclass of Class::Accessor and declare your
       accessor fields with mk_accessors() then you'll find yourself with a set of
       automatically generated accessors which can even be customized!

       The basic set up is very simple:

           package Foo;
           use base qw(Class::Accessor);
           Foo-&gt;mk_accessors( qw(far bar car) );

       Done!  Foo now has simple far(), bar() and car() accessors defined.

       Class::Accessor also provides a basic constructor, "new".  It generates a hash-based object
       and can be called as either a class method or an object method.

           my $obj = Foo-&gt;new;
           my $obj = $other_obj-&gt;new;

           my $obj = Foo-&gt;new(\%fields);
           my $obj = $other_obj-&gt;new(\%fields);

       It takes an optional %fields hash which is used to initialize the object.
       The fields of the hash correspond to the names of your accessors, so...

           package Foo;
           use base qw(Class::Accessor);
           Foo-&gt;mk_accessors('foo');

           my $obj = Foo-&gt;new({ foo =&gt; 42 });
           print $obj-&gt;foo;    # 42

       However %fields can contain anything, new() will shove them all into your object.

Accessor Usage with wxPerl(from a Mark Dootson email)
-----------------------------------------------------

       It is generally accepted that accessing the members of an object directly
       by their hash keys is bad practice. So,

       $object-&gt;{something} ; # is bad
       $object-&gt;something() ; # is good

       Apart from all the OO theory that says $object-&gt;something is the correct thing to have,
       in practical terms the major disadvantage of the direct hash access is that errors
       in your code are more difficult to debug / catch.

       For example, if I misspell the accessor name

       $object-&gt;{somting} ;
       $object-&gt;somting() ;

       Then for the hash based access I get no error and the type of warning will be dependent on context.
       For the method based accessor ( $object-&gt;somting ) I always get 'no method named somting' error.

       The plain Perl method for creating the method would be along the lines of

       sub something {
       my $self = shift;
       $self-&gt;{_something} = shift if(@_);
       $self-&gt;{_something};
       }

       The module 'Class::Accessor' just gives a few shorthand ways of doing this and
       I wanted to demonstrate that you don't have to do the longhand code above.
       Class::Accessor also claims a speed increase for the accessors it creates.

       *** However, we have a problem incorporating this into Wx. ***
       Class::Accessor relies on an inheriting class calling its 'new' method. But we
       also need to call the 'new' method of Wx::Window so we inherit from that.
       There are various ways of working around this, but there isn't one that would be
       regarded as a 'standard' as far as I am aware. So rather than subject you
       to some possibly confusing code, I just put the data into a separate class.

       For example:

       #########################################################################################

       package Meter::Data;

       #########################################################################################
       use strict;
       use warnings;
       use Class::Accessor::Fast;
       use base qw( Class::Accessor::Fast );

       # Create the Accessors
       __PACKAGE__-&gt;mk_accessors( qw( ActiveBar PassiveBar ValueColour BorderColour
       LimitColour TagsColour ScaledVal RealVal Max Min DirOrizFlag ShowCurrent
       ShowLimits Font Tags ) );

       # Create the Object
       sub new { shift-&gt;SUPER::new( @_ ); }
       1;
  
Class::Accessor Usage Example in wxPerl
---------------------------------------

       See the comments below relating to the BEGIN block. Only needed due to the
       structure of this example - multiple packages within the same source file.

       #! /home/xxxx/CitrusPerl/perl/bin/perl

       # Test of Class::Accessor::Fast

       package main;
       use strict;
       use warnings;
       my $app = App-&gt;new();
       $app-&gt;MainLoop;

       package App;
       use strict;
       use warnings;
       use base 'Wx::App';
       sub OnInit {
           my $frame = Frame-&gt;new();
           $frame-&gt;Show(1);
       }

       package Frame;
       use strict;
       use warnings;
       use Wx qw(:everything);
       use base qw(Wx::Frame);
       use Data::Dumper;

       sub new {
           my($self) = @_;

           $self = $self-&gt;SUPER::new(undef, -1, "Class::Accessor Test", 
                                     wxDefaultPosition, wxDefaultSize);
           my %defaults = (
                           vara =&gt; 10,
                           varb =&gt; 20,
                           varc =&gt; 30,
                           vard =&gt; 40,
                           vare =&gt; 50,
           );

           my $obj = Data-&gt;new(\%defaults);			# Object created and initialized correctly
           print Dumper($obj);

           $obj-&gt;vara(100);					# Use of generated accessors
           $obj-&gt;varb(200);
           $obj-&gt;varc(300);
           $obj-&gt;vard(400);
           $obj-&gt;vare(500);
           print Dumper($obj);

           return $self;
       }
       1;
       BEGIN {							# Begin block required since Data is
       package Data;						# not in a separate module. Therefore
       use strict;						# mk_accessors not run before being used
       use warnings;						# and accessor subs would not be defined.
       use Class::Accessor::Fast;				# Normally use Data would fix this issue
       use base qw(Class::Accessor::Fast);

       __PACKAGE__-&gt;mk_accessors(qw(vara varb varc vard vare));

       sub new {shift-&gt;SUPER::new(@_);}
       1;
       }
&lt;/code&gt;&lt;/readmore&gt;

&lt;p&gt;James&lt;/p&gt;
&lt;div class="pmsig"&gt;&lt;div class="pmsig-982107"&gt;
&lt;p&gt;There's never enough time to do it right, but always enough time to do it over...&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</field>
<field name="root_node">
1016970</field>
<field name="parent_node">
1016970</field>
</data>
</node>
