The Artima Developer Community
Sponsored Link

Weblogs Forum
Frustration-Driven Language Development

11 replies on 1 page. Most recent reply: Sep 2, 2006 3:47 AM by James Mead

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 11 replies on 1 page
Michael Feathers

Posts: 448
Nickname: mfeathers
Registered: Jul, 2003

Frustration-Driven Language Development (View in Weblogs)
Posted: Apr 6, 2004 1:13 PM
Reply to this message Reply
Summary
There are an incredible number of programming languages out there. What would it be like if we had a few with features that really supported testing?
Advertisement

I just noticed that Brian Marick had an interesting response to something I said in my last blog entry. I was talking about how difficult it is to instantiate classes outside of their applications. He mentioned that it would be great to have a tool that would allow you to create an arbitrary object and poke at it, test it etc, regardless of how many dependencies it has. You could supply the tool with mocks for the bad dependencies and it would use the mocks. That would be useful.

Brian's post reminded me of something I ended up making a while ago, a little framework I called Ghostworld. It was a tool for that sort of thing. I ditched it because I discovered that PicoContainer has every feature I added and quite a few more. The world doesn't need any more duplicate projects so Ghostworld remains unreleased. But, there is another reason why I never released Ghostworld. I felt it was incomplete. It was missing the killer feature. Let me tell you about it.

To make an arbitrary class you fill up the Ghostworld with types:

Ghostworld world = new Ghostworld();
world.addImposter("Profile", UserProfile.class);
...

Then you ask it to create an object:

Reservation res = (Reservation)world.makeObject("Reservation");

The ghostworld walks the constructors of Reservation and attempts to create one using the classes it knows about. So far, so good. PicoContainer does this also, but what I really wanted was a framework that lets me do this:

class Reservation
{
	private AIGConnection connection;
	
	public Reservation(..) {
		connection = new AIGConnection(..);
	}
}

world.addImposter("AIGConnection", TestingAIGConnection.class);
Reservation res = (Reservation)world.makeObject("Reservation");

Now, here's what I want to have happen. Every time that that Reservation object or one of its subobjects creates a AIGConnection using a 'new' expression, I want a TestingAIGConnection object to be created instead. In the example above, we'd now have a reservation which holds onto an instance of TestingAIGConnection rather than AIGConnection. Wouldn't that be useful? We could instantiate and test nearly any piece of code without refactoring. I'm not convinced that is great thing. Abused it would just let code get uglier without bound. But, used well, it could really help people out of same jams.

Unfortunately, I never had time to really dig in and find out whether there is some sort of classloader, AOP, or bytecode manipulation magic that would allow me to substitute classes over and over again at runtime. But, the thing that I have been reflecting about is the fact that there seems to be a lot of energy behind efforts like this. And when that happens it usually means that language support is something to consider.

I forget whether it was Paul Graham or Richard Gabriel (or someone else entirely) who said something like this: "the algorithm for developing every "next" language is simple.. it has to be more dynamic than its predecessor and it has to look like C." So, let's imagine a language like that.

class Account
{
	private balance = 0;
	private log = new TransactionLog();
	
	deposit(value) {
		log.addEntry(balance, value);
		balance += value;
	}
	...
}

(By the way, just in case you haven't seen it before, there's actually a language with syntax close to this. It's called Groovy).

The Account class is simple enough, but let's suppose we want to test it, and let's make it a real bear. The TransactionLog class talks to a database behind the scenes. Every time you add an entry, it's sloooowww.

The way languages are today, if we want to get past this, we have to add a constructor that accepts a log, or introduce a factory method and override it, or.. well there are a bunch of solutions, but what if we had a language which let us to do this?

test Account
{
	class TransactionLog
	{
		entries = new ArrayList();
		addEntry(entry) {
			entries.add(entry);
		}
	}

	testDeposit {
		a = new Account();
		a.deposit(3);
		assertEquals(3, a.getBalance());
		assertEquals(1, a.log.entries.size());
	}
}

The language would allow us to define classes inside a test class. The classes we define in tests supersede classes outside the test. So, whenever some object creates a transaction log in this test class, they get an instance of this simple replacement class that doesn't touch a database.

Another feature... the tests have access to all private data.

Could these features be abused? Yes. If you can test without breaking dependencies it's easier to create snarls of complicated code. On the other hand, it would be much easier to get out of them too.

What do you think? Isn't it about time languages had first-class support for testing?


Daniel Berger

Posts: 1
Nickname: phooey
Registered: Apr, 2004

Re: Frustration-Driven Language Development Posted: Apr 7, 2004 6:05 AM
Reply to this message Reply
Mock objects have been around for a while. Does your language not have this? Or do mock objects not work for what you want?

BTW, your example in Ruby looks like this:

class Account
balance = 0
log = TransactionLog.new

def deposit(value)
log.addEntry(balance, value)
balance += value
end
end

I can't figure out how to do spacing here (doesn't seem to take literal html tags), but you get the idea. Thought you might like it.

- Dan

Gregg Wonderly

Posts: 317
Nickname: greggwon
Registered: Apr, 2003

Re: Frustration-Driven Language Development Posted: Apr 7, 2004 11:33 AM
Reply to this message Reply
> <p>I just noticed that <a
> href="http://www.testing.com/cgi-bin/blog">Brian
> Marick</a> had an interesting <a
> href="http://www.testing.com/cgi-bin/blog/2004/04/05#feathe
> rs-coupling">response</a> to something I said in my last
> blog entry. I was talking about how difficult it is to
> instantiate classes outside of their applications. He
> mentioned that it would be great to have a tool that would
> allow you to create an arbitrary object and poke at it,
> test it etc, regardless of how many dependencies it has.
> You could supply the tool with mocks for the bad
> dependencies and it would use the mocks. That would be
> useful.</p>

If you use Java, you can do this by simply declaring standard methods as private inside of your classes (as opposed to creating test classes using package private access as JUnit does). These are then, not visible to the world as part of the objects API. However, you can grant AllPermission in a test harnass, and it can use introspection to find these standard methods, and invoke them in a way similar to JUnit.

I prefer in class tests because that allows me easy access to changing the tests as I develop and keeps everything together for compilation checks as well as for review...

David Ramsey

Posts: 34
Nickname: dlramsey
Registered: Apr, 2002

Re: Frustration-Driven Language Development Posted: Apr 8, 2004 10:47 AM
Reply to this message Reply
Have you looked at Aspect Oriented Programming and at Aspect-J in particular? It might let you do what you want, not only at the constructor level but for methods as well.

Johannes Brodwall

Posts: 19
Nickname: jhannes
Registered: Jun, 2003

Re: Frustration-Driven Language Development Posted: Apr 8, 2004 1:59 PM
Reply to this message Reply
The language would allow us to define classes inside a test class. The classes we define in tests supersede classes outside the test. So, whenever some object creates a transaction log in this test class, they get an instance of this simple replacement class that doesn't touch a database.

If I understand you correctly, this is what is known as partial classes - that is, classes that can be extended or changed after they are defined.

The next version of C# is supposed to bring partial classes using a special keyword partial. I don't know if C# partial classes will allow for the redefinition of methods, or just for the extension of a class with more methods. (BTW: The primary use of partial classes in C# is for code generation)

Ruby's classes are partial by default, and allow for redefining methods as per your example. I see no reason why your transaction log example shouldn't work as if in Ruby.

Maik Schmidt

Posts: 2
Nickname: mschmidt
Registered: Jul, 2003

Re: Frustration-Driven Language Development Posted: Apr 9, 2004 9:29 PM
Reply to this message Reply
> (By the way, just in case you haven't seen it before, there's actually a language with syntax close to this. It's called Groovy).
As others already said before: There is already a language that supports this style with even less line noise ({,}). It's Ruby (http://www.ruby-lang.org). It has excellent support for unit testing, mock objects, and all you need for test-driven development. Additionally, it makes fun!!

Todd Blanchard

Posts: 316
Nickname: tblanchard
Registered: May, 2003

You want Smalltalk Posted: Apr 10, 2004 7:36 AM
Reply to this message Reply
Which, incidentally, is where Unit Testing (as in JUnit), and XP (as in eXtreme Programming), and practically every other "modern" development idea was invented.

Mock objects? Make a dumb proxy and change doesNotUnderstand to always answer success, or failure, or whatever. Inspect and debug any object at any time, without restarting the app in "debug mode".

I am laughing AT the struggling java developers, not WITH them.

Bruce Eckel

Posts: 875
Nickname: beckel
Registered: Jun, 2003

Re: Frustration-Driven Language Development Posted: Apr 13, 2004 9:13 AM
Reply to this message Reply
The D language has built-in support for unit testing, very similar to the way you show it here.
http://www.DigitalMars.com.

Jeremy D. Miller

Posts: 1
Nickname: jdmiller
Registered: Jul, 2004

Re: Frustration-Driven Language Development Posted: Jul 1, 2004 11:29 AM
Reply to this message Reply
My current project has created a new IoC container called StructureMap (http://sourceforge.net/projects/structuremap) somewhat like PicoContainer in C# that is on the way to doing exactly what you are describing using what we call "Mock Injection." Any type constructed by the container can be set to be replaced with an NMock mock instance whenever the type is requested from the container. We have found this technique in conjunction with constructor injection to be very effective in isolating classes for unit tests. Right now the functionality only supports mocking one class at a time, but we are working on something that can look at a requested class, create it with the appropriate dynamic mocks, and return both the new object and the DynamicProxy objects in one step to simplify the mechanics of setting up unit tests. An NUnit test using this technique looks like this:



using System;
using StructureMap;
using NMock;


[TestFixture]
public class MyClassTester
{
private IMock _dependencyMock;

[SetUp]
public void SetUp()
{
_dependencyMock = ObjectFactory.Mock(typeof(IDependency));

}

[Test]
public void Test1()
{
_dependencyMock.Expect("SayHello", "Hello");

MyClass foo = new MyClass();
foo.DoSomething();
_dependencyMock.Verify();

}
}


public class MyClass
{
public void DoSomething()
{
IDependency dependency = (IDependency)ObjectFactory.GetInstance(typeof(IDependency));
dependency.SayHello("Hello");
}

}

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Frustration-Driven Language Development Posted: Nov 18, 2004 11:15 AM
Reply to this message Reply
This post was very interesting and inspired a new blog post in my OOP Case Study series of blog entries at http://www.artima.com/weblogs/viewpost.jsp?thread=80672

I enjoy your writing Michael, and I would love to read more blog entries by you.

Alejandro M. Ramallo

Posts: 3
Nickname: aramallo
Registered: May, 2003

Re: You want Smalltalk Posted: Nov 21, 2004 10:06 AM
Reply to this message Reply
Or...Objective-C (Todd I guess you will describe this better than me, I have seen you in the Cocoa/WebObjects lists)

2 features available in Objective-C that will enable you to do what you describe are Object Posing and Categories (aka mixin inheritance).

Posing lets a class present itself to the runtime as another class. Instances of the parent class will never be created, instead instances of the poser will be created.

Categories allow you to override or add methods to an existing class, without having to create a subclass or access the source.

I guess we do not need NEW languages but old ones. Still I understand why these features are "disabled" in JAVA :-)
AOP will do the trick in JAVA I guess.

James Mead

Posts: 1
Nickname: floehopper
Registered: Sep, 2006

Re: Frustration-Driven Language Development Posted: Sep 2, 2006 3:47 AM
Reply to this message Reply
If you use Ruby, you might like to take a look at the Mocha mocking library at http://mocha.rubyforge.org with examples at http://blog.floehopper.org/articles/2006/09/01/mocha-quickstart.

Flat View: This topic has 11 replies on 1 page
Topic: Frustration-Driven Language Development Previous Topic   Next Topic Topic: Requiem for an operator

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use