-
Content Count
324 -
Joined
-
Last visited
-
Days Won
25
Everything posted by Arnaud Bouchez
-
Good practices with nested methods
Arnaud Bouchez replied to Mike Torrettinni's topic in Tips / Blogs / Tutorials / Videos
I don't agree - don't add new private methods. It is not SOLID. Try to keep the class definition small and readable. Rather add a hidden object or class in your implementation section. -
Recommended Cryptographic Library
Arnaud Bouchez replied to Ivana's topic in Project Planning and -Management
Our Open-Source https://github.com/synopse/mORMot/blob/master/SynCrypto.pas has almost all that you require. About performance, it is the only one in the Delphi area using AES-NI and optimized SSE3/SSE4.2 assembly - as far as I know. So it should blow alternatives. It is cross-compiler (Delphi and FPC) and cross-platform (Windows, Linux, BSD... thanks to FPC). For elliptical curves, see its sibbling https://github.com/synopse/mORMot/blob/master/SynEcc.pas It supports only secp256r1 but it is feature complete (e.g. simple CA management) and fast (1 ms to create a key pair, 0.4 ms to sign or verify on x86-64) - also cross-platform and cross-compiler. See the documentation at https://synopse.info/files/html/Synopse mORMot Framework SAD 1.18.html#TITL_187 Both are highly maintained, and used on production since years. They don't require any external dll (like OpenSSL) which tends to be a maintenance nightmare on Windows. -
Good practices with nested methods
Arnaud Bouchez replied to Mike Torrettinni's topic in Tips / Blogs / Tutorials / Videos
Yes, @Bill Meyer is right: do not put the nested functions part of the main class. It would break SOLID principles for sure - at least the single responsibility. Always favor composition in OOP. About refactoring and breaking huge functions, you could take a look at those slides: Following these proposals, for code refactoring, I would move the code into dedicated records with methods (or classes). -
Switch to a n-Tier architecure is the way to go. Keep the database locally on your server computer (or network), then use regular REST/JSON over secure HTTPS for the communication with clients. HTTPS will be much easier to secure and scale than forcing encryption with the database driver. Certificate management is a difficult think to do - I have seen so many solutions running fine... until a certificate becomes obsolete. 😉 We usually use a nginx server as reverse proxy, with https://letsencrypt.org/ certificate management.
-
Good practices with nested methods
Arnaud Bouchez replied to Mike Torrettinni's topic in Tips / Blogs / Tutorials / Videos
A quick and simple rule would be to define only mandatory variables as shared for the nested procedures, i.e. above them. That is, try to keep all variables of the main block in the lower part of the code, just before the main block. Just as you did. From my experiment, nested functions are fine if there is only 1 (or 2) of them. Once I reach the number of 2/3 nested functions, I usually define a private record type, with proper methods. It is kept private in the implementation section of the unit. The trick of using a record with methods, and not a class, allows to allocate it on the stack in the main method, with no try..finally Free block. It is much cleaner (more SOLID), and also much more extendable. The main benefit is that it is re-usable: you could reuse some code, in another function. Last but not least, you have the possibility to add a unitary test method, and browse easier the code in your IDE. -
with SomeUnitName do doesn't compile on my Delphi 10.3 (nor FPC). Compiler complains with [dcc64 Error] Test.dpr(200): E2029 '.' expected but 'DO' found
-
@Bill Meyer Is with UnitA, UnitB do even suppose to compile?
-
What is sure with "with" discussion is that it is a trolling subject in the Delphi community since decade(s). For instance, the topic is about "with" in general, and that @Yaron stated that the IDE debugger has troubles with it. TRect came as a true problem about "with" - I do agree with Stefan. But problem came from Embarcadero, not taking into account existing code base. Just like ARC, or the AnsiStrings... Most dev people outside this forum would argue, paraphrasing @Dalija Prasnikar, that 'Delphi is a relic of another time and another coding practices: for instance, there is no GC !'. Php adepts would argue that writing $this->foo is much cleaner/safer than what Delphi (and other languages) do about properties. I like "with" - when properly used for two-liners code - as I wrote. It is a clean way of writing code, "making it easier to read" as wrote Yaron. Similarly, I like "object" more than "record with methods", since it allows easy inheritance - when using high-performance code with pointers and pre-allocated memory buffers/arrays. Of course, with only static methods. This was just my 2 cents, to introduce another POV into the discussion. Nothing is totally black nor white.
-
Breaking compatibility by adding properties is very likely to break code... My assumption is that you use and maintain your own classes. This was not my point. I didn't mean CarWheel for sure. Wheel, Engine and Drive are fine. a, b and x aren't. And I wouldn't use "with" over two TCar instances, or two classes with a Wheel property. But it would have sense, say e.g. to write something like: with currentCar do CarInfo.Caption := format('Engine %s with %d wheel(s)', [Engine.ModelName, Wheel.Count]); My point was that "As everything powerful can be armful when misused, I like "with", when it is not over-abused". If the "with" scope is small enough to be obvious and safe, fine. Otherwise, use local variables.
-
As everything powerful can be armful when misused, I like "with", when it is not over-abused. For instance, I like "with", when it has only several lines of scopes. It does make sense to me, when used for a single line. Otherwise, I switch to an implicit local variable: asm generation would be the very same. If you think "with" should be avoided due to its implicit context switch, I guess next step would be to force using self.foo for class properties... just like the $this->foo of Php... what a progress! 🙂 I am against any new warning at compiler level. And if you are confused by with someclass do x := a * b and don't know to which class a, b, or x belongs to, it is time renaming the properties/functions to something more explicit!
-
Relaxed JSON
Arnaud Bouchez replied to John Kouraklis's topic in Algorithms, Data Structures and Class Design
From the relaxed JSON website: I still don't get what a "JSON number" is - from its json.org definition, it is any kind of number with none to any decimals... -
Relaxed JSON
Arnaud Bouchez replied to John Kouraklis's topic in Algorithms, Data Structures and Class Design
The worse about Relaxed JSON is that it is not reversible. It may change the values. For instance, { number: 1.0 } will become { number: 1 } which is not the same. So for an exchange format, I would never use Relaxed JSON. For a settings local file, edited via vim or nano - why not? but as @David Heffernan stated, YAML (or TOML) sounds like better candidates. -
Relaxed JSON
Arnaud Bouchez replied to John Kouraklis's topic in Algorithms, Data Structures and Class Design
The mORMot parser supports "extended JSON", as used with MongoDB: field names can be without quotes. It follows in fact the JavaScript object declaration syntax. Internally - between mORMot client and server - it will use it to slightly reduce size and enhance performance. For regular clients (e.g. JavaScript), it will server standard JSON with quoted field names. As @Lars Fosdal states, a rigid format seems better when exchanging data between heterogeneous ends. -
General mobile app <-> REST design question
Arnaud Bouchez replied to David Schwartz's topic in General Help
List of ingredients are stored in at least two MicroServices: the "Pizzaiolo" service (which prepare the pizza) and the "accounting" service (which take into account the ingredients stock, and order them if needed). You may put the list of ingredients in the "Menu" MicroService... if you want to generate an accurate menu. Each service may need additional information: the Pizzaiolo would need to have the weight of each ingredient per kind of pizza, the accounting service may have delivery information, and the menu just need the name... -
Delphi default MM is a cut-down version of FastMM4 on Windows. You may achieve slightly better performance on multi-threading by using FastMM4 with some custom conditionals. IIRC on Apple, Linux or mobile platforms, it uses the clib heap manager. Which is not bad in practice. ScaleMM2 or others - like BrainMM - may be better for multi-threaded apps, but tend to consume much more memory. Under Linux, switching to Intel TBB or JMalloc may give a performance boost, but will also consume much more memory - see my tests with FPC https://github.com/synopse/mORMot/blob/8a55fb3bf2d4cffeb779dd19a8be18e227188f2f/SynFPCCMemAligned.pas#L68 But the main performance enhancement would probably be by changing your algorithms... Mainly avoiding heap allocations... See http://blog.synopse.info/post/2018/11/12/EKON-22-Slides-and-Code
-
Take a look at https://github.com/synopse/mORMot/blob/master/SynCrypto.pas It is Open Source, works from Delphi 6 up to latest Delphi 10.3, and is the fastest library for Delphi AFAIK - for instance, there is an Intel's SSE4 x64 optimized asm for SHA-256 on x86_64 (Windows and FPC Linux). You can use the THMAC_SHA256 record, or HMAC_SHA256() function for your purpose.
-
General mobile app <-> REST design question
Arnaud Bouchez replied to David Schwartz's topic in General Help
Following DDD principles, I will define several REST services - MicroServices, to be more exact. The first service would be a public API. You won't put here ingredients, but only the pizza kinds (marguarita, regina, calzone...), with some potential additional change (add an egg for proteins, remove tomato if allergic...). This service is known as the application layer. It could be called directly from a web site, a mobile app, or a Linux GTK app (for geeks). It follows the typical high level use-cases of a customer wanting to eat a pizza. This application layer will then use an internal REST service, in which my pizza "domain" will be coded. That is, it will know the "pizzaiolo" knowledge. What are the ingredients, how much of each, cooking time, heaven scheduling... This is the DDD domain, since it is where the real value of the pizzeria is: the better the pizza, the more customers, the more income... But this application layer may also notify other REST services, like: - the billing microservice; - the ingredient stock microservice; - the user preferences microservice (to retrieve the customer preferred pizzas); - the delivery microservice when the pizza is ready; - the management microservice (for the big boss to get consolidated information about the restaurant)... Those microservices won't be part of the main "domain", and could even be third-party services (billing, delivery...). Think of the application layer as the "orchestrator" of the whole system. For more info about services design, and DDD - and how to use Delphi to write such backends, see https://synopse.info/files/html/Synopse mORMot Framework SAD 1.18.html#TITL_68 -
Delphi version of Fast inverse square root
Arnaud Bouchez replied to Tommi Prami's topic in Algorithms, Data Structures and Class Design
The github link is interresting - if you go to the project page https://github.com/itchyny/fastinvsqrt you find some explanation in English. See https://en.wikipedia.org/wiki/Fast_inverse_square_root for the theory. 🙂 -
Best practices for system migration?
Arnaud Bouchez replied to PeterPanettone's topic in Delphi IDE and APIs
The license number is used to identify the sale, and you can activate a limited number of times a given licence number. -
Best practices for system migration?
Arnaud Bouchez replied to PeterPanettone's topic in Delphi IDE and APIs
For a new migration, I would go into creating a VM. The numbers of Delphi installations is restrained, and after a few setup, you would need to reactivate the licence count - which requires an active licence! So in the future you may need to actually pay a new licence, just to install Delphi on a new computer! (this changed a few weeks ago IIRC) With a VM, you won't face this problem in the future. Also note that creating a VM with Windows 10 is free. You are not even required to validate it, if you can stand up with a black wallpaper - which should be find for a VM running a dev environment. -
Using '' is the way to go. It works since pascal days, and compiles as a `nil` pointer. Using `EmptyString` or `string.empty` does not make any sense, in the pascal language context. There is no such thing as a null string. An empty string is stored as a nil pointer, and there is never some allocated memory with a length prefix of 0. When the length reaches 0, the string is always unallocated by the RTL. Note: I usually see people writing if length(something)=0 then and still thinking that it is faster than if something='' then. This is plain wrong. The faster version is the latest: if somestring='' - it just checks if the variable pointer is nil, whereas calling length(), even if it is inlined, generates more assembly, and is slower (dual comparison, and an additional jump if the string is void).
-
UltraCode64 for Delphi (aka 64-bit FastCode)
Arnaud Bouchez replied to chmichael's topic in RTL and Delphi Object Pascal
We need rather our own optimized pure pascal code. The RTL did change between versions, so a reference fast pascal version is IMHO mandatory - I have seen pascal version faster than naive assembly. It could be a very good benefit to install it to old Delphi versions too. Also be aware that some FastCode pascal is not compatible with 64-bit, nor with FPC, since it targeted 32-bit Delphi only at that time. And, as with FastCode, you will need to have a system to register benchmarks, on actual diverse computers. A centralized DB would be better than some XLS files (as with FastCode): any dev could compile and run the code on its own HW, for a given Delphi version, then send it to the main DB. -
UltraCode64 for Delphi (aka 64-bit FastCode)
Arnaud Bouchez replied to chmichael's topic in RTL and Delphi Object Pascal
First step may be to write faster code in pure pascal, with the associated tests. Then add some asm version, and see if it is actually faster. There is already a lot of code in http://mormot.net SynCommons.pas which has faster alternatives than the Delphi version. But two remarks: 1. I wouldn't stick to 64-bit - do why call it UltraCode64 ? 2. FPC compatibility could be very beneficial - as we did for mORMot. -
Funny Code in System.Types
Arnaud Bouchez replied to Fritzew's topic in RTL and Delphi Object Pascal
oh I missed the result.x := result.x assignment! 😄 -
Funny Code in System.Types
Arnaud Bouchez replied to Fritzew's topic in RTL and Delphi Object Pascal
Type-casting to Smallnt() won't be the same as the origin code, for very small or very big values (e.g. x>32768). Of course, no screen has a 32k horizontal resolution yet... but it may sooner than expected...