In my perpetual search for brain food for programmers, I’ve found this article: Holding a Program in One’s Head
Stackoverflow: Reputation over 1000 :)
2. December, 2008Just a tiny post to cheer the fact that my reputation on Stackoverflow.com has transcended 1,000. Yay!
Writing Testable Code
1. December, 2008Just stumbled over this article: “Writing Testable Code“. Apparently, it’s a set of rules which Google uses. While I’m not a 100% fan of Google, this is something every developer should read and understand.
How To Be Agile
29. November, 2008The article “When Agile Projects Go Bad” got me thinking. I’ve talked to many people about XP and Agile Development and TDD and the usual question is: “How do we make it work?” And the next sentence is: “This won’t work with us because we can’t do this or that.”.
This is a general misconception which comes from the … uh … “great” methodologies which you were taught in school: the waterfall model, the V model, the old dinosaurs. They told you: “You must follow the rules to the letter or doom will rain on your head!” Since you could never follow all the rules, they could easily say “Told you so!” when things didn’t work out.
Agile development is quite different in this respect. First of all, it assumes that you’re an adult. That you have a brain and can actually use it. It also assumes that you want to improve your situation. It also assumes nothing else.
When a company is in trouble, it will call for help. Expensive external advisers will be called, they will think about the situation for a long time (= more money for them). After a while (when the new yacht is in the dry), they will come up with what’s wrong and how to fix it. Did you know that in most companies in trouble, the external advisers will just repeat what they heard form the people working there?
It’s not that people don’t know what’s wrong, it’s just not healthy to mention it … at least if you want to work there. So people walk around, with the anger in their hearts and the fist in the pocket and nothing will happen until someone from the outside comes in and states the obvious. Can’t happen any other way because if it could, you wouldn’t be in this situation in the first place.
Agile Development is similar. It acknowledges that you’re smart and that you know what’s wrong and that you don’t have the power to call in help. What it does is it offers you a set of tools, things that have worked for other people in the past and some of them might apply to you. Maybe all. Probably not. Most likely, you will be able to use one or two. That doesn’t sound like much but the old methodologies are pretty useless if you can’t implement 90%+. Agile is agile. It can bend and twist and fit in your routine.
So you’re thinking about doing TDD. Do you have to ask your boss? No. Do you have to get permission from anyone? No. Do you have to tell anyone? No. Can you do it any time you like, as often as you like, stop at will? Yes. If it doesn’t work for you in your situation, for the current project, then don’t use it. No harm done, nothing gained either.
But if you can use it, every little bit will help. Suddenly, you will find yourself to be able to deliver on time. Your code will work and it will be much more solid than before. You will be able to do more work in less time. People will notice. Your reputation will increase. And eventually, they will be curious: How do you do it? “TDD.” What’s that?
You win.
Be agile. Pick and choose. Pick what you think will work, try it, drop it if it doesn’t deliver. And if it works, try the next thing. Evolve. Become the better you.
Agile is not a silver bullet. It won’t miraculously solve all your issues. You still have to think and be an adult about your work. It’s meant to be that way. I don’t do every Agile practice every day. Sometimes, I don’t even TDD (and I regret every time). But I always return because life is just so much more simple.
Space: Not So Black And Empty After All
28. November, 2008If you always wanted to know what NASA does with all the billions of dollars spent, here are some images.
Navigating SharePoint Folders With Axis2
26. November, 2008I’ve just written some test code to get a list of items in a SharePoint folder with Apache Axis2 and since this was “not so easy”, I’ll share my insights here.
First, you need Axis2. If you’re using Maven2, put this in your pom.xml:
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-kernel</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-adb</artifactId>
<version>1.4.1</version>
</dependency>
Next stop: Setting up NTLM authorization.
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.commons.httpclient.auth.AuthPolicy;
HttpTransportProperties.Authenticator auth = new
HttpTransportProperties.Authenticator();
auth.setUsername ("username");
auth.setPassword "password");
auth.setDomain ("ntdom");
auth.setHost ("host.domain.com");
List authPrefs = new ArrayList (1);
authPrefs.add (AuthPolicy.NTLM);
auth.setAuthSchemes (authPrefs);
This should be the username/password you’re using to login to the NT domain “ntdom” on the NT domain server “host.domain.com”. Often, this server is the same as the SharePoint server you want to connect to.
If the SharePoint server is somewhere outside your intranet, you may need to specify a proxy:
HttpTransportProperties.ProxyProperties proxyProperties =
new HttpTransportProperties.ProxyProperties();
proxyProperties.setProxyName ("your.proxy.com");
proxyProperties.setProxyPort (8888);
You can get these values from your Internet browser.
If there are several SharePoint “sites” on the server, set site to the relative URL of the site you want to connect to. Otherwise, leave site empty. If you have no idea what I’m talking about, browse the SharePoint server in Internet Explorer. In the location bar, you’ll see an URL like this: https://sp.company.com/projects/demo/Documents2/Forms/AllItems.aspx?RootFolder=%2fprojects%2fdemo%2fDocument2%2f&FolderCTID=&View=%7b18698D80%2dE081%2d4BBE%2d96EB%2d73BA839230B9%7d. Scary, huh? Let’s take it apart:
https:// = the protocol,
sp.company.com = The server name (with domain),
projects/demo = The “site” name
Documents2 = A “list” stored on the site “projects/demo”
/Forms/AllItems.aspx?RootFolder=... is stuff to make IE happy. Ignore it.
So in out example, we have to set site to:
String site = "/projects/demo";
Mind the leading slash!
To verify that this is correct, replace “/Documents2/Forms/” and anything beyond with “/_vti_bin/Lists.asmx?WSDL”. That should return the WSDL definition for this site. Save the result as “sharepoint.wsdl” (File menu, “Save as…”). Install Axis2, open a command prompt in the directory where you saved the WSDL file and run this command (don’t forget to replace the Java package name):
%AXIS2_HOME%binWSDL2Java -uri sharepoint.wsdl -p java.package.name -d adb -s
This will create a “src” directory with the Java package and a single file “ListsStub.java”. Copy it into your Maven2 project.
Now, we can get a list of the lists on the site:
ListsStub lists = new ListsStub
("https://sp.company.com"+site+"/_vti_bin/Lists.asmx");
lists._getServiceClient ().getOptions ()
.setProperty (HTTPConstants.AUTHENTICATE, auth);
If you need a proxy, specify it here:
options.setProperty (HTTPConstants.HTTP_PROTOCOL_VERSION,
HTTPConstants.HEADER_PROTOCOL_10);
options.setProperty (HTTPConstants.PROXY, proxyProperties);
We need to reduce the HTTP protocol version to 1.0 because most proxies don’t allow to send multiple requests over a single connection. If you want to speed things up, you can try to comment out this line but be prepared to see it fail afterwards.
Okay. The plumbing is in place. Now we query the server for the lists it has:
String liste = "Documents2";
String document2ID;
{
ListsStub.GetListCollection req = new ListsStub.GetListCollection();
ListsStub.GetListCollectionResponse res = lists.GetListCollection (req);
displayResult (req, res);
document2ID = getIDByTitle (res, liste);
}
This downloads all lists defined on the server and searches for the one we need. If you’re in doubt what the name of the list might be: Check the bread crumbs in the blue part in the intern explorer. The first two items are the title of the site and the list you’re currently in.
displayResult() is the usual XML dump code:
private void displayResult (GetListCollection req,
GetListCollectionResponse res)
{
System.out.println ("Result OK: "
+res.localGetListCollectionResultTracker);
OMElement root = res.getGetListCollectionResult ()
.getExtraElement ();
dump (System.out, root, 0);
}
private void dump (PrintStream out, OMElement e, int indent)
{
indent(out, indent);
out.print (e.getLocalName ());
for (Iterator iter = e.getAllAttributes (); iter.hasNext (); )
{
OMAttribute attr = (OMAttribute)iter.next ();
out.print (" ");
out.print (attr.getLocalName ());
out.print ("="");
out.print (attr.getAttributeValue ());
out.print (""");
}
out.println ();
for (Iterator iter = e.getChildElements (); iter.hasNext (); )
{
OMElement child = (OMElement)iter.next ();
dump (out, child, indent+1);
}
}
private void indent (PrintStream out, int indent)
{
for (int i=0; i<indent; i++)
out.print (" ");
}
We also need getIDByTitle() to search for the ID of a SparePoint list:
private String getIDByTitle (GetListCollectionResponse res, String title)
{
OMElement root = res.getGetListCollectionResult ().getExtraElement ();
QName qnameTitle = new QName ("Title");
QName qnameID = new QName ("ID");
for (Iterator iter = root.getChildrenWithLocalName ("List"); iter.hasNext (); )
{
OMElement list = (OMElement)iter.next ();
if (title.equals (list.getAttributeValue (qnameTitle)))
return list.getAttributeValue (qnameID);
}
return null;
}
With that, we can finally list the items in a folder:
{
String dir = "folder/subfolder";
ListsStub.GetListItems req
= new ListsStub.GetListItems ();
req.setListName (document2ID);
QueryOptions_type1 query
= new QueryOptions_type1 ();
OMFactory fac = OMAbstractFactory.getOMFactory();
OMElement root = fac.createOMElement (
new QName("", "QueryOptions"));
query.setExtraElement (root);
OMElement folder = fac.createOMElement (
new QName("", "Folder"));
root.addChild (folder);
folder.setText (liste+"/"+dir); // <--!!
req.setQueryOptions (query);
GetListItemsResponse res = lists.GetListItems (req);
displayResult (req, res);
}
The important bits here are: To list the items in a folder, you must include the name of the list in the “Folder” element! For reference, this is the XML which actually sent to the server:
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns1:GetListItems xmlns:ns1="http://schemas.microsoft.com/sharepoint/soap/">
<ns1:listName>{12AF2346-CCA1-486D-BE3C-82223DEC3F42}</ns1:listName>
<ns1:queryOptions>
<QueryOptions>
<Folder>Documents2/folder/subfolder</Folder>
</QueryOptions>
</ns1:queryOptions>
</ns1:GetListItems>
</soapenv:Body>
</soapenv:Envelope>
If the folder name is not correct, you’ll get a list of all files and folders that the SharePoint server can find anywhere. The folder names can be found in the bread crumbs. The first two items are the site and the list name, respectively, followed by the folder names.
The last missing piece is displayResult() for the items:
private void displayResult (GetListItems req,
GetListItemsResponse res)
{
System.out.println ("Result OK: "
+res.localGetListItemsResultTracker);
OMElement root = res.getGetListItemsResult ()
.getExtraElement ();
dump (System.out, root, 0);
}
If you run this code and you see the exception “unable to find valid certification path to requested target”, this article will help.
If the SharePoint server returns an error, you’ll see “detail unsupported element in SOAPFault element”. I haven’t found a way to work around this bug in Axis2. Try to set the log level of “org.apache.axis2” to “DEBUG” and you’ll see what the SharePoint server sent back (not that it will help in most of the cases …)
Links: GetListItems on MSDN, How to configure Axis2 to support Basic, NTLM and Proxy authentication?, Java to SharePoint Integration – Part I (old, for Java 1.4)
Good luck!
“Hunderte von Milliarden” auf Perry-Rhodan.net
19. November, 2008I’ve published a story 🙂 Since the story is in German, this post is, too.
Ich gebe es zu, ich bin ein Perry Rhodan Fan. Nicht nur, weil es die grösste SciFi-Serie der Welt ist (mit inzwischen 2466 Heften à 64 Seiten jede Woche, seit nunmehr fast 50 Jahren! Die aktuellen Ereignisse um Roi Danton und Dantyren haben mich so lange beschäftigt, bis ich eine Geschichte zu Papier (oder in diesem Fall zu PDF) bringen musste.
Arndt Ellmer war so freundlich sie in der LKS Galerie auf der Homepage von Perry Rhodan zu platzieren. Der Titel ist “Hunderte von Milliarden” und enthält meine Interpretation von Aussagen wie “Der Erbe des Universums”.
Viel Vergnügen!
Feedback ist erwünscht. Entweder als Kommentar anhängen oder per eine Mail (digulla at hepe dot com bzw. dark at pdark dot de).
Stuck? Ask Stack Overflow
19. November, 2008Stuck with a hard programming problem? Just solved an impossible problem and want to show the world your genius? Don’t know how to solve a problem with your favorite OS or programming language? Check out stackoverflow.com.
Testing the Impossible: Rules of Thumb
19. November, 2008When people say “we can’t test that”, they usually mean “… with a reasonable effort”. They say “we can’t test that because it’s using a database” or “we can’t test the layout of the UI” or “to test this, we need information which is buried in private fields of that class”.
And they are always wrong. You can test everything. Usually with a reasonable effort. But often, you need to take a step back and do the unusual. Some examples.
So your app is pumping lots of data into a database. You can’t test the database. You’d need to scrap it for every test run and build it from scratch which would take hours or at least ages. Okay. Don’t test the database. Test how you use it. You’re not looking for bugs in the database, you’re looking for bugs in your code. Saying “but some bugs might get away” is just a lame excuse.
Here is what you need to do: Identify independent objects (which need no other objects stored in the database). Write tests for those. Put the test data for them in an in-memory database. HSQLDB and Derby are your friends. If you must, use your production database but make the schema configurable. Scrap the tables before the test and load them from clean template tables.
So you need some really spiffy SQL extensions? Put them in an isolated place and test them without everything else against the real database. You need to test that searching a huge amount of data works? Put that data in a static test database. Switch database connections during the tests. Can’t? Make that damn connection provider configurable at runtime! Can’t? Sure you can. If everything else fails, get the source with JAD, compile that into an independent jar and force that as the first thing into the classpath when you run your tests. Use a custom classloader if you must.
While this is not perfect, it will allow you to learn how to test. How to test your work. Testing is always different just like every program is different. Allow yourself to make mistakes and to learn from them. Tackle the harder problems after the easier ones. Make the tests help you learn.
So you have this very complex user interface. Which you can’t test. Let alone starting the app takes ten minutes and the UI changes all the time and … Okay. Stop the whining. Your program is running on a computer and for same inputs, a computer should return the same outputs, right? Or did you just build a big random number generator? Something to challenge the Infinite Improbability Drive? No? Then you can test it. Follow me.
First, cut the code that does something from the code that connects said code to the UI. As a first simple step, we’ll just assume that pressing a button will actually invoke your method. If this fails for some reason, that reason can’t be very hard to find, so we can safely ignore these simple bugs for now.
After this change, you have the code that does stuff at the scruff. Now, you can write tests for it. Reduce entanglement. Keep separate issues separate. A friend of mine builds all his code around a central event service. Service providers register themselves and other parts of the code send events to do stuff. It costs a bit performance but it makes testing as easy as overwriting an existing service provider with a mock up.
Your software needs an insanely complex remote server? How about replacing this with a small proxy that always returns the same answers? Or at least fakes something that looks close enough to a real answer to make your code work (or fail when you’re testing the error handling).
And if you need data that some stubborn object won’t reveal, use the source, Luke (download the source and edit the offender to make the field public, remove “final” from all files, add a getter or make it protected and extend the class in the tests). If everything else fails, turn to java.lang.reflect.Field.setAccessible(true).
If you’re using C/C++, always invoke methods via a trampoline: Put a pointer somewhere which contains the function to call and always use that pointer instead of the real function. Use header files and macros so no human can tell the difference. In your tests, bend those pointers. The Amiga did it in 1985. #ifdef is your friend.
If you’re using some other language, put the test code in comments and have a self-written preprocessor create two versions that you can compile and run.
If all else fails, switch to Python.
Posted by digulla
Obama Goes Creative Commons
2. December, 2008If you’ve been living under a stone for the past few months, the next president of the USA, Barack Obama, had his team build a web site where he shares his thoughts, ideas and plans. That is itself probably constitutes a revolution but it gets better: You can talk to these guys. Or rather send them your ideas, hopes and worries. And it seems these really count. I mean, how much better can it get?
It can: The site and all content is under the Create Commons license CC-BY which basically means the content is free as long as you say where you got it from (read the license for details). Amazing 🙂
Thanks for the nice Christmas present, Mr. Soon-President! It really makes me happy to know that there is finally someone who gets the Internet.
Links: Lawrence Lessig’s Blob (he’s the inventor of CC, just in case).
Share this: