Archive for the ‘Programming’ Category
Rewards of “Frequent Check In”
I have worked with many developers and many times, I ran into following conversation. Whenever we are in the middle of development and I ask for checking in the code, one of following reply is heard -
- Umm, lets do check-in towards end-of-the day. We are not yet done with the code.
- Let me clean up these things and make them perfect.
- I don't want to check-in as I have some ongoing changes and I can't checkin partial files.
- Lets checkin tomorrow when we complete major functionality.
I am sure you must have heard similar conversation (or had it). Can you give a moment and think about why do are we afraid of checking-in? I have been constantly thinking about this issue and there are many reasons which makes sense on this issue. Few of them are -
Fear of bad code - Developers are afraid of peers criticizing their code. Its GOOD! Believe me, you're never going to write perfect code without receiving feedback about it. Sooner you receive the feedback, better you perform in short time. This is the reason, people don't make their changes public until they are convinced that they can't do any better. It is clearly a false fear.
One of the way to improve and influence your team is to make your work public as it is in progress. This way, you make team aware of your approach. If there is any conflict in approach or disconnect in understanding, it becomes visible sooner and you can resolve it better.
Not sure about impact on other parts of the system - Yes! This is very valid reason. You're in middle of a feature and you're not sure how it will impact rest of the system if you check-in early. Half baked features can take the whole system down. To get over this fear, unit testing your code, running a full build before check-in and having continuous integration makes sure your changes are fail-safe. Make sure that you are providing a working build to the team by writing solid unit tests and more comprehensive integration tests.
Working on multiple parallel streams - It is often a bad practice to work on multiple parallel streams of work. Even worse when you don't commit any of those changes in VCS.
If you're working with DVCS like Git, it is very easy to branch and commit code. If you're working on central VCS like subversion, then it is little tricky to keep your parallel working streams with minimal effort. There are few simple things you can do to make your life little easy -
Use DVCS. This will prove immense value in long run, if you use it properly. There is a learning curve associated with it, but it is definitely worth it.
If you are using SVN, create a branch if it is a big change. If it is small change, evaluate if you can checkin without breaking application. Taking patch is another option too. Use unit testing safety net on your side and make sure you progress smoothly.
In any situation, its not helpful when you're working on parallel streams of work and those changes co-exist. I have often observed people checking in partial or missing content. This happens when they are confused and trying to understand what all files are required to make one of streams live.
Why frequent check in is important?
- Getting feedback from your application and team.
- Never lose any of your changes and hard work. Machines do crash and when they do, its bad!
- Avoid stepping on each others toes, particularly when team is distributed and code churn is faster.
- Making whole team aware of your approach and remove silo operations. This helps bringing everybody on the same page and triggers conversations whenever required.
- You can't explain in 30 minutes of speech what code explains in 10 minutes. It eliminates confusion.
- Discipline of frequent checkin allows you to make sure, changes are not causing any conflicts.
- Smaller changes, encourages you to refactor and improve code quality.
If you want to read more -
Golden principle of development: Check-in-early, check-in-often.
DVCS introduction from the master: Google Video on Git.
Continuous integration: Wikipedia entry.
Things to ponder with Alfresco (Part-II: Workflow Design)
As I mentioned in my earlier post that I will be writing few more posts about the Alfresco. This is second installment in the series. If you are thinking to use Alfresco at the center of your application then it is hard that it will not have a workflow. If your business process is just more than simple workflows mentioned in Alfresco, then for sure you have to write your own business model definition.
If you are planning to do so, here are few lessons I have learned –
- Simplicity – We got lot of benefits just by keeping our process definition simple and neat. Don’t add unnecessary steps which will cause confusing steps for the end users.
- Right things at right place – Alfresco is very flexible in terms of business logic implementation. You will always have multiple options to accomplish same operation. Web Scripts, Java classes or Web Service and you will be tempted to use different things at times. Decide one approach and stick to it. Put as much as logic in the workflow and don’t spread across the workflow business logic outside the workflow.
- Loops can be evil – Loops in the workflow actions can be daunting at times. Rethink on the circular steps in the workflow and make sure you are not violating the “simplicity” rule. It might be difficult sometimes to achieve these steps.
- Blocking is good sometimes – Next bigger decision should be synchronous operations or asynchronous. All the operations which might result in inconsistent states should be synchronous i.e. transactional. Asynchronous operations are better in terms of responsiveness. Sending e-mails could be asynchronous tasks as you people can receive emails after couple of seconds, but if it is related to pushing records to a queue, let it be synchronous. You got the idea!
You are advised to check Alfresco wiki for more details. There is plenty of documentation available for the administration and authoring custom workflows.
Things to ponder with Alfresco (Part-I: Content Model)
For any content repository, content model definition is similar to the DDL (schema definition) for databases. It is expected in a big application to have evolutionary content model like databases. Updating the table structures or introducing new tables is common in any business application. In content repository, you should also keep in mind that your content model should be open to evolve. Define the content model which will be extensible. Most of the good practices of database design should be applicable here.
Few tips for better content models -
- Use aspects for specializing types instead of defining content types. There are few advantages of that, aspects can be applied or removed at run-time which gives you much more control over the dynamic nature of types.
- Aspects also helps in keeping the default set of properties over a content type to be small. Alfresco recommends you to prefer aspects over custom content types.
- Aspects helps you to logically group properties. This helps your data to be part of multiple groups at the same time. If you have aspects Publishable and Indexable; you can apply or revoke a nature at your will without much hassle.
- Indexing is very helpful for searchable content. It is useful but use it wisely. The cost of indexing in Alfresco is much higher than cost of index in Databases as this will be full-text search indexes. It will take up more disk space as well as time to index the data. Don't index the content which people are not expect to search! You can define this at the time of content model definition.
- Versioning is similar to indexing and use this wisely. The content which is versionable is handled separately by Alfresco. This might be affecting performance as your repository size grows. Don't mark content as versionable if you don't plan to maintain revisions for content.
I will continue this series with other experiences with Alfresco. Later.
Alfresco: Workflow managed by JavaScript
If you are a regular reader of this blog, you might have figured out that I am currently working on a project involving alfresco at the center and it's a content management system. Earlier I have worked with Content repository (Apache Jackrabbit) and that was a good experience. Alfresco is next step of a content repository which extends it into a full blown content management system and much more. I was working on a problem where we defined a custom (Advanced workflow) to be precise in Alfresco lingo. This workflow was needed to be monitored, managed and accessed only via a webscript as we have used webscripts to do almost everything in our project. I was very pleased to see this, but that is only available in 2.9 labs release (as of now). We are using alfresco 2.2.0 version for our development and that is production stable version, so I have very little choice but go with production version. Alfresco has very limited JavaScript API support for workflow manipulation and that was difficult job for manage. There was no other option than writing custom JavaScript API which allows to manage workflow in Alfresco. We did that and it was very powerful and easy!
I wanted following features for JavaScript API -
- Easy to extend
- Can handle any workflows
- Provides easy ways to retrieve tasks, definitions, paths etc.
- Provides as much functionality possible which is available in Alfresco Workflow Console.
Alfresco workflow console is command line interaction component which allows you to manipulate, get information about workflows using simple commands and I wanted to do all that using JavaScript. I started exploring the source code and found a class 'org.alfresco.service.cmr.workflow.WorkflowService'. This class has generic API which allows you to do all the operations possible through workflow console. This bean is used for workflow console operations. So all I needed was expose this bean in JavaScript as root object and start using it. That simple! I wrote a simple java class to expose the bean as follows:
package com.xxxx.yyyy.workflow; import java.util.List; import org.alfresco.repo.processor.BaseProcessorExtension; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.workflow.WorkflowService; public class WorkflowManager extends BaseProcessorExtension { private ServiceRegistry services; public void setServiceRegistry(ServiceRegistry serviceRegistry) { this.services = serviceRegistry; } public WorkflowService getWorkflowService(){ return services.getWorkflowService(); } }
The method getWorkflowService() exposes the workflow service to the JavaScript calls. To expose the Workflow Manager as root object in JavaScript create WEB-INF/classes/alfresco/extension/custom-script-context.xml and you will be good! (If you don't know how to do that, read this) Now, you can get the handle of workflow service in JavaScript code. Yet, we need to write a small component which will allow us to retrieve the active workflows, tasks etc. To do so, I wrote a small JavaScript object which provides those functionality to the user.
var workflowService = workflow.getWorkflowService(); var W = { transitions: function(noderef){ var task = W._currentTask(noderef); var trans = []; try{ var tasks = task && task.path.node.transitions; for(var index=0; index < tasks.length; index++){ trans[trans.length] = tasks[index].id; } }catch(error){ // Ignore error } return trans; }, move: function(noderef, command){ workflowService.endTask(W._currentTask(noderef).id , command); }, _workflowPath: function(noderef){ var workFlows = workflow.getWorkflows ("workspace://SpacesStore/" + noderef, true); if(workFlows.size()>0){ return workFlows.get(0).id + "-@"; } return ""; }, _currentTask: function(noderef){ var curTask; var tasks; try{ tasks = workflowService.getTasksForWorkflowPath (W._workflowPath(noderef)); if(tasks.size() > 0) curTask = tasks.get(0); } catch(Error){ // Ignore error } return curTask; } } function initWorkflow(noderef) { var wflow = actions.create("start-workflow"); wflow.parameters.workflowName = "jbpm$xxxxyyyy:abc"; // your workflow name wflow.parameters["bpm:assignee"] = person.properties.userName; wflow.parameters["bpm:workflowDescription"] = "Put your description"; wflow.execute(noderef_for_which_workflow_will_associate); }
Thats it! The initiate workflow method is used to apply a workflow to a node. Once that is done, the W object can be used to do operations like retrieving the active tasks, ending the workflow and making the workflow transition. Hope that helps. If you need more workflow related information and reading material you can visit following places:
Guarding in JavaScript
After looking at JavaScript programming sessions by Douglas Crockford (here), I couldn't stop but admire JavaScript. There are many many impressive things in JavaScript but one of the eye-catchy thing was guarding operator in JavaScript.
The && operator in JavaScript can be acted in two ways. The normal 'and' operator which is used in determining the conditional logic results. The other lesser known feature of JavaScript is the guard operator. In following code -
/* The if is checking if specs is not undefined, false, null, "" (empty string) or 0 (numeric zero) as these all values are falsy conditions in JavaScript */ if(specs) width = specs.width; // To avoid the if condition you can simply do like - width = specs && specs.width; /* This makes sure that specs is not falsy and they returns the second operand which is convenient way to write null check */
The same is with || operator too. If the first operand is falsy then it just returns the second operand instead. Consider following code:
name = specs.name || "Name not set"; /* Use the specs.name, but if name doesn't have a value, use default value instead. */
Very simple and very efficient!


