473,387 Members | 1,812 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Require help learning how to decompose class into policies

Below is a class that is suppose to represent a segment of memory or a
contents of a binary image (e.g. ELF executable). I have started to read
Modern C++ Design and thought the best way to ensure I was understanding
the chapter on policy classes was to attempt to apply them to my project.
I understand the general concept of policies but I lack the knowledge and
wisdom of how to identify them in an existing project. So I figured to get
an existing class and start from there.

Some notes about the code:

- Tracing: The following statement is only activate if the ./configure
script was run with --enable-debug. Otherwise its compiled out by
the compiler. If debugging is enabled AND the trace level of the
library was set to TraceLevel::DETAIL or higher then the message
will appear.

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map::swap" );

- Assert: The following statement will perform either a throw an exception
which performs a typical abort after finding a false expression,
reporting where in the code the assert happened along with a descriptive message.
Otherwise a developer can provide another exception which can take a different
approach to terminating the program.

Assert::bool_check ( size != 0, "Size of memory map is zero." );

My first thoughts where to make the Asserts into a policy. Second place could be the to_String
function. One way of printing could be a indented string with spaces or another method writing the content
of the class as a XML string. Any help is appreciated.

Stephen

----------------------
HEADER
----------------------

#ifndef MEMORY_MAP_H_
#define MEMORY_MAP_H_

#include <boost/shared_ptr.hpp>
#include <iostream>
#include <iomanip>
#include <vector>
#include <map>
#include <boost/enable_shared_from_this.hpp>
#include "Data_Types.h"

namespace libreverse { namespace data_container {

class Memory_Map : public boost::enable_shared_from_this<Memory_Map>
{
public:

/**
* \brief Set up a blank memory map of a set size
*
* \param size Size of memory map to allocate
*
* \param base_address The memory address of the first byte
*
* \pre size has a value of 0 or more
*
* \pre base_address has a value of 0 or more
*
* \post Size of memory map has been set to the value of the
* input variable 'size'
*
* \post Base addres of the memory map has been set to the
* value of the input variable 'base_address' or the default
* value of zero
*/
explicit Memory_Map ( boost::uint32_t size,
boost::uint32_t base_address = 0 );

/**
* \brief Set up a memory map of a set size with the contents
* of the input file stream.
*
* \param input_ref Input file stream where data is stored.
*
* \param base_address The memory address of the first byte
*
* \pre size has a value of 0 or more
*
* \pre base_address has a value of 0 or more
*
* \post Size of memory map has been set to the value of the
* size of the input file stream.
*
* \post Base addres of the memory map has been set to the
* value of the input variable 'base_address' or the default
* value of zero
*/
explicit Memory_Map ( std::ifstream& input_ref,
boost::uint32_t base_address = 0 );

/**
* \brief Copy constructor
*
* \pre The input reference is a fully initialized Memory_Map
*
* \post The output Memory_Map is a deep copy of the input
*/
explicit Memory_Map ( Memory_Map const& rhs );

virtual ~Memory_Map();

/**
* \brief assignment operator
*
* This function handles copying the rhs reference even if the rhs
* is a reference to this object.
*
* \pre The input reference is a fully initialized Memory_Map
*
* \post The output Memory_Map is a deep copy of the input
*/
Memory_Map& operator= ( Memory_Map const& rhs );

/**
* \brief assignment operator
*
* \pre The input reference is a fully initialized Memory_Map
*
* \post The output Memory_Map is a deep copy of the input
*/
void swap ( Memory_Map& rhs );

/**
* \brief Adjust the pointer into the memory to the location
* specified in by the address.
*
* \post The present position is set to the new location.
*/
boost::int8_t address_Seek ( boost::uint32_t address );

/**
* \brief Adjust the pointer into the memory to the location
* specified in by the index.
*
* \post The present position is set to the new location.
*/
template <typename Offset_Type>
boost::int8_t
index_Seek ( Offset_Type offset )
{
if ( offset m_data.size() - 1 )
{
std::cerr << "The offset given, " << offset
<< " is invalid. Its pointing to a "
<< std::endl
<< "memory location outside of space "
<< "allocated to"
<< std::endl
<< "this Memory Map. ("
<< m_data.size() << ")"
<< std::endl;

return data_types::Memory_Map::OUT_OF_RANGE;
}

m_present_pos = offset;

return data_types::Memory_Map::SUCCESS;
}

/**
* \brief Read 'length' units of data from this Memory Map.
*
* The read data will be placed into the destination startin
* at the beginning.
*
* \pre The destination pointer is initialized.
*
* \pre Read length is non-zero
*
* \post The present position is set to the new location.
*/
boost::int8_t read ( data_types::Memory_Map::pointer_t dest_addr_ptr,
boost::uint32_t length );

/**
* \brief This copies from the src_ptr to the local Memory
* Map. It is assumed that the local Memory Map has been
* adjusted to the position where data will be store. It is
* also assumed that the src_ptr has been adjusted to the
* position where we will start reading data.
*
* \pre The destination pointer is initialized.
*
* \pre Read length is non-zero
*
* \post The present position is set to the new location.
*/
boost::int8_t copy ( data_types::Memory_Map::ptr_t src_ptr,
boost::uint32_t length );

/**
* \brief This produces a new Memory Map containing a subset
* of the parent map. It is assumed that the parent Memory Map
* has been adjusted to the position where we will start
* reading data.
*
* \pre Present Position of the pointer into the data will not
* go past the boundary with the given length.
*
* \pre Length is non-zero
*/
std::pair <data_types::Memory_Map::ptr_t, boost::int8_t>
subset ( boost::uint32_t length );

data_types::Memory_Map::iterator begin();

data_types::Memory_Map::const_iterator begin() const;

data_types::Memory_Map::const_iterator end() const;

boost::uint32_t get_Present_Position_Value (void) const;

data_types::Memory_Map::const_iterator get_Present_Position (void) const;

boost::uint32_t get_Present_Position_Address (void) const;

boost::uint32_t get_Previous_Position_Value (void) const;

data_types::Memory_Map::const_iterator get_Previous_Position (void) const;

boost::uint32_t get_Previous_Position_Address (void) const;

boost::uint32_t const size (void) const;

std::string to_String (void) const;

bool operator== ( Memory_Map& rhs_ref ) const;

bool allocate_Range ( boost::uint32_t address, boost::uint32_t size );

private:

Memory_Map();

data_types::Memory_Map::Values_t m_data;

boost::uint32_t m_present_pos; // Present index

boost::uint32_t m_previous_pos; // Previous index

boost::uint32_t m_base_address;

};

} /* namespace data_types */
} /* namespace libreverse */

#endif /* MEMORY_MAP_H_ */

--------------------
SOURCE
---------------------
#include "Memory_Map.h"
#include <sstream>
#include <fstream>
#include <boost/format.hpp>
#include "libreverse/Trace.h"
#include "libreverse/Assert.h"

using namespace libreverse::api;
using namespace libreverse::assert;
using namespace libreverse::trace;

namespace libreverse { namespace data_container {

template < template<classclass CheckingPolicy >
Memory_Map::Memory_Map ()
: m_data (),
m_present_pos ( 0 ),
m_previous_pos ( 0 ),
m_base_address ( 0 )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map constructor" );
}

Memory_Map::Memory_Map ( boost::uint32_t size,
boost::uint32_t base_address )
: m_data ( size, 0 ),
m_present_pos ( 0 ),
m_previous_pos ( 0 ),
m_base_address ( base_address )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map constructor (uint32,uint32)" );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DATA,
boost::str ( boost::format ( "paramaters: size = 0x%1X base address = 0x%2X")
% size
% base_address ) );
Assert::bool_check ( size != 0, "Size of memory map is zero." );

Assert::bool_check ( ( m_data.size() == size ), "Size of the image data array is not equal to the requested size." );
Assert::bool_check ( ( m_base_address == base_address ), "Base address of image is not equal to the requested address.");

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map constructor (uint32,uint32)" );
}

Memory_Map::Memory_Map ( std::ifstream& input_ref,
boost::uint32_t base_address )
: m_present_pos ( 0 ),
m_previous_pos ( 0 ),
m_base_address ( base_address )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map constructor (ifstream,uint32)" );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DATA,
boost::str ( boost::format ( "paramaters: ifstream = 0x%1X base address = 0x%2X")
% &input_ref
% base_address ) );
Assert::bool_check ( input_ref.good(), "Input file stream is not ready for I/O operations." );

char byte = 0;

while ( !input_ref.eof() )
{
input_ref.read ( &byte, sizeof(byte) );
m_data.push_back ( byte );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DATA,
boost::str ( boost::format (" byte: 0x%1X" )
% static_cast<boost::uint16_t>(byte) ) );

}

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DATA,
boost::str ( boost::format (" data size: 0x%1d" ) % m_data.size() ) );

input_ref.clear();
input_ref.seekg ( std::ios_base::beg );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map constructor (ifstream,uint32)" );
}

Memory_Map::Memory_Map ( Memory_Map const& rhs )
: boost::enable_shared_from_this<Memory_Map>(rhs),
m_data ( rhs.m_data.size() ),
m_present_pos ( rhs.m_present_pos ),
m_previous_pos ( rhs.m_previous_pos )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map copy constructor" );

std::copy ( rhs.m_data.begin(),
rhs.m_data.end(),
m_data.begin() );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map copy constructor" );

}

Memory_Map::~Memory_Map ()
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Memory_Map destructor called" );
}

boost::int8_t
Memory_Map::read ( data_types::Memory_Map::pointer_t dest_addr_ptr,
boost::uint32_t length )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map::read" );

assert ( dest_addr_ptr != 0 );
assert ( length != 0 );

if ( m_present_pos + length m_data.size() )
{
Trace::write_Trace
( TraceArea::DATA_CONTAINERS,
TraceLevel::ERROR,
boost::str(boost::format("Present Position: %d") %
m_present_pos) );

Trace::write_Trace
( TraceArea::DATA_CONTAINERS,
TraceLevel::ERROR,
boost::str(boost::format("Input read length: %d") %
length) );

Trace::write_Trace
( TraceArea::DATA_CONTAINERS,
TraceLevel::ERROR,
boost::str(boost::format("Data size: %d") %
m_data.size()) );

Trace::write_Trace
( TraceArea::DATA_CONTAINERS,
TraceLevel::ERROR,
boost::str(boost::format("The resulting pointer is invalid. %d + %d %d")
% m_present_pos
% length
% m_data.size() ) );

Trace::write_Trace
( TraceArea::DATA_CONTAINERS,
TraceLevel::ERROR,
"Its pointing to a memory location out side of space allocated to this Memory Map.");

return data_types::Memory_Map::INVALID_INDEX;
}

data_types::Memory_Map::Values_t::const_iterator pos = m_data.begin();

std::copy ( pos + m_present_pos,
pos + m_present_pos + length,
dest_addr_ptr );

m_previous_pos = m_present_pos;
m_present_pos += length;

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map::read" );

return data_types::Memory_Map::SUCCESS;
}

data_types::Memory_Map::iterator
Memory_Map::begin()
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::begin" );
return m_data.begin();
}

data_types::Memory_Map::const_iterator
Memory_Map::begin() const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::begin (const)" );

return m_data.begin();
}

data_types::Memory_Map::const_iterator
Memory_Map::end() const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::end (const)" );

return m_data.end();
}

boost::uint32_t
Memory_Map::get_Present_Position_Value (void) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::get_Present_Position_Value" );

return m_present_pos;
}

data_types::Memory_Map::const_iterator
Memory_Map::get_Present_Position (void) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::get_Present_Position" );

return m_data.begin() + m_present_pos;
}

boost::uint32_t
Memory_Map::get_Present_Position_Address (void) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::get_Present_Position_Address" );

boost::uint32_t position_address = m_base_address + m_present_pos;

return position_address;
}

boost::uint32_t
Memory_Map::get_Previous_Position_Value (void) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::get_Previous_Position_Value" );

return m_previous_pos;
}

data_types::Memory_Map::const_iterator
Memory_Map::get_Previous_Position (void) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::get_Previous_Position" );

return m_data.begin() + m_previous_pos;
}

boost::uint32_t
Memory_Map::get_Previous_Position_Address (void) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::get_Previous_Position_Address" );

boost::uint32_t position_address = m_base_address + m_previous_pos;

return position_address;
}

boost::uint32_t const
Memory_Map::size (void) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::size" );

return m_data.size();
}

boost::int8_t
Memory_Map::copy ( data_types::Memory_Map::ptr_t src_ptr,
boost::uint32_t length )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map::copy" );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DATA,
boost::str ( boost::format ("parameters: src_ptr address = 0x%1p length=0x%2X (%3d)" )
% src_ptr.get()
% length
% length ) );

assert ( src_ptr.get() != 0 );
assert ( length != 0 );

// Off the end check
if ( m_present_pos + length m_data.size() )
{
Trace::write_Trace
( TraceArea::DATA_CONTAINERS,
TraceLevel::ERROR,
boost::str(boost::format("The present position
pointer will be invalid if we write from the present\nposition with the
given length. It will cause an segfault. Recheck the value\ngiven for
length (%d) or check the setting of the present position.")
% length ) );

return data_types::Memory_Map::OUT_OF_RANGE;
}

std::copy ( src_ptr->get_Present_Position(),
src_ptr->get_Present_Position() + length,
m_data.begin() + m_present_pos );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map::copy" );

return data_types::Memory_Map::SUCCESS;
}

std::pair<data_types::Memory_Map::ptr_t, boost::int8_t>
Memory_Map::subset ( boost::uint32_t length )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map::subset" );

assert ( length != 0 );

data_types::Memory_Map::ptr_t result_ptr
( new Memory_Map ( length,
this->get_Present_Position_Address() ) );

/*
* There is something wrong with the m_data. Its
*/
boost::int8_t result =
result_ptr->copy ( this->shared_from_this(), length );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map::subset" );

return std::make_pair ( result_ptr , result );
}

std::string
Memory_Map::to_String (void) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map::to_String" );

std::stringstream output;
std::stringstream char_output;

output << "----------------------------------------" << std::endl;

boost::uint8_t byte_counter = 0;

for ( boost::uint32_t index = 0;
index < m_data.size();
++index )
{
if ( byte_counter == 0 )
{
output << boost::format("%1X: ") % ( m_base_address + index );
}

output << boost::format("%1X") %
boost::io::group ( std::hex,
std::setw(2),
std::setfill('0'),
static_cast<boost::uint16_t>(m_data[index]));

if ( ( m_data[index] 0x1F ) &&
( m_data[index] < 0x7F ) )
{
char_output << boost::format("%1c") % m_data[index];
}
else
{
char_output << ".";
}

if ( ( byte_counter == 3 ) ||
( byte_counter == 7 ) ||
( byte_counter == 11 ) )
{
output << " ";
byte_counter++;
}
else if ( byte_counter != 15 )
{
output << " ";
byte_counter++;
}
else
{
byte_counter = 0;
output << " " << char_output.str();
char_output.str("");
output << std::endl;
}
}

if ( byte_counter != 15 )
{
for ( ;
byte_counter <= 15;
byte_counter++ )
{

output << " ";
char_output << ".";

if ( ( byte_counter == 3 ) ||
( byte_counter == 7 ) ||
( byte_counter == 11 ) )
{
output << " ";
}
else if ( byte_counter != 15 )
{
output << " ";
}
else
{
output << " " << char_output.str();
output << std::endl;
}
}
}

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map::to_String" );

return output.str();
}

bool
Memory_Map::operator== ( Memory_Map& rhs_ref ) const
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Inside Memory_Map::operator== (equality)" );

return ( m_data == rhs_ref.m_data );
}

boost::int8_t
Memory_Map::address_Seek ( boost::uint32_t address )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map::address_Seek" );

// If index is outside the range of the map
if ( ( address < m_base_address ) ||
( address m_base_address + m_data.size() ) )
{
std::cerr << "The address given, "
<< boost::format("%1X") % address
<< " is invalid. Its pointing to a "
<< std::endl
<< "memory location outside of space "
<< "allocated to"
<< std::endl
<< "this Memory Map. (";

std::cerr << boost::format("%1X") % m_base_address << " - ";

std::cerr << boost::format("%1X") % ( m_base_address + m_data.size() ) << ")"
<< std::endl;

return data_types::Memory_Map::OUT_OF_RANGE;
}

m_previous_pos = m_present_pos;
m_present_pos = address - m_base_address;

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map::address_Seek" );

return data_types::Memory_Map::SUCCESS;
}

Memory_Map&
Memory_Map::operator= ( Memory_Map const& rhs )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map::operator= (assignment)" );
Memory_Map temp ( rhs );
swap ( temp );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map::operator= (assignment)" );

return *this;
}

void
Memory_Map::swap ( Memory_Map& rhs )
{
Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Entering Memory_Map::swap" );

std::swap ( m_data, rhs.m_data );

Trace::write_Trace ( TraceArea::DATA_CONTAINERS,
TraceLevel::DETAIL,
"Exiting Memory_Map::swap" );

}

} /* Namespace data_types */
} /* namespace libreverse */

Sep 5 '07 #1
3 2280
On Sep 6, 12:49 am, Stephen Torri <sto...@torri.orgwrote:
Below is a class that is suppose to represent a segment of memory or a
contents of a binary image (e.g. ELF executable). I have started to read
Modern C++ Design and thought the best way to ensure I was understanding
the chapter on policy classes was to attempt to apply them to my project.
I understand the general concept of policies but I lack the knowledge and
wisdom of how to identify them in an existing project. So I figured to get
an existing class and start from there.
This sounds slightly backwards to me. Policies are a tool: a
means, and not a goal. If you don't feel the need for them (and
most application software won't), then all they do is add
unnecessary complexity. It's only when you end up with several
classes which differ only in a few specific operations that you
should start thinking about some sort of generic solution: the
template method pattern, policies, or whatever.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 6 '07 #2
On Thu, 06 Sep 2007 08:35:23 +0000, James Kanze wrote:
This sounds slightly backwards to me. Policies are a tool: a means, and
not a goal. If you don't feel the need for them (and most application
software won't), then all they do is add unnecessary complexity. It's
only when you end up with several classes which differ only in a few
specific operations that you should start thinking about some sort of
generic solution: the template method pattern, policies, or whatever.
I do not know if I need policies or not. I see the strength in using them but
what I do not gather from Alexandrescu's book is when I should use them. He
gives the advice that

"When you decompose a class in policies, it is very important to find an
orthogonal decomposition. An orthogonal decomposition yields policies that
are completely independent of each other. You can easily spot a nonorthogonal
decomposition when various policies need to know about each other."

I first do not understand what the word orthogonal decomposition means here.
I do not understand how to think about this advice.
Sep 6 '07 #3
On Sep 6, 3:43 pm, Stephen Torri <sto...@torri.orgwrote:
On Thu, 06 Sep 2007 08:35:23 +0000, James Kanze wrote:
This sounds slightly backwards to me. Policies are a tool: a means, and
not a goal. If you don't feel the need for them (and most application
software won't), then all they do is add unnecessary complexity. It's
only when you end up with several classes which differ only in a few
specific operations that you should start thinking about some sort of
generic solution: the template method pattern, policies, or whatever.
I do not know if I need policies or not.
You almost never need policies unless you are writing very low
level library code, and not that often then. With a very few
notable exceptions, policies are a solution in search of a
problem.
I see the strength in
using them but what I do not gather from Alexandrescu's book
is when I should use them.
The answer is: almost never.
He gives the advice that
"When you decompose a class in policies, it is very important
to find an orthogonal decomposition. An orthogonal
decomposition yields policies that are completely independent
of each other. You can easily spot a nonorthogonal
decomposition when various policies need to know about each
other."
I first do not understand what the word orthogonal
decomposition means here.
It's exactly what he says in the second sentence: orthogonal
decomposition means that the separate parts are independant, and
don't need to know about any of the other parts. This is
important anytime you start decomposing: policies, mixins, or at
a higher level, subsystems. With regards to policies: if the
need for policies is not very frequent, the need for a single
component to have several different policies is even rarer (and
orthogonal decomposition only enters into account in those
cases).

If you're familiar with OO technology and design patterns:
policies are basically the equivalent of the template method
pattern or the strategy pattern (both of which are generally
preferable to policies anywhere but at the lowest level); using
multiple policies on a single component is basically the same as
mixins. And the use of the first two patterns if far more
prevalent than the use of mixins (to the point that some
so-called OO languages don't even allow mixins).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 7 '07 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Deon | last post by:
Greetings, I need assistance in the following area please. I'm trying to search thought the WHOLE active directory to find all policies that are applied (active or not). And the description and...
4
by: Steven T. Hatton | last post by:
I'm in a situation where I want to be sure all my data is organized in a specific pattern in memory. The array is vertex data which I want to represent as individual vectors per vertex, and per...
2
by: Justin | last post by:
I am currently working on a windows app in C# that when given a computer's name needs to check local security policies on that computer across the server. Some of the policies I would like to...
1
by: anderberg | last post by:
Reading about policies in Andrei Alexandrescu's Modern C++ Design, I was wondering about the complexity of policies. It there a general recommendation that these policies should be relatively...
0
by: sjallard | last post by:
Dear all, This is my first work with the XML extenders: I'll have to decompose an XML file into a DB2 table, and "flatten" it in the same time, like in the example at the end of this message. I...
2
by: Ninereeds | last post by:
I'm messing around with using mixin-layers (look for papers by Yannis Smaragdakis and Don Batory) to define data structures. One issue is that nodes tend to have pointers to other nodes - the...
59
by: Kevin Walzer | last post by:
From the introduction to PyObjC, the Python-Objective-C bridge on Mac OS X: "As described in Objective-C for PyObjC users the creation of Objective-C objects is a two-stage process. To initialize...
15
by: Bob Johnson | last post by:
I have a base class that must have a member variable populated by, and only by, derived classes. It appears that if I declare the variable as "internal protected" then the base class *can*...
0
by: er | last post by:
hi, i'm trying to understand A) policy classes and see if they meet my needs. the book "C++ templates" has something similar called B) "bridge pattern implemented with templates". would it be...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.