Re: The Sort Excercise
From: Daniel T. (postmaster_at_eathlink.net)
Date: 12/30/03
- Next message: Val: "Re: The Sort Excercise"
- Previous message: Amir Michail: "Re: A New Site for Discussing Innovative Computer Science Ideas"
- In reply to: Val: "Re: The Sort Excercise"
- Next in thread: Val: "Re: The Sort Excercise"
- Reply: Val: "Re: The Sort Excercise"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Tue, 30 Dec 2003 06:25:41 GMT
"Val" <valmont_gaming@hotmail.com> wrote:
>
> "Daniel T." <postmaster@eathlink.net> wrote in message
> news:postmaster-034C69.08125429122003@news04.east.earthlink.net...
> > "Val" <valmont_gaming@hotmail.com> wrote:
> >
> > > ROFL, now I am doomed!
> > > You play hardball with this hobby-programmer....
> >
> > You have the skill necessary for this task. First get past the first
> > assertion, then the second, and so on. All the while looking for
> > duplication in your code that you can remove.
> >
> > The hard part of creating any class is deciding what the interface is
> > going to be, how does the client code use the class? That is done by the
> > time the test is written. After all, the test is a client.
>
>
> I created a monster!!! :(
First, let's get rid of that "DidSort" function. I don't think clients
care much about that, what they want to know is if the strings are
sorted, that will tell them if the machine did it's job.
int main()
{
string sortedString[] = { "a", "b", "c" };
SortingMachine sm;
sm.SetSortStrategy( new AscendSort );
sm.SetArray( sortedString, 3 );
assert( sm.IsSorted() );
sm.SetSortStrategy( new DescendSort );
assert( !sm.IsSorted() );
sm.StartSort();
assert( sm.IsSorted() );
cout << "OK" << endl;
return EXIT_SUCCESS;
}
Here is how I solved the problem. First I wrote IsSorted and StartSort
independently:
class SortingMachine
{
public:
SortingMachine(): strategy( 0 ), array( 0 ), array_size( 0 ) { }
void SetSortStrategy( SortStrategy* s ) {
delete strategy;
strategy = s;
}
void SetArray( string* arr, int len ) {
array = arr;
array_size = len;
}
bool IsSorted() const {
bool result = true;
for ( int i = 0; i < array_size - 1 && result == true; ++i )
if ( strategy->OutOfOrder( &array[i], &array[i + 1] ) )
result = false;
return result;
}
void StartSort() {
for ( int i = 0; i < array_size - 1; ++i ) {
for ( int j = i + 1; j < array_size; ++j ) {
if ( strategy->OutOfOrder( &array[i], &array[j] ) ) {
string temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
private:
SortStrategy* strategy;
string* array;
int array_size;
};
Simple and works! Now let's look for duplication... Well both functions
have the line "for ( int i..." with the same args and everything. So
let's try to combine that. First break out the stuf inside the two loops
into their own functions...
class SortingMachine
{
public:
SortingMachine(): strategy( 0 ), array( 0 ), array_size( 0 ) { }
void SetSortStrategy( SortStrategy* s ) {
delete strategy;
strategy = s;
}
void SetArray( string* arr, int len ) {
array = arr;
array_size = len;
}
bool IsSorted() const {
bool result = true;
for ( int i = 0; i < array_size - 1 && result == true; ++i )
result = checkOrder( i );
return result;
}
void StartSort() {
for ( int i = 0; i < array_size - 1; ++i ) {
setNext( i );
}
}
private:
bool checkOrder( int i ) const {
return !strategy->OutOfOrder( &array[i], &array[i+1] );
}
void setNext( int i ) {
for ( int j = i + 1; j < array_size; ++j ) {
if ( strategy->OutOfOrder( &array[i], &array[j] ) ) {
string temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
SortStrategy* strategy;
string* array;
int array_size;
};
Our two 'for (int i...' loops are nearly identical. We can make them
exactly identical one of two ways, either have checkOrder throw an
exception, or have setNext return a true every time. I'll go with the
exception...
class SortingMachine
{
class BadOrdering { };
public:
SortingMachine(): strategy( 0 ), array( 0 ), array_size( 0 ) { }
void SetSortStrategy( SortStrategy* s ) {
delete strategy;
strategy = s;
}
void SetArray( string* arr, int len ) {
array = arr;
array_size = len;
}
bool IsSorted() const {
bool result = true;
try {
for ( int i = 0; i < array_size - 1; ++i )
requireOrder( i );
}
catch ( BadOrdering& ) {
result = false;
}
return result;
}
void StartSort() {
for ( int i = 0; i < array_size - 1; ++i ) {
setNext( i );
}
}
private:
void requireOrder( int i ) const {
if ( strategy->OutOfOrder( &array[i], &array[i+1] ) )
throw BadOrdering();
}
void setNext( int i ) {
for ( int j = i + 1; j < array_size; ++j ) {
if ( strategy->OutOfOrder( &array[i], &array[j] ) ) {
string temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
SortStrategy* strategy;
string* array;
int array_size;
};
Now let's combine those loops...
class SortingMachine
{
class BadOrdering { };
typedef void (SortingMachine::*Fn)( int );
public:
SortingMachine():
strategy( new AscendSort ), array( 0 ), array_size( 0 ) { }
void SetSortStrategy( SortStrategy* s ) {
delete strategy;
strategy = s;
}
void SetArray( string* arr, int len ) {
array = arr;
array_size = len;
}
bool IsSorted() {
bool result = true;
try {
loopAndDo( &SortingMachine::requireOrder );
}
catch ( BadOrdering& ) {
result = false;
}
return result;
}
void StartSort() {
loopAndDo( &SortingMachine::setNext );
}
private:
void loopAndDo( Fn fn ) {
for ( int i = 0; i < array_size - 1; ++i )
(this->*fn)( i );
}
void requireOrder( int i ) {
if ( strategy->OutOfOrder( &array[i], &array[i+1] ) )
throw BadOrdering();
}
void setNext( int i ) {
for ( int j = i + 1; j < array_size; ++j ) {
if ( strategy->OutOfOrder( &array[i], &array[j] ) ) {
string temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
SortStrategy* strategy;
string* array;
int array_size;
};
Is this solution better or worse than yours, or no different? How big a
factor was the fact that I wrote both functions (StartSort and IsSorted)
out before attempting to find duplication?
I could have used another Strategy pattern instead of using
member-function pointers. Why do you think I didn't? Do you think I
should have?
Any other questions? :-)
- Next message: Val: "Re: The Sort Excercise"
- Previous message: Amir Michail: "Re: A New Site for Discussing Innovative Computer Science Ideas"
- In reply to: Val: "Re: The Sort Excercise"
- Next in thread: Val: "Re: The Sort Excercise"
- Reply: Val: "Re: The Sort Excercise"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|