Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 03/29/19 in all areas

  1. 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
  2. There is a bit more to it than simply following a mantra - here is some more food for thought: https://www.thoughtworks.com/insights/blog/composition-vs-inheritance-how-choose
  3. 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.
  4. It is problem with bad inheritance. Like I previously said, if you take narrow approach and only focus on Circle IS specialized case of Ellipse, you are bound to make a mistake. Even more so, if you lock particular behavior in base class that cannot be universally applied to all sub-classes.
  5. That is why there are no clean and absolute rules. You have to decide what makes sense in each particular case. Sometimes creating wrapper classes that will expose only valid functionality makes sense, sometimes list is just a list.
  6. I'm not sure how many of you are like me, use implementation (class) inheritance (not interface inheritance, this one is OK) without too much thinking, with the intention of primarily for code reuse. Inheritance for extension is Ok, but for code reuse? Maybe not that good. Although I have achieved code reuse with class inheritance, but from time to time I feel unwanted class coupling were introduced too. It doesn't sound right and today I have spend many hours reading through aquite amount of discussions through stackoverflow, StackExchance, wikipedia, and so on, many articles seem to prove my feeling, for example: https://codeburst.io/inheritance-is-evil-stop-using-it-6c4f1caf5117 (especially this one) https://www.artima.com/lejava/articles/designprinciples4.html https://softwareengineering.stackexchange.com/a/65180/37358 Update 1: Let me quote from StackExchange user Stephen Bailey which is really well said: My conclusion === If it's only about code resue, most of the case we should consider use composition instead of implementation inheritance, like assembling a car with various more fine-grained, more manageable components. What do you think?
  7. Steve Maughan

    Advice Needed: PDF Graphics Rendering Suite??

    It's one of Joe Hecht's sites. He has a few and they all look the same. I gave him some similar honest feedback over on Google+ a few years' ago. He agreed, but nothing seems to have changed. It's a pity since I'm sure the components are decent. It would take no more than two days to replace these sites with a good WordPress theme.
  8. That is why in my lists (inspired by the behavior of .NET) it causes an exception when the source changes during enumeration causing the enumerator to be possible invalid. I also have a Remove method where I can pass a delegate that determines what elements to remove. IME much more robust than handwriting loops and keeping track of such things.
  9. No I didn't miss it. But code reuse is separate matter. It is not a primary drive. Code reuse plays significant part in OOP design - you don't want to unnecessarily repeat code, but you also don't want to make your choices solely based on code reuse. Whatever you do, you always must look at the problem from many different aspects and all basic OOP principles. If you take too narrow approach, you will most likely make wrong choice. Sometimes, answer to inheritance vs composition for code reuse is neither, because doing one or the other can result in monstrosity. Sometimes, repeating two lines of code and keeping things simple is more viable approach. So back to your question and original article - "If it's only about code resue" Answer depends on how you interpret the question... it is never ONLY about code reuse... but if reusing some lines of code IS the only reason to use inheritance, then you are probably doing that part wrong... at the same time composition in such case can also be wrong choice. Depends what is the purpose of that code and its function. If you cannot clearly define its responsibility then you are bound to go wrong with composition, too.
  10. TList<T>.GetEnumerator does not call DoGetEnumerator but directly creates its TEnumerator - so overriding it is pointless. Considering the design in TEnumerable<T>.GetEnumerator to use the virtual DoGetEnumerator I would call this a defect that TList<T> does not stick to this pattern but has its own GetEnumerator. Anyhow why make a new list class just to enumerate stuff in reverse order?
  11. @Dalija Prasnikar I agree with your characterization but in some cases I find that composition is better suited than inheritance even though inheritance would be more natural. For example if I were to create a list of TSomething it would be tempting to use TList<T> as a base class, Problem is that it might give me too much. If I only need an Add method, a Count and an array property, then composition is probably better (I guess one could call it inheritance through composition). I've seen too many examples of inheritance (not just from TList) where most of the inherited methods doesn't make any sense and would break the application if used.
  12. Sherlock

    Strange messages at run-time

    So, just to be clear. These are messages in the "Event Log"? They do not come from the compiler. They are messages triggered by your application and the DLLs it uses. Either you dive in deeper using the process monitor from SysInternals or check out how you access those files (standard API, some old legacy code, some new self made code, some alien technology and so forth) in your code. Where are those files? In the MS cloud aka OneDrive?
  13. astral2k5

    Visual Styles at runtime

    Here is an example: https://stackoverflow.com/questions/9906312/delphi-vcl-styles-tutorial-how-to-change-the-style-at-runtime
  14. Dmitry Arefiev

    FireDAC - Change Expired Password

    Yes, it is.
  15. Dmitry Arefiev

    FireDAC - Change Expired Password

    This issue was (most probably) fixed in 10.2.2. Your workaround is almost correct.
  16. Holger Flick

    Rio 10.3.1 IDE Compiler Error

    Then, you should not have referred to that bug report if you are not certain what causes the error. Sadly, without producing a test-case, you will never get a resolution. This is sadly the case for commercial and open-source products. It is painful, I agree, if a new version introduces unforeseen issues. Again, there is a formal definition of a showstopper in QA. The term does not refer to your (or anybody's) ability to use the product or not.
  17. ByteJuggler

    Creating a "pull request" for jvcl

    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...)
  18. Holger Flick

    Rio 10.3.1 IDE Compiler Error

    This does not qualify as a showstopper. You might feel like it, but it is not. Especially as the error seems to be only appearing in certain situations, and it seems to be avoidable if you compile without the IDE. In order to go ahead with your project, I would suggest to put the problematic class in a separate bpl and compile it using the command line. Then you can continue daily work inside of the IDE.
  19. Uwe Raabe

    Rio 10.3.1 IDE Compiler Error

    Are you sure that the bug report actually describes your problem and it really is a show stopper? According to the bug report it is something about the compiler not being able to infer the type, but explicitly mentioning the type works. How can that be a show stopper? Nevertheless, as long as you are on an active subscription you have three support incidents per year included. You can burn one of them to ask for an individual fix for that issue, although there is no guarantee that this will succeed.
  20. Stefan Glienke

    How to create a weak array?

    Not natively using [weak] attribute. You can only make a record with a [weak] IFoo field and put that into the array.
  21. The example I made is trivial. It expands a queue, so the size of the leak is directly proportional to the number of records you en-queue. Even if you destroy the queue, the leak persists. I am aware of RegisterExpectedMemoryLeak function. The call stack shows the problem comes from the Collections.TListHelper.InternalSetCapacity in Delphi's collections unit, that eventually calls the ReallocMem routine: LeakExample.exe!@ReallocMem$qqrrpvi Line 4900 004070b8 LeakExample.exe!DynArraySetLength$qqrrpvpvipi Line 35920 + 0x5 bytes 0040c466 LeakExample.exe!Generics.Collections.TListHelper.InternalSetCapacity Line 4489 + 0x9 bytes 004eb6f1 In the example I provided the actual collection is a queue of records that is created and destroyed. However when the queue grows, FastMM internally calls FastReallocMem to expand and internally determines it's a large block reallocation. If I simply redirect the ReallocMem routine back to SysReallocMem inside of FastMM, everything deallocates properly. Like you said, it could be a flaw in this tool, but the problem doesn't happen with Delphi's built in memory manager. It also doesn't happen if I change FastMM's source to simply call SysReallocMem immediately upon calling FastReallocMem. It also doesn't happen with numerous other data types, just collections, specifically queues of records.
×