Home > Delphi > TSafeMe… BindMe

TSafeMe… BindMe


Forget Try-Finally to make sure your TObject instance destroyed completely on exit block procedure. TSafeMe makes your code clean without worrying with underlaying memory leaks.

Common try-finally pattern, is this your usual code?

function TXServer.ServiceDelete(const ServiceID: string): IXResponse;
var
  Q_SERVICES: TORM_Q_SERVICES;
begin
  Result := TXResponse.NewResponse();

  Q_SERVICES := TORM_Q_SERVICES.Create; // create new instance
  try
    try
      Q_SERVICES.SERVICE_ID.WhereValue := ServiceID;
      Q_SERVICES.Controller.Delete;
    except
      on E: Exception do
      begin
        Result.RESP_CODE := RC_ERROR;
        Result.RESP_MSG := E.Message;
      end;
    end;
  finally
    Q_SERVICES.Free; // then relese it
  end;
end;

Now compare with this one, see TSafeMe in action:

function TXServer.ServiceDelete(const ServiceID: string): IXResponse;
var
  Q_SERVICES: TORM_Q_SERVICES;
begin
  Result := TXResponse.NewResponse();
  TSafeMe.BindMe(TORM_Q_SERVICES.Create, Q_SERVICES);  // new instance and bind to TSafeMe

  try
    Q_SERVICES.SERVICE_ID.WhereValue := ServiceID;
    Q_SERVICES.Controller.Delete;
  except
    on E: Exception do
    begin
      Result.RESP_CODE := RC_ERROR;
      Result.RESP_MSG := E.Message;
    end;
  end;

  // no need release here, TSafeMe takes care for you
end;

function TXServer.ServiceUpdate(const ServiceID, ServiceName: string): IXResponse;
var
  Q_SERVICES: TORM_Q_SERVICES;
begin
  Result := TXResponse.NewResponse();
  TSafeMe.BindMe(TORM_Q_SERVICES.Create, Q_SERVICES);

  try
    Q_SERVICES.Controller.Edit;
    Q_SERVICES.SERVICE_ID.Value := ServiceID;
    Q_SERVICES.SERVICE_NAME.Value := ServiceName;
    Q_SERVICES.Controller.Post;
  except
    on E: Exception do
    begin
      Result.RESP_CODE := RC_ERROR;
      Result.RESP_MSG := E.Message;
    end;
  end;
end;

OK, here is another example, using common classes (as requested by b_squared):

procedure SafeMeInAction;
var
  MyStrings: TStrings;
  MyStream: TStream;
  MyComponent: TMyComponent; 
begin
  // new instances
  TSafeMe.BindMe(TStringList.Create, MyStrings);
  TSafeMe.BindMe(TStringStream.Create('Well this is the string data.'), MyStream);
  TSafeMe.BindMe(TMyComponent.Create(nil), MyComponent);

  // it is safe & ensure the instances will be destroyed once exit block procedure
  
  MyStrings.Add('One');
  MyStrings.Add(MyStream.DataString);
  MyStrings.Add(MyComponent.Name);

  // it is safe... even when exception occurred...

  raise Exception.Create('Ups something wrong here');
  MyStrings.Add('This never executed');

  // nice is it
  // bump... the instances destroyed as soon the program quit this block
end;

How this works? What a tricks inside this? Before I write the tips let me know your mind, write comment bellow about how this should achieved.

Advertisements
Categories: Delphi Tags:
  1. March 24, 2011 at 10:15 am

    No comment… yet? :-“

  2. Abdellah Al-Arief
    March 24, 2011 at 10:51 am

    Wonderfull. Please let me know? how the magic can happen?

    • March 24, 2011 at 11:00 am

      I do care your though… lets me know your way first.
      Try this try this… please solve the puzzle :-“

  3. Abdellah Al-Arief
    March 24, 2011 at 11:24 am

    i guess,

    1. you may use a something like TList,
    every class function:
    TSafeMe.BindMe(TORM_Q_SERVICES.Create, Q_SERVICES);
    called, it register reference of Q_SERVICES instance.
    and the end of program.. simply you free every instance registered by looping.

    2. another scenario, you may use and interface. every the class function called, it simply assign to a an interface variable. and then.. of course, looping no need here

    • March 24, 2011 at 11:42 am

      Good instinct, nice guess… let’s the other wrote they own…
      Ayo dimari…

      For your info, my own implementation takes only 34 lines of code (declaration & implementation). And I could shrink it to 21 lines of code when I cut some helper 😀

  4. March 24, 2011 at 11:46 am

    Show me your best design for easy use and keep it simplicity 😀

  5. b_squared
    March 24, 2011 at 12:46 pm

    Need another more hints:
    1. Instead of TORM_Q_SERVICES, can you use another more commonly used object in your code? (TStrings, TComponent, TSteams….) It might be more readable for me

    2. When does the TSafeMe do the release?
    At the end of program? (as proposed by Abdellah, and the only way I can think of). But why wait till the end of program to release the object, if the object is no longer required?)
    OR
    TSafeMe release your object as soon as the object is no longer required? I’d like to know how TSafeMe do it (ilmu saya belum nyampe sini…)

    • March 24, 2011 at 1:13 pm

      1. Updated, see your request example 🙂
      2. When? Yes, as soon as the instance no longer used, not at the end of program 😉

      Get the points? Lets me know your answer 😀

  6. Mario Ray Mahardhika
    March 24, 2011 at 2:10 pm

    I’ve seen something like this in a garbage collector implementation for Object Pascal. It makes use of COM-style interface’s reference counting capability.

    • March 24, 2011 at 2:15 pm

      TSafeMe actually works like that, but not TRULY fully garbage collector because it is not blended as language feature. I would love to see your implementation of TSafeMe 😀

  7. jrp
    March 24, 2011 at 9:06 pm

    Hello brother-brother,

    I’m walking-walking to pascal-id.org then I meet the link to go here 🙂

    Perhaps it would add something to this discussion if you take a glance at JclSysUtils unit in Jedi Code Library (JCL). The implementation is called “Guards”. As you guys know already, it is based on the fact that Delphi would release interfaces automatically when they go out of scope.

    The guards were handy but my “Delphi hands” would always type the try…finally…end block automagically, so finally I gave up using guards 🙂

    • March 24, 2011 at 10:01 pm

      Sorry I miss understanding your komeng. What actually that mean? The TSafeMe approach doesn’t meet your habbit? Or JCL’s Guards won’t works as you expected? You know, try-finally mostly heavy used like above case, we also could create TSafeMePtr for dynamic memory alloc version.

  8. jrp
    March 24, 2011 at 10:43 pm

    Yes Mr. D.E, it is just a matter of habit. Both TSafeMe & JCL’s guard are good and practical. It is just my habit to type try…finally…end and forget that I should have been using guards instead.

    Like the abang sate that was being hit by a car then told to “nyebut”, but he said “Te…sate…” because that was what he had always remembered 😀

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: