Warning: include(/home/ensonik/public_html/wp//wp-content/plugins/google-buzz-er/google-buzz-er.php) [function.include]: failed to open stream: No such file or directory in /home/ensonik/public_html/wp/wp-content/themes/lightword/header.php on line 3

Warning: include() [function.include]: Failed opening '/home/ensonik/public_html/wp//wp-content/plugins/google-buzz-er/google-buzz-er.php' for inclusion (include_path='.:/usr/local/lib/php:/usr/lib/php') in /home/ensonik/public_html/wp/wp-content/themes/lightword/header.php on line 3
March « 2009 « the higher you fly

the higher you fly

6Mar/090

The jury is out – SpringContracts is s – l – o – w

Honnestly, I'm not surprised. We've got an aspect that hits every single method call on every object, AND it needs to do reflection and interpret through an EL.

But, really; it's friggin slow. Prohibitively slow. Painfully slow.

The test

There's nothing magic in all this code. It's only an interface where the contracts are defined, a bogus implementation and a test class containing two test methods. The first method uses nothing at all (straight objects with no contracts), and the second method uses the full burito.

First thing was the interface

public interface IPersonManager {
   @Precondition( condition = "arg1 > 0" )
   @Postcondition(condition="not empty return and return.id > 0")
   public Person getPerson(int id);

   @Postcondition(condition="not empty return")
   public List<Person> getAll();

   @Precondition(bindArgs="arg1=person", condition = "not empty person and person.id < 1")
   @Postcondition(condition="not empty return and return.id > 0")
   public Person insert(Person person);

   @Precondition(bindArgs="arg1=person", condition = "not empty person and person.id > 0")
   @Postcondition(condition="not empty return and return.id > 0")
   public Person update(Person person);

   @Precondition(bindArgs="arg1=person", condition = "not empty person and person.id > 0")
   public void delete(Person person);
}

And a simple bogus implementation

public class PersonManagerImpl implements IPersonManager {
   public void delete(Person person) {
   }

   public List<Person> getAll() {
      List<Person> list = new ArrayList<Person>();
      list.add(new Person());
      return list;
   }

   public Person getPerson(int id) {
      Person p = new Person();
      p.setId(id);
      p.setFirstName("Mike");
      p.setLastName("McLean");
      return p;
   }

   public Person insert(Person person) {
      Person p = new Person();
      p.setId(3);
      p.setFirstName("Mike");
      p.setLastName("McLean");
      return p;
   }

   public Person update(Person person) {
      return person;
   }
}

The spring configuration


 


	
		
			
     	
  	 

	 

	

And finally the test class:

@Test
	public void testWithNoContracts() throws Exception {
		IPersonManager manager = new PersonManagerImpl();

		long start = System.currentTimeMillis();
		loopAFewTimes(manager);
		long end = System.currentTimeMillis();

		System.out.println("No spring, no contracts: " + ((end - start) / 1000) + " seconds and " + (end - start)  + " millis.");
	}

	@Test
	public void testWithContracts() throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
		IPersonManager manager = (IPersonManager)  context.getBean("personManager");

		long start = System.currentTimeMillis();
		loopAFewTimes(manager);
		long end = System.currentTimeMillis();

		System.out.println("Full enchilada: " + ((end - start) / 1000) + " seconds and " + (end - start)  + " millis.");
	}

	public void loopAFewTimes(IPersonManager manager) {
		for (int x = 0; x < 10000; x++) {
			manager.getPerson(1);
			manager.getAll();

			Person personInsert = new Person();
			personInsert.setId(0);

			manager.insert(personInsert);

			Person personUpdate = new Person();
			personUpdate.setId(2);
			manager.update(personUpdate);

			manager.delete(personUpdate);
		}
	}

The results

No spring, no contracts: 0 seconds or 14 millis.
Full enchilada: 24 seconds or 24792 millis.

Now, I understand that this is not scientific, bordering on stupid and unprofessional, but still. Across 10000 loops ....! Nuff said.

I'd seriously have to re-consider using this in anything that has any need for performance. I might consider it for a low-traffic data entry site, but nothing much more. I haven't tried other implementations, so this might not be fair towards the whole DBC community.

5Mar/090

Design by contract musings

A colleague of mine introduced me to the Design By Contract implementation done for Spring called SpringContracts. It's gotten me looking at it for the last couple days. It's most definitely an interesting concept, so I brought it up to the rest of the guys at work to find out what they thought.

The biggest concerns were:

1) Binds you to Spring (if you use SpringContacts):

No big deal here. We're already fully invested into Spring.  Either way, I don't beleive in complete de-coupling of technology. If you're using a technology and investing time and man-power into it, you had better make the most of it. I reject the idea that putting Spring specific annotations in your code is bad practice (in my current environment at least)

2) Need to learn a new technology/language

Again, I have a lot of trouble with this. Do we need to always stay at the lowest denominator just to satisfy the ones who refuse to learn? I beleive that enthousiasm for something new and teams that are willing to teach and share their knowledge don't mind these types of additions, especially if they get something out of it. Luckily, I work with that type of team (they really are friggin great!)

There's a good discussion about that very subject here.

3) AOP + Introspection = Lowered performance

Yup. Absolutely. If this thing puts a major hit on the performance of my code, then I'd have to re-consider. In my current environment, I can't afford a big hit to performance. But in most places, having more solid, more self-documented, more bug free code is what you should strive for. An extra millisecond here or there won't kill anyone. Remember: "Scalability is not your problem. Getting people to give a shit is."

I'll try to post some benchmarks this weekend ...

4) All this to avoid a few null checks

EXACTLY! If I can enforce the semantics of every class that implements an interface, then I don't need to check for those nulls and those illegal arguments. Ever. How many times do you just do that check ... just in case a new implementation doesn't do what you expect it to. With an annotated interface defining and enforcing the state of a returned object, you have cleaner and more readable code.

What's important here is that Design By Contract isn't just about fancy assertions. It's a way to enforce the semantics of an implementing class.

That being said, all the Java implementations of DBC libraries have been inactive forever. That makes me think that it may have turned out to be a big shinny and temporary toy. I'd be curious to know if anyone has used this. I'm still on the fence, but the concept is definitely winner.

(Something to read)