-
Content Count
1237 -
Joined
-
Last visited
-
Days Won
25
Everything posted by David Schwartz
-
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
Aside from that, did you get anything from reading the post? (I don't have a compiler in my head, and I figured if I didn't show the declarations then someone would ding me on that.) -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
This should definitely be available in Delphi. Maybe in 5 years? -
Perhaps I'm beating a dead horse here, but I'm going to go out on a limb and guess you're fairly new to the programming game, based on this statement. Please allow me to fill in some blanks for you. An "INI file" has a particular structure to it, and it's not dependent on the filename or its extension. Whomever wrote your code originally decided to use the INI file format to store the data, and also decided to use a .cfg extension on the filename. These are totally arbitrary choices. Back when INI files were first used, they did all tend to have .ini file extensions, but it's unnecessary. DOS introduced the use of "standard" file extensions and INI files were one such standard usage. Windows followed suit, as it as built on top of DOS. (CP/M probably also used INI files.) Today, most people would choose a JSON file structure for a config file format. It would NOT be named .json nor .ini, but .cfg could very well be used. Linux employs a LOT of config files, and they may be .config (NOT 'xyz.config' but just .config), xyz.conf, or even xyz.cf. Some are in a loose INI format, some are CSV, some are JSON, and many are whatever format the author decided to use. My point here is that you're thinking that a "configuration file" is always going to use some standard format -- that's simply not the case. There's no standard way to interpret a file with a .cfg extension. But most files with a .ini extension are very likely to use the INI file format. Putting JSON data in a file with a .ini extension would be deceptive. And I'd say most files that contain JSON data do not use a .json file extension; it's just not a common practice. (When DOS came along, file extensions were not used very much in other environments other than as 'hints' of sorts. But DOS used them to make it easier to know what a given file contained. So a .INI file always employed an INI file format; likewise, files with .txt, .doc, .ws, .wp, .obj, .lib, .exe, .com, and other extensions all had the same types of contents and could be opened with a specific tool. But .tmp is one that's used for any kind of temporary file, regardless of what the format of data in them might be.) Linux does not make any assumptions about what format the data in a file might be based on given its file extension. Mac is based on Unix, and does not care either. On the other hand, Windows itself does. People who write apps with Delphi ... not always. So use the file extension as a guide towards what the internal file format might be, but don't bet your life on it.
-
Sorry, you're quite confused here. On the TPageControl / TRzPageControl, the "pages" are TTabSheet types. They are NOT TPanel types. That's why TTabSheet.Enabled turns the tabs on and off -- it's to hide/show the TABSHEET (including its TAB). Not what's on it. You can drop a TPanel / TRzPanel on a tabsheet and then set it's Enabled property to get the desired effect without all the other rigamarole. Be sure to set the panel's Alignment to Client so it fill the entire tabsheet. Iterating over a TPageControl / TRzPageControl lets you access the Pages array property, which is an array of TTabSheet. I don't think that's what you want. From a more global perspective, there are typically two or three different forms I recommend for handling CRUD actions on DB records: one is for entering NEW record data; one is for VIEWING / EDITING an existing record's data; and a third one is to confirm DELETING a record. I won't go into detail here as to why, but after you've dealt with this a few hundred times, you'll understand why. Yes, you can only use ONE form, but the amount of logic needed to handle all three cases can get crazy. (If you just need to work with one single record, then you can do all of the CRUD stuff on one form. But when you introduce computed fields, lookup fields, child records listed on the form, and other common stuff, you will quickly find yourself going nuts trying to get everything to work on one single form for all possible cases. For me, it's easier to just make two or three distinct forms. The Delete can be a simple confirmation dialog. And record viewing / retrieval can be done with the Edit form, just make the fields read-only for viewing and enable them for editing when the user enables Edit mode.)
-
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
This is an interesting example. Off-by-one errors are extremely common, especially when you first start programming. Over time, you learn to prevent them. Considering Delphi: Given this declaration: var ary[10] : char; str[10] : string; One might be tempted to write: for var i := 0 to 10 do ary[ i ] := ''; and similarly for var i := 0 to 10 do str[ i ] := ''; The first loop would blow up when i = 10, and the second would blow up when i = 0. And the compiler would fail to flag either as a possible problem. A smarter programmer might write: for var i := Min(ary) to Max(ary) do ary[ i ] := ''; for var i := Min(str) to Max(str) do str[ i ] := ''; But the safest way is to use this syntax (when it makes sense): for var ch in ary do xyz(ch); for var ch in str do xyz(ch); There are other variations that can attract off-by-one errors (while ... do, repeat ... until, etc.) that the compiler is helpless to do anything about. What's needed is a syntactical way to totally AVOID such off-by-one errors in the first place. Well, the for ... in syntax is the safest, but it's not valid in some use cases -- like if you want to initialize the contents of the array, because it yields a value, not an index. Some languages have the ability to let you say "foreach ..." or "for ... each ...", but that's still a decade away from showing up in Delphi, if it ever will. So we're left to use far less efficient libraries to provide these common-sense solutions, or just go bare-knuckle and let the cards fall where they may. There are plenty of ways to make the language "safer" in many such respects, but if nobody is willing to actually make the compiler changes needed then it's a wasted discussion. -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
Sorry, but while GC might address SOME issues, it's hardly a panacea. There's a memory manager you can link into Delphi that lets you turn on things that scan for stuff and flag things that turn up, both in real-time and when the program quits. There are syntactically correct expressions that Delphi will compile without any hints or warnings that are deadly. Most of them are hangovers from old TurboPascal days that haven't been addressed, mostly because the code they allowed is not used today. -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
Uh, no, it's the TSA that PREVENTS you from carrying weapons onto planes! TSA is there to PROTECT PEOPLE FROM THEIR OWN STUPID IDEAS. One of them that some people make is, "the only SAFE plane is one where EVERYBODY is armed!" In the computing field, that would be like saying, "We don't need the language or compiler to protect us from bad coding practices because ... WE KNOW WHAT WE'RE DOING! Code reviews and compiler checks (both compile-time and run-time) are like the TSA of software dev teams. Yet in my experience, they're all talk and no walk -- that is to say, I may have participated in two or three code reviews in the past 20 years, only because they were mandatory for some reason or other. We had agile demos every sprint, but NOBODY ever looked at the code. (One project I worked on briefly was required by the client to do regular code reviews as part of their Agile process. But most of the time was spent listening to a lecture by someone followed by people commenting on the funky variable names and how the code itself was structured. There was no effort to look at the code's logic itself. I don't consider these "code reviews" since they never uncovered anything meaningful. Like, what if TSA never found any guns even when they were planted? That has happened at some airports, to be sure.) As I've mentioned elsewhere, at one place I worked, I found over 100 instances of bugs in the code of a large software product that stemmed from 8 erroneous coding patterns that were spread throughout the code using a copy-and-paste coding practice employed by the original programmer. I wrote up a paper documenting them and sent it to the team and my management team. Then I set up a code review meeting to discuss my findings in detail and Management cancelled it with a note saying we were too busy working on a deadline to get distracted with this "nonsense". I tried everything I could think of, and was eventually kicked to the curb because they just didn't want anybody to know about this crappy code. And these guys claimed they were totally committed to climbing this latter of ISO 900x, CMMI, and other high-level certifications to show they had it on the ball.) And, oh, BTW, these errors were all due to memory faults that were mostly "invisible" to not just the compiler, but human readers. They had been in the code for over a decade at that point, causing all sorts of weird and unpredictable errors to show up. Their extensive test suites were unable to detect them. Exactly the things we're talking about here. Where's TSA when you need them? Programmers all like to think we're smart and are capable of writing great code that "breaks the rules" SAFELY -- even those considered "unsafe". The problem isn't now, but what might happen later on down the road? How many incidents turned up when compilers switched from 16-bit code to 32-bit code, and hand optimizations using pointers broke? Ditto for 32-bit to 64-bit code. How many people have the presence of mind to add conditional compiler statements there -- WHEN THEY WROTE THE CODE -- that raise a compiler warning when something they DID think of actually breaks the code LATER? Better yet, how many things did they NOT think of? The older and more experienced you are, the more likely you are to think of more situations to be guarded against, right? But that's just one set of eyes. How many people actually DO participate in regular code reviews and DO look at stuff like this? -
My earlier question isn't getting me what I'm looking for, so I thought I'd rephrase it. How does one obtain the final user-visible data from TWebBrowser after all the dynamic JS code that's loading up result data on-the-fly has been executed? (I'm using VCL in this case; a solution in FMX would be good to see as well, if it's different.) I need to be able to get the visual contents of a Google search results page -- but I think it could be just about ANY kind of web page that uses dynamic JS to fill data fields when the page is loaded. The well-documented methods I've found thus far all return a bunch of JS code, not the final results they produce. I want what the user sees, not what the browser initially gets from the server. I wonder if the ultimate end-result of this paradigm shift is that web page queries are going to return a super simple HTML document that contains one line in the HEAD or BODY that triggers a JS query like, "<script>loadpage(sessionID,...);</script>" and everything the user sees is rendered through recursive JS calls on a field-by-field basis (with most if not all running in parallel).
-
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
I think you're missing the point of this thread -- which, BTW, I did not start. This has nothing to do with me. If you like waving sharp knives and axes around when people are saying, "Hey! That's DANGEROUS!" why are you lashing out at THEM and calling THEM names? This isn't MY fight! As an aside, do you have any idea how many thousands of GUNS are taken off of people at TSA checkpoints at airports around the country? I suspect you'd call people who defend the need for TSA checkpoints ignorant and arrogant as well. -
I'm pointing at something that I think might be interesting to you and you're upset at my fingers being crooked.
-
It wasn't. It's just a general attitude that I find quite pervasive in the programming community. Maybe because details of the trial are irrelevant to the offer itself? When you click the link for a trial DL on most sites, it usually goes to a page where all of the TRIAL details are listed, which are sometimes (but not always) different from the MAIN OFFER. If you put them on the MAIN OFFER PAGE then people will often get the two confused and a confused mind does nothing. A lot of times, the trial offer can vary by switching out the trial DL page rather than the main sales page.
-
Looking for a couple of good "starter" Delphi books
David Schwartz replied to t2000kw's topic in General Help
Any Delphi book from D2010 and later will help you learn the language and develop basic UI skills. And they pretty much all teach the same bad habits to simplify showing how to build forms. There are also tons of videos on YT and other sites, some of which are step-by-step tutorials, as well as lots on specific topics. Don't forget the annual CodeRage virtual conferences that CodeGear and then Embarcadero have hosted over the years. There are always a few presentations for beginners as well as lots of interesting niche topics. -
I imagine you prefer visiting projects on GitHub that have no documentation at all and require you to read the code to figure out exactly what they do. But, hey, they're free, so what's a few hours of your time worth, right? And of course, besides being free everything on GitHub works perfectly and they've got terrific support, saving you even more time! FWIW, I found this tool in 2010, and the author has been regularly updating it ever since. To his credit, he charges a very modest annual fee rather than saying "free updates for life", which usually means he'll be out of business within 2-3 years. I'd encourage you to 'click the link' on most WP plugins to see how few of them have been around since 2010, and how many have NOT been updated in the past year or three. Sorry, but I don't understand why so many programmers are allergic to paying for the same stuff that they themselves get paid to do without regard for how or where those funds come from -- usually from sales of the software they write. But who's counting...
-
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
I can totally relate to this! At one gig I was on, I discovered some coding patterns in a quite large Delphi system that compiled without any warnings or hints, but were wrong. It was by sheer luck that the code worked most of the time, and when it didn't, it produced strange down-stream errors unrelated to the actual coding mistakes. I tracked down over 100 instances of these patterns and tried mightily to get them fixed. At one point, I pushed out a version with about half of the issues corrected. The testing group asked what happened because my new update was running about 25% faster. They were very happy. At the end of the day I asked if they had encountered any of the random irreproducible errors they seemed to get regularly, and was told "not one!" The next day, I pushed out an update with the rest of the issues corrected and speed increased again. Also, none of the irreproducible errors showed up. But the third day I was told to revert everything because the tickets I put into the backlog weren't done properly; they wanted me to enter a separate ticket for each change. So I reverted the code and the next day the testing team was unhappy because it was running slowly again, and those weird errors were back. I kept trying to get these issues resolved, but after 9 months of this nonsense, I believe I was terminated for refusing to stop. At one point, someone suggested that, for this particular project, the company had guaranteed to the client that it was "bug-free", although any errors they found and could give us code that reproduced the error, then it would be fixed. For all my efforts, all that happened was that more stringent rules were published about who can submit bugs, and ultimately the Dev Team was explicitly prohibitied from introducing either bug or refactoring tickets into the backlog (even though we supposedly "owned" the backlog). A few days before I was let go, word came down that every single line of code that was changed had to have a comment tying it back to a specific ticket in the backlog, and an audit of said changes was added to our sprint completion meetings. To make matters worse, there had been dozens of reports of a certain type of error that was not reproducible, and part of what I discovered explained this -- it was a data-sensitive error, and feeding the same data in repeatedly via the UI did not produce the exact same result in terms of what the erroneous code was looking at, so it was not reproducible. -------------------------------------------------- To this day, nothing has been done to the Delphi language that would help these issues be detected and reported by the compiler. I have no idea if this code ever went into production or not, but those 100+ coding errors were bugs waiting to be triggered. I only found them by accident, stumbling into some code that looked odd but actually compiled. After a while, it suddenly made sense when I looked at from another perspective -- one that was specific to the main programmer's previous experience and the language he used for several years prior to working with Dephi. Reading bits of that code as if it was written in that other language was exactly what he expected the code to be doing. Delphi considered it syntactically ok, but it was nonsense from a semantic standpoint, although Delphi didn't care about that part. I even ran samples of this code through some Pascal code analyzers and they didn't catch these errors either. Unfortunately, backtracking from the points where the faults were raised was fruitless. -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
Pretty much any programming language that lets you do bitwhacking can do this. Just like anybody can walk on their hands or ride a unicycle with some practice. The question is, "Why?" Just because you can? Most people would argue that C is far better for this sort of thing. Sure, Delphi already does this, but I don't see it being used as a language of choice by devs who do a lot of bitwhacking, like gamers. But at some point, this becomes a circular argument: Why doesn't Dephi support language features that most contemporary languages now include? Because nobody uses Delphi for that purpose. Why is that? Because it's too inefficient without the built-in language support. As if that's going to encourage the Powers That Be to take an "Add it and they will come" attitude... I want to see enhancements that make the language safer, and make it easier to use with less verbiage for things that other languages now routinely support. Constantly offering-up verbose and unsafe workarounds is not encouraging to anybody. -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
So what DO you do in a case where, say, you might use an object to collect an accumulation of data that is provided by multiple sources? It's often done for contextual state management over time... -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
That's what I'd like to hear more about. -
Is this code running in C++ Builder? If so, you may just need an interface unit, not a full DLL. I can probably help if you'd like to discuss it.
-
Has anybody played with AppGini from BigProf Software? I've built several small DB-based web apps with it, and you can do quite a lot without having to write any code. The UI isn't anything to write home about, but unlike most low/no-code platforms, it generates php/MySQL code that runs totally on its own. https://bigprof.com/appgini/
-
ChatGPT - Plugins removed - Still available until 19.04.24 perhaps
David Schwartz replied to Rollo62's topic in Network, Cloud and Web
I've not been following this, but it seems what they're saying is "the beta-test is ending" and they've got a slightly different way of naming things now. BTW, can you recommend any resources that discuss different aspects of writing prompts? I mean, are there any clear patterns defined for "prompt", "meta-prompt" and so on? They seem to be a combination of "macros" and "procedures". Most of what I find is just long lists of different types of prompts that people have written. -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
Well, the two patterns I can think of are: (1) when you have everything contained within a single method; and (2) when you're working with an object that has an unpredictable lifetime and lots of methods are touching it. I encounter errors in (1) when the code is rather long and I declare an object but forget to add the Free to the Finally clause. For (2), I'd love to see what your approach is. I've not found an approach that is robust and works well everywhere, other than something that takes a lot of extra code to check things everywhere. -
A Question of Style
David Schwartz replied to rgdawson's topic in Algorithms, Data Structures and Class Design
Einstein is credited with saying, "Everything should be made as simple as possible, but no simpler." There are usually three steps in most non-trivial algorithms: * declaration / initialization (can be optional) * process * destruction (may be automatic) I like it when each of these is clearly identifiable. I get nervous when the class designer tried to be too cute and save me from typing a line or two of code, so I end up wasting time digging into the code to see what's being done implicitly. Eg., sometimes there's an implicit object being used that you need to copy stuff into before anything will work. Sometimes the result set is in a (hidden) object that you need to deal with, starting with whether it's even valid or not. You can shuffle things around in many interesting ways to simplify how much code you need to write in different places, but just be sure it's clear and unambiguous so when you look at it in six months you can quickly figure out what it's doing. None of these three examples does a good job of that, IMHO. Unless you're passing in an already prepared query object, then you need to prepare it -- that the first item. If it succeeds, then you want to process the query, typically iterating over what might well be 'n' result sets. Finally, you want to free up the object(s), although this may be done automatically. So for me, Pattern 1 fits this best with the separate Prepare statement, but the 'process' part can be improved. Try this approach and see how you like it. Note that this doesn't conflict with what Nick teaches. Just don't try to do everything in one statement. 🙂 -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
Ok, all of these nuances aside, I for one would LOVE to see something added to the Delphi language that DOES make it more "memory safe", specifically an option that let you tell the compiler (simply in the declaration) that some var is to be treated local to a block and to free it at the end of the block, without requiring try...finally. C++ has done that forever, as well as many other languages. Off-the-cuff, maybe something like this: function get_users_name : string; begin Result := ''; local tmpForm := TUserNameForm.Create(...); // set some properties tmpForm.Caption := 'Enter name'; . . . if tmpForm.ShowModal = mrOK then Result := tmpForm.aName; end; tmpForm will be automatically freed at the end of the block and the memory cleared. I'd like this because chasing down orphaned blocks and references to objects that got deleted early seem to take up more of my time than any other types of debugging issues. I want more help from the compiler and language for this common situation using LESS CODE! Maybe we'll see something when Delphi turns 30 next February? The try...finally, Free, and clearing memory are all managed implicitly by the 'local' variable designator (as an example). It only needs to work initially with normal TObject references (including lists), and arrays of anything (including Objects). If you declare 'local' scalars, they'll be cleared at the end. For pointers, just come back later and use AI to figure out what's going on with the pointers so the code can help deal with them. -
Delphi and "Use only memory safe languages"
David Schwartz replied to Die Holländer's topic in General Help
I have not used any calculus since college. I've never had a job that required it. I know I'd be remiss in asserting that calculus must be a dead part of math in the same way that Latin is a dead language, as I'm confident there are plenty of projects where their programmers are implementing solutions to calculus problems on a daily basis. However, I seriously doubt they're using Delphi to do so. (queue up those here who want to tell me otherwise...) FWIW, I've known plenty of programmers who do nothing but write highly-performant code that implements math functions I can't begin to explain, most of which employ calculus. And not one of them said they used Dephi. The most commonly used languages they mentioned are C, FORTRAN, and MATLAB. For those who've looked, Delphi has far too much "compiler overhead" added to the code it generates. Likewise, I'm confident that there are plenty of problems that can be written without pointers and bit-whacking, but if you want to drop down to that level, then the program will definitely run much faster. And if you go all the way down to Assembly language, they'll run even faster. Does this mean that we should avoid adding features to the language that the vast majority of people who write Delphi code would find beneficial, simply because some tiny percentage of users aren't served by them because of hand-optimized code that uses pointers? I've probably seen millions of lines of Delphi code in my career, and aside from a few isolated routines here and there, there was no use of the ^ operator anywhere, indicating a very broad lack of employing pointers simply because they run a little faster. Sure, pointers are heavily used in the RTL and common libs that I think SHOULD be highly optimized. But the people responsible for them are the library vendors, not end-users. This attitude is probably why there have been so few changes to the Delphi language over the years. The industry considers Delphi fairly "ancient" because it's lacking so many features that most contemporary programming languages have. Those features were added to help a majority their of users, not 100%. Nothing seems to get added to Delphi's language unless it benefits as close to 100% of users as possible. When Delphi was introduced, many of it's features were state-of-the-art. Today, it's almost an anachronism. Nobody teaches Pascal any more, and features found in most languages used today are probably years away from showing up in Delphi, if they ever do. -
There's also this: https://github.com/delphi-blocks/WiRL