prototyping good OOdesign in Python?
Ken Seehof
kseehof at neuralintegrator.com
Sat Jun 1 16:04:50 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
I agree with what you are saying. Here's my approach :-)
0. Write a project schedule for management; something like this:
1. Prototype in python
2. Convert to C++
1. Prototype in python
2. Give a nice demo, and convince management to skip step 2
3. Re-implement a few cpu intensive classes in C++
Since most of the code never /actually/ gets rewritten in C++,
the need for special C++ "discipline" in the python code goes
away. Weeks are slashed from the schedule, and the program is
more maintainable.
Another nice advantage is that the python programmer gets to ask
for a raise, and has excellent job security!
There may be a few oddball examples of projects that actually
need to end up written in C++ after prototyping in python, but
for the most part, the most common reason to target C++ is to
alleviate fear of the unknown. (Hmm, is this also why people,
(including myself), still buy from Microsoft? :-)
- Ken Seehof
More information about the Python-list
mailing list