Archiv der Kategorie: Java

News zu Java

CodeKata Back to the CheckOut

Zurück zum Supermarkt. Wir implementieren den Code für ein Kassensystem, das  die Preisgestaltung übernimmt. Zu implementieren sind solche Regeln wie “Äpfel kosten 50 Cent, drei Äpfel kosten $1,30.”
In einem normalen Supermarkt werden die Dinge über SKUs identifiziert. In unserem können wir Buchstaben des Alphabets verwenden (A, B, C, und so weiter). Unsere Waren werden individuell berechnet. Darüber hinaus werden einige Elemente rabattiert: kaufen Sie n davon, und diese werden Ihnen y Cent kosten. Beispielsweise kann Artikel “A” 50 Cent einzeln kosten, aber in dieser Woche haben wir ein besonderes Angebot: kaufen drei von A und zahlen Sie $1,30. In der Tat sehen in dieser Woche die Preise wie folgt aus:

Item Unit Price Special Price
A 50 3 for 130
B 30 2 for 45
C 20
D 15

 

Unsere Kasse übernimmt Elemente in beliebiger Reihenfolge, so dass, wenn wir ein B scannen dann  ein A und ein anderes B, bekommen wir einen Gesamtpreis von 95  (wir erkennen, das wir einen Mengenrabatt auf 2xB geben müssen).  Da der Preis sich häufig ändert, müssen wir in der Lage sein den Gesamtpreis bei jeder Transaktion neu zu berechnen.

Das Interface für Checkout kann wie folgt aussehen:

   co = CheckOut.new(pricing_rules)
   co.scan(item)
   co.scan(item)
       :    :
   price = co.total

Hier ist ein Unit-Test implementiert in Ruby. Die Hilfsmethode preis bekommt eine Liste von Artikel und ruft scan-Methode der Kasse für jedes Element der Liste auf, bevor sie schließlich wieder den Gesamtpreis ausgibt.

class TestPrice < Test::Unit::TestCase

    def price(goods)
      co = CheckOut.new(RULES)
      goods.split(//).each { |item| co.scan(item) }
      co.total
    end

    def test_totals
      assert_equal(  0, price(""))
      assert_equal( 50, price("A"))
      assert_equal( 80, price("AB"))
      assert_equal(115, price("CDBA"))

      assert_equal(100, price("AA"))
      assert_equal(130, price("AAA"))
      assert_equal(180, price("AAAA"))
      assert_equal(230, price("AAAAA"))
      assert_equal(260, price("AAAAAA"))

      assert_equal(160, price("AAAB"))
      assert_equal(175, price("AAABB"))
      assert_equal(190, price("AAABBD"))
      assert_equal(190, price("DABABA"))
    end

    def test_incremental
      co = CheckOut.new(RULES)
      assert_equal(  0, co.total)
      co.scan("A");  assert_equal( 50, co.total)
      co.scan("B");  assert_equal( 80, co.total)
      co.scan("A");  assert_equal(130, co.total)
      co.scan("A");  assert_equal(160, co.total)
      co.scan("B");  assert_equal(175, co.total)
    end
  end

Es gibt viele Wege zur Umsetzung dieser Art von Algorithmus; wenn Sie Zeit haben, experimentieren Sie mit mehreren.

Ziele der Kata

Zu einem gewissen Grad ist dies nur ein lustiges kleines Problem. Der Format der Preisregeln wird in der Aufgabe nicht beschrieben. Wie können diese aussehen, damit der Checkout ohne das Wissen über die Preisregeln-Strategie immer einen korrekten Gesamtpreis berechnen kann? Wie können wir das Design flexibel genug halten, so dass wir neue Preisregeln in der Zukunft hinzufügen können?

Kuriositäten der Notationen

Kuriositäten der Notationen

Heute habe ich eine interessante Kuriosität entdeckt, die auf den ersten Blick irritiert.

Ich erstellte eine ArrayList und befüllte die inline mit Werten:

ArrayList<String> list = new ArrayList<String>() {{ add("A"); add("B"); add("C"); }};

Danach habe ich versucht die ArrayList zu serialisieren. ArrayList implementiert bekanntlich Interface Serializable.
SerializationUtils.serialize(list);
Dabei flog eine java.io.NotSerializableException.

Ich habe die ArrayList auf eine konventionelle Weise erstellt und mit werten befüllt:
ArrayList list1 = new ArrayList();
list1.add("A");
list1.add("B");
list1.add("C");

Die Serialisierung ging ohne Probleme durch….. Hmmm…..

Die Erklärung ist einfach: die erste Variante erzeugt keine ArrayList, sondern eine anonyme Subklasse von ArrayList und diese ist nicht serialisierbar.

IcedTea

IcedTea

RedHat ermöglichte das Einschließen in die Distribution OpenJDK unter Benutzung ausschließlich von offenen Bibliotheken. Dabei werden binäre Dateien mit den aus GNU Classpath ausgetauscht. Diese Technologie wurde IcedTea genannt.

Realisierung der JVM vom Cacao www.cacaojvm.org setzt auch den GNU Classpath ein.