Jump to content


Popular Content

Showing content with the highest reputation since 03/19/19 in Posts

  1. 12 points
    Guys, while pulling updates from a remote repo is part of git (e.g. git pull from the command line for example), a "pull request" is not something intrinsically part of git, but something that github institutes, or that we agree between ourselves as developers. It literally is saying to someone else "Please {git} pull from me as I've got something you might want to review/use." It follows that in order for someone else to "pull" changes from you, that you must have some accessible place for them to pull from. Obviously users on the internet won't have access to your local repo on your developer PC, so they cannot pull from there. Nor would you normally be able to push to their repo (or their github repo) if that is where you originally pulled from (unless you're one of the project administrators/owners of course.) There therefore needs to some other repo, that must belong to you and is accessible so that someone else can pull from, that you can also first push to. (Just like there needs to be a shared SVN server, say, if you want another dev to get some changes you've made and are using subversion.) And this is where github comes in. It provides an easy to access place where you can fork and create your own remote repositories (from others) that are therefore just as easily accessible by others too. All that background is to help you understand the following: The normal process for working on github, if you want to contribute changes, is to 1.) Fork the repo of the project you want to contribute to in your github account. This creates a cheap remote repo (think "my own SVN server at github" if that helps) that belongs to you, than you can push to. 2.) Clone this fork (your own copy of this github repo) to your local PC. 3.) Do your work, commit locally. Once totally happy, git push, which obviously goes to your own remote repo (from the fork.) 4.) Now you're a few revisions ahead of the original repo, and you can then tell the original upstream repo maintainers that you'd like them to pull from your repo as you've got changes to fix some issue or whatever. In github, you do this by simply clicking "New Pull request" button in github. Hope that helps! Edit: By the by, if you've previously pulled from someone else's project directly, made some changes and now want to push this somewhere else, it's quite easy to fork the project "after the fact" and then tell git/update that "remote"/"upstream" is now else, to e.g "push" to your fork instead. (It's also possible to have multiple remotes if you want, but I digress...)
  2. 7 points
    There are a few things that every single one of our internal programs should do: Every dialog should be sizeable if it makes any sense at all. Delphi makes that easy with the Align and Anchor properties. Ask yourself the following questions. If you answer any of them with Yes, ... https://blog.dummzeuch.de/2019/04/03/things-that-every-desktop-program-should-do/
  3. 7 points
    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
  4. 7 points
    Having worked in Delphi since D1, and twice having had to deal with the issue of components without source, I would say that the value without source is essentially zero, as the risk factor is not worth any benefits in the short term. So I would suggest that the question as you ask it is simply wrong.
  5. 5 points
    Not only IT-designers. It's designers <period>. Show me an unusable product and in 90% it will turn out that it was perfectly usable when the engineers finished. And then the designers ruined it. There used to be a credo "form follows function", but today it's "it doesn't matter whether it works, let's make it flashy." </rant>
  6. 5 points
    Just in time before April fools day 2019 there is the new GExperts release (it’s still 2019-03-30 so you are safe 😉 ). Please be aware that I mostly work with Delphi 2007, so this version can be regarded as tested quite well, followed by Delphi XE2. The others are only known to compile and new features are usually tested superficially with all versions. This is particularly true for Delphi 6/7 and 2005/2006. If you want to help by testing new versions before I release them, please contact me [...] https://blog.dummzeuch.de/2019/03/30/gexperts-1-3-13-experimental-twm-2019-03-30-released/
  7. 5 points
    There is a bit more to it than simply following a mantra - here is some more food for thought: https://www.thoughtworks.com/de/insights/blog/composition-vs-inheritance-how-choose
  8. 5 points
    I think you found all options. There are no others. I would Kick the person who bought this component without source. (Who was / is an idiot, nobody did that even back when Delphi 7 was new.) Suggest not updating to Delphi 10.3 but 10.2 (which will be rejected) Go with the DLL solution.
  9. 5 points
    In some piece of code somewhere, a pointer was set to $DEADBEEF, most likely after the object it was pointing to had been freed, and then that same pointer was used afterwards by code running at address $0040CEEC trying to access a data member at offset -8 ($DEADBEE7) via that pointer. Magic addresses like $DEADBEEF are commonly used for debugging such mistakes. In this case, the code at address $0040CEEC is the System._UStrAsg() function, which is used to assign a UnicodeString to another UnicodeString. Offset -8 is the StrRec.refCount field in the UnicodeString data header, which makes sense as UStrAsg() does increment that field. In other words, some piece of code tried to assign a UnicodeString value to a dead UnicodeString variable. UStrAsg() was called by TFieldValue.SetValue(), so SetValue() was likely called on an invalid TFieldValue object inside of TGridSet.CopyRow(), which was called by TDeliverySet.UpdateFromDeliverySet() inside of TDeliveryGrid.RefreshByRouteList(). So, start in RefreshByRouteList() and work your way into UpdateFromDeliverySet() and try to figure out how it may be accessing an invalid TFieldValue object. The Operation System, when the invalid memory address $DEADBEE7 is accessed. Delphi's RTL catches that error from the OS, creates an EAccessViolation object for it, and then raises it.
  10. 4 points
    Pretty bad reasoning. If it's for paid customers only, then there's no security in case Emba go bust. "Because we love Delphi more than you do." How to win friends and influence people.
  11. 4 points
    I so so agree with "In terms of UX, copying into clipboard should be taken into account." and the image. This used to work very good back when. Then - enters the designers. If it isn't Win10 native messing something up it's skins. DevExpress even have some skins that show a gray-box for readonly and some skins that do not and they refuse for years to do anything about it because it was "the vision of the designer". Such important functionality. If corrupt legislation and greed won't kill IT, designers will.
  12. 4 points
    Well, then you went down the wrong rabbit hole, and you need to start climbing your way out of it. Such as? You really need to stop using ProcessMessages(), and start using proper code designs. Even if you don't want to use timers/threads, there is always TThread.ForceQueue(), for instance. Anything that allows code flow to return to the main UI message loop naturally will be better than manually pumping the message queue artificially. Then file a bug report with Embarcadero. But don't litter your code with ProcessMessages() calls just to satisfy the framework. Find other alternatives. Stay away from ProcessMessages() whenever possible. That was true even in the old days of the VCL. More so now in the days of FMX on mobile.
  13. 4 points
    There is a possibility, but it would be difficult to apply that behavior on any TDateTime field to be converted, which could as well be a pretty unwanted side effect. Instead you can put an attribute to each field being treated this way. What you need here are two classes (well, one would do, but the second one simplifies things a lot). The first one is the interceptor: type TSuppressZeroDateInterceptor = class(TJSONInterceptor) public function StringConverter(Data: TObject; Field: string): string; override; procedure StringReverter(Data: TObject; Field: string; Arg: string); override; end; function TSuppressZeroDateInterceptor.StringConverter(Data: TObject; Field: string): string; var ctx: TRTTIContext; date: TDateTime; begin date := ctx.GetType(Data.ClassType).GetField(Field).GetValue(Data).AsType<TDateTime>; if date = 0 then begin result := EmptyStr; end else begin result := DateToISO8601(date, True); end; end; procedure TSuppressZeroDateInterceptor.StringReverter(Data: TObject; Field, Arg: string); var ctx: TRTTIContext; date: TDateTime; begin if Arg.IsEmpty then begin date := 0; end else begin date := ISO8601ToDate(Arg, True); end; ctx.GetType(Data.ClassType).GetField(Field).SetValue(Data, date); end; The second one is a special attribute: type SuppressZeroAttribute = class(JsonReflectAttribute) public constructor Create; end; constructor SuppressZeroAttribute.Create; begin inherited Create(ctString, rtString, TSuppressZeroDateInterceptor); end; Now you can decorate your class fields like this: type TDateClass = class private [SuppressZero] FHasDate: TDateTime; [SuppressZero] FNoDate: TDateTime; public constructor Create; property HasDate: TDateTime read FHasDate write FHasDate; property NoDate: TDateTime read FNoDate write FNoDate; end; As I mentioned earlier, you can omit the new attribute and use the JsonReflectAttribute directly, but that is a bit cumbersome: type TDateClass = class private [JsonReflect(ctString, rtString, TSuppressZeroDateInterceptor)] FHasDate: TDateTime; [JsonReflect(ctString, rtString, TSuppressZeroDateInterceptor)] FNoDate: TDateTime; public constructor Create; property HasDate: TDateTime read FHasDate write FHasDate; property NoDate: TDateTime read FNoDate write FNoDate; end;
  14. 4 points
    Not natively using [weak] attribute. You can only make a record with a [weak] IFoo field and put that into the array.
  15. 3 points
    <sigh> I keep reading that, especially from Delphites, but ISTM that many totally misunderstood "program to the interface". Interfaces (no matter if they are actual language constructs or abstract classes) are fine and have their use, but like with everything, one can overdo it. Not everything is or should be an interface. The author of the article you link to seems to be one of those dependency injection, "interface only" gurus. ISTM that all these techniques should be part of a larger toolbox, not just a toolbox with lots of nails and a few hammers. I am not even sure if the VCL would have been better with interfaces, if they had been available. And the claim "composition is better than inheritance" is just as wrong. Both have their place, and which one should be preferred depends on the situation.
  16. 3 points
    IDE tooling does not work properly and some of it completely stops, Also inline variables of a managed type are not always properly initialized. As much as I like this feature syntax wise - I would stay away from it for now 😞
  17. 3 points
    Interfaces don't have implementation, so if you want to reuse code you either have to use class inheritance or you must use composition. IS-A and HAS-A rule can help you determine whether inheritance makes sense in a first place. If IS-A rule is satisfied, then you have to see whether in that particular case you should use class inheritance or composition. When it comes to creating God objects, they break other OO principles. Composition is preferred - problem with that approach and your original question "Prefer composition over inheritance for code reuse?" is that people tend to interpret it like NEVER use inheritance. And then they go down the different rabbit hole.
  18. 3 points
    I have done an intensive debug session and found the issue although I don't understand why it works with older Delphi versions. At line 2710, where the server hang, we have the code: Result := GetOverlappedResult(FPipe, FOlapRead, FRcvRead, TRUE); I simply changed the last argument by FALSE like this: Result := GetOverlappedResult(FPipe, FOlapRead, FRcvRead, FALSE); And now it works! That last argument when TRUE tells GetOverlappedResult to wait until completion. If FALSE, it returns immediately with whatever data is available, setting FRcvRead variable with actual number of bytes read. Since we only go to that code line when data is available, because of WaitForMultipleObjects called at line 2939, we can safely don't wait for more data. I will do more testing with the actual - real world - application using that code. In case the issue persist, I will report it here. Thanks to all having participated in this conversation. -- François Piette Embarcadero MVP
  19. 3 points
    This issue was fixed now, and a new version was released today. Once again, thank you for showing me this error.
  20. 3 points
    I ended up using the following code: constructor Tf_MyForm.Create(_Owner: TComponent); begin inherited; WindowState := wsMinimized; ShowWindow(Handle, SW_SHOWNOACTIVATE); end; So far it seems to work fine.
  21. 3 points
    No chance! It is difficult enough for MMX to adhere to its own settings and in some cases MMX even tries to adhere to the IDE settings. Why should I take the burden to look after some settings from any other 3rd party tool, especially one that I don't use by myself nor am planning to do so? What if several plugins offer such a functionality, which one to prefer? What if none of these is installed at all? Should MMX provide a similar setting for its own?
  22. 3 points
    Correct - it seems to be EurekaLog (see point 3. "When memory is released": https://www.eurekalog.com/help/eurekalog/index.php?memory_leaks_page.php) I would say its that a destroyed TFieldValue was not removed from the list inside the TGridSet - so locate where those are destroyed and check if they are properly removed from that list when in it.
  23. 3 points
    The best open source Delphi parser I know is DelphiAST. It is the foundation https://www.tmssoftware.com/site/fixinsight.asp which catches way more code issues than the Delphi compiler itself does. DelphiAST gets you an abstract syntax tree. Code is at https://github.com/RomanYankovsky/DelphiAST
  24. 3 points
    Funny that you bring up that DevExpress change - I remember upgrading our software and it was a non-issue. And in fact the "what's new" for that version explains exactly what to do. Not saying any of us is right or wrong but you can see that something is a huge issue for one and none for another. Yes, there is always some bad code that did not follow best practices or did not properly encapsulate something, leak an implementation detail or does something else making it a chore to move forward. But that is exactly why I wrote what I wrote 2 posts ago. You can always come up with an excuse (valid or not) to damn some breaking change. However sometimes you have to take the bitter pill to move forward painlessly either yourself or the library/framework developer that decided for such a change. I for example will introduce quite some breaking changes for the next version of Spring4D and I experienced them myself when migrating a branch of our software to an early version and experienced all the required work. I even reverted some change because I saw that it was rather painful to find all the places and convert them easily. That means as a developer of a component/library/framework you should use that yourself in more than a toy project to get a feeling what consequences possible changes have to evaluate if they should be taken or not. And it then is an important responsibility to document them and if necessary provide some tooling to migrate your code - I remember more than 10 years ago when moving from QuantumGrid 3 to 4 (I think) DevExpress provided a tool to convert all your code for that heavy breaking changes that came with that version change. If they would not have done that, I guess no existing customer would have done it - however I cannot tell about the problems that still existed, I joined the company when the change was done already.
  25. 3 points
    Good thing you're not in charge of the RTL then. IRL backward compatibility matters.