Thursday, 10 April 2014

Big Data : An Introduction

What is Big Data?

For years together, companies have been making decisions based on analytics performed on huge data stored in relational databases. Saving data in the structured manner in relational databases used to be very costly. Storing and processing huge amount of unstructured data (big data) is much cheaper and faster. This is the main reason why big data has attracted so much of attention. Big data typically has following types:
  • Data from social media sites.
  • Enterprise data including customer related information of CRM applications.
  • Logs of any system- be it related to software or manufacturing.
Big data and its processing are characterised by 3 qualities:
  • Volume : Normally we speak of gigabytes or GBs. Here it goes from tera, peta and exa and so on bytes. And the amount keeps on increasing.
  • Velocity : Relational databases do not scale up in linear way. We expect having same performance even when the data is huge.
  • Variety : Most of the data is unstructured data with a small amount of structured data too.
Why big data is important?

The economic value of big data varies a lot. Sometimes there are indirect advantages of big data as in decision making. Typically there is good amount of information hidden within this big chunk of unstructured data. We should be able to figure out precisely what part of data is valuable and can be used further. This leaves us wondering what do we ultimately do with such a huge amount of data analytics which should be produced as fast as possible. There are so many use cases- Twitter wants to find out most retweeted tweets or trending ones, find tweets containing a particular hashtag, Google has to get the results of so many queries, ad publishers need to know how many new ads have been posted, Quora has to publish the questions posted newly or generate news feed as per every user’s topics and people followed, millions of emails are being sent as notification and much more from so many websites, number of applications downloaded from app store, new article or post published on various news sites to be displayed and a whole lot many things. Especially with the increasing use of smart phones and GPS enabled devices, ad publishers want to display location specific ads or ads of stores located nearby the current location of the user. This helps in targeting the right set of customers.

Challenges

To get maximum benefit of the big data, we should be able to process all of the data together instead of processing it in distinct small sets. Since this data is much larger than our traditional data, the real challenge is to handle it in a way so as to overcome the computational and mathematical challenges. The heterogeneous and incomplete nature of the data is to be tackled in processing. When we do manual computations, we can handle such heterogeneity of data. However when the processing has to be done by machine, it expects the data to be complete and homogeneous. Another challenge with big data is its volume and it keeps on increasing rapidly. On hardware front, this is taken care by increasing the number of cores rather than simply increasing the clock speed and by replacing traditional hard disc drives by better I/O performance storage. Cloud computing too helps handle this volume challenge by being able to process varying workloads. The large volume of data poses the difficulty of achieving timeliness. As larger data is to be processed, it will take more time. However the quickness of getting analysis is very crucial in most of the cases.

Wednesday, 19 February 2014

Independent projects I worked on while being a software developer

Note : Everything mentioned here was developed after regular office hours and mostly for fun/learning purpose only.

When I started my career as a software developer(Java), all I knew was OOPS concepts, Collections, I/O and Exception packages, a bit of Multi-Threading and XMLs (DOM parser only).

Apart from regular day-to-day development, the first personal project I worked on was a file-search-app. Very similar to how Windows file search works. After doing some coding, I was able to: 1.Search in sub-directories 2. Search by file-type/modified-date 3. Search by file name patterns (*VO.*, notes*.txt) etc.
Next, I wanted to create a UI for this app. So learnt Swing and created a nice (If I can say so) UI for the same.
Couldn't find time to do file-indexing to improve search performance. 

Few months later, I got some more interest in Swing and started working on another project - A Java based IDE. It was just for fun and not with the intention to build something better than Eclipse or NetBeans :) After I spent few weekends on coding, I was able to build and run a Java project through my IDE. Auto-suggest for method-names etc. was interesting to develop (Learnt reflection).

It was the 2nd year of my software development career and I was working on web/enterprise apps. I was getting introduced to various web technologies like - JSP, Servlets, Struts, JSF, GWT etc. Influenced by the magic of web technologies, I decided to build my own social network (you can laugh now :)). I knew I would never launch it but it helped me think like Mark Zuckerberg. Someone found this project interesting and finally used it for a closed group networking (with a small user-base). To be honest, what I gave was a very basic version (I realised it is a lot of work and not worth spending that much time on it) which they got enhanced later by others.

Learning so far from my independent projects - Even though I was a software developer in good companies, I was working as a Product Manager, Designer, Architect and Programmer on my pet projects.

My next project started when Google App Engine was launched. It did not take me more than a second to realize that I can now host and run my web applications for free. I was so motivated that I learned python to create my first web app on GAE (as python was the only supported language at that time). And published one more app few months later, but gradually lost interest as I was using Java, Java EE, Spring, Hibernate etc. in my office-related work.  

But hey...wait a second...Google adding Java support to GAE. Is it true?...yes it is...and GAE with Java support was released. I had a big smile on my face!!!

And then I started again and never stopped actually. Till today I have created around 15 apps (using 4 Google Accounts).

Learning so far - apart from what I highlighted in the first part of my answer, I also got the opportunity to learn new language (and related tech-stack), GAE (and hence Cloud computing- IaaS/PaaS/SaaS etc and other cloud service providers) and enjoyed seeing my web applications live (at appspot dot com).

Next - I became the API-maniac. I got into the habit of breathing with APIs. Every week I used to choose some APIs from programmable-web(API directory) and do something with it. Apart from learning API programming, it also helped me win an iPad in PayPal X Developer Challenge.

Chrome Apps and Extensions - Rolling out my ideas in the form of utilities was quick, easy and interesting. For example - 'Java Populars' which I build in half an hour, has 40K+ users. Similarly, News-You-Like and Favorite-Bollywood-Tweets apps got featured in the Digit magazine. I learnt a lot about HTML5 and JavaScript through this and built 20+ apps/extensions so far - 'Quick Chart', 'Simple Task Manager', 'TechCrunch Slides' etc to name a few.

Summary : The entire journey helped me become a better contributor in the main projects (for which I am getting paid).

PS : Getting lazy to share my interest in mobile apps ( and other areas) and what did I do as part of this.

Thursday, 7 November 2013

OGNL Implementation in Struts

Struts 1.x

Struts 1.x used expression language(EL) which uses JSTL as its base.  Struts-EL tag classes are subclasses of Struts tag classes. The EL has basic object graph traversal, but it is not very powerful  and also the  indexed property support is very weak.

Struts 2

Struts 2 was released in 2007 with many exciting features. As compared to Struts 1.x, it simplified the app development task by automating data transfer(form beans to data beans and vice versa as in Struts 1.x) and type conversion(parsing string into double/integer along with exception resolution was to be done in Struts 1.x).

OGNL

With Object Graph Navigation Language(OGNL) in Struts 2, data can be transferred with complex data structures like List and Map. User-defined types can be used with the help of custom converters, which are quite easy to write. OGNL acts as a layer between Struts 2 framework and Java-based processing unit.

ValueStack

OGNL greatly relieves developer from extra coding and maintenance effort. OGNL binds Java-side data directly to the corresponding fields in view layer. Built-in data converters save conversion work while data passes to or from Java environment. Field names in HTML can be generated using OGNL expressions to bind them directly to corresponding Java property and thus eliminates redundant code in Action classes. On contrary to the standard JSP mechanism for binding objects into the page context for access in Struts 1.x, Struts 2 uses ValueStack technology by which  taglibs can access values without coupling view to the object type it is rendering. ValueStack is set as OGNL’s root object. It contains application specific objects like action and also the model objects.

Context Map



OGNL context is set to ActionContext. ActionContext is a container of objects in which action is executed. We get a reference of it by simply calling ActionContext.getContext(). There are other objects in ActionContext like Maps(referred to as context or context map) to represent application, session and request contexts.

Data Access

The root object is referred simply by its name, without any special symbol prefixing it. Since Action instance is always pushed on ValueStack, which is the OGNL root, references to Action properties can omit pound sign. But for rest of the objects in ActionContext, ‘#’ has to be used.
Example: To refer to Action property:


<s:property value=”firstName”/>

For other objects:


<s:property value=”#session.username”/>   Or

<s:property value=”#session[‘username’]/>

Similarly we can refer to properties of request, application or attr (attribute in scope).
Collections can also be referred using OGNL.List is referred by {value1, value2,....}


<s:select label=”Continent” list=”{‘Asia’, ‘Europe’, ‘Africa’} value=”defaultContinent”/>

Alternatively, the list can be populated in Action class with its getter, setter provided.

Map is referred by #{key: value ,....}


<s:select label=”Continent” list=”#{‘first’:‘Asia’, ‘second’:‘Europe’,’third’: ‘Africa’} value=”defaultContinent”/>

In case of Set, we can check whether an item exists in it or not using ‘in’ or ‘not in’.


<s:if test=”’Asia’ in {‘Asia’, ‘Europe’, ‘Africa’}
        Exists in the set
</s:if>

Percent (%) symbol

It is used to force OGNL expression evaluation, which results in querying ValueStack for the property.


<s:property name=”%{continent}”/>  (‘#’ accesses named ValueStack property)

At (@) symbol

It is used to refer static properties and method. We need to enable it in properties file by setting-


struts.ognl.allowStaticMethodAccess=true
and then access like this-

<s:property value="@com.test.TestClass@STATIC_PROP" />

Dollar ($) symbol

Used in JSTL expressions.


‘OGNL’ name might have sounded like something difficult to first time readers. But I’m sure, after reading this post you must be ready to shake hand with OGNL!!


Friday, 6 September 2013

Challenging Work

When do you find a given task to be hard/difficult/challenging? During school days we used to call it as 'hard', in college days as 'difficult' and in job days as 'challenging'!

  1. The work needs to be delivered in less than how much time you estimated for it.
  2. You don't have clarity on the work but delivery date is fixed.
  3. Problem statement is clear but you don't know how to do it.
  4. Multiple tasks are assigned to you and the priority keeps on changing.
  5. You need to take leave for some reason and all of a sudden an easy task becomes challenging.
  6. Sometimes you do not like to work on a particular task and this is why it is challenging for you.
  7. You are stressed and everything looks challenging to you.
  8. When delivery date is very close, work appears as extraordinarily challenging.
  9. Someone couldn't do it and the same work gets delegated to you...especially when that 'someone', you consider to be a techie (Such situation can have positive impact too..you take it up as a challenge!).
  10. You are sincerely working on the task and your boss repeatedly asks you 'Done?'
  11. A combination of the above.

Have I missed any scenario?



Wednesday, 31 July 2013

When to use AngularJS and when to use Backbone!

In this post I am documenting my thoughts on when to use Backbone vs AngularJS with the help of examples (This post is not a comparison between AngularJS and Backbone).

E-Commerce Application

It should not be a single page app (unless we are trying to address few small use-cases or building shopping site for a small merchant). 

We need a framework which provides support for data-binding. Struts OGNL, Spring MVC, JSF EL etc work fine but these are backend technologies. For a modern web-app we need similar support using JavaScript. AngularJS from Google offers this kind of functionality and hence recommended. 

Online HTML/CSS Builder 

Edit functionality becomes more important than view/read. It should be a single page app (User experience is good in this case). 

A lot of UI specific work involved - like drag n' drop, animation effects etc. Text rendering is limited. AngularJS can be used to create a SPA but Backbone is recommended.

Interactive Reporting Tool

Dynamic UI, report editing and cool UI effects. Backbone is recommended. Please not that Backbone alone is not sufficient so we must use a suitable js-tech-stack which is known to work properly with Backbone.

Content Management System

Data representation in TEXT format. Edit functionality using regular forms. 
Single Page App with content getting managed in various Views. AngularJS is recommended.

Question - What will I use if I have to build GMail? 
Answer - AngularJS :)

* In most of the projects where I use Backbone, I define proper architecture for the JS layer, design with the help of a complete js-tech-stack and let backbone play its role (I do not let backbone drive the architecture of front-end).

Friday, 26 July 2013

My Findings with ModelDriven Struts Action

We are well aware of the usual action classes of Struts- values of the fields entered in UI populate the corresponding action properties. In case of ModelDriven action class, the properties of its model class get populated. Here is an example of it:


public class EmployeeRegistrationAction extends ActionSupport implements ModelDriven<EmployeeData>{

 private EmployeeData employeeData = new EmployeeData();

 
 public EmployeeData getModel() {
  return employeeData;
 }

 //Rest of the methods

}


public class EmployeeData implements Serializable{

 private String firstName;
 private String lastName;
 private String city;

 //setters & getters

}


The next step is to implement the getModel() method in such a way that it returns the application domain object, in our example we return the EmployeeData object. We can either use ModelDriven<Object>, where getModel will return Object or can specify the model class as above.
Prerequisite for using such action class is that it should implement ModelDriven interface, for which Model Driven Interceptor should be applied to action. Since this interceptor is part of the default interceptor stack, it is applied to all actions by default. Wow...we don't have to do anything out of the way to use it!

JSP:

<s:form method="POST" action="/registration.html" name="registrationform" enctype="multipart/form-data" id="registrationform">

     <s:textfield name="firstName" placeholder="First Name"/>
     <s:textfield name="lastName" placeholder="Last Name"/>
     <input type="submit" class="button" value="Create Employee"/>

</s:form>


Since I did not want to navigate to any other page and wanted the json response by staying on same page, I used ajaxSubmit(). I'd used ajaxSubmit earlier too and json response was returned just as I expected. Xml entry:

<action name="registration" class="employeeRegistrationAction" method="createEmployeeRecord">

 <result type="json"></result>

</action>


Javascript:

var registrationFormOptions = {

 resetForm : false,// reset the form after successful submit
        success   : showRegistrationResponse

    };


$("#registrationform").validate({

 submitHandler:function(form){
 //perform not-null validations. If fine,submit. else show validation error messages
 $(form).ajaxSubmit(registrationFormOptions);

 }
});

But in case of ModelDriven, json response that I was getting, was surrounded by <pre style="word-wrap: break-word; white-space: pre-wrap;"> tag. I thought of extracting json sitting inside the <pre> tag, in javascript. Thankfully I was saved from it, just one minor addition and it worked:


var registrationFormOptions = {

 resetForm : false,// reset the form after successful submit
 success : showRegistrationResponse,
 dataType: 'json'
};


Addition of dataType: 'json' in the options worked wonders. I was getting a clean json response!


Monday, 8 July 2013

Don't eval(Javascript)

I was looping through the Department data-departmentVO_1 to departmentVO_5 (each contained DepartmentVO complexType's object) and display info against the respective department.


for ( var x = 1; x < 5; x++) {

   var info = "departmentVO_"+x;

   var department = data.info;

   $("#totalEmployeesDepartment_"+x).val(department.departmentVO.totalEmployees);

}

Surprisingly javascript was throwing error for department being undefined. That indicated data.info was not working as I expected.

I searched for concatenating loop variable to access a variable in javascript and found out that something on this line would work:


eval('var department = ' +data.info);

w3schools says: The eval() function evaluates or executes an argument.
If the argument is an expression, eval() evaluates the expression. If the argument is one or more JavaScript statements, eval() executes the statements.

But misuse of eval has led to serious concerns like security issues or performance issue or often simple bugs. Also each invocation of eval() creates a new instance of the JavaScript interpreter and hence creation of new execution context. In short additional resource being put to use. Plus such code is harder to debug and maintain (Reminds me of 'goto' statement...we can still use it, but difficult to find problems). So it is better to check if there is any better, neater and safer alternative.

I decided not to use eval in my case. Understanding what I was trying to obtain, I realized that square brackets can be used instead of literal dot-names. So my code:


var department = data.info;

replaced with

var department = data[info];

I'm convinced, so lets use eval with care!

Thursday, 4 July 2013

Struts + Ajax + JSON

It wasn't my first experiment with Struts or Ajax or jsp! Despite this fact, I ran into problems and had to spend time to fix it. So let me share what dawned to me (I'm specifically avoiding term 'what I learnt'...since I already knew it).

My home.action had jsp with div in it which would open as a popup with a link click.

<s:textfield id="fullName" value="%{datamodel.fullName}" placeholder="Full Name"/>
In brief, on click of the link, it was supposed to show the div with values populated, fetched from db.

Action class with a method to serve my need was already in place to fetch data and populate in bean. However the action was returning another jsp. Using the same method in Action class, making an additional entry which returned result type as json, did the job.

<action name="homePage" class="HomePageAction" method="loadUserData">
     <result type="json"></result>
</action>

I wrote a function to send ajax request (to be called with link click):

function loadData(index){

var userName = $("#userName").val();

$.ajax({

type: "GET",

url : '/site/loadUserData.action?userName ='+userName,

success: function(data){

     showProfile();

   }

 });

}

I was getting 'data' in success part of ajax request. Happy! I was expecting the bean values to be displayed on the pop up since bean is populated and popup opens after that. But I continued to see blank fields. Disheartened!

The reason behind it was straightforward(though it didn't trigger me while I was working on it!): jsp got rendered when home.action was called. That time bean was not having values. Jsp displayed/resolved the values it had at that time. Now when I click link, send ajax request, get json response, how would jsp be aware of that!

Setting the values of fields on success of ajax(), before opening the pop up call was the way out:

$.ajax({

type: "GET",

url : '/site/loadUserData.action?userName ='+userName,

success: function(data){

showProfile(data.profileVO);

  }

 });

function showProfile(profileVO){

  $("#fullName").val(profileVO.fullName);

}


Happy ajaxing & struting(strutting ;) ).


Sunday, 30 June 2013

Spring Data - REST

Gone are the days when people used to take significant amount of time to expose REST service APIs for their domain objects. "SPRING DATA - REST" project is under active development to make your life easy. Its 1.0.0.RC3 version was released on Sep 14, 2012. We can expect the final build to be released soon.

The goal of this project is to expose CRUD operations on JPA entities in the form of REST services.

You can focus on defining your domain classes and SPRING DATA - REST framework will do the job of exposing them in the form of REST services (In simple words you don’t have to write even a single line of code to achieve this.) It is just a matter of configuring your project rightly with the framework.

Here are few simple steps to get started with.

Step 1 :

Add the following maven dependency in your pom.xml :

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-rest-webmvc</artifactId>
  <version>1.0.0.RC3</version>
</dependency>

Use the following repository to resolve this dependency :

<repository>
  <id>spring-milestone</id>
  <name>Spring Maven MILESTONE Repository</name>
  <url>http://repo.springsource.org/libs-milestone</url>
</repository>

Step 2 :

Add RepositoryRestExporterServlet in your web.xml which will act as an exporter for your JPA repositories :

<servlet>
 <servlet-name>exporter</servlet-name>
 <servlet-class>org.springframework.data.rest.webmvc.RepositoryRestExporterServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet> 

<servlet-mapping>
 <servlet-name>exporter</servlet-name>
 <url-pattern>/*</url-pattern>
</servlet-mapping>

Step 3 :

No change is needed in your Spring JPA config file. Here is my config file for your reference :


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jpa="http://www.springframework.org/schema/data/jpa"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd         http://www.springframework.org/schema/tx
 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd
 http://www.springframework.org/schema/data/jpa
 http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

<context:property-placeholder location="classpath*:*.properties" />
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${database.driverClassName}"/>
        <property name="url" value="${database.url}"/>
        <property name="username" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
</bean>  

<bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <property name="packagesToScan" value="com.viracct.rest.demo" />
 <property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
 <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
     <property name="showSql" value="${hibernate.showSql}" />
     <property name="generateDdl" value="true" />
        </bean>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
 <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<jpa:repositories base-package="com.viracct.rest.demo.dao" />

</beans>

Here I have defined some simple JPA entities - Company, Department, Employee.

package com.viracct.rest.demo.domain;

@Entity

public class Company {

 @Id

 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private String name;
 private String description;
 @OneToMany
 private List<Department> departments;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public List<Department> getDepartments() {
  return departments;
 }

 public void setDepartments(List<Department> departments) {
  this.departments = departments;
 }

}


@Entity

public class Department {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private String name;
 private String description;
 @OneToMany
 private List<Employee> employees;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public List<Employee> getEmployees() {
  return employees;
 }

 public void setEmployees(List<Employee> employees) {
  this.employees = employees;
 }

}



@Entity

public class Employee {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private Long code;
 private String name;
 private String designation;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public Long getCode() {
  return code;
 }

 public void setCode(Long code) {
  this.code = code;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDesignation() {
  return designation;
 }

 public void setDesignation(String designation) {
  this.designation = designation;
 }

}

Here are the JPA repositories for the entities mentioned above.

package com.viracct.rest.demo.dao;

public interface CompanyRepository extends JpaRepository {
}

public interface DepartmentRepository extends JpaRepository {
}

public interface EmployeeRepository extends JpaRepository {
}

Once you have deployed this application, you can see the service end points for your entities by hitting the following URL:  http://localhost:8080/restdemo and the output will be :

{
  "links" : [ {
    "rel" : "department",
    "href" : "http://localhost:8080/restdemo/department"
  }, {
    "rel" : "company",
    "href" : "http://localhost:8080/restdemo/company"
  }, {
    "rel" : "employee",
    "href" : "http://localhost:8080/restdemo/employee"
  } ],
  "content" : [ ]
}

You can browse employee objects with the following URL : http://localhost:8080/restdemo/employee and the output will be :


{
  "links" : [ ],
  "content" : [ {
    "links" : [ {
      "rel" : "self",
      "href" : "http://localhost:8080/restdemo/employee/1"
    } ],
    "name" : "Anuja Kumar",
    "designation" : "Software Developer",
    "code" : 100051
  } ],
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 1
  }
}

Similarly you can access department object with id=2 with the following URL : http://localhost:8080/restdemo/department/2 and the output will be :

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8080/restdemo/department/2"
  }, {
    "rel" : "department.Department.employees",
    "href" : "http://localhost:8080/restdemo/department/2/employees"
  } ],
  "description" : "Product Development Team",
  "name" : "Development"
}

Now if you want to access employee with employee-id=1 from department with department-id=2, you can get that using the following URL: http://localhost:8080/restdemo/department/2/employees/1 and the output will be :

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8080/restdemo/employee/1"
  }, {
    "rel" : "department.Department.employees",
    "href" : "http://localhost:8080/restdemo/department/2/employees/1"
  } ],
  "name" : "Anuja Kumar",
  "designation" : "Software Developer",
  "code" : 100051
}

Friday, 28 June 2013

Sharing CSS Properties Between Classes

Very recently I came across a situation where one of the existing CSS class was a perfect fit for it except for its background property. Just because 1 property was unwanted, I thought to override it with 'style' attribute and setting the background with no image. Very straightforward! Despite the simplicity of this solution, I felt to check what is the recommended practice in such scenarios...may be putting needed common features in one class and inheriting from it. I stumbled across the question- Does CSS support inheritance? (I felt stupid for not knowing the answer).
There are tools/frameworks like OOCSS and LESS which do support inheritance. Without any of them, the better approach to my scenario would be to have a css class and write common properties in it. Then repeat the css class and add rest of the properties to it. Here it is:

.oldClass, .newClass{
 common properties go here
}

.old class{
 the extra one goes here e.g. background: url("../images/arrow.png");
}