Jump to content

Dalija Prasnikar

Members
  • Content Count

    1062
  • Joined

  • Last visited

  • Days Won

    91

Everything posted by Dalija Prasnikar

  1. Dalija Prasnikar

    Using uninitialized object works on Win32, throws AV on Win64

    Easier said than done.
  2. Dalija Prasnikar

    Using uninitialized object works on Win32, throws AV on Win64

    But, Delphi out parameters have some unpleasantries and many developers choose to use var instead. https://delphisorcery.blogspot.com/2021/04/out-parameters-are-just-bad-var.html
  3. Dalija Prasnikar

    Using uninitialized object works on Win32, throws AV on Win64

    Yes, you were lucky. Uninitialized variable will contain whatever was previously written at that location. If you were lucky enough that value is zero, broken code would work. Yes, there is a compiler difference one is 32bit compiler another is 64bit one. Pointer sizes are different. Memory layout will be different. But, different compiler is besides the point. Working with uninitialized variables is undefined behavior. That means anything can happen even with the same compiler.
  4. TMessage from System.Messaging? System.Messaging is not thread-safe so you cannot use it for anything thread related.
  5. Different languages have different set of features and also differ in implementations of those features. Properties in general are a tool that provides additional level of abstraction around encapsulation and enables future implementation changes while preserving stable public API. Some of the benefits are more visible in some languages than the others. For instance, if you have public field Name and you want to add some code around retrieving that field is easy to do in Delphi. You can rename field and move it to private section and declare public function Name to retrieve it. I Java, you cannot do such thing because calling method must include brackets. This requires refactoring all code that uses such field. If you want to add setter, you will break the code in any language. This is where using properties helps with encapsulation. They hide unnecessary implementation details and give implementing class to ability to change those without breaking user code. You can start with simple field backed property, which from performance aspect is no different than public field and you can add getters and setters as needed without breaking code. Without properties, you can also maintain stable API, but the cost is having getters and setters for everything and paying the price in performance. No matter how small it is, eventually it can add up. Additionally, code with simple assignment is easier to read than setter method. There are some parts of general properties functionality that Delphi does not implement, like different access levels for reading and writing, or some additional ceremony when declaring properties, especially in interfaces. Some of those could be improved to make properties more flexible, but lacking them is poor argument against using properties. In situations where you really need some functionality properties don't provide, you can use other ways to achieve what you need, but not using properties everywhere else because you cannot do something in rare occasions is also not very convincing argument. Arguments around name refactoring are not very convincing either. They compare name refactoring, where there is a bit more renaming in declaration. Now, compare that single place where you need to make additional rename, to refactoring all code in case where you need to replace public fields with accessor methods. When it comes to extra declaration code needed for properties with accessor methods comparing to only having accessor methods, think how much unnecessary getters and setter methods you need to write in cases where you could use field backed property declaration. Overall using properties results with cleaner code and having more functionality than you can have with simple fields or just accessor methods. The little bit of ceremony around the declaration is price I am more than willing to pay, to get all other benefits.
  6. Dalija Prasnikar

    Class methods Polyformism

    You cannot use property. The only thing you can do is removing property and static getter and renaming virtual getter function to id.
  7. Dalija Prasnikar

    Class methods Polyformism

    procedure TForm2.Button1Click(Sender: TObject); begin Edit1.Text := inttostr(TChild.id) { <= Calling the Child's property} end; When you use the above call, TChild.id calls static GetMasterID method. Because that method is static it does not have Self parameter passed, which in context of class methods represents class itself. So when you are inside GetMasterID method, compiler no longer knows from which class you have called that method. It only knows the class where the method is implemented, in this case TMaster. And calling GetChildID will be interpreted as calling TMaster.GetChildID. If you remove abstract on TMaster.GetChildID and implement that function as regular virtual method, which returns different integer than TChild.GetChildID you will no longer have abstract exception, but you will get wrong results.
  8. Dalija Prasnikar

    Which option to use for a large batch of REST queries?

    Testing is one things, calling something that serves no purpose is another. If the system is over stressed then pumping messages from UpdateLV will not make it run any faster. If the system is not stressed it will pump messages even without you forcing it, literally as soon as you exit UpdateLV method. If you have too many items on list view and UpdateLV is killing your overal performance, then you should modify that logic and instead of updating the whole list all the time update only item that is modified. Yes, you could see some differences in behavior with Application.ProcessMessages, but none that really matter. Just remove those.
  9. Dalija Prasnikar

    Which option to use for a large batch of REST queries?

    Why? It serves no purpose whatsoever. I am not familiar with OTL enough to comment other code.
  10. Can you please translate your logic to English. It is extremely hard to follow what you are doing. Especially, since TTask.Run code is basically empty and it requires way more context.
  11. Dalija Prasnikar

    Delphi profiler

    Understandable. I would do the same. GPX format is ideal for SAX parser. Avoiding allocations of thousands of XML nodes would be my best bet for optimization.
  12. Dalija Prasnikar

    Delphi profiler

    Unrelated to the profiling, there are other optimizations. First, SAX parsing is generally more performant than DOM parsing, especially when DOM is based on interfaces. If you don't need XML DOM, then building your business classes directly during parsing will be more efficient. But not all structures cane be equally easy parsed by SAX. Next, IXmlDoc works on top of standard IDOM interfaces, so you have additional slowdown there. If you cannot use SAX, modifying code to work directly with IDOM interfaces might be a solution. Or using different DOM parser.
  13. Dalija Prasnikar

    Delphi profiler

    Sampling profiler will give you better insight. https://www.delphitools.info/samplingprofiler/
  14. Dalija Prasnikar

    Interface question

    I cannot say whether something in logs changed, but as far as I can remember FastMM works in Sidney the same way it worked before. I don't have the Tokyo installed for comparison. And it shows the stack trace correctly so I can follow to the line where issue happened. Yes, I know that in more complex code it can be harder to figure out real culprit, but that has always been the case.
  15. Dalija Prasnikar

    Interface question

    Would you elaborate that? Memory manager works fine in Sydney and detects memory leaks.
  16. I am talking about your comment to @Wagner Landgraf where he mentioned memory management and you are saying this thread is not about memory management. I am not trying to prove anything, just wanted to say that memory management is indirectly involved in this conversation, and Wagner didn't post in the wrong thread.
  17. The way I am reading that is: if you pass parameters in constructor to initialize fields and you validate them there, raising exception if they are not valid, then you can avoid checking those fields when you are using them in other places because you know they cannot hold invalid values.
  18. try...finally implies cleanup which in Delphi terms implies memory management Maybe memory management is not main topic, but it is certainly related.
  19. Depends on the context. If you open some file for processing and it turns out to be a too large so processing it raises out of memory, you just clean up and tell to the user: "Sorry, your file is too large and you don't have enough memory." But after proper cleanup your application will be in fine condition to process some other smaller file. On the other hand, there are situations where out of memory is not recoverable. You still may be able to show message to the user there is not enough memory, but you will just have to kill the application after that.
  20. If you want to handle the exception on site, then the second option is the wrong way to do it for several reasons. Construction of an object can always fail because of OutOfMemory, so if you wanted to handle all exceptions at that point you have failed to do so. If you are fine to bubble up that exception further on and if except part (handling the exception) cannot raise exceptions, you don't need try..finally at all.
  21. You tell me. It doesn't feel bad to me at all I think you are overcomplicating. If you have class that requires some setup (that will commonly not be changed once object is created) to function properly then passing those parameters through constructor and raising exception in constructor is the best and simplest thing to do. Use the approach that requires the least amount of code for safely using such class and where you cannot easily forget to do something vital. Usually that will be the best code.
  22. Actual purpose of try...finally in above code is to ensure cleanup of the MyThing instance if MyThing.DoIt raises exception. If constructor raises the exception there will be automatic cleanup and MyThing.Free will never be, nor it should be called.
  23. No, you don't. If the instance is never constructed it will be nil in the destructor and you can just call Free on such instance. You only need to consider that any instance in the destructor can be nil, so if you are calling any other methods you need to check for nil before calling those in destructor.
  24. Nobody said that you must validate in the constructor. It all depends whether this is critical or not and at which point. There are no wrong or right answers here, it all depends how class functionality and how it is used. Each approach has downsides and upsides.
×