Archive for January, 2020

MvnIndex

Friday, January 17th, 2020

Der MvnIndex ist äusserst praktisch, wenn man ein neues Projekt mit Maven aufsetzt.
Neben einer “Artifact”-Websuche gibts auch ein Eclipse Plugin für die Suche nach GroupId, ArtifactId und Version.

Effective Java: Builder-Pattern

Wednesday, January 15th, 2020

7 Jahre nach der ersten Auflage ist das Buch “Effective Java” von Joshua Bloch nun endlich in der zweiten Auflage erschienen. Der Klassiker wurde komplett runderneuert: Best-Practises für ‘neue’ Sprachelemente wie Generics und Enums kamen hinzu, veraltete Kapitel (wie der Ersatz von C-Strukturen) wurden gestrichen.

Neu ist auch das “Builder-Pattern”. Es kommt zum Einsatz, wenn ein Objekt viele optionale Variablen besitzt. Die bisherige, klassische Variante bei solchen Objekten ist das Schreiben von mehreren Konstruktoren (’telescoping constructor’), die über unterschiedliche Anzahl von Parametern verfügen. Allerdings sinkt die Lesbarkeit bei mehr als 6 Parametern gewaltig (vor allem wenn die Parameter vom gleichen Typ sind).

Das “Builder-Pattern” verzichtet auf die ‘telescoping constructors’ und arbeitet stattdessen mit einer statischen inneren Klasse, die für das Erzeugen einer Instanz der äusseren Klasse zuständig ist. Der Konstruktor des Builder-Objekts enthält alle “Pflicht”-Variablen, die optionalen Variablen werden über (verkettbare) Methodenaufrufe hinzugefügt. Abschliessend wird die build Methode aufgerufen, die ein unveränderliches Objekt der äusseren Klasse erzeugt. Der Konstruktor der äusseren Klasse ist privat, d.h. nur ein Builder kann ein Objekt tatsächlich instanzieren:

Hier ein Beispiel:

  1. package ch.javablog.builderpattern;
  2.  
  3. import java.math.BigDecimal;
  4.  
  5. public class Product {
  6.         // all fields are final: immutable object
  7.         private final String id;
  8.         private final BigDecimal price;
  9.         private final String salesDescription;
  10.         private final Product baseProduct;
  11.         private final boolean approved;
  12.  
  13.         private Product (Builder builder) {
  14.                 // private Constructor can only be called from Builder
  15.                 this.id = builder.id;
  16.                 this.price = builder.price;
  17.                 this.salesDescription = builder.salesDescription;
  18.                 this.baseProduct = builder.baseProduct;
  19.                 this.approved = builder.approved;
  20.         }
  21.  
  22.         public String getId() {
  23.                 return id;
  24.         }
  25.  
  26.         public BigDecimal getPrice() {
  27.                 return price;
  28.         }
  29.  
  30.         public String getSalesDescription() {
  31.                 return salesDescription;
  32.         }
  33.  
  34.         public Product getBaseProduct() {
  35.                 return baseProduct;
  36.         }
  37.  
  38.         public boolean isApproved() {
  39.                 return approved;
  40.         }
  41.  
  42.         public static class Builder {
  43.                 // mandatory parameter
  44.                 private final String id;
  45.                 private final BigDecimal price;
  46.  
  47.                 // optional
  48.                 private String salesDescription = “”;
  49.                 private Product baseProduct     = null;
  50.                 private boolean approved        = true;
  51.  
  52.                 public Builder(String id, BigDecimal price) {
  53.                         this.id = id;
  54.                         this.price = price;
  55.                 }
  56.                 public Builder salesDescription(String salesDescription) {
  57.                         this.salesDescription = salesDescription;
  58.                         return this;
  59.                 }
  60.                 public Builder baseProduct(Product baseProduct) {
  61.                         this.baseProduct = baseProduct;
  62.                         return this;
  63.                 }
  64.                 public Builder approved(boolean approved) {
  65.                         this.approved = approved;
  66.                         return this;
  67.                 }
  68.  
  69.                 public Product build() {
  70.                         return new Product(this);
  71.                 }
  72.         }
  73. }
  74.  
  75. public class ProductClient {
  76.         public static void main(Stringargs) {
  77.                 BigDecimal price = BigDecimal.valueOf(36.5);
  78.                 Product.Builder builder = new Product.Builder(“050-0047”,price);
  79.                 // create Product using the builder
  80.                 Product p = builder
  81.                                 .salesDescription(“great product”)
  82.                                 .approved(false)
  83.                                 .build();
  84.         }
  85. }

Private Methoden in JavaScript dank Closures

Friday, January 10th, 2020

Momentan lese ich das Buch “JavaScript: The Good Parts” von Douglas Crockford.
Ein durchweg empfehlenswertes Buch, das eine klare und kompakte Übersicht über die Stärken (und Schwächen) von JavaScript bietet. Sehr interessant ist das “Functional”-Pattern: Mit Hilfe von Closures können private Instanzvariablen und Methoden definiert werden. In 4 Schritten erstellt eine sogenannte “Maker”-Methode eine neue Objekt-Instanz.
Erzeuge ein neues Objekt

Definiere in der Methode die (privaten) Instanzvariablen und Methoden.

Hänge an das neue Objekt die öffentlichen Methoden. Dank dem “Closure”-Prinzip haben nur diese Methoden Zugriff auf die vorher definierten Instanzvariablen und Methoden.

Gebe das neue Objekt zurück.
Hier das Beispiel:

  1. var vehicle = function(spec) {
  2.      // the spec object contains all attributes needed to create the object.
  3.  
  4.      // create a new empty object using the object literal
  5.      var o = {};    
  6.  
  7.      // vars of this function are the private variables of the new object
  8.      var age            = 0;
  9.      var maxSpeed       = spec.maxSpeed;
  10.      var name           = spec.name;
  11.      var price      = spec.price;
  12.  
  13.      // private methods
  14.      var calculateDegradation = function() {
  15.            return age * price / 10 ; // assuming linear degradation
  16.      };    
  17.  
  18.      // public methods
  19.      o.getName = function() {
  20.          return name;
  21.      };
  22.  
  23.      o.getMaxSpeed = function() {
  24.          return maxSpeed;
  25.      };
  26.  
  27.      o.setAge = function(v) {
  28.         age = v;
  29.         return o; // cascade pattern
  30.      }
  31.  
  32.      o.getResidualValue = function() {
  33.          return price – calculateDegradation();
  34.      };
  35.  
  36.      return o;
  37. }
  38.  
  39. var myVehicle = vehicle( { name: ‘Audi R8’,
  40.                                 price: ‘106400’,
  41.                                 maxSpeed: ‘301’});
  42.  
  43. alert(myVehicle.getMaxSpeed()); // 301
  44. alert(myVehicle.getResidualValue()); // 106400;
  45. alert(myVehicle.setAge(2).getResidualValue()); // 85120;

Interessant ist die Ansicht im Firebug: Keine Spur von den privaten Methoden oder Instanzvariablen. Sie werden durch das “Closure” geschützt.

trakkcor auf dem Nürburgring

Sunday, January 5th, 2020

Alle paar Wochen bekomme ich EMails von trakkcor Anwendern, die mir beschreiben, wo und wie sie trakkcor einsetzen. Letzte Woche habe ich wohl vom bisher spannendsten Anwendungsfall erfahren:

Guten Tag,
Ich habe trakkcor letztes Wochenende erfolgreich zum Tracken eines Ford Escort RS2000 beim 500km Youngtimer-Rennen im Rahmenprogramm des 24 Stunden Rennens auf dem Nürburgring eingesetzt. Ich habe trakkcor einfach jede Sekunde ein GPS Signal holen lassen, dieses dann online in eine Datenbank gespeichert und mittels Google Earth “Netzwerklink” sekündlich auslesen lassen.
Daher erstmal ein großes Lob für die bisherige Arbeit, alles lief sowohl während den beiden 1,5 stündigen Traininssitzungen als auch im 4 stündigem Rennbetrieb stabil und ohne nennenswerte Probleme (Handy Sony Ericsson K700i, GPS Reciever Bluemax GPS-710).
Im laufendem Betrieb stellte sich heraus das eventuell eine Geschwindigkeits- bzw. Richtungsanzeige hilfreich bei der Visualisierung wären.
Ich würde mich daher sehr freuen, wenn in einem der nächsten trakkcor releases auch NMEA-Messages im GPRMC-Format übertragen werden könnten.
Falls gewünscht könnte ich ihnen Bildmaterial des trakkcor einsatzes zukommen lassen.

Mit freundlichen Grüßen
Gerrit Sturm

Sehr gerne… Wer sich davon ein Bild machen möchte, klickt hier, hier, hier, oder hier.
Solche EMails motivieren natürlich zur Weiterentwicklung von trakkcor. Im CSV befindet sich schon eine neuere Version, die aber nicht vollständig durchgetestet ist.

Folgende Features sind geplant:

  • Umschalten von HTTP POST auf HTTP GET (Es gibt mit manchen J2ME-Laufzeitumgebungen Probleme mit POST)
  • GPRMC-Support

Übrigens haben Hans-Dieter und Ralf Sturm das Youngtimer-Rennen wie auch im letzten Jahr gewonnen.
Herzlichen Glückwünsch!

;)