Jump to content

Dalija Prasnikar

Members
  • Content Count

    1067
  • Joined

  • Last visited

  • Days Won

    91

Posts posted by Dalija Prasnikar


  1. 45 minutes ago, edwinyzh said:

    @Dalija Prasnikar Thanks for sharing.

    Correct, it depends on the specific situation, I agree with you, except that I somehow think the 3 things you mentioned - delegation, composition and aggregation are the same thing.

    Not exactly... there are slight differences in behavior. Not that this part matters when you are choosing between inheritance and composition (as general term)


  2. It always depends on particular situation. Both composition and inheritance have their place. Sometimes you can use either, sometimes there is a clear distinction.

     

    Some tips that can help you decide.

     

    • IS-A - inheritance - Sword IS-A Weapon so Sword should inherit Weapon
    • HAS-A - composition or aggregation - Unit HAS-A Weapon so Unit can be composed with Weapon object

     

    With simple classes that satisfy IS-A condition plain inheritance will do. With more complex classes, you may want to use composition or delegate some behavior to other classes, especially if that behavior can be reused independently. 

     

    • Delegation - delegate behavior to another class when it is not an objects responsibility to implement behavior on its own
    • Composition - when object is gone the composed objects are also gone - when Pizza is gone so are the ingredients
    • Aggregation - class is used as a part of another class, but still exists outside that other class - when Unit dies Weapon still exists
    • Like 8

  3. That change was not worth while even back then. You had two variants for Seek and it was very easy to use wrong one. If you used 32 bit one on streams that support 64 bit your code would only work for streams smaller than 2GB. 

    Change didn't affected older code, but it had permanent negative effect on new code.

     

    I encountered such bugs myself, and also have seen others bumping into it on numerous occasions. Yes, at the end our code was at fault, but it was really easy mistake to make. 

     

    There was several bug reports around that issue at the time in old Quality Central. 

    • Like 1

  4. 33 minutes ago, Anders Melander said:

    Good thing you're not in charge of the RTL then.

    IRL backward compatibility matters.

    YES, backward compatibility matters. But in cases where backward compatibility causes more trouble down the road, then it is not worth the price.

     

    In this case, maintaining backward compatibility also opened TStream and descendant classes to subtle bugs when working with streams larger than 2GB. 

    • Like 3
    • Thanks 1

  5. 29 minutes ago, ByteJuggler said:
    • As a digression, I've also found (irritatingly) that out of the 2 phones I have available, debugging also doesn't work on the newer one (Note 8 ) because of "reasons" (something Google changed supposedly and Emba therefore says they won't fix), while it does work on the older phone (note 4).

    If your Note 8 has Oreo 8.0 OS then debugging does not work because Google screwed up on OS level. You need to update OS to 8.1 that fixes the issue. It was not something EMBT could fix.

     

    http://blog.marcocantu.com/blog/2017-december-delphi-android81-debugging.html

    • Like 1

  6. 9 minutes ago, Sherlock said:

    I really don't get the whole theming bull anyway. I set my windows to look exactly the way I want it, and along comes some wannabe designer and imposes his take on what a GUI should look like. Most of the time it's just hilarious, but whe I have to work with a tool (yes a tool) I want it to be as unobtrusive as possible and just do it's thing. If i want glitter on a hammer I will buy glitter an stick it on there myself. Don't expect everyone to like glitter an a hammer. Jeeeez!

     

    </Rant>

    To some extent theming has a purpose because without it you could not have dark theme. Problem here is that Delphi (VCL Styles) based theming is just horrible since day one (even before it was introduced in IDE). 

     

    Instead of VCL Styles being fixed and then used at large, EMBT choose to use VCL Styles without fixing issues. Another problem is not that just in theming itself, but revamping Options dialog layouts without making proper alignment/size adjustments - so everything visually just falls apart.

    • Like 6

  7. 21 minutes ago, Primož Gabrijelčič said:

    As Stefan noted on a side-channel, calling MakeFib causes a memory leak because the anonfunc interface now contains a cyclic reference to itself.

    var
      [weak] fib: TFunc<integer,int64>;

    Marking it as weak breaks the cycle. However, there was a bug with weak that is only recently fixed (not sure whether in 10.3 or 10.3.1)

    • Like 4
    • Thanks 1

  8. If only making good examples would be so simple.... it is so much easier to trash other people's examples...

     

    Joking aside... bad examples (or ambiguous examples) can make more damage than good. OOP is complex matter and not always straightforward. Ask 100 experts about it and you will get 100 different answers. 

     

    My rule of thumb is learn about OOP, design patterns, testing and then apply common sense over it. If some rules collide, then apply KISS (Keep it simple, stupid)  and YAGNI (You aren't gonna need it) and DRY (Don't repeat yourself) before any other principles. If it seems too convoluted or you don't have clear understanding why... better don't use it than use it in a wrong way. That does not mean people should not strive to learning and understanding better practices.

     

    In that context, primary goal of encapsulation is protecting implementation details that can change to avoid subsequent changes in consumer code. 

     

    When you write your own classes you are the boss, you can decide what is implementation detail and what is not. Of course, you have to be careful about those decisions because you will have to live with them for a long time. When you consume other people's classes you must avoid using things that are not part of public API. Since it is not always possible to hide all implementation details, it is possible that not everything that is publicly accessible is really part of documented public API. Unless public API is clearly documented, sometimes it can be hard to know what is implementation detail, and what is not. Experience can help, but it is hard to give any good general tips on the matter - it all depends on the actual code. And this is where original question came from - what is implementation detail in some code and why is better to use some construct comparing to another. 

     

    Another thing to keep in mind is that OOP depend on the language. What fits in one, does not fit well in another. In Java encapsulation means having geter and setter methods for everything accessible - because Java does not have properties. If you expose field directly any changes in access logic that has to go through geter or setter will require changes in consumer code - because Java expects parens () when you access method.

     

    In Delphi you might as well start with directly exposed field... changing that into property will not change consumer code (unless you add read or write restrictions) and adding geter or setter methods will also have no direct impact on consumer code. Of course, most Delphi developers will use properties instead of directly exposing fields, but this is more of common practice than actual requirement for fields that will be publicly accessible - part of the public API.

     

    I could probably go on for days... but I have other things to do... 🙂 

    • Thanks 1

  9. 3 hours ago, David Schwartz said:

    This guy is asking about basic concepts of encapsulation and you guys are going off the rails trying to explain the historical evolution of the bit arrangements of strings from early 1990's through today in TurboPascal -> 16-bit Delphi -> 32-bit Delphi -> Unicode Delphi, and using that to imply that the entire concept of encapsulation is bogus and can never be trusted.... never mind the fact that this 2019 and newbies are probably only using the latest (Unicode) versions of Delphi (and certainly not some old version of TP or 16-bit Delphi, but maybe a pre-Unicode version of Delphi).

     

    So when you teach OOP to beginners now, do you say it's only about inheritance and polymorphism ... before you proceed to shred those concepts as well?

     

    Or do you tell people not to use properties or Interfaces because technically speaking they cannot be trusted to last for 30 years since they don't anticipate language and platform changes accurately?

    Sorry, but you started going off rails saying that you should not use fabc.ToString for displaying integer value as text, thus blowing the whole encapsulation and hiding the implementation thing out of proportion.

     

    Now, it is possible that you just used poor example and that you actually tried to say something completely different. 

     

    I am not trying to shred concepts to pieces, I am just trying to show their usage must be balanced. Abusing the concepts to the point of absurdity is as bad as not using them at all. What better example to show how not everything can be absolutely hidden and protected than to show that strings itself are leaking their implementation details. 

    • Like 1

  10. 1 minute ago, Bill Meyer said:

    No.

     

    It was not about leaking strings, rather Delphi strings leaking their implementation details like character size, encoding... Think about going from TP fixed size string implementation to pre-Unicode Delphi string implementation to Unicode Delphi string implementation.

     

    I remember writing about it, but don't remember where... 


  11. 1 hour ago, David Schwartz said:

    The function hides the implementation. 

    Not all of it. It only hides the integer, but it does not hide how you implemented conversion from integer to string. Also, string type itself leaks its implementation details in Delphi all over the place. 

     

    You are going extra mile to hide just about everything - without real reasons. Point is, no matter how far you go, you can never hide all implementation details. In one way or another they will leak.

     

    It is perfectly acceptable to have integer function or property as part of well defined public API.  The whole point of hiding implementation details, and not using them is that by doing so, you can change implementation without changing the public interface and without need to change all the code that relies upon it. That is the purpose of having well defined public API.

     

    Hiding inner collection implementation (so you can easily replace plain array with list or some other structure) or some other more complex data is one thing, but hiding basic type like integer is going over the top without actually accomplishing anything.

     

    One of the problems when it comes to following good practices like testing, proper OOP design... is that quite often those practices are explained and taught by going into extremes, making them overly complicated and losing original intent - making better, more maintainable code, with less bugs. That blowing things out of proportion, not only makes it harder to understand basic principles behind those practices but it also makes many developers just to drop the whole thing and not use any. It is hard to blame them when they see no point.

    • Like 2

  12. 9 hours ago, Silver Black said:

    Nobody talks about any improvements...

    IDE no longer flickers when you compile/build 😃

     

    Probably the most important fixes and improvements are in iOS platform - including fix for compiling/linking 3rd party libraries against iOS 12 SDK. 

     

    And then there is a bunch of bug fixes in other areas. So plenty of improvements, just not big ones. Or depends how you look at it, if your code was affected, then even single small fix can be great improvement.

    • Like 2

  13. On 2/9/2019 at 7:48 AM, Lars Fosdal said:

    Which is why my post specifically pointed out that there is a link to the SCCE in the blog post?

    To be honest, knowing the type of Handler.OnHandle is crucial for understanding the issue. The other implementation details don't matter as much. 

    Broker.AddHandler(Handler.OnHandle);

    And usually I don't go around and download code examples, just to get to the bottom of some problem. Only under special circumstances - mostly from bugs reported in QP, when having complete test project is crucial for reproducing the issue.

    The only reason, why I did go and download this example is because I know you. 

    So whether you like it or not, David does have a point.

    • Like 4

  14. 31 minutes ago, Uwe Raabe said:

    I imagine what is happening and I assume it to be expected behavior, although I admit one has to know how variable capturing works to get it. It is even documented (Variable Binding Mechanism)

     

    There is still a lot of guessing about what is THandlerClass, OnHandle and how AddHandler is defined and what it does with its parameter, so it is difficult to give a detailed analysis.

     

    You are on right track.

     

    What happens is something like this:

     

    procedure TTest.ConfigLoop;
    var
      Handler: THandlerClass;
      hType: THandlers;
      hRef: TOnHandle;
    begin
      Writeln;
      Writeln('--- ConfigLoop');
      Broker.Clear;
    
      for hType in [foo, bar]
      do begin
        case hType of
          foo: Handler := TFoo.Create;
          bar: Handler := TBar.Create;
          // wtf: ;
        end;
        hRef := Handler.OnHandle;
        // Capture does no discern between the foo instance and the bar instance
        Broker.AddHandler(hRef);
      end;
    end;

     

    and then this bridging assignment from plain method to anonymous method is expanded to

     

    hRef := 
      procedure
      begin
        Handler.OnHandle();
      end;

    Where before mentioned rules about capturing references (variables) and not values apply.

     

    • Like 1

  15. 1 hour ago, Hans♫ said:

    Thank you for your persistence Dalija. I have a heart for Delphi too, and I somewhat regret that I posted the image, because I still have no proof if it is our code or Delphi code that fails.
    With the graph I am basically bashing 10.3 RIO because I am tired of its quality.

     

    Our database access uses exactly the same code on Windows, Mac and iOS. No crashes detected or reported on Windows and Mac.
    But as you said, iOS is just waiting for a reason to take your app out. It is a lot more strict on everything.
     

    I understand how you feel. Sometimes it is going two steps forward three steps backward.

     

    One of the problems with cross-platform development is that not all code is the same. And different principles apply. OS architectures are different and what you can do on one platform, you cannot do on another. I am talking generally, regardless of whether offending code is yours or Embarcadero's.

    Also mobile platforms change frequently and are also changing rules and behaviors. What worked today, may break tomorrow.

     

    This is not related just to Delphi applications but all. I am using Xcode - Swift and Android Studio - Java for mobile development and situation is not much different. The only difference, is that when some policy or behavior changes, you immediately have appropriate tools to implement change. But your code will be broken left and right. You cannot take year old code and make simple recompile - in Swift everything is in a state of flux - language, frameworks, so every time you touch it, it is almost a rewrite. I don't even know what is the proper method for sorting list - its name changed dozen times - from sort to sorted to sort again... what is current one I have no idea - and that is just the simplest example. On Android, Java is the same, but frameworks are changing every week. If you have to support newer versions of OS, you have to use newer frameworks, that also change all the time, are buggy as hell... 

     

    I know Delphi could and should be better. But, I also painfully know that grass is not greener on the other side.  What we can do, is relentlessly report issues to Embarcadero. Not all will be fixed and not all will be fixed as fast as we would like, but Embarcadero is fixing them. Especially, more critical ones.

     

    • Like 1

  16. 6 hours ago, Hans♫ said:

    I investigated all recent crash reports delivered to XCode for the app. The majority of the crashes contains a reference to a sqlite file in our app and "Code 0xdead10cc", which means "terminated by the OS because it held on to a file lock or sqlite database lock during suspension"

     

    The positive news is that the user will not discover the crash because it happens when it enters suspension state anyway.

     

    Quick search through Quality Portal didn't reveal any reported issue similar to yours. Can you please file QP report. 

×