הצד האפל של הקוד – או רק בגלל שאתה יכול זה לא אומר שאתה צריך …

בעולם התכנות יש הרבה דרישות, לפעמים הזויות מידי בשביל לתאר.  אנשים רואים במחשבים כסוג של דבר שיכול לבלוע כל שיגעון שיש.  כאשר כוח מחשוב כלשהו היה יקר מאוד, אנשים נזהרו מאוד במה שהם דורשים. ככול שכוח המחשוב נהיה זול יותר, ככה הדרישות נהיו הזויות יותר ויותר.

העניין הוא שעם הדרישות הגיעו החידושים של שפות התכנות, אשר החליטו להקל על המפתחים לספק דרישות הזויות עם כלים שלפעמים גורמים לדרישות להראות הגיוניות לגמרי. אחד הדברים האלו הם דווקא Generics בשפת התכנות. לדעתי זה אחד הדברים המיותרים ביותר שיש, היות ובשביל לספק מענה לכל דבר שיכול להשתמש בכלי, יש סוג של hack שהוא בעצם feature אשר אומר שאני יכול לקבל כל סוג של טיפוס ולהשתמש בו בצורה טבעית, אבל הדרך להגיע לשם כל כך מגעילה וכל כך לא קריאה בעליל, אשר לדעתי זה לא שווה את האנרגיה, היות ורמת ההשקעה בטיפול בקוד שכזה דורשת המון אנרגיה, ולא תמיד אפשר להבין מאיפה בעיה מסויימת מגיעה בכלל בגלל המורכבות של דבר כזה, אבל זה לא מפריע לאנשים להשתמש בזה, בשביל לתת מענה לצורך מקומי, שאח"כ יחזור לנגוס בהם בצורות שלא תמיד אפשר לדמיין אפילו.

הנה קוד מתוך מימוש של ווקטור שקראתי השבוע, האם לדעתם הקוד הזה קריא ?



generic TheEnumerator<TIterator, TValue> = object
 public type
    TGetCurrent = function(const Iterator: TIterator): TValue of object;
    TMoveNext = function(var Iterator: TIterator): Boolean of object;
 private
    FGetCurrent: TGetCurrent;
    FIterator: TIterator;
    FMoveNext: TMoveNext;
    function GetCurrent: TValue;
  public
    procedure Init(const InitialIterator: TIterator; const Mover: TMoveNext; const Getter: TGetCurrent);
    function MoveNext: Boolean;
    property Current: TValue read GetCurrent;
  end;
...
  generic TheVectorSet<TItem> = class { http://code.google.com/p/fprb/wiki/TheVectorSet }
  public type
    TEnumerator = specialize TheEnumerator;
    TEnumeratorProvider = specialize TheEnumeratorProvider;
  private type
    PItem = ^TItem;
  private
    FCapacity: Integer;
    FCount: Integer;
    FData: PItem;
    function Extract(const Index: Integer): TItem;
    function Find(const Item: TItem; out Index: Integer): Boolean;
    function GetFirst: TItem;
    function GetItem(const Index: Integer): TItem;
    function GetLast: TItem;
    function GetMembership(const Item: TItem): Boolean;
    procedure Insert(const Index: Integer; const Item: TItem);
    function MoveNext(var Index: Integer): Boolean;
    function MovePrev(var Index: Integer): Boolean;
    procedure SetCapacity(AValue: Integer);
    procedure SetMembership(const Item: TItem; const AValue: Boolean);
  public
    destructor Destroy; override;
    function Exclude(const Item: TItem): Boolean; // true => was in set
    function GetEnumerator: TEnumerator;
    function Include(const Item: TItem): Boolean; // true => was in set
    function Reversed: TEnumeratorProvider;
    procedure Clear;
    procedure Pack;
    property Capacity: Integer read FCapacity write SetCapacity;
    property Count: Integer read FCount;
    property First: TItem read GetFirst;
    property Membership[const Item: TItem]: Boolean read GetMembership write SetMembership; default;
    property Last: TItem read GetLast;
  end;

נכון שתגידו שאולי זה הכרחי אם רוצים לעשות משהו גנרי מאוד (מכאן השם לא ?) אבל למה בשם הגמישות צריך לסבך כל דבר קיים ? אפשר גם לממש מחלקה חדשה אשר יורשת ועושה שכתוב למימוש הקיים ובכך להשיג את אותן התכונות עבור כל טיפוס שנרצה. אז כן זה יותר עבודה מצד אחד, ואף פעם אי אפשר לתת מענה לכל דבר, אבל אם עובדים נכון עם OO אז התחזוקה צריכה להיות פשוטה הרבה יותר ממה שזה נראה. הרי לרוץ על איבר אפשר לעשות במקום אחד. והצורה איך לדעת אם זה הערך זה הדבר אשר משתנה.

סתם משהו שמציק לי מאוד בקוד. ד"א בשביל להריץ את הקוד הבא, תהיו צריכים להשתמש ב FPC גרסת 2.5.1 (ומתישהו "ומעלה"), ולדעתי הקוד גם יכול לעבוד בדלפי בגרסאות החדשות שלו (צריך לבדוק).

מחשבה אחת על “הצד האפל של הקוד – או רק בגלל שאתה יכול זה לא אומר שאתה צריך …

  1. פינגבק: מחלקה מופשטת « לראות שונה

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s