I have certain modules which handle user actions – they are Control Modules. There were 6, Now there are 5 as I consolidated 2 which were very similar into a Module called Control
What I noticed is that as I consolidate similar code….it becomes a tad bit less efficient. For example in Control I now have an extra logical statement to determine program flow.
if( this.type === 'signup' && !this.text_object.checkPattern( 'name' ) )
This simple line allowed me to combine ControlSignIn and ControlSignUp as the only difference was checking the name in Sign Up which Sign In did not have.
I can continue in this manner and I get more complex code but my code footprint is smaller.
There is a trade-off between ( complexity and run time ) vs ( code foot print ).
I’m guessing it does not matter but I just wanted to make sure.
As an example I put in ControlTweet which I could also fit to Control.
Question?
Should I consolidate ControlTweet with Control?
In general, where do you draw the line or is it a matter of preference?
Control
/**
*Control - receives incoming requests for client use
*/
var Control = ( function ()
{
var Control = function ( type )
{
this.TIME = 4000;
this.type = type;
this.form_element = document.getElementById( type ),
this.response_element = document.getElementById( type + '_response' );
this.text_object = new TextValidator( this.form_element ),
this.message_object = new Message( this.response_element ),
this.effects_object= new Effects( this.response_element );
};
Control.prototype.invoke = function( )
{
if( Global.validate_input_on === 1 )
{
if( !this.text_object.checkEmpty() )
{
this.message_object.display( 'empty' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
if( this.type === 'signup' && !this.text_object.checkPattern( 'name' ) )
{
this.message_object.display( 'name' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
if( !this.text_object.checkPattern( 'email' ) )
{
this.message_object.display( 'email' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
if( !this.text_object.checkPattern( 'pass' ) )
{
this.message_object.display( 'pass' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
}
var response_element = this.response_element;
new Ajax().invoke( serializeArray( this.form_element ) + '&ajax_type=' + this.type + '_control', function( server_response_text ) { ajaxType( server_response_text, response_element, 'respond' ); } );
};
Control.in = function()
{
new Control( 'signin' ).invoke();
};
Control.up = function()
{
new Control( 'signup' ).invoke();
};
Control.out = function()
{
new Ajax().invoke( '&ajax_type=ControlSignOut', function( server_response_text ) { ajaxType( server_response_text, 0, 'simple' ); } );
};
Control.try = function()
{
new Ajax().invoke( '&ajax_type=ControlTryIt', function( server_response_text ) { ajaxType( server_response_text, 0, 'simple' ); } );
};
return Control;
} () );
ControlTweet
/**
* ControlTweet
*/
function interfaceTweet()
{
var fill_element = document.getElementById( 'tweet_fill' ),
form_element = document.getElementById( 'tweet' ),
response_element = document.getElementById( 'tweet_response' );
var text_object = new TextValidator( form_element ),
message_object = new Message( response_element ),
effects_object = new Effects( response_element );
if( Global.validate_input_on === 1 )
{
if( !text_object.checkEmpty() )
{
message_object.display( 'empty' );
effects_object.fade( 'down', 4000 );
return;
}
if( !text_object.checkPattern( 'tweet' ) )
{
message_object.display( 'tweet' );
effects_object.fade( 'down', 4000 );
return;
}
}
new Ajax().invoke( serializeArray( form_element ) + '&ajax_type=ControlTweet_add', function( server_response_text ) { ajaxType( server_response_text, response_element, 'tweet', fill_element ); } );
}
What I ended up using:
/**
*Control - receives incoming requests for client use
*/
var Control = ( function ()
{
var Control = function ( type )
{
this.TIME = 4000;
this.type = type;
this.form_element = document.getElementById( type ),
this.response_element = document.getElementById( type + '_response' );
if( type === 'tweet' ) { this.fill_element = document.getElementById( type + '_fill' ); }
this.text_object = new TextValidator( this.form_element ),
this.message_object = new Message( this.response_element ),
this.effects_object= new Effects( this.response_element );
};
Control.prototype.invoke = function( )
{
if( Global.validate_input_on === 1 )
{
if( !this.text_object.checkEmpty() )
{
this.message_object.display( 'empty' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
switch( this.type )
{
case 'signin':
if( !this.text_object.checkPattern( 'email' ) )
{
this.message_object.display( 'email' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
if( !this.text_object.checkPattern( 'pass' ) )
{
this.message_object.display( 'pass' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
break;
case 'signup':
if( !this.text_object.checkPattern( 'email' ) )
{
this.message_object.display( 'email' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
if( !this.text_object.checkPattern( 'name' ) )
{
this.message_object.display( 'name' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
if( !this.text_object.checkPattern( 'pass' ) )
{
this.message_object.display( 'pass' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
break;
case 'tweet':
if( !this.text_object.checkPattern( 'tweet' ) )
{
this.message_object.display( 'tweet' );
this.effects_object.fade( 'down', this.TIME );
return false;
}
break;
default:
}
}
var response_element = this.response_element;
if( this.type === 'tweet' ) { var fill_element = this.fill_element; }
new Ajax().invoke( serializeArray( this.form_element ) + '&ajax_type=' + this.type + '_control', function( server_response_text ) { ajaxType( server_response_text, response_element, 'respond', fill_element ); } );
};
Control.tweet = function()
{
new Control( 'tweet' ).invoke();
}
Control.in = function()
{
new Control( 'signin' ).invoke();
};
Control.up = function()
{
new Control( 'signup' ).invoke();
};
Control.out = function()
{
new Ajax().invoke( '&ajax_type=ControlSignOut', function( server_response_text ) { ajaxType( server_response_text, 0, 'simple' ); } );
};
Control.try = function()
{
new Ajax().invoke( '&ajax_type=ControlTryIt', function( server_response_text ) { ajaxType( server_response_text, 0, 'simple' ); } );
};
Control.bookmarkDelete = function( event_pull )
{
event_pull.preventDefault();
domBookmarkDelete( this );
new Ajax().invoke( encodeURIComponent( this.name ) + "=" + encodeURIComponent( this.innerHTML ) + '&ajax_type=ControlBookmark_delete', function( ) { } );
}
return Control;
} () );
This is pretty subjective question in the sense that everyone will have their own personal preference when it comes to consolidating code, and it is also localized as it can vary from project to project. That being said, there is obviously a line to be drawn because you don’t want everything consolidated to one massive
main()function that handles everything and then some.There are two programming rules of thumb which should help you out:
Now, the DRY principle states that–when reasonable–you should combine similar code into reusable modules. The keyword here being similar code, as it sometimes it makes sense for you to have multiple separate modules even at the risk of repeating code. The reason being is that you also have to account for code maintenance and readability, and it can become a readability nightmare when you start consolidating dissimilar modules in the name of DRY.
I also mentioned premature optimization because you brought up the idea small footprint versus code complexity. I suggest you forget about that and leave the code footprint to compressing/gzipping.
To finally answer your question, I would personally combine the modules. However, that should ultimately be your decision as you are the one who has to maintain that code. Just remember to properly comment and document everything so you aren’t lost in the dark when you revisit this months later.