David's Blog

Developer Week Nürnberg 2013

The fact that you are here probably means that we either met at Developer Week (DWX13) or that you are interested in the things I presented there. Here is some Information about who I am and what I did at DWX13.

My name is David Tanzer and I am a freelancer from Linz, Austria. I work as a trainer, coach and consultant and I help teams to become/stay agile and develop better software. More information about me, including all the ways you can contact me, can be found on the home page of davidtanzer.net.

I love getting mail! So, if you have any questions or you want to book me as a trainer or consultant - or if just want to get in touch:

Contact Me

DWX13 sessions

At the conference, I had two sessions. You can find some information about them and the slides I used here.

Konkurrenzfähig in die Zukunft

In this session I was talking about things that companies, teams and individuals can do to stay competitive in the future. Slides: KonkurrenzfaehigInDieZukunft.pdf
To stay competitive as a company, you should try to become better at delivering features quickly and to attract great developers. A focus on increasing software quality can help you with both.

You can find a much shorter version of this talk here:

Other Links:
Valve Handbook for New Employees

Offline Web Applications

In this session, I showed how you can write web applications that still work when the user is offline. For this you need a way to cache resources ("Appcache") and a way to store significant amounts of data at the client device ("IndexedDB").
Slides: OfflineWebApplications.pdf

Some time ago I wrote a series of blog posts about this topic, you might be interested in them too: Offline Web Applications

IndexedDB Polyfill: nparashuram.com/IndexedDBShim/, github.com/axemclion/IndexedDBShim
IndexedDB JQuery: http://nparashuram.com/jquery-indexeddb/

Other Resources

If you liked what you saw at DWX13 or in this blog post, you'll probably also find my newsletter interesting.

Subscribe Here

Stay in touch by following me on Twitter: @dtanzer

Posting Type: 

Mathema Campus 2013

About David Tanzer

David Tanzer works as freelance Trainer, Coach and Software Developer. You can find out more about me and what I do here.

You can book me for a 3-day in-house "Software Quality" workshop where you'll learn several principles of software quality by doing hands-on exercises like this one. You can find a detailed German description of the workshop here: Workshop: Softwarequalität für Entwickler.

Connect with David Tanzer: Follow me on Twitter, Add me on Google+ or Read my blog.

I love getting mail! So, if you have any questions or you want to book me as a trainer or consultant - or if just want to get in touch:

Contact Me

If you liked my sessions at Mathema Campus or this blog post you might also be interested in my newsletter. As a little "Welcome Present" you'll get a list of "7 ideas to try in your next sprint" right after subscribing.

Subscribe

From April 19th to April 20th I was at the Mathema Campus 2013 in Erlangen (Germany). There I gave talks about "Specification by example" and "Clojure".

Here are the slides I used during my sessions:

Specification by Example
Beispielistisch.pdf
Book Bridging the communication gap by Gojko Adzic
Book Specification by Example by Gojko Adzic
Book Impact Mapping by Gojko Adzic

(conj known-languages :clojure)
I have not used any slides in this talk. I maybe will put a video of this talk on youtube...
The following book is a great intro: Clojure Programming by Chas Emerick, Brian Carper and Christophe Grand
The IDE I used in my clojure session was "Light Table" by Chris Granger.

Posting Type: 

Immutable Business Objects

So, mutability is evil. At least some people think so - including myself. Because of that, I have been thinking about immutable business objects for some time now, and here are some of my ideas. I don't really know yet if these are good ideas and I have not yet tried to implement this. Maybe you could help me out here: Please send me your comments and suggestions, you can find my contact details at the bottom of this page.

I know that the code style of the examples below does not conform to the Java Bean conventions. This also means that code like this would not work properly with lots of existing frameworks. For example, you could not use these business objects together with Hibernate or JPA. Also, the names of certain concepts in the code below could probably be improved. Anyway, I think this is a nice thought experiment, so please continue with me.

What I want is a framework that allows me to easily write immutable business objects. Ideally I only want to write an interface, the framework would create the implementation for me. (N.B.: This should be really easy to implement with dynamic proxies.)

public interface Person {
    public FirstName firstName();
    public LastName lastName();

    public Address address();
}

public interface Address {
    public Street street();
    public StreetNumber streetNumber();
}

We need a way to create new objects and set the values. We could do this using a static method that does the heavy lifting:

Person person = create(Person.class, new Values<Person>() {
    public void setValues(Person p) {
        set(p.firstName()).to(new FirstName("Davdi")); //Typo, name has to be changed later!
        set(p.lastName()).to(new LastName("Tanzer"));

        set(p.address()).to(create(Address.class, new Values<Address>() {
            public void setValues(Address a) {
                set(a.street()).to(new Street("Brunnenfeldstr."));
                set(a.streetNumber()).to(new StreetNumber("5a"));
            }
        }));
    }
});

The "Values" class would probably be quite hard to get right, but I think it would be worth it. Why? See below...

We also need a way to create a new immutable object based on an existing one. In this example, we want to change the first name of our peron object because there was a typo in our database. Another static "create" method could do this job:

Person newP = create(person, new Values<Person>() {
    public void setValues(Person p) {
        set(p.firstName()).to(new FirstName("David"));
        set(p.address()).to(create(person.address(), new Values<Address>() {
            public void setValues(Address a) {
                set(a.streetNumber()).to(new StreetNumber("6a"));
            }
        }));
    }
});

The nice thing here is not only that all values are immutable. We also have defined state changes: There is no point in time where we have access to a person object where the name was already changed but the address is still wrong (*). What I have outlined here is really more of a struct than an object in the OO sense. But I really think it would be nice to have something like this. I just don't see a way how we could implement something like this that would still play nicely with a framework like JPA :(

(*) If "create" and "Values<T>" are implemented correctly.

Posting Type: 

Con-Fess 2013

About David Tanzer

David Tanzer works as freelance Trainer, Coach and Software Developer. You can find out more about me and what I do here.

You can book me for a 3-day in-house "Software Quality" workshop where you'll learn several principles of software quality by doing hands-on exercises like this one. You can find a detailed German description of the workshop here: Workshop: Softwarequalität für Entwickler.

Connect with David Tanzer: Follow me on Twitter, Add me on Google+ or Read my blog.

I love getting mail! So, if you have any questions or just want to get in touch:

Contact Me

If you liked my session of workshop at Con-Fess or this blog post you might also be interested in my newsletter. As a little "Welcome Present" you'll get a list of "7 ideas to try in your next sprint" right after subscribing.

Subscribe

From April 3rd to April 5th I was at the Con-Fess Conference in Vienna. There I gave a talk about "Offline Web Applications" and I facilitated a workshop about test driven development (TDD). If you came here because you met me at the conference, have a look at the right side bar, it might be interesting for you...

Here are the slides I used during my session and the workshop:

Session "Offline Web Applications"
OfflineWebApplications.pdf
Source code and step by step instructions: Offline Web Applications, a four-part series about building offline applications.

TDD Workshop
TDD_as_if_you_mean_it.pdf
BrutalRefactoringGame_Slides.pdf
BrutalRefactoringGame_Smells.pdf

This post is a placeholder for now, I will add more content after the conference.

Posting Type: 

Brutal Refactoring Game @JUG Erlangen/Nürnberg

About the facilitator

David Tanzer works as freelance Trainer, Coach and Software Developer. You can find out more about me and what I do here.

You can book me for a 3-day in-house "Software Quality" workshop where you'll learn several principles of software quality by doing hands-on exercises like this one. You can find a detailed German description of the workshop here: Workshop: Softwarequalität für Entwickler.

Connect with David Tanzer: Follow me on Twitter, Add me on Google+ or Read my blog.

I love getting mail! So, if you have any questions or just want to get in touch:

Contact Me

If you liked this workshop or blog post you might also be interested in my newsletter. As a little "Welcome Present" you'll get a list of "7 ideas to try in your next sprint" right after subscribing.

Subscribe

On January 28th, 2013 I facilitated a workshop called "Brutal Refactoring Game" at a meeting of the Java User Group Erlangen / Nürnberg. Here you can find the slides and rules used in the workshop:

BrutalRefactoringGame_Slides.pdf
BrutalRefactoringGame_Smells.pdf

Later this week I'll add a write-up about the workshop and some pictures, so stay tuned!

Posting Type: 

Announcing wicket-web-action

wicket-web-action is a little library that makes it easier to decouple wicket pages from the rest of your application. It allows you to bind return values and actions of components instead of hard-coding them in your page class.

Consider the following wicket page:

public class SomePage extends WebPage {
    public SomePage() {
        /* ... */
        Label someLabel = new Label("grandTotal", "Not Applicable");
        someLabel.setVisible(false);
        add(someLabel);
    
        Button submitButton = new Button("submitButton") {
            @Override
            public void onSubmit() {
                someService.doSomeBusinessLogic();
            }
        };
        someForm.add(submitButton);
    }
}

This page class does not only provide the structure of the page, it also defines what data should be displayed and what should happen when the user interacts with the page. With wicket-web-action, you can separate these concerns:

import static net.davidtanzer.wicket.webbinding.WebBinding.*;
/* ... */

public class SomePage extends WebPage {
    @Inject SomePagePresentationModel presentationModel;

    public SomePage {
        /* ... */
        Label someLabel = bindable(Label.class, "grandTotal", 
            new PropertyModel<String>(presentationModel, "grandTotal"));
        bind(someLabel.isVisible()).to(presentationModel).isGrandTotalApplicable()
        add(someLabel);

        Button submitButton = bindable(Button.class, "submitButton");
        bindAction(presentationModel.submitAction()).when(submitButton).onSubmit();
        someForm.add(submitButton);
    }
}

You can find more information about how to use this library on the Github page of wicket-web-action. I will collect all my blog posts about this library here: wicket-web-action Resources.

Posting Type: 

The Future is Agile

Here is my lightning talk from Herbstcampus 2012, translated to English and with full screen slides and better audio quality. You also may be interested in my newsletter: Subscribe here.

If you enjoyed this video, you might also like the following blog posts:

Posting Type: 

New newsletter, 7 things to try in your next sprint

Good news: I now have also added a newsletter ;) If you are interested in the stuff I write you should definitely subscribe to this newsletter! The content of the newsletter will be similar to my blog: I will give advice for agile teams and write about technologies and software development.

The first mail your'll receive will be "7 things to try in your next sprint":

7 things to try in your next sprint

Have you ever had the feeling that your team got stuck? That improvement slowed down or even halted? You are not alone.

Is it just me or are there many retrospectives focusing on completely irrelevant improvements while ignoring many important ones? Ideas why?

@jensschauder

Some people think that incremental improvement can get you anywhere. Just take the next step in the right direction. And then the next. But then you hit a local optimum, and every possible step you could take would make things a little worse: When worse is better (Kent Beck). Or you hit a wall and need a leap to further improve, not baby steps: Incremental vs. Revolutionary improvements (Kathy Sierry).

If you are stuck in a situation like this you should think about making a big change. Sign up for my newsletter to receive 7 ideas for things you could try in your next sprint: Subscribe now.

Posting Type: 

Specification by Example tool: The workflow

Earlier this week, I wrote about some ideas I have for a Specification by Example tool. I have also been working on a prototype for said tool for the last few days. Today I want to show you how said tool should work. Some implementation details shown here will probably change in later prototypes, but the workflow will stay roughly the same.

The tool should be a wiki, just like FitNesse. So, when you create a new page, you have to enter the title of the page and the page content:

creating wiki content

As soon as you enter the keyword "{table}", the wiki will split the text field at the position of the keyword and show you a specialized table editor in between. You have to enter a table headline. After this, you can enter zero or more table parameters. These table parameters are "given" values - values that should apply to all examples (i.e. rows) in the table. Then you can add an arbitrary number of columns and rows. You can also enter a description for every row, but this is not shown in the following illustration.

creating tabular content

When you save the page, the wiki creates (and compiles) two Java classes: "AutomaticReorderBasedOnReorderLimit", a class that represents the wiki page and "ExamplesOfAutoReordersBasedOnItemsInStock", a class that represents the table. The class names are generated from the headline of the page and the headline of the table.

ExamplesOfAutoReordersBasedOnItemsInStock

public class ExamplesOfAutoReordersBasedOnItemsInStock extends TabularExample {
    public void initialize(final String theReorderLimit) {
        super.initialize(new TabularExample.ExampleInitializer() {
            public void initialize() {
                TheTestTable.this.theReorderLimit = theReorderLimit;
            }
        });
    }

    public TabularExample.ExampleRunner tableRow(final int itemsInStock, 
            final int nextSale, final boolean shouldReorder) {
        return new TabularExample.ExampleRunner() {
            public void run() {
                throw new InconclusiveExampleException(
                    "Inconclusive: This example is not yet implemented.");
            }
        };
    }
}

The values for the "given" parameters and the table rows come from the wiki page itself, as we will see later. When you want to view the page, the wiki has to determine the table structure solely from this Java class. It does this by reading the debug information of the class. For example, the names of the columns are generated from the names of the parameters of "tableRow(...)". So, when you refactor this class and reload the wiki page, the page will reflect your changes.

AutomaticReorderBasedOnReorderLimit

public class AutomaticReorderBasedOnReorderLimit extends WikiPage {
    public AutomaticReorderBasedOnReorderLimit() {
        addText("When the *items in stock* fall below the reorder limit " +
            "because of a sale, a reorder should be placed automatically.");
        addTabularExample(ExamplesOfAutoReordersBasedOnItemsInStock.class);
        getTabularExample(ExamplesOfAutoReordersBasedOnItemsInStock.class)
            .initialize(12);
        addText("");
    }

    @Test @TableInitialization 
            public void examplesOfAutoReordersBasedOnItemsInStock_row1() {
        runTableRow(0, getTabularExample(
            ExamplesOfAutoReordersBasedOnItemsInStock.class)
            .tableRow(12, 1, false));
    }
    @Test @TableInitialization 
            public void examplesOfAutoReordersBasedOnItemsInStock_row2() {
        runTableRow(10, getTabularExample(
            ExamplesOfAutoReordersBasedOnItemsInStock.class)
            .tableRow(12, 3, true));
    }
    @Test @TableInitialization 
            public void examplesOfAutoReordersBasedOnItemsInStock_row3() {
        runTableRow(20, getTabularExample(
            ExamplesOfAutoReordersBasedOnItemsInStock.class)
            .tableRow(12, 2, true));
    }
}

The constructor initializes all parts of the page. The table rows are initialized in specialized methods, one table row per method. The "row1", "row2", ... suffixes of these methods are replaced with the row description if you entered it. These methods are annotated with the JUnit "Test" annotation, so you can already run this wiki page as a JUnit test. This is useful for debugging tests in your IDE. You can also run the test within the wiki, which will present the results as part of the page (similar to FitNesse).

Conclustions

Not everything I described in this post works yet (as of 2012-12-21), but I am still very satisfied with my progress. I think a tool like this would have several advantages over some existing tools. Integrating the executable specifications in your project is really easy with this approach. Also, you do not need any IDE plugins or DSL interpreters to run the examples. Implementing such a tool is a bit tricky, because the tool has to figure out all the data from the debug information in the Java class files. But this is something that can be done, and I hope that I can present some real code with my next blog post.

What do you think about this approach? If you don't like it, which existing tool do you prefer and why? Please contact me (contact info is at the bottom of this page) and tell me your opinion!

Posting Type: 

Specification By Example: Some Ideas

I have started using "Specification by example" - using FitNess to create the executable specifications - in a project some time ago. While I really like a lot of the ideas behind FitNesse, I think a tool could do better than that. And so I started implementing a proof-of-concept of a new tool that addresses some of the problems I had with FitNesse. In this blog post, I want to explain my ideas for the new tool. The tool itself is - at the moment - only a concept and some lines of code. I will make it open source once (or if?) there is some working functionality.

Challenges with FitNesse

FitNesse saves pages in it's own format and a directory structure that is separate from your project. You can keep this directory structure in your version control system, but it's not obvious how you should deal with problems like merge conflicts. And, FitNesse has it's own versioning for pages, so your version control has to ignore the history FitNesse keeps [*]. These problems can be solved, but they are sometimes a little bit annoying.

Because FitNesse saves pages in text files, there is some impedance mismatch between FitNesse and your code. Say you are refactoring some part of your system because you found a better name for a business concept. In your executable specifications, you have to change the names in two places: Your fixture code and the FitNesse wiki page. This also adds another source of errors: Your FitNesse specifications and fixture code can be out of sync. And you can only detect those errors when running the tests, which is pretty late IMHO.

To enable FitNesse to find your fixtures, you have to leak technical details - i.e. the class names of your fixtures - into your executable specifications. Of course you can teach the non-technical team members to ignore those, but it's still another minor annoyance.

Solutions

All the problems I described above can be addressed with a single solution: Store the executable specifications as Java code. The tool I'd like to see would still have a wiki server. This server would present the executable specifications - which are Java classes - in a non-technical way, just like FitNesse. When you edit a specification, the tool would create a new Java source file and build the project.

With this approach, you have your code and your specifications in the same project structure. You can use the refactoring tools of your IDE to change the code and the executable specification - and the wiki pages will immediately reflect your changes. The Java compiler will assist you when you resolve merge conflicts. There is no impedance mismatch between specification pages and fixture code - The fixture code is the specification page.

The downside of this approach is that this system would only work for JVM based languages. You'd have to completely re-write it to support a different platform. But for me this is not a top priority issue at the moment.

Current status

I already wrote some code to test these ideas. It is far from being usable at the moment, but I am satisfied with the progress I made so far. I will put the code on GitHub once I have a working prototype - I hope this will be the case before the end of the year.

Are you interested in a tool like this? How would you improve FitNesse or other tools like it? Please contact me (contact info is at the bottom of this page) and tell me your opinion!

[*] For more information about how to configure FitNesse in your project, see How do I add fitnesse pages to version-control? on StackOverflow or this video by Bob Martin.

Posting Type: 

Pages

My name is David Tanzer and I have been working as an independent software consultant since 2006. I help my clients to develop software right and to develop the right software by providing training, coaching and consultanting for teams and individuals.

Learn more...

Subscribe to RSS - David's Blog