Better Ways Of Storing Product Knowledge

Better Ways Of Storing Product Knowledge

So, the Brain-Format is not that good. Which is? To answer that, let’s first discuss the ideal attributes of a product knowledge and of the place we would keep the knowledge in, the repository. We shall start with the basic expectations from the documentation itself, and later discuss the expectations from the repository.
But before we begin, I would like to make a point – on my previous post I got feedback that I probably should not use the term ‘knowledge’, as it is too heavy a term for the simple ‘information’. Well, I disagree. I believe, knowledge in simple terms, is information in usable format, which includes the insights from the information, which of course, are not part of the information itself. It is processed information, and that is what differentiates it. This difference also highlights the importance of this information and that importance also happens to be the goal behind writing down these thoughts.
Now that it is clear, shall we begin?
The first and foremost point is that the product knowledge is better treated like the product code itself. Is that too much to ask? Consider this – we need the product knowledge to always be relevant. For it to be relevant it needs to be updated, it should reflect the latest changes and enhancements done to the product; in effect it is highly likely that it will be modified every time the code is modified. Hence, is it wrong to expect the same flexibility from the documentation that we come expect from the code? Why should we not apply the same quality guidelines? In general terms, should it not be as maintainable as the code itself?
So, the first list is of attributes of the knowledge storage format:
    1. Easy to create: It applies to new documentation, and new additions to existing documentation. Whatever the format, it should not require huge assembly or lot of people or say, multiple approvals.
    2. Easy to maintain: This attribute is rather an abstract one, and many points below shall touch on this in greater detail. (Clean Code, anyone?)
    3. Easy to extend: Extend, in context of documentation means that it should be possible to combine documents to bring related information together, without duplication, It could be through a link to the information, but best would be the ability to embed.
    4. Easy to use: What is the use of the documentation? It should be easy to read/watch/listen/touch/smell/taste etc. (Well, maybe not touch or smell, or taste..)
    5. Should be DRY: This directly relates to the ‘extend’ requirement, it should be possible to have a single authoritative representation of the knowledge.
    6. Presentable: But of course, we want to use it don’t we? We need to like it!
There are many more analogies we can draw, but I think these are enough to convey the point that it should be built with almost the same principles as the code. Now, we take on the documentation repository and also discuss some non-functional requirements that apply to do the documentation but not necessarily to code:
  1. Access Control: Does it need to be discussed? Of course we need access control, and multiple levels of control: Access to read, write/edit, to delete, and the access to grant access should all be controllable. Even better if we could integrate with the corporate account management system and also set roles.
  2. Record History: For the same reason as code, we need a way to undo (and also blame people) any changes done to documents, including restoring deleted content.
  3. Portable: Yes, portable. The knowledge is not only for developers, it is also for the marketing members of the team, the business analysts and the management. We cannot expect that these guys, whose job is to go out and meet people can always have access to internet and VPN. That makes it a non-functional requirement that the knowledge be portable in full or at-least in part. I imagine some companies having problem with this, but those who use distributed version control systems like Git, should not really worry; they are trusting their teams with the working code, knowledge is not going to cause any new special problems.
  4. Lightweight: It should be light on resources. Resources of all sorts, be it storage, network, computing power, but most importantly on the (arguably) costliest resource on the team: ‘user time’.
  5. Searchable: It should be possible to search within the repository by various categories, tags and of course the content.
  6. Shareable: Shareable by either exporting or by providing a reference pointing to the exact content, like a URL.
  7. Encourage Contribution: This is likely the most neglected but probably the most important requirement. If after being all this, the repository does not appeal to people, it is going stale real soon.
Phew..! However, the list is far from complete. But I think I have made my point, so now we’re off to the next task: Looking for a format and a repository that fits all these criteria! Till then, coke anyone?
Cinnamon Crashed, would you like to restart?

Cinnamon Crashed, would you like to restart?

I have been a fan of the Cinnamon DE for years. I like the way it looks and stays out of my way when I am not admiring it and actually doing something useful! But it is somewhat buggy.

This is a quick post about the cinnamon crashes, basically a new reason for it to crash. I was faced with a common issue of cinnamon crashes, suggesting me to restart cinnamon, which when clicked yes resulted in another crash and popup.

Google searches resulted in many solutions, starting with updating cinnamon, resetting the config by deleting the .cinnamon and .local/share/cinnamon directories and verifying if the correct video driver is in use. There was nothing obvious in the syslog, or xsession errors. Nothing helped.

Tired, I reinstalled mint but issue persisted. This was rather peculiar. I mount my home separately, and that of course survives the installs and OSes. This was the first hint at the problem, issue was configuration of something, not necessarily of cinnamon. So I created a new user and tried to login with the user, and voila, cinnamon worked without a crash. So certainly the issue was config for my regular user.

I decided to go about removing related config folders, and the first ones I chose was the gtk-3.0, gtk-2.0 and cinnamon-session directory inside .config directory. And to my luck, cinnamon is working just fine since then.

Probably, I should spend some time to check what exactly from these config was the issue. But at least I now know one more reason why this error might occur and one more way to fix it. And now, you too..!

Worst Place To Keep Your Product Documentation: Human Brains

Worst Place To Keep Your Product Documentation: Human Brains

One thing I can say from my experience with the products that I have worked on is this – documentation of a product is nearly as important as the code itself, and there should be a comparable amount of effort to keep it usable. Of course, it won’t earn you money-wise, but also won’t create new competition if it leaks either. But does that make the documentation any less important?
What it can do though, is it can save you money and time. It saves time when a new member joins, it saves time when a change is needed: to functionality or to technology, it saves time when requirements are conveyed to a vendor or details to a potential client. It takes the burden off your head, because you no longer have to remember things, except for remembering to document what you know. It is important to secure it, for if it leaks, your competitors can learn from your design, and that can potentially create new competitors. More importantly, it can create immediate threats, because knowing your architecture makes it easy to attack products. (Open Source case is different.)


Despite all these reasons, there is a reluctance to maintain the product documentation in document form! Products rely on team members to remember the technical details and functional flows, they rely on members to convey this knowledge to every new member, they rely on existing members to recollect it when the time comes, and members with all this knowledge to be with them – forever! It can’t work, it has been seen to not work, and yet, we insist!


If it is not yet clear, I haven’t been a great fan of this strategy. Here is why:
  1. No one can remember it all even if someone does, no one can always recollect it at the right time.
  2. When it comes to conveying the knowledge, people tend to convey only what is required for the current task at hand, not the full picture. I am not saying that it is wrong, because at that time that is the only knowledge required. But this process requires a long time for the new member to get the full picture, and hence, to be more productive. You can conduct sessions, but again we are expecting people to remember and recollect what was told to them only once (or twice)!
  3. Then there is the problem of members being reluctant to convey, having vested interests in not transferring the knowledge. The argument can be made that building a cooperative team can solve this, but we know how hard it is build a all-the-time cooperating, motivated team, we will accept it.
  4. Unavailability of ‘the person who knows the answer’ is hard to argue with. People can be unavailable for multiple reasons: they could be away from the office, involved in a different task, travelling for business purposes, unwell, on leave, not being reachable at the moment of the crisis and what not.
  5. And again, people switch jobs – we can’t expect every experienced employee to work with us forever. And even if they did, refer point 4.


And even after all this, people can get hit by a car, or a flowerpot in the head and get amnesia! My point is, can we leave the stability of our product to such things? There are better ways to handle this knowledge. Better, proven ways.


I think at this point it should be clear that we are talking about knowledge of the product. This does not only include the requirement documents, High and low level technical design documents or user-stories, acceptance criteria, issues raised in the agile tracking systems but also the insights, the gists, the summaries, the diagrams, the communications, MOMs, presentations, sessions in searchable, easily retrievable and referable form. (Too late in a post to define the core subject, but better late than never!)


I would not want to get into the details on how to store documentation outside of human brains right away, but understanding that we need to is the first step in that direction.

A Guess-The-Color-Code Game: ColorCode

A Guess-The-Color-Code Game: ColorCode

This post was written ~6 years ago, a lot of things in the world of browsers have changed since, the game may no longer work/look correctly.

A game with unknown name!
That is what it was when I started working on it…
I played this game first as a board game, on a very very old board, with no reference to the name. It was to be played by two players.
The other day, my younger sisters friends had come home, they brought with them a board game to play. It belonged to her mom (so old). No one knew the name, but it was just plain fun to play.

We decided to implement it in code. And here it is.. A digital version of the game.
But what to name it? First we thought of naming it colour-seq, but some amount of Googling revealed that there exist many versions of this game in digital format already and they are called ColorCode. So thats what it is! 🙂

Game objective:
Its simple, match the same colour sequence with same colours as the computer had in his mind.

Game rules:

  • The computer decides a sequence of the colours (in mind!)
  • The player puts the pegs in the holes and tries to arrive at the same sequence.
  • Computer will indicate on every entry how many of the colours the player missed and how many positions were incorrect.
  • You can choose from 3 different difficulty levels:
    • Easy: 4 colours,4 positions (no chance to choose a wrong color), 10 attempts
    • Medium: 5 colours, 4 positions, 10 attempts.
    • Hard: 6 colours, 4 positions and 10 attempts.
  • You can also select if you want numbers to be  displayed on the pegs along with the colours to identify them.

How to play:

  • Once you choose the options, you will see the game board.
  • Drag and drop the coloured pegs from the right hand side floating bar onto the central part of the board with 4 holes (not holes, but, u get it, right?)
  • You can rearrange the colour sequence.
  • Once you are satisfied, press the submit button.
  • Computer will match the code you entered with the one it had in mind and will answer in a colour code.
  • On the left part, where you see the holes arranged in two columns:
    • If a position turns orange, there is a colour in wrong position.
    • If a position turns black, there is a wrong colour.
    • Counting the number of black squares, you know how many colours were wrong. (i.e. you selected the colour but computer did not, choose another.)
    • Counting the number of orange squares, you know how many colours were in wrong position (i.e. the colour is correct, but not is correct position, rearrange.)
  • Starting with a guess for the first attempt, it goes all Logic from there on..
Known issues:
  • The floating bar has a little glitch, it floats a little weird sometimes.

Future enhancements

  • Forgot to mention, have not tested the code on Internet explorer at all. Will do the testing and required fixing once I find a windows machine. Till then, please use firefox or chrome.
  • I plan to make it more customisable: allow for choosing colours, columns and attempts manually.
  • Make them circles.
  • Remove the hiding plate above to reveal the code in computer’s mind.
  • What if computer never told you the colour was wrong..? Thinking… 😀

Well, a note:
I know its all JavaScript and all the geeks will simply turn on their firebug to check what the colour sequence is. But please don’t, otherwise, there is no fun! But if you just could not convince your conscience, let me tell you I have taken care not to spoil the fun for you. The colour code the computer remembers is actually salted, hashed number and not the simple colour name you might make some guess at.. The salt is randomly generated on every new game. Just to help you take a firm stand against your disobedient mind! (Oh I know, its still not difficult to crack it, but worth the effort! 🙂 )

So what are you waiting for? Hit the ‘Start the game’ button!

If you find more glitches and bugs please note them in the comments. And feel free to tell me you enjoy it! 😀

Just another object-oriented approach to jQuery plugins

Just another object-oriented approach to jQuery plugins

It has been almost a year since I have been working primarily in JavaScript. During this time I have written three jQuery plugins and loads of other scripts.This is the story of how my approach to writing jQuery plugins has evolved.

I was working on my first plugin, which was supposed to be a large (in LOC) and went through the authoring mentioned on the jQuery site. In the beginning- it was great, a few exposed methods, well organized code, private functions, everything looked pretty. Soon the code reached some 1000 lines and it started becoming messy for me. To clarify, I am basically a java developer. I accept that the coding practices will obviously differ in every language, but for me, object oriented approach to code seems much more understandable and tidier than ‘functions everywhere’ thing!

I began searching for object oriented approaches people take in writing jQuery plugins. There are many, but mostly at the cost of some other flexibility. Some approaches allow only one public method, claiming only one namespace is must but more control was needed in the calendar. Some allow complete public access to the options object, but additional control was needed. There were one time calculations based on options that were necessary for the required functionality. Now making the options object public won’t give me that control, will it? But apart from that, I could not understand the requirement of making it fully public. Pardon me, this statement is not to question those who follow these approaches, but this is what was thought.

A better approach was needed, where all the flexibility of making it a ‘functions everywhere’ is retained and a little more organization is achieved in the code. So there emerged a merger. A merger that:

  • Allows multiple methods to be made available.
  • Claims only one namespace.
  • Does not make options simply public.
  • Keeps a context, maintains a state.
  • And follows every other requirement mentioned as a guideline while writing plugins by the jQuery authors.
That merger has now evolved into a simple, precise plugin template! All you need is a case-sensitive, replace-all and you are ready with a working plugin, set with the basic features ready for more, organized plugin…
Here’s the code:
/**
* Plugin comments
*/
(function($, undefined){
var MyPlugin = function(element, options){

/*
* *************************** Variables ***************************
*/
var defaults = {
defaultValue : '2'
}; //default options

/*
* *************************** Plugin Functions ***************************
*/

/*
* Initializes plugin.
*/
function initialize(options){
extendOptions(options);
sl.log("Got Options- initialize: ");
sl.log(options);
}

/*
* Updates plugin.
*/
function update(options){
sl.log("Got Options- update: ");
sl.log(options);
}

/*
* Destroy plugin changes
*/
function destroy(options){
// Remove all added classes.
// Remove all bound methods.

// Remove plugin data
element.removeData('myplugin');
}

/*
* Updates plugin options after plugin has been initialized.
*/
function setOptions(options){
extendOptions(options);
}

//expose plugin functions
this.initialize = initialize;
this.update = update;
this.destroy = destroy;
this.setOptions = setOptions;

/*
* *************************** Utility Methods ***************************
*/
/*
* Extend the default options using the passed options.
*/
function extendOptions(options){
if (options) {
$.extend(true, defaults, options);
}
}
};

var mP = $.myPlugin = {version: "0.01"};
$.fn.myPlugin = function(options){
var args = arguments; // full argument array passed to the plugin.

// Available methods in plugin
var pMethods = {
init : function(options){
// Get the plugin data
if (this.data('myplugin')) return;
// Initialize the plugin
var myplugin = new MyPlugin(this, options);
// Add plugin data to the element
this.data('myplugin', myplugin);
myplugin.initialize(options);
},
update : function(options){
// Get the plugin data
var myplugin = this.data('myplugin');
if (!myplugin) return; // do nothing if plugin is not instantiated.

myplugin.update(options);
},
destroy : function(options){
// Get the plugin data
var myplugin = this.data('myplugin');
if (!myplugin) return; // do nothing if plugin is not instantiated.

// destroy data and revert all plguin changes.
myplugin.destroy(options);
},
setOptions : function(options){
// Get the plugin data
var myplugin = this.data('myplugin');
if (!myplugin) return; // do nothing if plugin is not instantiated.

// Update the plugin options
myplugin.setOptions(options);
}
};

// For each element, check and invoke appropriate method passing the options object
return this.each(function(i, tElement){
var element = $(tElement);

if (pMethods[options]){
pMethods[options].call(element, args[1]);
} else if (typeof options === 'object' || !options){
pMethods['init'].call(element, args[0]);
} else {
$.error( 'Method ' + options + ' does not exist in jQuery.myplugin' );
}
});
};
})(jQuery);
Now what you need to get going is the replace-all, this is what you replace:

MyPlugin : PluginName
myPlugin : Plugin JQuery Method Name/pluginName
myplugin : Data Name/Variable Name
mp       : pN
pMethods : pluginNameMethods
defaults : defaulsObjectName

That’s it!
You are ready with a working plugin!
Oh yes, that sl there in the code is actually the SmartLogger. Read about it here.
This is a quick post and I plan to update the post with more explanation of the code, do visit again!

Let me know how you find it in the comments.

Habit-Firebug Saver: SmartLogger

Habit-Firebug Saver: SmartLogger

How many of the web developers do not depend on Firebug or the chrome’s console… Just wondering..

BTW, its plain fun to work with firebug, makes life a lot easier.. Its a different matter all together that the other browser that you have to develop for does not have a powerful enough tool. (Name deliberately avoided to avoid the eminent flame-war!) Yes the current versions have a quite powerful debug and development tools but (hopefully) few developers working on products still have to consider some 10 year old versions (namely 6, 6.5 and 7). Ah, the pain.. Anyways, we are not discussing that..

What we are talking about is the issues that we face when testing our changes to a thousand lines JavaScript code on multiple browsers, especially after we are accustomed to the ease of firebug. 🙂

I spent much of my time commenting my console.log() statements before I could dare to open the page in IE. Well, fear not, the days have passed! The pain drove me to write a logger object that can not only sense presence of console object but can do much more than that, like ability to assert, selective logging and more..

I call it the SmartLogger.

//Global Logger Object, for use during development, configurable logger.
var SmartLogger = function(options) {

var sl = {}; // Logger Object

// Accepting passed params.
options = options || {};
sl.enableLogger = options.enableLogger!==undefined?options.enableLogger:true;
sl.enableAssert = options.enableAssert!==undefined?options.enableAssert:true;
sl.loggerOutput = options.loggerOutput!==undefined?options.loggerOutput:undefined; //'console', 'alert', undefined
sl.selectiveEnable = options.selectiveEnable!==undefined?options.selectiveEnable:'';
sl.selectiveDisable = options.selectiveDisable!==undefined?options.selectiveDisable:'';

// Logger properties
sl.name = "SmartLogger";
sl.whoami = function(){ return "SmartLogger_"+sl.enableLogger+"_"+sl.enableAssert+"_"+sl.loggerOutput+"_"+sl.selectiveEnable+"_"+sl.selectiveDisable;}
sl.version = '0.7';

// Checks if console object is defined. Checked only at the time of instantiation.
var hasConsole = (typeof console === "object");

// Checks if logging should be done to console.
function logToConsole(){
if (sl.loggerOutput){
if (sl.loggerOutput === 'console') return true;
} else {
if(hasConsole) return true;
}
return false;
}

// Handles the logging intelligence
function handleLogging(logMethod, logString, strId){
if(!sLog(strId)) {return;}
// Decides if to log and logs or alerts appropriately.
if(sl.enableLogger){
if (logToConsole()){ // && hasConsole
if(hasConsole)console[logMethod](logString);
} else {
alert(logString);
}
}
};

// Handles the selective logging functionality
function sLog(strId){
var allowLog = true;
if (sl.selectiveEnable) {
allowLog = strId === sl.selectiveEnable;
} else if (sl.selectiveDisable) {
allowLog = !(strId === sl.selectiveDisable);
}

return allowLog;
};

// Returns a formatted object structure with current values to complete depth.
function printString(obj, name, str, strEnd){
var stringified;
name = name?name:"Object",
str = str?str:"";
strEnd = strEnd?strEnd:"";
stringified = str+name+" : {n";
for (var a in obj){
if (typeof obj[a] === 'object'){
stringified+= printString(obj[a],a,"t",",");
} else {
stringified+= str+"t"+a +" : "+obj[a]+",n";
}
}
stringified += str+"}"+strEnd+"n";
return stringified;
};

// Exposed methods of the object
//log a string to console/alert
sl.log = function(str, strId){
handleLogging('log', str, strId);
};

//debug logging a string to console/alert
sl.debug = function(str, strId){
handleLogging('debug', str, strId);
};

//write an information string to console/alert
sl.info = function(str, strId){
handleLogging('info', str, strId);
};

//throw error string to console/alert
sl.error = function(str, strId){
handleLogging('error', str, strId);
};

//Assert an assumption
sl.assert = function(str, strId){
if(sl.enableAssert){
handleLogging('log', 'Assumption: true', strId);
if(!str){
handleLogging('error', 'Assumption failed!', strId);
debugger;
}
}
};

// Logs the formatted object structure with current values to console/alert
sl.stringToConsole = function(obj, str){
sl.log(printString(obj, str));
};

return sl;
};

var sl = new SmartLogger();

Features:

  • Multiple logging profiles can be maintained at the same time with different properties.
var sl = new SmartLogger();
var sl2 = new SmartLogger({selectiveEnable: 'block1'});
  • Proprieties can be set at the time of instantiation or even later.
var sl = new SmartLogger();
sl.loggerOutput = 'console';
var sl2 = new SmartLogger({loggerOutput: 'console'});
  • name, version number and whoami to identify the logger with a string of its current properties.
var sl = new SmartLogger();
sl.name // SmartLogger.
sl.version // 0.7
sl.whoamI() // Returns a string of its properties with the name of the object in a specific sequence:
// "SmartLogger_"+ enableLogger +"_"+ enableAssert+"_"+ loggerOutput+"_"+ selectiveEnable+"_"+ selectiveDisable;
// Example: SmartLogger_true_true_console__b
// We will see what these properties are in some time..
  • Enable or disable logging altogether: enableLogger controls if the statements should ever be logged.
var sl = new SmartLogger();
sl.log('gets logged');
sl.enableLogger = false;
sl.log('never gets logged');
  • Intelligently decides where the logging statements should go…
sl.loggerOutput = undefined; //default
/* Decides based on presence of 'console' object.
If console is present statements will be logged to console,
else like in case of IE, will be 'alerted' to the user.
Now at times this can get messy, with loads of log statements alerting on our face..
But wait, we have ways to handle that.*/

sl.loggerOutput = 'console';
// Plain instruction, no intelligence, all statements will always go to console.
// If console is not present statements will just be eaten-up.

sl.loggerOutput = 'alert';
// Another plain instruction, all statements will always be alerted.
// Will not bother to check if console exists or not.
  • Log formatted objects to console. Now you wont need that much with firebug but to see the entire contents of the object, well formatted you can just say stringToConsole.
// Just a sample object with unknown properties.
var obj = {prop1: 'value',functProp:function(){return "this is a function that returns me!";}, propObj:{prop2:'value2'}};
sl.stringToConsole(obj); // You say this.

// On console or in the alert prompt, you get this
Object : {
prop1 : value,
functProp : function () {
return "this is a function that returns me!";
},
propObj : {
prop2 : value2,
},
}
  • Assert your assumptions. Checks that the assumption is true, if yes, logs so. If assumption fails, will write out an error on the console and invoke the debugger so the user can check in the stack exactly where the assumption failed and why.
sl.assert(Obj.str===Obj2.str)
sl.assert(1==1); // logs 'Assumption: true' to console.
sl.assert(1==2); // Logs error 'Assumption: failed!' and invoke debugger to the assert line in SmartLogger.

//Now you can go and check in the stack and watch to panels to check value and call stack.
  • Has a wrapper for 4 of the logging APIs from firebug and adding new is not much of a task. What it already has:
    • log
    • debug
    • info
    • error
  • Has ability of selective logging.
Now this thing is a live saver. The properties selectiveEnable and selectiveDisable control what statements to log. While these are not mandatory inputs to all the wrappers but I suggest you set them always. These are logging context that can be used to selectively enable logs for only partial of the code, the code that currently interests you..
// Suppose we were working on a defect number 101 and now we are developing a functionality for
// automating welcome messages to users and are asked to urgently fix defect 203.
// Ah, complex scenario, but it will only help understand the purpose.

// When we are working on defect 101, we had the logger configured as statements as:
sl.log("reached here"); // worst way to log: who knows wheres here! but just an example.

// Now we are working on the functionality and
// we would not want those 10 logging statements added while we were working on the defect.
// We can remove them or simply enable the 'selective logger'!
sl.selectiveEnable = 'welcomer';
sl.log("fetching message", "welcomer");
// And voila, only the 'welcomer' messages will be logged.

// Now we get the next urgent defect.
sl.selectiveEnable = 'defect203';
sl.log("value in Obj1.str"+Obje1.str, "defect203");
// We get only the defect203 logs!

// Now some of our new changes depend on the changes we made in defect101, but we cant get the logs from those..
// What do we do? If someone did not enable selective logger and removed the statements, please add them back (:p),
// remove statements for 'welcomer' functionality. Or simply, disable 'welcomer' messages..!
sl.selectiveEnable = '';
sl.selectiveDisable = 'welcomer';
sl.log("value in Obj1.str"+Obje1.str, "defect203");
sl.log("value in Obj2.varInt1"+Obj2.varInt1, "defect101");
// Ha ha! Log statements for 'welcomer' gone and we get the rest!
While using the SmartLogger, I suggest you always pass the string identifier, so that you can control the logs at any point of time later.

What can you expect next in SmartLogger:

  • Use assert from firebug itself.
  • Check that the function exists in the logger before calling it.
  • Make the selective logger take arrays.
  • In stringToConsole, handle functions too to remove that glitch in no closing bracket.

Let me know what you think about the SmartLogger, if you would like any additions to its behaviour and also if you find any defects in the comments below.

How to add a nice code block to blogger

How to add a nice code block to blogger

While there are awesome syntax highlighting and styling libraries  with nicely written tutorials for using them with blogger, a simple ‘code’ tag can suffice at times…

For such times:

.myCodeHighlighter {
border-left: 4px solid #FF9933;
display: block;
font-family: Courier,"Courier New",monospace;
margin: 15px;
overflow: auto;
padding: 15px;
text-align: left;
white-space: nowrap;
}

And use as:

<code class="myCodeHighlighter">
//the code codes here..
</code>

A preview of how it will make your code tags look like? You are looking right at it! 🙂

Creating a Local Version Control System

Creating a Local Version Control System

Now this is a post that is going to be updated time and again.. The very post that made me abandon my previous blog to move on to a Google site..

Requirement:
Need to setup a local repository.. a version control system.. Given that I use VSS (I know, please dont make faces..!) at my work place, I am used to the ‘ease’.. However it may be, it sure is simple to use…! I need the repository to be platform independent, as I dual boot into Windows 7 and Ubuntu, secondly need it to be local.. Now thats the background, next is a journal…
Which one to use?
Tried:
CVS: on Ubuntu 11.4 and on windows 7.. dint find it so impressive..
TortoiseCVS: Dont know why but the options in the context menu never appeared…! :S
Mercurial: confused about its use.. yet to be tried..
Trying out git.. many friends suggest this.. seems interesting.. simple to learn, they say.. lets see!
Git setup
Alright, what helped me understand it whole was two great articles, one form tiredblogger and another from a harvard site.
Do go through them both… (And you don’t have to read this page any further! 🙂 )
Rest is for my reference, for my own understanding..
It was simple to setup..
Download and install git from the ubuntu download center… Download and install git for windows from Google code project.. Done.. Both OS set.
In windows, left almost all settings unchanged during installation..
All I need to do is to create a bare repository to start with, its better they say.. so
in a new folder:

git init --bare

Then clone it into a new repo.. That’s the working folder I guess…
so..

git clone <prev folder> <new folder name>

Done..
Then create and add new file to this new folder.. Thats the first source file..
Then, add it to repo..

git add .

Commit the repo..

git commit -a -m "a message"

Push the updates to the main repo, which would otherwise have been a remote repository, the original one from which the working was cloned.

git push origin master

Cool enough.. Lets try new things..

Working on multiple OS
The local repository cant be directly used from both the OS.. so What I am gonna have to try is to work as if I am 2 different persons contributing to a project.. haven’t very well understood it all yet! lets see…!

Change only the origin url!

Alright.. Now, all I need to do is change only the path / url in the git config file for the head origin! Once done, the push was fine…! 🙂 so…
Is there a way to avoid this manual work???
like having 2 origins? remotes I mean..
In manual it is said that the remote path can also be passed from a file in $GIT_DIR/remotes
But does that create new branches? If so, that’ll clutter the repository unnecessarily…
lets see…

This post will be updated as and when I learn new things..!

mGSD With CheckboxPlugin

mGSD With CheckboxPlugin

    To give an introduction, TiddlyWiki is a wiki in a single html page, a must have tool for every developer, what you use it for is subjective. And mGSD is a TiddlyWiki variant to aid in GTD.

    I believe, CheckboxPlugin is a must have in a tiddly wiki that can even remotely be used to track things! In spite of warnings that it ‘damages your mGSD’ I haven’t been able to damage mine nor the data in it for a while now.. Thought should share it with you..
    But I must remind that it can ‘potentially’ damage the file or the data in it if proper precaution is not taken. So please backup your wikis if you plan to proceed on the steps I mention here. Do proceed only when you are sure of what you are doing and that you have a copy of the file safe somewhere.
    I did damage a few of the mGSDs when I first tried out using CheckboxPlugin, the auto-backups saved me. What I have found out is that the file is damaged or the data is corrupted only when the CheckboxPlugin-specific constructs are used in mGSD-specific tiddlers!

mGSD-specific tiddlers: By this, I mean the type of tiddlers specific to mGSD, like actions, projects, references, various lists of actions, anything that is not in tiddly wiki but in mGSD.( and where mGSD has its own checkboxes!)
CheckboxPlugin-specific constructs: These refer to [ ], [_], [x] and [X], the constructs used to denote checkbox states in CheckboxPlugin.

installation and use:
  1. Backup the file! (just reminding..)
  2. Ensure that you do not have CheckboxPlugin-specific constructs are used in mGSD-specific tiddlers, simply install the plugin, restart mGSD and check that everything is fine. A rare chance of failure I hope, the constructs are not so very common to be used otherwise. (You have a backup, just in case)
  3. If something fails, find and remove the CheckboxPlugin-specific constructs from the tiddlers.
  4. When you want to add a list for tracking, do not add it in the action directly. Create a tiddler, simple Plain-Old-Tiddler, by going to : ‘More… –> TW –> New Tiddler’. name it appropriately and add a link to it in the action, something like: [[MyTracker]].

One Rule: Keep the ‘CheckboxPlugin-specific constructs’ out of ‘mGSD-specific tiddlers’ and you should be just fine!

Eclipse: Same Workspace in windows and linux

Eclipse: Same Workspace in windows and linux

I believe almost all dual booters wish for something like this.. The eclipse workspace should be independent of the operating system they are logged in..! well.. I have found a way to do it..

Issue:
    The problem with using the same workspace is that ‘it doesn’t work!’ 😀 well.. the configuration of a workspace is stored in .metadata folder inside the working directory.. it has all the paths.. Most importantly, the path to JRE/JDK..! If a workspace from Windows is opened in Linux/ubuntu the java projects wont compile cause of the build path issues.. If you set it right in ubuntu, it wont work in windows..

Solution:
Well..One of the solutions that works or at least worked for me is:
    Having 2 ws with all projects pointing to an external folder..!

There may be other solutions, but this is how it is done:
    Say you have a workspace under windows, now you need it to work under ubuntu..
Well.. leave alone the original workspace.. Create a new one and ‘import’ the projects from the original one.. What needs to be taken care of is: dont copy them to their default locations, that is the new workspace… You can also choose to copy the layout and other settings as well.. That way the projects will still be in the original workspace, pointed to from your new one, with all your operating specific data stored in the new workspace..! Works! You can do this for the Windows as well, keeping the ‘projects folder’ completely independent..

Problems with the approach:
The problem with this approach is that when you create a new project you need to be careful to create it in the original workspace i.e. where all other projects are.. Thats not all that difficult.. And even if you forget once, you can copy this project to the central projects location! Simple…?

What did I try it with:
Windows 7 & Ubuntu 10.10 & 11.4.
Eclipse 3.6.2 Helios

Thats it.. And you have the OS independent Workspace!! 🙂