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.
Advertisement
No comment… yet? :-”
Wonderfull. Please let me know? how the magic can happen?
I do care your though… lets me know your way first.
Try this try this… please solve the puzzle :-”
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
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
Show me your best design for easy use and keep it simplicity
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…)
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
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.
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
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
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.
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
LOL… I see