-
Content Count
2771 -
Joined
-
Last visited
-
Days Won
147
Everything posted by Anders Melander
-
Bug in Delphi string behavior?
Anders Melander replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
Why? It's a programmer error. Not a bug. -
Variations of this question has been asked countless times. Always with the same answer: Don't do it. Why would you expect a different advice this time? Move the conversion into a separate process and kill that process instead.
-
Advice on searching within nested records
Anders Melander replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I'm back. The point of my example was that, provided you use classes, you can generalize the tree structure and the function that traverses the tree. And you can delegate the operation to perform on each node to the caller via the predicate function. In your example you'd examine the Disabled value of the node and store the node in a list on match. The return value of the predicate specifies if the search should continue or stop. E.g. if you wanted to just test if the tree contains any node that match a certain criteria, the you'd return False on the first match. If Find returns False then you know there was a match. For each level in the tree you would specialize the generalization for that level to add the necessary data members. -
Advice on searching within nested records
Anders Melander replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
If you could drop the records and use classes instead you could do something like this (very incomplete - I'm in a rush): type TItem = class private type TPredicate = function(AItem: TItem): boolean; private FItems: TList<TItem>; FDisabled: boolean; public function Find(Predicate: TPredicate): boolean; virtual; property Disabled: boolean read FDisabled write FDisabled; end; function TItem.Find(Predicate: TPredicate): boolean; var Child: TItem; begin if (not Predicate(Self)) then Exit(False); for Child in FItems do if (not Child.Find(Predicate)) then Exit(False); Result := True; end; var Item: TItem; Result: TList<TItem>; begin if (Item.Find( function(AItem: TItem): boolean begin if (AItem.Disabled) then Result.Add(AItem); Result := True; end)) then begin ...Result contains list of disabled items... end; end; -
Advice on searching within nested records
Anders Melander replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
You're not nesting records. TList<T> doesn't contain a list of T. It contains a pointer to a list of T. -
Why do we need google when we have @David Heffernan? David, the range and depth of your knowledge never cease to amaze me.
-
Interfaces, to abuse or not abuse?
Anders Melander replied to Clément's topic in Algorithms, Data Structures and Class Design
That's my experience too. Yup. I'm very satisfied too. There are some layouts that are hard to get right (layout in columns comes to mind), but generally it has saved me a ton of work. -
Interfaces, to abuse or not abuse?
Anders Melander replied to Clément's topic in Algorithms, Data Structures and Class Design
Thanks for the explanation. It seems much more reasonable now. With regard to validation rules some purists will insist that they belong with the business logic on that tier, and I've seen many examples that implement n-tier that way (post data to the server - get an error message back), but in my experience that result in poor user experience. Much better to validate data as early as possible, on the client, and validate it on the server. If the server can supply the meta data required for the client to build the UI and do validation I see no problem with that. Just out of curiosity: Have you tried using the DevExpress layout control to handle different font sizes and resolutions? Since I started using it to layout dialogs I've pretty much stopped worrying about what resolution/font/sizes the users are using; The layout control takes care of it. -
How do you deal with non-critical customer feature requests?
Anders Melander replied to Mike Torrettinni's topic in Project Planning and -Management
Yes. I'm sure we all experienced that a simple, innocent change ends up leading to much more work later one because we introduced a bug or side effects that we didn't think of. -
How do you deal with non-critical customer feature requests?
Anders Melander replied to Mike Torrettinni's topic in Project Planning and -Management
Of course. If the customer can cover the development expenses directly, then that will increase the priority. If the change will benefit other customers, make the product easier to sell or benefit the product in some other way that can also increase the priority and lower the price of the change. There's still the matter of finite resources to take into account though. Even if the customer pays the expenses up front it still means something else is not getting done. I used to think I could solve the finite resources problem by implementing stuff in my spare time. Unfortunately that just created another problem as the QA, documentation and marketing departments was completely unable to keep up with the amount of features I could produce that way. I don't understand. So in the scenario you describe you're not the customer but the developer? If so, why do you have a request at all? -
Interfaces, to abuse or not abuse?
Anders Melander replied to Clément's topic in Algorithms, Data Structures and Class Design
I don't like this part; It sounds like you're polluting your business logic tier with presentation stuff. Even if you're just using the database and BO tiers for storage of the UI definitions, my guess is that you have created a strong binding between the UI definitions and the presentation tier, so the definitions can only be used by the one presentation tier(s). I've seen this done several times and it always ends up with half the UI being created the way you describe and the other done the traditional way because of special UI needs that the generic framework can't handle. And then eventually the need arises for a new type of client (e.g. web or mobile) that cannot use the existing UI definitions and slowly the definition framework decays because it turns out that it's faster to just create the whole UI on the client than trying to make the definition framework handle everything for everybody. It's a bit like the write once, run everywhere promise. Sometimes it just faster to write three separate applications than to have one application support three separate platforms. -
How do you deal with non-critical customer feature requests?
Anders Melander replied to Mike Torrettinni's topic in Project Planning and -Management
Sure. Professional relationships, personal preferences and even mood, are just some of the many factors that affect priority. We're humans. As long as you know why you are making a choice I don't see anything wrong with making it based on "feelings" or intuition. Just don't make all your choices that way 🙂 I regularly make technical decisions based on intuition. I may not be able to rationally explain why I choose one solution over another, except that one "feels" right or the other doesn't "feel" right. -
How do you deal with non-critical customer feature requests?
Anders Melander replied to Mike Torrettinni's topic in Project Planning and -Management
Even trivial changes consume project resources and resources are finite. Implementing a low priority change takes resources away from higher priority changes and unless there's something wrong with way changes are prioritized I can't really see how one can justify that. The really hard part is weighing all the different factors when calculating the priority. Giving a ticket priority just because it's old doesn't make much sense. But if the age will cause enough customer dissatisfaction that it ends up having economical consequences then it might make sense. Apart from that I don't think age should be a factor. Each time we go through our ticket list we look at it fresh: At this point in time, what is the most important change for us to focus on. In my projects it's common for trivial but very low priority changes to be rejected. I think it's better to let the requester know that there's minimal chance their request will ever be granted, given that there will always be more important changes to work on, than to give them false hope. -
Interfaces, to abuse or not abuse?
Anders Melander replied to Clément's topic in Algorithms, Data Structures and Class Design
I can't really tell from your statement if you're saying that he doesn't do that but should or if you're just stating a general principle. From the code posted it's not possible to see if the implementation uses aggregation and/or delegation. No. It's another way. Which is better depends on many factors and we can only guess since we don't know anything about the architecture or size of Clément's application, and it's not really relevant to the question asked. In my experience an application has to reach a certain size and complexity before it's worth even considering the overhead and added complexity of SRP. And even then I would only apply it if it solved an actual (present or near future) problem. -
Interfaces, to abuse or not abuse?
Anders Melander replied to Clément's topic in Algorithms, Data Structures and Class Design
I don't see any problems with it; It's a very common (and very sensible) pattern. Just make sure, if your base class is reference counted, that all references to the object is through interfaces. If it's not reference counted then that doesn't matter. -
Code style to tentacles in three posts. I didn't see that coming.
-
Most efficient way to delete multiple items from a TList<T>...
Anders Melander replied to Steve Maughan's topic in Algorithms, Data Structures and Class Design
Very interesting. Thanks for the pointer. One of the other answers explains it even better IMO and points to this gem: https://kjellkod.wordpress.com/2012/08/08/java-galore-linkedlist-vs-arraylist-vs-dynamicintarray/ I guess I'll have to revisit some of my old code and redo the benchmarks. -
Most efficient way to delete multiple items from a TList<T>...
Anders Melander replied to Steve Maughan's topic in Algorithms, Data Structures and Class Design
That's quite a unnuanced (is that a word?) statement. Wouldn't you say it depends on the access and allocation pattern? -
That's a strange question. It's based on the experience that unnecessary nesting makes the code harder to read. Sure it's a personal preference, some like it, some don't (just google Early Return - I'm sure you will find one or two that doesn't advocate it), but at least one of your "if" blocks are complete superfluous and would be removed by the optimizer if it was worth anything. What's the relevance? Are you saying that because some simple rule based validator doesn't flag your code then it can't be improved? - Because I can spot several goofs in it.
-
Most efficient way to delete multiple items from a TList<T>...
Anders Melander replied to Steve Maughan's topic in Algorithms, Data Structures and Class Design
Huh? You have heard of premature optimization haven't you? -
It's a refactoring; It improves the readability of the code without changing the functionality.
-
Nice. But: Early Return ... if ParamCount < 2 then Exit; if not FileExists(ParamStr(1)) then Exit; if not System.SysUtils.TryStrToInt(ParamStr(2), ThisLine) then Exit; ...
-
Blogged : Introducing DPM - a Package Manager for Delphi
Anders Melander replied to Vincent Parrett's topic in Delphi Third-Party
Congratulations! I love it when that happens. I do think the phrase "Attempting restore on [...]" sounds a bit pessimistic though. Why not just "Restoring [...]" -
-
Yes, but you can't. I don't know the history behind it but I can see arguments both for and against having actions disabled if there's no handler and maybe that's why they decided to make it optional. Maybe not making it published was to avoid having the noobs shoot themselves in the foot with it. I don't know (and I don't care which is why I tried to delete my question after I asked it 🙂). It's a very minor annoyance that can easily be worked around with an empty OnExecute handler so I don't really care about it anymore. Submit a change request if it's important to you.