Meeting 6

Aus Java Student User Group Austria - Java + JVM in Wien Österreich / Vienna Austria
Wechseln zu: Navigation, Suche

When: Monday, November 3rd, 2008 - 19:00

Where: Freihaus HS4


Bazaar

Download the slides (pdf, 68KB).
You can also view the slides online.

Contents

Bazaar was introduced by Florian Motlik, which is an opensource, distributed verion control system completely written in python.

Core Concepts

First of all, you have to be aware of some necessary terms and their meaning:

  • Revision: A snapshot of the files you are working with.
  • Working tree: The directory containing your version controlled files and subdirectories.
  • Branch: An ordered set of revisions that describe the history of a set of files.
  • Repository: A store of revisions.

See: http://doc.bazaar-vcs.org/bzr.dev/en/user-guide/index.html#core-concepts


Distributed vs Centralized

Fehler beim Erstellen des Vorschaubildes: sh: 1: /usr/bin/convert: not found

Error code: 127
Distributed vs Centralized Versioning System

The big difference (as compared to traditionally VCS like CVS and SVN) is that bazaar manages sources in a distributed way. Instead of a central server with a single repository where each developer commits his changes, in the bazaar world every developer has its own repository and instead of commits there are only merges.

Workflows

With bazaar, you can work in many different workflows, depending on your environment: solo, partner, central (with local commits) or decentral (shared mainline, human or automated gatekeeper). Depending on that workflows, you have to execute different commands.

Solo & Partner

Initialize the repository:

$ bzr init-repo # create meta repository (for performance reasons)
$ bzr init # transform directory into repository

In solo mode:

$ cd my-stuff
$ bzr init
$ bzr add
$ bzr commit -m "Initial import"

In partner mode:

UserA$ bzr init
... some code changes on UserA's machine ...
UserA$ bzr commit
UserB$ bzr branch http://server.com/UserA
... some code changes on UserB's machine ...
UserB$ bzr commit
UserA$ merge http://server.com/UserB
... some code changes on UserA's machine ...
UserA$ bzr commit
UserB$ bzr merge http://server.com/UserA

Central

Necessary steps are similar to CVS/SVN, where the branch is bound to the server and a network connection is required.

$ bzr checkout http://server.com/repo
... some code changes on local machine ...
$ bzr commit
$ bzr update

Decentral

In this case you mirror the main branch which is not supposed to be used for development.

$ bzr branch http://server.com/trunk
$ bzr branch trunk feature1
... some code changes related to feature1 ...
$ bzr branch trunk fix1
... some code changes related to fix1 ...
$ cd trunk
$ bzr merge ../fix1
$ bzr commit # locally
$ bzr update # to update the mirrored branch


Links

Maven

By Michael Greifeneder.

Fluent Interfaces

Unfortunately there are no slides available for the presentation from Axel Gross but you can have a look at Martin Fowler's article about fluent interfaces who coined the term.

To be short, it's kind of an internal DSL with the aim to provide a readable API.


The following example shows the use of JMock: <source lang="java"> mock.expects(once()).method("m").with(or(stringContains("hello"),

                                        stringContains("howdy")));

</source>


In a preceding presentation about db4o we had similar code for querying a OO database: <source lang="java"> query.descend("matrNr").constrain(500000).greater().equal(); </source>


Simple Example

Personally, I (Christoph Pickl) like to use that technique to construct complex objects which should be on the one side immutable but on the other easy to create (values for creation are sometimes scattered throughout many different classes). Imagine you have a Person type with its only attributes name:String and age:int which are both marked final.

<source lang="java"> public class Person {

 // final attributes
 private final String name;
 private final int age;
 // constructor is package-private, so only PersonBuilder can access it
 Person(final String name, final int age) {
   this.name = name;
   this.age = age;
 }
 // simple getter methods
 public String getName() {
   return this.name;
 }
 public int getAge() {
   return this.age;
 }

} </source>


A PersonBuilder now provides the single possibility to create Persons. The interesting thing here is, that it forces the caller to invoke methods for each attribute of Person, and returns itself but with another "face" (builder interface). Only if the last attribute was set the create() method is accessible which finally returns a new instance. Guard clauses (actually used to avoid nested conditions) help to ensure that the instance will only store valid values. This gives the advantage of defining a valid state outside of the entity itself so it can be reused in a complete different environment with complete different limitations (name can be null, etc). <source lang="java"> public class PersonBuilder implements IPersonBuilder1, IPersonBuilder2, IPersonBuilderFinisher {

 // (non-final) attributes
 private String name;
 private int age;
 // constructor
 private PersonBuilder() {
   // constructor not visible; use static factory method build()
 }
 public static IPersonBuilder1 build() {
   return new PersonBuilder();
 }
 // fluent interface implementations
 public IPersonBuilder2 name(final String name) {
   if(name == null) { // guard clause
     throw new IllegalArgumentException("name == null");
   }
   this.name = name;
   return this;
 }
 public IPersonBuilderFinisher age(final int age) {
   if(age < 0 || age > 200) { // guard clause
     throw new IllegalArgumentException("age not within range 0-200: " + age);
   }
   this.age = age;
   return this;
 }
 public Person newInstance() {
   return new Person(this.name, this.age);
 }

}

</source>


Two obvious disadvantages come to my mind: The overhead of creating an interface for each method plus one for the creation and you have to invoke the methods in exactly the way they are defined via the fluent interfaces. You can't change the order, and you can't skip any attribute. <source lang="java"> public interface IPersonBuilder1 {

 IPersonBuilder2 name(String name);

} public interface IPersonBuilder2 {

 IPersonBuilderFinisher age(int age );

} public interface IPersonBuilderFinisher {

 Person newInstance();

} </source>


Finally you can use the builder to create Person instances via a very readable API. The second Person instance is created in a distributed manner, which would not be that easy if you would have to create the instance in the old-fashioned way because of final attributes you have to pass to the constructor. <source lang="java"> public class App {

 public static void main(final String[] args) {
   // short version:
   final Person p1 = PersonBuilder.build().name("Christoph Pickl").age(23).newInstance();
   // or use different builders and pass them around
   final IPersonBuilder2 builder2 = PersonBuilder.build().name("Christopherus Pickl");
   final Person p2 = App.computeAge(builder2).newInstance();
 }
 private static IPersonBuilderFinisher computeAge(final IPersonBuilder2 builder2) {
   final int age = 42; // some complicated computation
   return builder2.age(age);
 }

} </source>