AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Code-Kata: Cache-Klasse. Wer produziert den besten Code
Thema durchsuchen
Ansicht
Themen-Optionen

Code-Kata: Cache-Klasse. Wer produziert den besten Code

Ein Thema von Dejan Vu · begonnen am 30. Jul 2015 · letzter Beitrag vom 1. Aug 2015
 
Dejan Vu
(Gast)

n/a Beiträge
 
#7

AW: Code-Kata: Cache-Klasse. Wer produziert den besten Code

  Alt 1. Aug 2015, 08:51
Das Interface der Klasse habe ich bewusst etwas anders gestaltet als in der Vorgabe
Wieso hältst Du dich nicht an die Vorgabe? Wieso soll sich ein Cache um das Schreiben kümmern? Wieso soll er Statistiken pflegen?

Durchgefallen.

Im Ernst: Sollen wir für deine Sonderklasse extra eigene Test- und Prüfroutinen schreiben?


Schreib Deine doch bitte um, dann kann man die mit den MRU-Ansätzen vergleichen. Dein Algorithmus ist wirklich sehr interessant.

Ein Tipp bezüglich der function TCache.FindPlaceInCache: integer; : Du rennst mit einer For-Schleife durch die Liste? Das ist jetzt aber nicht so sonderlich performant, denn ein Cache verwaltet i.a. Millionen von Elementen.
Diese Routine wird bei jedem Cache-Aufruf einmal komplett durch alle Elemente laufen. Das kannst Du mit einer Priority-Queue (bzw. einem Baum) viel effizienter Lösen. Der wird bei jedem Zugriff sortiert bzw. mit wenigen Handgriffen angepasst, sodass dein 'worst element' immer automatisch 'oben' ist. Aber die Implementierung ist natürlich ungemein komplexer.


Ein paar Worte zu meinen Designentscheidungen:
- Ich prüfe nicht explizit ob die Aufrufe gültig sind (z.B. ob bei Get der Key auch wirklich existiert) und werfe daher auch keine Exceptions. Denn offensichtlich ist die Schnittstelle so angelegt, dass der Benutzer vorher selbst mit Contain prüfen soll, ob der Key existiert....
Gut gesehen.
Zitat:
...Die ganze Schnittstelle ist meiner Meinung nach nicht optimal...
Gegenvorschlag?

Zitat:
Ich verwende grundsätzlich (fast) nie private sondern immer protected (bis auf sehr wenige Ausnahmen, bei denen es wirklich gute Gründe gibt, die dagegen sprechen).
Welche Gründe sprechen gegen private Felder? Properties sehe ich ein, aber Felder sollten so strict private sein, wie es nur geht.
Ich deklariere Felder immer privat (außer bei DTO) aber den Zugriff per Property als protected. Vermutlich ist das das Gleiche, aber mit mehr Tipparbeit verbunden.

Das 'MakePair' würde ich dem TKeyValuePair als Create spendieren. Gehört -finde ich- dorthin.
Delphi-Quellcode:
// function TCache.MakePair(Key: Integer; Value: TObject): TKeyValuePair;
// begin
// Result.Key := Key;
// Result.Value := Value;
// end;

constructor TKeyValuePair.Create(aKey: Integer; aValue: TObject)
begin
  Self.Key := aKey;
  Self.Value := aValue;
end;
Das Freigeben des Cache-Items gehört (finde ich) in den Destruktor des TCacheItem.... Aber wieso gibst Du dort auch das 'Value' frei? Das ist doch das zu cachende Objekt? Damit hat doch der Cache nix am Hut. Oder hab ich mich verlesen?

Delphi-Quellcode:
procedure TCache.Evict(Item: TCacheItem);
begin
  ...
  CacheItem.Value.Value.Free; // <<<--- Mööp, ich glaube, da ist ein Value. zu viel
  CacheItem.Free;
end;
Hier würde ich zwei zusätzliche kleine Methoden draus machen (Lesbarkeit, Clean Code).
Delphi-Quellcode:
// procedure TCache.Put(ID: Integer; Item: TObject);
// var
// CacheItem: TCacheItem;
// begin
// Assert(not Contains(ID));
//
// if GetCurrentNumberOfElements >= FMaxSize then
// Evict(FMRU.Last);
//
// CacheItem := TCacheItem.Create(MakePair(ID, Item));
// FMap[ID] := CacheItem;
// Bump(CacheItem);
// end;

procedure TCache.RemoveLeastUsedElementFromCache;
begin
  if GetCurrentNumberOfElements >= FMaxSize then
    Evict(FMRU.Last);
end;

procedure TCache.AddItemToCache(ID: Integer; Item: TObject);
var
  CacheItem: TCacheItem;

begin
  CacheItem := TCacheItem.Create(MakePair(ID, Item));
  FMap[ID] := CacheItem;
  Bump(CacheItem);
end;

procedure TCache.Put(ID: Integer; Item: TObject);
begin
  Assert(not Contains(ID));

  RemoveLeastUsedElementFromCache;
  AddItemToCache(ID, Item);
end;
'Bump' und 'Evict' sind für mich ungewöhnliche Begriffe. Ich würde zumindest 'Bump' anders benennen. Aber vermutlich ist das bei Dir/euch Standard. Dann müsste ich mich anpassen

Deckt sich ziemlich mit meiner Implementierung, nur das ich keine Generics habe und die MRU selbst implementieren muss.

PS: Es gibt keine Vorgabe, das eine MRU verwendet werden soll! ICH hätte das so gelöst. Wie ihr das macht, ist mir schnuppe (im Gegenteil: Sehr interessant)
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:55 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz