Jump to content

Darian Miller

Members
  • Content Count

    583
  • Joined

  • Last visited

  • Days Won

    14

Everything posted by Darian Miller

  1. Darian Miller

    InterBase or Firebird?

    Ancient subject, but after years of progress on both sides... how does it look today for a new, small Windows desktop project? Don't need outrageous speed, or size, just a dependable data store. One nice feature is to be easy to backup/restore as needed. Another alternative is PostgreSQL. Does anyone even use InterBase anymore?
  2. Darian Miller

    Is datasnap Webbroker a good approach?

    There are quite a few different avenues you could take to support API development. The first step in any is to get it "to work" which you seemed to have accomplished! Your next question is valid - will it scale? The question remains, how much do you need it to scale? How many concurrent connections are planned, what sort of total throughput is required and what are acceptable latencies? Once you define those, you can test those things yourself by using tools like JMeter and BlazeMeter and see if your performance is acceptable. If it's not, then you can look at scaling methods, either locally with Windows Clusters or migrating to cloud services on AWS or Azure. If the performance isn't satisfactory, you could also look into different implementations. One of the most commonly used frameworks is mORMot which has been highly optimized. If you join their community you'll likely get some help getting started. There's a LOT of code available, and much you can ignore to get started. Another option is to get a commercial finely-tuned multi-tier approach from Components4Developers. This option has been around a very long time and is quite mature, and quite performant. Another commercial option to look into is the Remoting SDK from remobjects. This also has been around quite a long time and is widely used. For a real simple and performant commercial toolkit, also look at RealThinClient components. There are plenty of other choices out there. The next step that I would recommend is to analyze your projected usage and start establishing some real testing metrics that you can validate current and future decisions on. Get the tools in place to back up your API infrastructure with measurements and validation. In addition to API testing, get line-by-line performance measurements with ProDelphi or Nexus Quality Suite to track down different implementations.
  3. Darian Miller

    FireDAC Add On discountinued? (Good by Embarcadero?)

    That's a honest question, when you know the answer?
  4. Darian Miller

    FireDAC Add On discountinued? (Good by Embarcadero?)

    DevArt subscriptions default to 1 year of support and upgrades. You have the option to buy 2 or 3 years up front at a discount. It's a perpetual license, but you won't get any updates after your subscription expires if you don't renew. Renewals are typically 40-50% of the price of the initial subscription, but you are correct, they don't display that cost. I assume you can get a close guess of what the cost of annual renewal will be by comparing the 1 year to the 2 year initial price, and add about 10%. (Rough estimate) Before purchase, I sent them an email and specifically asked what the renewal price was. I purchased pgDAC Pro last year for $500, which is the current list price. I can renew the annual subscription today for $250. It's getting close to be a real good time to buy tools and components. As I posted on my blog last year, many component vendors offer Black Friday discounts: https://www.ideasawakened.com/post/black-friday-discounts-from-delphi-related-third-party-vendors DevArt is apparently using the same URL as last year and this page contains discount codes good from Nov 23-29th, saving 20-50% off. https://www.devart.com/blackfriday.html I'll probably do a 2020 blog post with Black Friday deals once more are announced from various vendors.
  5. Darian Miller

    Outdated Delphi Roadmap

    Roadmap released: https://blogs.embarcadero.com/rad-studio-roadmap-november-2020/
  6. Thanks. I don't think I ever torqued him off and got banned, but then again I don't remember what I ate for lunch yesterday...
  7. Thanks! Maybe I angered the moderator....called him a Visual Basic programmer or something.
  8. Thanks. I am a member of these 3 facebook Delphi groups: Delphi Dev: https://www.facebook.com/groups/delphidevelop 3.3k members Delphi Developers: https://www.facebook.com/groups/DelphiDevelopers 4.4k members Delphi Programmers: https://www.facebook.com/groups/DelphiProgrammers/ 6.2k members For the Facebook group link you provided, I get an error message below so it must be a private group. Or maybe I've been banned! 🙂
  9. Thanks. I guess I don't have access to that group. Can you invite me?
  10. Curious - which Delphi facebook group? I didn't see your post listed in the few groups I checked. (I'm wondering if I'm missing a group.) Also - have you received your payment yet? Try contacting their "VP of Product" Kurt Smith. The email I have for him is firstname at fastspring.com
  11. Darian Miller

    Outdated Delphi Roadmap

    I think a new roadmap is past due.... any news @Jim McKeeth or @Marco Cantu?
  12. I imagine one of the biggest problems of being self-taught is missing out on some well-documented practices. Well, I confess that I did not know about the use of double-dabble to quickly manually convert a base-2 representation to base-10, for example: 1001000110 to 582. Quick blog post published today: https://www.ideasawakened.com/post/double-dabble-and-conversions-from-base-10-and-base-2-number-systems
  13. Darian Miller

    Compiler: Endless loop

    Which version of Delphi? Sometimes corrupt .FRM files cause an issue. Test in a new directory and convert all To / From text to binary.
  14. Darian Miller

    Organizing enums

    No, not all the time but the more I do it, the more I like it. You were wanting a better system of not having to remember a specific enumeration like htTemplate. One suggestion was to just create a HTML related unit that contains the main generic HTML related types that you want to use so you can remember the general unit name and then lean on code completion to find the type/enumeration. Create a naming system that you like for these types of units, something like HTMLTypes.pas, HTMLUtils.pas, HTMLShared.pas, or whatever naming style you prefer and then you can type HTMLTypes. and invoke code completion to get all of your shared HTML related types and drill down to the one you want. If you have HTTP related items you also create HTTPTypes.pas (or whatever) and then DBTypes, EmailTypes, etc. These shared units usually have type definitions with little code. One code smell is if you are including a bunch of code in one of these shared units, then that code should be split out to its own unit (likely several new units.) Defining where the code should live is a primary key to the ability to maintain the code over time. It also helps you code much faster if the organization makes internal sense. Choice 1 is one unit with every single line of code. Choice 2 is a separate unit for every class or type definition, no matter how small. There's a balance somewhere in the middle, leaning greatly towards 2.
  15. Darian Miller

    Initialization of returned managed types

    It's a "feature" not a bug. But, yes, I would love a compiler warning.
  16. Darian Miller

    Organizing enums

    Note: A real good Delphi reference book is "Delphi XE2 Foundations" by Chris Rolliston. Well worth the money and it will help with issues like this.
  17. Darian Miller

    Organizing enums

    In your example, HTML is a field variable of the TReportEnums structure with the specific type defined to be THTMLType. You are trying to access it as an Enumeration and not as a variable. Delphi offers meta classes where you can define a variable to be a class type such as: TMySomethingClass = class of TMySomething, and you can define a variable of type TMySomethingClass, but this only works with classes. AFAIK there's no similar thing for records. Not a great solution, but if you could group your defines in one class you could get code completion from a master class like: TMasterRecordTypes = class type THTMLType = (htTemplate, htStatic, htHeader, htCustom); TSecondRecordType = (srOne, srTwo, srThree); end; vHTMLReportType := TMasterRecordTypes.THTMLType.htTemplate; Or just put all your related record types into a particular unit and use the unit name as the scope, which is how it's normally done. vHTMLReportType := MyUnitName.THTMLType.htTemplate;
  18. Issue created, status is waiting on further demand before action is taken: https://gitlab.com/gitlab-org/gitlab/-/issues/254725 GitLab offers built-in SAST support for many languages and suggest creating an issue to add support for any dev language. Issue created, just need your votes!
  19. You seem highly concerned about performance implications - so measure the performance. Simulate a million (or whatever constitutes a significant amount) receipts of randomized sample data and measure your few possible implementations. If you find very little difference, then pick the one that is easiest for your team to extend and maintain. If your original source is TBytes, and perhaps your output source is TBytes, then introducing any conversions seems wasteful, but gut feelings should only act as a general guide. You either measure or you keep guessing. If you keep guessing, you may accidently determine if it's (currently) providing acceptable performance.
  20. Darian Miller

    Double-dabble to convert binary to decimal

    Literally LOL. Thanks. I'll try to absorb it! 🙂
  21. Darian Miller

    Double-dabble to convert binary to decimal

    Thanks, that was also pointed out by others online and it will likely be in a follow-up article. I simply didn't know about the double-dabble trick and thought it was kinda cool. I don't do these number system conversions enough to be able to convert any lengthy amount in my head yet. Lately I've been attempting to spend a lot more time learning rather than just always doing. Unfortunately, I was always the work-harder and not the work-smarter type. Few could out-work me, but many could out-smart me. I want to combine the two, and maybe the next buyout will have an extra zero or two behind it. Or, I'll simply enjoy it more. Either way, it's a win.
  22. Darian Miller

    Automatically killing a service when stuck

    I like using child processes. The main windows service process starts two processes: a task launcher and a server updater. 1) Windows service process: Launcher thread simply runs the child task-launcher and optionally the server-updater processes. Main process thread waits for service stop/shutdown signal. If detected, signal its launcher thread to terminate. Terminate the windows service process once launcher thread terminates (or timeout reached and child processes are forcibly terminated.) 2) Task-launcher process: For each externally configured task worker process to be launched: Look for update of task worker executable. If update available, install (typically just a simple .exe copy) If no update, or after update is completed, launch the task worker process. Wait for task worker process to terminate. If task worker process terminates, and the service isn't shutting down, repeat. (auto-update of worker executables) If task-launcher is signalled to terminate, then signal all child applications to terminate (send a close message.) 3) Optional server-update task process: Each task-worker executable is in it's own directory. The job of server-update is to find/download any update to any task-worker executables. It simply puts the new exectuables in a predetermined newversion folder. 4) Every child process (including the task-launcher, server-update, and all custom task-worker executables) Single task launcher thread simply looks for any configured task threads and launches child threads as needed. Main thread also looks for new executable version, if found then signal task launcher thread to terminate. Automatically terminate the process once launcher thread terminates (or timeout reached and child threads forcibly terminated.) Automatically terminate process if close message received after signaling task launcher thread to terminate. These can be simple VCL applications with a main form that has a Start / Stop button (which are only used for running in debug mode within the IDE, or standalone outside of IDE and outside the Windows Service) and a timer that is looking for updates Benefits: Windows service has very minimal code and never needs to be updated, which is nice because updating service processes are much more painful. The task-launcher process also has very little code and rarely needs to be updated. The optional server-update code is isolated to a single stand-alone executable and separated from task-worker custom code. (Could also move server-updates to a centralized management server and just copy new task-worker .exe to new version folder as needed.) The much more frequently changing task-worker code is isolated to stand-alone executables and these executables have no windows service, process launching, or server-update plumbing type code (other than the knowledge of where to look for a new version is ready to be installed.) Each task-worker can be built, debugged and tested just like any standard VCL type application. So if you have a many middle-tier application Windows Server machines to manage, each machine can run identical windows-service, task-launcher, and server-update executables. You decide on which machines to run various simple to create task-worker executables as needed. You can make changes on the fly by editing external configuration files (add new task-worker executables for example) and never have to restart the windows service. This system worked great for years. The only main trick is that your worker threads should periodically check for Terminated. If you don't code worker threads in a responsive way, the worker threads can be forcibly aborted in the middle of a task if the server is being shut down and your timeout is exceeded (which is likely no different than a current problem that has to be managed somehow.) Given the stability of Windows Server these days, the only time you have to restart the machine is when a Windows Updates requires it so that's also the only time this windows service will ever need to be restarted (it's a very good day indeed when you no longer have to stop a windows service to do some sort of application update.) You can also deal with 'stuck' task-worker executables by simply putting a copy of the executable into the newversion folder and the application will self-terminate and auto-restart based on your timeout preference. (Or simply use Windows task manager to kill the custom task-worker process and it will be automatically relaunched by the task-launcher.)
  23. Darian Miller

    Workaround for binary data in strings ...

    I dispute the concept that it was always considered bad practice. Like many things, over time it was eventually agreed to be universally known as bad practice, but it's revisionist history to claim that it was always considered such. How many Delphi Informant magazine articles, website articles and blog posts, along with commercial components and enterprise wide codebases were littered with this usage and there wasn't a peep about bad practice for years?
  24. No. It's just a byte like any other single-byte character. In ASCII and UTF-8 this single byte represents a Vertical Tab, a control character rarely used today and originally used for advancing the print head when printing. This special character has seen other uses and this StackOverflow question has some history: https://stackoverflow.com/questions/3380538/what-is-a-vertical-tab Apparently this is used as an alternate line feed character in various systems. So, depending on where your data is coming from, you may want to replace each character #11 that you come across with a CRLF pair. (Look at your data and see if that decision makes any sense.) memo2.Lines.Text := StringReplace(memo1.lines.text, #11, sLineBreak, [rfReplaceAll]); Not sure when sLineBreak was introduced...if you are using an old version of Delphi: memo2.Lines.Text := StringReplace(memo1.lines.text, #11, #13#10, [rfReplaceAll]); Curious... are you getting other odd characters, or is it just #11? (0b)
×