prototyping good OOdesign in Python?

Roman Suzi rnd at onego.ru
Sat Jun 1 14:54:49 EDT 2002
Maybe this was already discussed, but I'd liked to raise this topic again.

Python has superb OOProgramming support. Lets not dispute this for a
moment. Now let's consider that we need to make well-designed OOP solution
first prototyped in Python.

What troubles are there? Python is too dynamic and all that. And all
those nifty features need to be translated properly into, say, C++.

Recently I encountered the following piece of code
(from Arts++ project):

//===========================================================================
//  Copyright Notice
//
//  By accessing this software, arts++, you are duly informed
//  of and agree to be bound by the conditions described below in this
//  notice:
//
//  This software product, arts++, is developed by Daniel W. McRobb, and
//  copyrighted(C) 1998 by the University of California, San Diego
//  (UCSD), with all rights reserved.  UCSD administers the CAIDA grant,
//  NCR-9711092, under which part of this code was developed.
//
//  There is no charge for arts++ software.  You can redistribute it
//  and/or modify it under the terms of the GNU Lesser General Public
//  License, Version 2.1, February 1999, which is incorporated by
//  reference herein.
//
//  arts++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF
//  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use
//  of it will not infringe on any third party's intellectual
//  property rights.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with arts++.  Copies can also be obtained from:
//
//    http://www.gnu.org/copyleft/lesser.html
//
//  or by writing to:
//
//  Free Software Foundation, Inc.
//  59 Temple Place, Suite 330
//  Boston, MA 02111-1307
//  USA
//
//  Or contact:
//
//    info at caida.org
//===========================================================================

//  constructor

............skip

Arts::Arts()
{
  this->_data._ipPath = (ArtsIpPathData *)0;
  this->_data._asMatrix = (ArtsAsMatrixData *)0;
  this->_data._netMatrix = (ArtsNetMatrixData *)0;
  this->_data._portTable = (ArtsPortTableData *)0;
  this->_data._portMatrix = (ArtsPortMatrixData *)0;
  this->_data._protocolTable = (ArtsProtocolTableData *)0;
  this->_data._selectedPortTable = (ArtsSelectedPortTableData *)0;
  this->_data._interfaceMatrix = (ArtsInterfaceMatrixData *)0;
  this->_data._nextHopTable = (ArtsNextHopTableData *)0;
  this->_data._bgp4RouteTable = (ArtsBgp4RouteTableData *)0;
  this->_data._rttTimeSeriesTable = (ArtsRttTimeSeriesTableData *)0;
  this->_data._tosTable = (ArtsTosTableData *)0;
  
  #ifndef NDEBUG
    ++_numObjects;
  #endif
}

Arts::Arts(const Arts & arts)
{
  this->_header = arts.Header();
  this->_attributes = arts.Attributes();

  switch (this->_header.Identifier()) {
    case artsC_OBJECT_IP_PATH:
      this->_data._ipPath = new ArtsIpPathData;
      assert(this->_data._ipPath != (ArtsIpPathData *)0);
      *(this->_data._ipPath) = *(arts.IpPathData());
      break;
      
    case artsC_OBJECT_AS_MATRIX:
      this->_data._asMatrix = new ArtsAsMatrixData;
      assert(this->_data._asMatrix != (ArtsAsMatrixData *)0);
      *(this->_data._asMatrix) = *(arts.AsMatrixData());
      break;

    case artsC_OBJECT_NET:
      this->_data._netMatrix = new ArtsNetMatrixData;
      assert(this->_data._netMatrix != (ArtsNetMatrixData *)0);
      *(this->_data._netMatrix) = *(arts.NetMatrixData());
      break;

    case artsC_OBJECT_PORT:
      this->_data._portTable = new ArtsPortTableData;
      assert(this->_data._portTable != (ArtsPortTableData *)0);
      *(this->_data._portTable) = *(arts.PortTableData());
      break;

    case artsC_OBJECT_SELECTED_PORT:
      this->_data._selectedPortTable = new ArtsSelectedPortTableData;
      assert(this->_data._selectedPortTable != (ArtsSelectedPortTableData *)0);
      *(this->_data._selectedPortTable) = *(arts.SelectedPortTableData());
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      this->_data._portMatrix = new ArtsPortMatrixData;
      assert(this->_data._portMatrix != (ArtsPortMatrixData *)0);
      *(this->_data._portMatrix) = *(arts.PortMatrixData());
      break;

    case artsC_OBJECT_PROTO:
      this->_data._protocolTable = new ArtsProtocolTableData;
      assert(this->_data._protocolTable != (ArtsProtocolTableData *)0);
      *(this->_data._protocolTable) = *(arts.ProtocolTableData());
      break;

    case artsC_OBJECT_TOS:
      this->_data._tosTable = new ArtsTosTableData;
      assert(this->_data._tosTable != (ArtsTosTableData *)0);
      *(this->_data._tosTable) = *(arts.TosTableData());
      break;

    case artsC_OBJECT_INTERFACE_MATRIX:
      this->_data._interfaceMatrix = new ArtsInterfaceMatrixData;
      assert(this->_data._interfaceMatrix != (ArtsInterfaceMatrixData *)0);
      *(this->_data._interfaceMatrix) = *(arts.InterfaceMatrixData());
      break;
      
    case artsC_OBJECT_NEXT_HOP:
      this->_data._nextHopTable = new ArtsNextHopTableData;
      assert(this->_data._nextHopTable != (ArtsNextHopTableData *)0);
      *(this->_data._nextHopTable) = *(arts.NextHopTableData());
      break;

    case artsC_OBJECT_BGP4:
      this->_data._bgp4RouteTable = new ArtsBgp4RouteTableData;
      assert(this->_data._bgp4RouteTable != (ArtsBgp4RouteTableData *)0);
      *(this->_data._bgp4RouteTable) = *(arts.Bgp4RouteTableData());
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      this->_data._rttTimeSeriesTable = new ArtsRttTimeSeriesTableData;
      assert(this->_data._rttTimeSeriesTable != (ArtsRttTimeSeriesTableData *)0);
      *(this->_data._rttTimeSeriesTable) = *(arts.RttTimeSeriesTableData());
      break;
      
    default:
      break;
  }

  #ifndef NDEBUG
    ++_numObjects;
  #endif
}

..........skip the rest of file - there are 2-3 more similar
.......... switch-constructs.

------------------------------------------------------------

This code looks like... automatically generated. Rather than manually
written. I do not know why it was written in C++ at all. Of course, I
imagine 2-3 variants of how to refactor it if I were writing the code
in Python. I am pretty sure there were no select statement (switches)
in Python code, because that is what polymorphism is about.

But then again, translating back to C++ could be difficult. The
mentioned example is all about reading a specially formatted binary
file to produce certain slices of information. And for each
class it uses separate .cc/.hh file! While all the difference
between different classes - structure of corresponding data entries.

My approach in this case could be one resource file, with format
specification (like DTD). Plus one univarsal class to handle big
binary file according to "DTD"). Plus maybe separate resource file
with data query specifications. And it could be at most 80 Kb Python
project, not that monster Arts++ is in both source and binary forms...

Well, if you still follow this thread, the question is - how well
Python could serve as an ARCHITECTURAL prototype if it has too rich
OOP facilities? That is, is Python of help when trying to
prototype certain design? Developing in C++ looks so unnecessary hard
after things were done in Python... 
Or, it may be put this way: what discipline a Python programmer must
obey to allow it's prototype to be conveniently rewriten in C++?

The above thoughts aren't probably well-formed. But I hope
my concern is understood.


Sincerely yours, Roman Suzi
-- 
\_ Russia \_ Karelia \_ Petrozavodsk \_ rnd at onego.ru \_
\_ Saturday, June 01, 2002 \_ Powered by Linux RedHat 7.2 \_
\_ "Tried to play my shoehorn... all I got was footnotes!" \_






More information about the Python-list mailing list