Feature Suggestion for FPC: Managed Objects lazarus / 62-General ---------------------------------------------------------------------- Warfley · 2020-05-02 15:17 The other thread had me thinking a lot about the differences between pascal an C++, and I think oldschool objects are heavily underappreciated Idea: managed objects: What I mean by that is quite simple, In c++ the no parameter constructor is called automatically as soon as an object is created, parametized constructors are called by hand. The destructor is called whenever the scope in which the object is defined is left. This means the following c++ code: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i { // begin of block, e.g. a function  some_class obj;  obj.foo;}Is equivalent to the pascal code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var obj: some_object; // using an oldschool "object" type, not classes as they are very different to c++ classesbegin  obj.init();  try    obj.foo;  finally;    obj.cleanup;  end;end; So basically in C++ the destructor takes the role of try-finally. While this can not be so fine granular as in C++ (where you can define objects in any scope, not only global or in a function like in pascal), I think it would be really useful for some objects you need inside a function, but only locally. So my suggestion would be to be able to define an "auto" constructor and destructor that will be called when the function is called/left. Example: A useful usecase for this might be such a type: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i typeTIntList = managed objectprivate  FData: PInteger;  FLen: SizeInt;  FCapacity: SizeInt;public  constructor Init; auto;  destructor cleanup; auto;  // typical list functions like Add, Delete, find, Value, whateverend;...constructor TIntList.Init;begin  FCapacity := 0;  FData := nil;  FLength := 0;end; destructor TIntList.CleanUp;begin  if Assigned(FData) then  begin    FreeMem(FData);    FCapacity := 0;    FLength := 0;  end;end; // Usage:function ComputeMedian: Integer;var list: TIntList; // auto constructor will be called herebegin  ReadValues(list); // assume list given via var parameter  if list.Length mod 2 = 0 then    Result := (list.Value(list.length div 2-1) + list.Value(length div 2)) div 2  else    Result := list.Value(List.Length div 2);end; This would be a way to get rid of a lot of boilerplate code, as te usual way to do this would be: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i // Usage:function ComputeMedian: Integer;var list: TIntList; // auto constructor will be called herebegin  list.init;  try    ReadValues(list); // assume list given via var parameter    if list.Length mod 2 = 0 then      Result := (list.Value(list.length div 2-1) + list.Value(length div 2)) div 2    else      Result := list.Value(List.Length div 2);  finally    list.cleanup;  end;end; What would be needed for this: Calling the default constructor should be similar to the default assignment: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var i: Integer = 42;Maybe this could even be implemented such that the Default Intrinsic returns a freshly created object where the auto constructor is called, this could then be solved like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var i: TIntList = Default(TIntList); The destructor would be a little bit more tricky, it would need to be called: 1. whenever the enclosing function is left (Exit, end of function, Exception, like try-finally). 2. Wenn the owning type gets destroyed 3. assignment (i.e. obj1:=obj2) (optional) Because there are already managed types, this could be implemented analogously Related to this: Idea: Assignable constructors This is really simple, basic idea is that Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i myobj := TObject.Init;would automatically call the destructor before calling the constructor meaning you can simply write Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i obj := TMyObject.Init(...);// rather thanobj.cleanup;obj.Init(...); Idea: Overloadable Assignment This is also quite simple, sometimes you don't want to simply copy all the members but do something a little more fancy with it. Take the List class above. On assignment you might want to do the following: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i constructor TIntList.Init(const other: TIntList);begin  FData := GetMem(rhs.Capacity * Sizeof(Integer);  FCapacity := rhs.Capacity;  FLength := rhs.Length;  Move(rhs.FData^, FData^, FLength * SizeOf(Integer));end; operator :=(const rhs: TIntList): TIntList;begin  Result.Init(rhs);end; Which would allow to easiely copy the object, so no one has to worry about accidentally freeing FData because it is shared between two TIntList. Basically the role of TPersistant.Assign, but because objects are not pointers like classes, this could be implemented on an operator basis Idea: Named With I really like the with feature: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i with TFileStream.Create(..) dotry  WriteBuf(...);finally  Free;end;The problem here is shadowing of member names, so I would think a named variant like in python would be neat: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i with TFileStream.Create(...) as fs dotry  fs.WriteBuf(...);finally  fs.Free;end;Now this could neatly be integrated with the thing I described above, leading to the following: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i with TFileStreamObject.Init(...) as fs do  fs.WriteBuf(...)Which would be the same as using: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var fs: TFileStreamObject;...fs.Init(...);try  fs.WriteBuf(...);finally  fs.cleanup;end;And would thereby get rid of a lot of boilerplate code. Comming all together: this could be used for example to write a reference counter for Classes: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i generic TReferenceCounter = managed objectprivate type   TManageInfo = record    RefCount: SizeInt;    Data: T;  end;  PManageInfo = ^TManageInfo;private  FManageInfo: PManageInfo;  function getData: T; // returns FManageInfo^.Datapublic  constructor Init; auto;  constructor Init(other: TReferenceCounter);  constructor Init(AData: T);  destructor cleanup; auto;  property Data: T read GetData;end; operator :=(rhs: TReferenceCounter): TReferenceCounter;begin  Result.Init(rhs);end; constructor TReferenceCounter.Init;begin  FManageInfo := Nil;end; constructor TReferenceCounter.Init(other: TReferenceCounter);begin  self.FManageInfo := other.FManageInfo;  if Assigned(FManageInfo) then    Inc(FManageInfo.RefCount);end; constructor TReferenceCounter.Init(AData: T);begin  New(FManageInfo);  FManageInfo.RefCount = 1;  FManageInfo.Data = AData;end; destructor TReferenceCounter.cleanup;begin  if Assigned(FManageInfo) then  begin    Dec(FManageInfo.refCount);    if FManageInfo.Refcount < 1 then    begin      FManageInfo.Data.Free;      Dispose(FManageInfo);  end;  end;end; This is just one example I think would be really awesome, because this way a lot of try-finally code could be avoided, while not having the "compiler magic" reference counting  of for example Interfaces. Besides this there are of couse also a lot of other options this would be usefull for e.g. FileStreams,  Containers, etc. while simultaniously removing a lot of boilerplate code you currently have with objects. Why: These are all things that objects, due to their property to sit on the stack, could do, which would make them less as the "oldschool" OOP but rather as a very usefull tool, whenever the use of a class might not be the best solution. A programming language is nothing more than a set of tools. And I think this would add a neat tool to the box that could ease development massively E.g. whenever you create A TStringList for reading a CSV file, which is destroyed right afterwards, you have to add a try-finally. With such managed objects this could be done very neatly increasing readability of the code. As this would be it's own object variant It wouldn't break any existing code, and IMHO would be a great addition to the ObjectPascal language. I know this would be a rather big addition to the language and I have no idea how complicated something like this would be. All my experience with compiler construction is lexing and parsing, I have no idea about the backend implementations neccesary for such a thing. But I think it would be a really nice addition to the language ---------------------------------------------------------------------- jamie · 2020-05-02 15:37 The same could be true for Classes, too.  I believe I suggested this somewhere long ago to have a AUTO or managed keyword in the Constructor and destructor tags..  But there has to be a away to nullify the effect if you desire to manually create it and that would be to have a NotAuto keyword for example Var   MyAutoClass:TAutoClass; NotAuto; // not today.. Begin   MyAutoClass := TAutoClass.Create; etc and of course if your chose is for auto then just don't use the NotAuto and if there is an Autos then there you go..  But there also another issue, Objects do not need  Constructors/Destructors so the naming needs to be  alittle different...  AutoConstruct, AutoDestruct appended to what ever methods in this case.  And I agree with  you that would make it easier on the eyes.  Or course these need to be parameter free; EDIT   And I wanted to add , good luck in getting some motion on it. ---------------------------------------------------------------------- Martin_fr · 2020-05-02 15:58 At least the "with ... as .. do" was discussed previously. Though I do not have a link, nor remember the details. AFAIK: As for "managed" your ideas are (from a compiler implementation detail) quite different to "managed types" (ansistrings/dyn-array, both of them only work the way they do, because they are pointer based. "object" is not pointer based). While not directly on your subject: Lots of people (Afaik, especially Delphi users) use undocumented side effects of IInterface, to get refcounted behaviour. However since they relay partly on undocumented behaviour, their code may break with any fpc upgrade. Other related (though not old school object) topics that can be found in this forum: - Upcoming support for closures (at least most likely upcoming). Closures are ref-counted. - Discussion on (future) "smart pointers" (ref counted / IIRC: auto called methods for init, copy(?), free) --- Note that any "ref counted" does not include any form of GC. Circular refs are not detected. (This is already true for dyn arrays) ---------------------------------------------------------------------- avk · 2020-05-02 16:27 Is that what you are talking about? ---------------------------------------------------------------------- Martin_fr · 2020-05-02 16:45 Quote from: avk on May 02, 2020, 06:27:37 pmIs that what you are talking about? I don't know LGenerics, or if it pertains to either of the things I mentioned. As for closures, probably: https://svn.freepascal.org/svn/fpc/branches/blaise/closures But no idea if that is the most recent. As for "smart pointers"  they were discussed in the past, and searching through svn: https://svn.freepascal.org/svn/fpc/branches/maciej/smart_pointers Afaik, neither is functional yet. ---------------------------------------------------------------------- Warfley · 2020-05-02 16:52 Quote from: avk on May 02, 2020, 06:27:37 pmIs that what you are talking about? Pretty much, but I've absolutely never head about the operators Initialize, Finalize or Copy. Also this is a record, so it misses some of the functionality of objects (like inheritance) Quote from: Martin_fr on May 02, 2020, 05:58:44 pmAFAIK: As for "managed" your ideas are (from a compiler implementation detail) quite different to "managed types" (ansistrings/dyn-array, both of them only work the way they do, because they are pointer based. "object" is not pointer based). Yeah I don't mean the exact functionality but simply analogously to exectue the constructor and destructor at the same point such functions would be called for the managed types. For example the Refcount object I've wrote in the end is pretty much exactly the same as a dymaic string. Quote from: Martin_fr on May 02, 2020, 05:58:44 pmLots of people (Afaik, especially Delphi users) use undocumented side effects of IInterface, to get refcounted behaviour. However since they relay partly on undocumented behaviour, their code may break with any fpc upgrade. Other related (though not old school object) topics that can be found in this forum: - Upcoming support for closures (at least most likely upcoming). Closures are ref-counted. - Discussion on (future) "smart pointers" (ref counted / IIRC: auto called methods for init, copy(?), free) --- Note that any "ref counted" does not include any form of GC. Circular refs are not detected. (This is already true for dyn arrays) Yes I know, the thing is, simply implementing ref-counting is IMHO simply adding some "compiler magic" for some specific occasion. This would be an approach where you could build this (and a lot more useful things) as you please. It is in my oppinion more powerful, even though some syntaktic sugar for refcounting would of course be nice (i.e. that you don't have to write something like ref.get to get the data). This allows for much more flexibility, for example this could be extended to unique objects where you could do something like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i operator :=(const rhs: TUniqueObject): TUniqueObject;begin  Raise EObjectCantBeDublicatedException.Create;end;Another possibility would be to use this to implement critical sections that live as long as the containing object lives. With using (ref counted) classes this would 1. add overhad through more pointer chases, 2. add overhead through refcounting operations when copying the pointer. Here you can copy the pointer to that object without fear of triggering the constructor or destructor C++ does the smart pointers quite similar, the big exception here is that C++ can overload the dereference operators -> and *. If there would be an appropriate operator to overload this could be also done like: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ref := TReference.Init(TStringList.Create);ref^.LoadFromFile(filename);for line in ref^.lines do  ... But I must say, I'm not a big fan of "compiler magic" I rather like having one unified approach that can be used to cover all of these things. I really like the idea that a programmer could say: I don't like lazy copy ansistrings, I want to implement no-copy ansistrings, and this would be possible with such an approach. But maybe thats just me QuoteThe same could be true for Classes, too.I don't think that this makes that much sense for classes because if you have something that should only live during a scope (e.g. a function), IMHO it doesn't make much sense to use a class anyways because you allocate memory to deallocate it afterwards. Limiting classes to a scope means no matter what you do with their pointer it will be invalid after the scope. For classes it would be better to implement reference counting, which in turn could be implemented using such objects (even though some syntactic sugar might be nice) QuoteBut there has to be a away to nullify the effect if you desire to manually create it and that would be to have a NotAuto keyword for exampleFor classes defenetly, so the pointer does not get invalid (as I said) for objects I don't see this as that neccesary, but of course such an addition could be usefull if one want's to abuse some side effects (e.g. creating a list and then getting the memory pointer without the list freeing it afterwards). ---------------------------------------------------------------------- 440bx · 2020-05-02 17:05 Quote from: Warfley on May 02, 2020, 06:52:04 pmI don't think that this makes that much sense for classes because if you have something that should only live during a scope (e.g. a function), IMHO it doesn't make much sense to use a class anyways because you allocate memory to deallocate it afterwards. Limiting classes to a scope means no matter what you do with their pointer it will be invalid after the scope. For classes it would be better to implement reference counting, which in turn could be implemented using such objects (even though some syntactic sugar might be nice) That's one of the many problems with classes.  Their maintenance requirements are very similar to those of global variables. If classes were stack objects, they wouldn't get in the way of recursion, it wouldn't take any code to create them and destroy them (memory leaks are a fairly common subject in the forum), they would be as easy to manage as local variables (can't leak those!.)  As long as they are initialized, everything is fine, everything else happens automatically.    Not to mention that it's quite a bit faster to allocate/release memory on the stack than on the heap and, doesn't require any code. Forget everything I said... I cannot stand all the problems these "objects" and "classes" create. ---------------------------------------------------------------------- flowCRANE · 2020-05-02 17:46 An interesting idea with these managed elements. But I still don't understand why this wave of dissatisfaction with the current functionality of classes and objects, and why people still have a problem with memory leaks. IMO the compiler magic is a real problem, not the current form of class use, which is trivial and pure. At least for me. ---------------------------------------------------------------------- Martin_fr · 2020-05-02 17:53 Quote from: 440bx on May 02, 2020, 07:05:39 pmForget everything I said... I cannot stand all the problems these "objects" and "classes" create. Just to clarify: "object" can refer to "instance of class" or "old style object, resides on stack, like record". In this thread the latter was referred to. As for instances, ignoring all else you mentioned except "alloc on heap". If you do none OOP style code, where do you put your data? If you wrote a text editor, would you put the entire text on the stack? At least I would use some form of AllocMem/New/... to get heap mem, to store such data. And then in terms of memory alloc and leaks, I would be pretty much where I am with OOP. Off topic: Except, that an instance use one additional pointer to point to the class info. So yes, in cases where the class does not carry actual information that pointer is wasted. In cases where the class-type is actual data, that otherwise needed to be stored, it equals out (can be a partial waste, or can be a saving). And yes, there is the once of cost of maybe 30 bytes for the class itself. But forget the last paragraph, the point is, that I can not see how you avoid allocating heap mem by using none OOP style. It may well be possible in the projects you have. None of the work I have done, could live without heap in some form or another. --- EDIT: One point for you, that I forgot. But not OOP in general. Only OOP in current Pascal: Using a class, means that the compiler stores the classname as string in your exe. Even if you do not use it. So a few more bytes gone, and some Info provided to people hacking your exe. But also beside the point of using heap and risking leaks There are more diffs, but as far as I can see they do not pertain to"using heap and risking leaks", which is what I ask about. ---------------------------------------------------------------------- Warfley · 2020-05-02 18:30 Quote from: furious programming on May 02, 2020, 07:46:48 pmBut I still don't understand why this wave of dissatisfaction with the current functionality of classes and objects, and why people still have a problem with memory leaks. IMO the compiler magic is a real problem, not the current form of class use, which is trivial and pure. At least for me.  First regarding my dissatisfaction with current objects, Simply if you have to initialize and finalize them, you need to explicitly call the constructor and add try-finally for the destructor. I think that this code can really clutter the code making the important bits less obvious. For example in Strings you know when your procedure starts it will be empty, if your procedure ends the memory will be freed. In an object when you start your procedure you have random stuff written into it, when your procedure ends allocated resources need to be freed automatically. It's a readability issue first and foremost. With classes it is especially a bit different. Let's say I need to read a CSV file, great all I need is a stringlist. Create stringlist -> Read file -> delimited text -> access as array -> free stringlist. If the StringList was an object, it would be placed on the stack, which first of all is faster than a heap allocation (basically placing something on the stack is adding a number to esp, the fastest instruction a CPU can do), allocating memory on the heap requires a complicated memory manager. There are things where you need your heap variables. Polymorphic Tree structures (e.g. components on a form) are such a thing, and here classes really shine. But in situations where you need a single object for a short amount of time, objects would be a much better solution. Add this with such managed objects, this csv reading would reduce to read file -> delimited text -> access as array. And with memory leaks it's also quite simple, everyone will eventually produce a memory leak somewhen. This might be small and easy to fix, or you are in a situation where it is not that easy to fix because you don't actually know whos the last object to access it (e.g. having a DAG where you can only free your kids if all of their parents got freed). But this is a solved problem. In C++, Rust, Swift, Go, etc. (all compiled languages, so no GC like in Java or C#) producing memory leaks is really hard to impossible due to reference counting and (in the case of rust and C++) strict ownership models. Sure it impacts the performance a bit, but the code gets much cleaner and you don't need to worry about memory leaks. Take simply this code as an example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   concatKey := Key + WebsocketMagicString;  keyHash := SHA1String(concatKey);  OutputStream := TStringStream.Create('');  try    b64Encoder := TBase64EncodingStream.Create(OutputStream);    try      b64Encoder.WriteBuffer(keyHash[low(keyHash)], Length(keyHash));      b64Encoder.Flush;      Result := OutputStream.DataString;    finally    b64Encoder.Free;    end;  finally    OutputStream.Free;  end;With reference counting it would be: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   concatKey := Key + WebsocketMagicString;  keyHash := SHA1String(concatKey);  OutputStream := TStringStream.Create('');  b64Encoder := TBase64EncodingStream.Create(OutputStream);  b64Encoder.WriteBuffer(keyHash[low(keyHash)], Length(keyHash));  b64Encoder.Flush;  Result := OutputStream.DataString;It's half the amount of lines, which simply was nothing more than boilerplate code that was just required because of the manual memory management. So to summarize, everyone will once in a while produce a memory leak. Avoiding them requires lots of boilerplate code. The problem can be pretty hard to solve. It is simply avoided using reference counting and/or ownership models, with the overhead being one addition and check against > 0. Sure there are situations in which you need that performance (and I had to switch from smartpointers to manual memory management in a C++ project once), but the benefits outweigh the performance loss by far. Also what should be noted is that memory leaks are one thing, but if you free your memory to early you can get a use-after free, which not only can result in Segfaults, but can also get you in real trouble because it could create problems at totally different points in the program. This is also fixed when using reference counting. The worst thing that can happen with a memory leak is that your application might get killed by the OS because it requires to many resources. A use after free in a server software could end up with someone poping a root shell on your server. This is one of the reasons why firefox is currently rewritten in rust. Take a look at this https://hacks.mozilla.org/2019/02/rewriting-a-browser-component-in- rust/ In a CSS component of Firefox there where 32 out of the 34 high risk bugs that where found in there memory related, something that simply could not have happend with a strict ownership model like rust ---------------------------------------------------------------------- Thaddy · 2020-05-02 18:47 OP is confusing C# (or Java() with C++. C++ - as a language - has no automatic memory release at all. Although there are some libraries for it that do. Same as in FreePascal. ---------------------------------------------------------------------- 440bx · 2020-05-02 18:53 Quote from: Martin_fr on May 02, 2020, 07:53:47 pmIf you do none OOP style code, where do you put your data?I simply allocate a memory block from the O/S (in Windows using VirtualAlloc(Ex) and manage that block myself. Quote from: Martin_fr on May 02, 2020, 07:53:47 pmIf you wrote a text editor, would you put the entire text on the stack? No, of course not.  I'd memory map the original file and make it read- only. I'd have one "database" structure that keeps track of all the files being edited (an editor should be able to edit many files simultaneously - preferably in the hundreds.)  That structure would probably be an array of "descriptors" which would include the filename, its size, its undo chain, its modified areas chain, etc for each file.  The important thing is, the only variable needed would be a pointer to that database and that pointer would be on the stack (no need to have it as a global).  The database, in turn would be a series of pointers into VirtualAlloc-ated blocks that I carve myself according to what's needed. Sometimes, very rarely, I feel lazy and what I do is create a heap, put a bunch of stuff in there (the pedestrian way, with HeapAlloc) and I when I no longer need the data it contains, I destroy the entire heap.  That way, I don't have to keep track of a bunch of small blocks that if not deallocated end up being memory leaks.  "Leaking" an entire heap is very noticeable, that leak won't last long   Actually, almost always that I code a call to "HeapAlloc" it's because I know the block I am asking for is too large for the heap manager which will result in the heap manager calling VirtualAlloc for me.  That saves me a couple of lines of code when I want the entire block committed. Also, if the "database" structure that keeps track of all the memory blocks uses somewhere in the ballpark of 128K or less, I have no problem having it on the stack and, either passing a pointer to it around or passing it as a var (which is the same thing.  Of course, with a structure that large, recursion is either not an option or limited to one or levels and no more. Quote from: Martin_fr on May 02, 2020, 07:53:47 pmAt least I would use some form of AllocMem/New/... to get heap mem, to store such data. And then in terms of memory alloc and leaks, I would be pretty much where I am with OOP. The thing is, once using a class, the programmer is committed to a specific way of managing memory. I was a bit "cavalier" with the "object" and "class" references.  I know that old style "objects" can reside on the stack (a huge advantage over classes).   Managing little chunks of memory (be them classes or anything else) is cumbersome, not flexible and definitely error prone.   When you do your own memory management, you can choose how to break groups of information/data, allocate blocks based on their use and lifetime.  You can easily design a program that uses VirtualAlloc yet, can easily be made recursive. Honestly, that the class may use 30 bytes or more to keep its name or whatever else it wants to keep is not a concern.  If it wants 256 bytes, no problem, it's lucky-byte hour - it's on the house. ---------------------------------------------------------------------- Warfley · 2020-05-02 19:18 Quote from: Thaddy on May 02, 2020, 08:47:55 pmC++ - as a language - has no automatic memory release[/b][/i] at all. Although there are some libraries for it that do. Same as in FreePascal. The C++ standard also defines that the standard library, which needs to contain std::shared_ptr and std::unique_ptr. It's not that some libraries provide that, every C++ installation needs to provide that. I think it is therefore fair to say that it C++ provides it ---------------------------------------------------------------------- Warfley · 2020-05-02 19:36 Quote from: 440bx on May 02, 2020, 08:53:01 pmI simply allocate a memory block from the O/S (in Windows using VirtualAlloc(Ex) and manage that block myself. I have a questions about this, why do you use a system call for this? I mean you could do the same but rather than using VirtualAlloc use getmem and then work on that memory region? Why would you want to do a context switch for every memory block you need. The reason people use memory managers is mostly because they allocate large chunks using VirtualAlloc and divide them into sub chunks. To get a chunk using the MM from an already allocated block of memory is much faster than a syscall. See https://blog.tsunanet.net/2010/11/how-long-does-it-take- to-make-context.html doing a context switch can be really expensive, and I would guess that you are wasting at least 10x the time instead of using a memory manager. Besides this I'm reading VirtualAlloc and HeapAlloc, both of those are windows only functions, in fact there is no alternative HeapAlloc in POSIX systems, because there the System can not provide you a heap, meaning there you would need to use a memory manager, which opens up the question again, why not use it in the first place? ---------------------------------------------------------------------- Martin_fr · 2020-05-02 19:40 @440bx: Thanks for explaining your point. Yes OOP gets you to use whatever mem manager you selected (you can choose, and you can do your own). Btw, so does ansi-string and dyn array. Actually, about using classes, and being bound to a memory model.... You can override NewInstance/FreeInstance and provide memory for your instance by any means you want (I guess, including dividing a block you got yourself from the OS). If you know you need a 1000 instances of TFoo, and you want to avoid mem fragmentation, then you allocate one block to fit all 1000 of them (and if you need more, you allocate a 2nd block and so on), and then all your instances use that block of mem. And, yes I am aware, there are more things about OOP that deter you from using it. No problem. It's about choice. ---------------------------------------------------------------------- flowCRANE · 2020-05-02 19:47 Quote from: Warfley on May 02, 2020, 08:30:06 pmSimply if you have to initialize and finalize them, you need to explicitly call the constructor and add try-finally for the destructor If the creation and destruction are in the same scope. QuoteI think that this code can really clutter the code making the important bits less obvious. And the compiler silent-magic is more obvious? Really? If I see the constructor, then I'm sure that I will deal with class instance — it's obvious. If I see such a code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i concatKey := Key + WebsocketMagicString;keyHash := SHA1String(concatKey);OutputStream := TStringStream.Create('');b64Encoder := TBase64EncodingStream.Create(Ou tputStream);b64Encoder.WriteBuffer(keyHash[low(keyHash)], Length(keyHash));b64Encoder.Flush;Result := OutputStream.DataString; I completely don't know what is going on in it, I have no idea what the identifiers are and I need to check their declaration to find out how this code works. The code is not self-explanatory and requires more attention than that written in the standard way. QuoteIt's a readability issue first and foremost. No, it is only a matter of convenience (in theory), because it has nothing to do with readability. Sorry. A readable code is one that one looks at and immediately knows what it consists of and how it works (to some extent, because you can't read everything at once). QuoteIf the StringList was an object, it would be placed on the stack, which first of all is faster than a heap allocation If you need efficiency, write efficient code — use tricks, come up with custom optimizations. For the rest of purposes (probably 95%) it does not matter. Stop hurting yourself thinking that the using of the heap is a bottleneck. Quote[…] allocating memory on the heap requires a complicated memory manager. So? We have a year 2020, not 1980, memory manager is just nothing extraordinary. Just like executable files weighing several megabytes, which still a lot of people consider a huge disadvantage (which every time makes me laugh). QuoteBut in situations where you need a single object for a short amount of time, objects would be a much better solution. Maybe, but why complicate the code if I use classes everywhere else? To save a few dozen bytes or a few nanoseconds in runtime? In addition, I can conveniently pass the instance because it is a (hidden) pointer and the objects are not. QuoteAnd with memory leaks it's also quite simple, everyone will eventually produce a memory leak somewhen. I don't remember the last time I caused a memory leak, really. And all because I use an extremely simple solution. If I need to use an instance of a class (or a dynamically allocated block, no matter), I take three steps: I declare a variable (never use with).I am writing a line with a constructor in the given place and immediately……writing a line with the destructor in the right place (if in the same scope, also the try finally block).Problem solved. It doesn't matter if I use simple classes or collections, trees etc. QuoteAlso what should be noted is that memory leaks are one thing, but if you free your memory to early you can get a use-after free, which not only can result in Segfaults, but can also get you in real trouble because it could create problems at totally different points in the program. It looks like looking for a reason to relieve the programmer of thinking. If you use a hypothetical managed class in a given location, you know that it will expire out of scope. And since you know it will expire, you also know that here you should release the normal class instance. No profit and readability worse. In summary, I'm not a fan of the approach that the compiler should think instead of a programmer. For me, it's natural and clear that if I allocate memory, I should deallocate it — and these are the two most important things before I start using the instance. If I use complicated elements, such as classes, I want to have full control over them. The more the compiler tries to be smarter than the programmer, the more the programmer will not be able to control the code he produces. The easiest way to disaster. But I will not advise against introducing managed classes/objects. I will probably not use them anyway, at most I will learn how to use them to be able to understand someone else's code. After all, programmers learn all their lives, so it is not a problem for me. ---------------------------------------------------------------------- Warfley · 2020-05-02 20:20 Quote from: furious programming on May 02, 2020, 09:47:03 pmAnd the compiler silent-magic is more obvious? Really? If i see the constructor, then I'm sure that I will deal with class instance — it's obvious. The variable gets initialized as soon as it is declared and gets finalized as soon as it get's out of scope. Do you really think that is hard to understand? Quote from: furious programming on May 02, 2020, 09:47:03 pmIf I see such a code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i concatKey := Key + WebsocketMagicString;keyHash := SHA1String(concatKey);OutputStream := TStringStream.Create('');b64Encoder := TBase64EncodingStream.Create(Ou tputStream);b64Encoder.WriteBuffer(keyHash[low(keyHash)], Length(keyHash));b64Encoder.Flush;Result := OutputStream.DataString; I completely don't know what is going on in it, I have no idea what the identifiers are and I need to check their declaration to find out how this code works. The code is not self-explanatory and requires more attention than that written in the standard way. You should have read it before making that claim . Because all that is missing from the previous example is the .Free and the try-finallys. If you can spot the type of a variable by it's .Free but not by the .Create call (which still exists) you must be a magician. Also the types are all declared in the var section above. If you follow well readable code guidelines and your code is at most 20 lines long, shouldn't be so hard to spot the variable definition. QuoteNo, it is only a matter of convenience (in theory), because it has nothing to do with readability. Sorry. A readable code is one that one looks at and immediately knows what it consists of and how it works (to some extent, because you can't read everything at once). So feel free to argue why try-finally and .Free add to the readability? How do these lines improve the understanding of the code? QuoteIf you need efficiency, write efficient code — use tricks, come up with custom optimizations. For the rest of purposes (probably 95%) it does not matter. Stop hurting yourself thinking that the using of the heap is a bottleneck. So? We have a year 2020, not 1980, memory manager is just nothing extraordinary. Just like executable files weighing several megabytes, which still a lot of people consider a huge disadvantage (which every time makes me laugh).It's not that you need the performance, I'm happily willing to give up some performance for other perks. The thing is that in many situations the use of classes does not grant you any perks and is less efficient. QuoteMaybe, but why complicate the code if I use classes everywhere else? To save a few dozen bytes or a few nanoseconds in runtime? In addition, I can conveniently pass the instance because it is a (hidden) pointer and the objects are not. Yes in some cases classes are better fitted in others objects. Whats wrong with having more efficient tools at your disposal? If you want to you can still only use classes. This is about adding new features to the language, not to take anything away from you. QuoteI don't remember the last time I caused a memory leak, really. And all because I use an extremely simple solution. Ok, maybe you are simply an insane programmer who is better than the whole development team at Mozilla. I'm not, I will sometimes get problems managing memory. QuoteIf I need to use an instance of a class (or a dynamically allocated block, no matter), I take three steps: I declare a variable (never use with).I am writing a line with a constructor in the given place and immediately……writing a line with the destructor in the right place (if in the same scope, also the try finally block).Problem solved. It doesn't matter if I use simple classes or collections, trees etc. So you are creating your instances in the constructor and destroy them in the destructor, but above you were complaining that leaving out a few .Free's inside a scope will make the code unreadable? Interesting... QuoteIt looks like looking for a reason to relieve the programmer of thinking.You make it sound like this is a bad thing. The less the programmer has to think the less mistakes he can make the better the quality of the code. Why don't we all code in brainfuck, there you have to think much more -> it is better. QuoteIf you use a hypothetical managed class in a given location, you know that it will expire out of scope. And since you know it will expire, you also know that here you should release the normal class instance. No profit and readability worse.So again, how does leaving out the .Free and try-finally make the readability worse? You can still call the constructor by hand if you wan't, the most important thing is the removal of the uneccesary of the destructor. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i In summary, I'm not a fan of the approach that the compiler should think instead of a programmer.Again, why is this bad? The more the compiler can do for you, the less mistakes you are going to do and the more time and energy you have to focus on the important bits. I mean sure, you are better than the whole development team of Mozilla, and maybe you never have problems, we mere mortals do. If we could write a compiler that takes an Idea out of my head and creates a perfect program from it, I would use it. According to the same logic we should abolish optimizers, because why don't we write optimal code directly. We should abolish high level conecpts like functions because goto let's you think more. QuoteThe more the compiler tries to be smarter than the programmer, the more the programmer will not be able to control the code he produces. The easiest way to disaster.That is in my oppinion the complete wrong approach. IMHO the compiler (and libs) should take most of the work from the programmer, and only if it is needed, one should lay his hands on this. C++ is quite a great example for this. You can use really high level stuff. In modern C++ code you shouldn't see a single new/delete anymore. But if you need it, you can still go low level. As I said, I was in that situation exactly once that I simply needed the raw performance of manual memory management. But all the other times using shared_ptr (reference counted pointers in C++) was the better solution QuoteBut I will not advise against introducing managed classes/objects. I will probably not use them anyway, at most I will learn how to use them to be able to understand someone else's code. After all, programmers learn all their lives, so it is not a problem for me.As you might have noticed from this response, I have a completely different philosophy on how code should be written. But I think the most important thing is to not restrict the available tools. I think it would be a nice addition that could be helpful in some circumstances. Classes on the other hand of course still have their strength and weaknesses, and the more tools one has, the better code he can write ---------------------------------------------------------------------- marcov · 2020-05-02 20:25 This has been broad up before, and there are some practical problems. First, static objects are not true objects, as there is no form of polymorphism., a key aspect of objects. So these are not managed objects, but autoinitialized/finalized records. While these have some use, that usage is again more record like. But maybe I'm wrong, and I never fully understood RAII properly. Please enlighten me, with nice examples. (added later:) Oh, and afaik FPC 3.2.0 supports it using management operators: https://wiki.freepascal.org/management_operators an example of record initializers: https://forum.lazarus.freepascal.org/index.php/topic,46699.msg360398.h tml#msg360398 ---------------------------------------------------------------------- Warfley · 2020-05-02 20:39 Quote from: marcov on May 02, 2020, 10:25:23 pmThis has been broad up before, and there are some practical problems. First, static objects are not true objects, as there is no form of polymorphism., a key aspect of objects. So these are not managed objects, but autoinitialized/finalized records. While these have some use, that usage is again more record like. But maybe I'm wrong, and I never fully understood RAII properly. Please enlighten me, with nice examples. Yes, they are no replacement for classes, but also aren't records either. You can have polymorphism but only on a pointer basis. Example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type   { TShape }   TShape = object  public    X, Y: Double;    constructor init(AX, AY: Double);    function getArea: Double; virtual; abstract;  end;   { TCircle }   TCircle = object(TShape)  public    Radius: Double;    constructor Init(ARadius, AX, AY: Double);    function getArea: Double; virtual;  end; constructor TShape.init(AX, AY: Double);begin  X:=AX;  Y:=AY;end; { TCircle } constructor TCircle.Init(ARadius, AX, AY: Double);begin  inherited Init(AX, AY);  Radius:=ARadius;end; function TCircle.getArea: Double;begin  Result := 2*pi*Radius*Radius;end; procedure PrintShape(var S: TShape);begin  WriteLn('X: ', S.x, ' Y: ', S.Y, ' Area: ', S.getArea);end; var  circ: TCircle;begin  circ.Init(4, 2, 1);  PrintShape(circ);  ReadLn;end.   Note the var in PrintShape(var S: TShape); this is required so the instance is passed by reference (i.e. a hidden pointer), which allows for the polymorphism. Classes are always pointers, therefore you don't need to care how to pass the data. So while during the initialization you can't have polymorphism, but you can call functions that make use of the polymorphism. So besides still having a form of polymorphism, you also have constructors, destructors, private fields, inheritance in general (which can be useful not only for polymorphism, also for reducing code dublication). You can think of them as more advanced advanced records. ---------------------------------------------------------------------- marcov · 2020-05-02 20:46 Quote from: Warfley on May 02, 2020, 10:39:36 pmYes, they are no replacement for classes, but also aren't records either. You can have polymorphism but only on a pointer basis. Example: No, not polymorphic IMHO. Yes, you can pass it to a by-reference or pointer parameter in a polymorphic way, but that doesn't allow the function to really do something  polymorphism, since it needs to pass it  to another procedure first. I was more thinking about getting some by objects by ref, doing something with some local objects as state (e.g. swap) Then again, I didn't immediately think of this example, so it is at least something, even as limited as it is. Anyway, I don't know if management operators work for old objects. And I still don't think it is worth setting up a parallel object primitive type for. I think TP objects are better left forgotten. ---------------------------------------------------------------------- Warfley · 2020-05-02 20:55 Quote from: marcov on May 02, 2020, 10:46:46 pmAnd I still don't think it is worth setting up a parallel object primitive type for. I think TP objects are better left forgotten. I really like them because they have some key advantages over advanced records. Constructors, Destructors (which this is all about), private members, and still some form of inheritance, which at least allows for reducing code dublications. (I have edited my post right when you posted so I'll put this here again) And one major advantage over classes for the purpose of this thread is the overloading of the assignment operator for same types. For classes this would be a bad Idea, because the assignment operator there assigns pointer not values. Objects on the other hand this wouldn't be a problem, because if you would want to copy them bytewise you could still use Move(obj1, obj2, sizeof(obj1)) and to pass references still use pointer. So the assignment could be overloaded in comparison to classes (which have to provide the .Assign method like TPersistent). This for example would allow to easiely open different files using one Object which is assigned a newly constructed object for each filestream, and closing that stream in the destructor ---------------------------------------------------------------------- flowCRANE · 2020-05-02 20:59 Quote from: Warfley on May 02, 2020, 10:20:14 pmThe variable gets initialized as soon as it is declared and gets finalized as soon as it get's out of scope. Do you really think that is hard to understand? It is simple to understand as a theory, but I think that in the actual code it will not be that obvious. QuoteYou should have read it before making that claim Sure, but you forgot to attach the veriable declarations — I don't know what the b64Encoder is. A local variable? Global? An argument? If is see the try finally, I'm sure that it is a local variable — nothing to check. QuoteSo feel free to argue why try-finally and .Free add to the readability? How do these lines improve the understanding of the code? It is simple — the try finally block tells the programmer that he is dealing with a local instance and there is no way it could be otherwise. The Free method says that the instance is no longer needed and is released (not stored somewhere else, not passed and no managed elsewhere). The lack of block and Free will make things less obvious. QuoteThe thing is that in many situations the use of classes does not grant you any perks and is less efficient. Come on, but still it does not mean that the usage of the classes is the bottleneck and must be optimized. QuoteYes in some cases classes are better fitted in others objects. Whats wrong with having more efficient tools at your disposal? If you want to you can still only use classes. This is about adding new features to the language, not to take anything away from you. Of course, I have the same approach for having more useful features. Just look at the last paragraph in my previous post. QuoteOk, maybe you are simply an insane programmer who is better than the whole development team at Mozilla. I'm not, I will sometimes get problems managing memory. Thank you, but I bet that it's not a true. QuoteSo you are creating your instances in the constructor and destroy them in the destructor […] In many cases, yes, but not in all cases. We have a many more places to allocate and dispose the resources, not only in local scope and in contructor/destructor. QuoteYou make it sound like this is a bad thing. This is useful to some extent, but if the compiler does too much magic, fully understanding the code will also require magic. But of course this is my opinion, you may not agree with it. ---------------------------------------------------------------------- marcov · 2020-05-02 21:12 Quote from: Warfley on May 02, 2020, 10:55:40 pmAnd one major advantage over classes for the purpose of this thread is the overloading of the assignment operator for same types. For classes this would be a bad Idea, because the assignment operator there assigns pointer not values. Not really. You could have a deep copy operator for classes, and check classtype equivalency (the most recent common ancestor so to speak). I assume nowadays most language would use RTTI or some other form of reflection.  The assign option was not the most elegant option, but I assume they needed it to be in code for some cases, and having two systems might have been a bit too much in then still 16-bit Delphi. QuoteObjects on the other hand this wouldn't be a problem, because if you would want to copy them bytewise you could still use Move(obj1, obj2, sizeof(obj1)) and to pass references still use pointer. (also copies the VMT pointer, ugh, dangerous if declared differently) In the classes case, the compiler knows the size of the fields area of an object too, and the relative offset of the first field, so a deep copy operator could be made. That is in itself not the reason for a totally new object hierarchy. QuoteThis for example would allow to easiely open different files using one Object which is assigned a newly constructed object for each filestream, and closing that stream in the destructor But that works for advanced records with management operator too I think. You don't need tired old TP Object and revamp it with umpteen "modern features" and debug their cross-talk for that since TP object only adds polymorphism, which is somewhat hindered in this case. ---------------------------------------------------------------------- Warfley · 2020-05-02 21:27 Quote from: furious programming on May 02, 2020, 10:59:37 pmSure, but you forgot to attach the veriable declarations — I don't know what the b64Encoder is. A local variable? Global? An argument? If is see the try finally, I'm sure that it is a local variable — nothing to check. If you can work this out for keyHash, which never had a try finally, I trust you to also find this out for b64Encoder QuoteCome on, but still it does not mean that the usage of the classes is the bottleneck and must be optimized.Not saying we need to optimize this, but with the right tools at hand we could optimize this without losing anything QuoteThank you, but I bet that it's not a true. As I noted earlier, 32 out of the highly critical 34 bugs in a Firefox component where memory errors. Sure there are a lot of situations in which managing memory is not hard, but in such cases (especially if you are writing a securitiy critical application like a browser) having tools at your disposal that take care about this issue, is a good idea. QuoteThis is useful to some extent, but if the compiler does too much magic, fully understanding the code will also require magic. But of course this is my opinion, you may not agree with it. I agree with you but I think I have a different understanding of "magic". Because the thing I'm proposing is basically a pretty small set of rules (construction on entering the procedure, destruction on destruction of the containing memory object or assignment), which then allows for a large variety of tools like reference counting. "Compiler Magic" to me is when the rules are either 1. not clear or 2. to specific. e.g. in python the "is" operator checks the type of a variable (i.e. x is None, where None is the type of the value None). Its a binary operator that takes a variable and a type and returns a boolean. Simple as that. Not is an unary operator that inverts a boolean. Also simple. not x is None therefore tests if x is not of type None. But you can also write x is not None. The "in" operator checks if an object is in a collection, e.g. x in [1, 2, 3]. But for not x in ... you could also write x not in ... but you can't either write x not is None or x in not ... These are rules that are only implemented for these respected operators. Highly specific and not really clear (you could say it should increase readability but thats at most vaguely defined). So to me that is magic. So while I agree with the sentiment in general, I disagree on the degree ---------------------------------------------------------------------- Warfley · 2020-05-02 21:43 Quote from: marcov on May 02, 2020, 11:12:37 pmBut that works for advanced records with management operator too I think. You don't need tired old TP Object and revamp it with umpteen "modern features" and debug their cross-talk for that since TP object only adds polymorphism, which is somewhat hindered in this case. Ah I didn't know about management operators. Thats of course great news! I guess they will then be available with the next FPC stable version? But there are still a few things I think are much better about objects. Most notably: 1. Private fields 2. Properties 3. Parametrized constructors 4. Inheritance Parameterized constructors can circumvented using functions, but the others are in my oppinion defenetly advantages from classes to advanced records. But having these managed records is at least something ---------------------------------------------------------------------- 440bx · 2020-05-02 21:47 Quote from: Warfley on May 02, 2020, 09:36:06 pmI have a questions about this, why do you use a system call for this? I mean you could do the same but rather than using VirtualAlloc use getmem and then work on that memory region?because I'd much rather depend on an O/S function that on any language's RTL functions.  If I am interested in portability, I can wrap the call to VirtualAlloc in a function (I commonly use MemoryAllocate but not because of portability.) Quote from: Warfley on May 02, 2020, 09:36:06 pmWhy would you want to do a context switch for every memory block you need. I don't.  Usually, there is a context switch only for large blocks (added: because I only make the call to allocate large blocks), which I then carve into smaller blocks myself, which is extremely fast.  However, sometimes there are some areas of memory in a program, which may not be large but, I want to ensure I can visually inspect them no matter where the program execution happens to be.  In those cases, I will VirtualAlloc a block (often just one page), which is usually alive for the entire duration of the program, because that way, I can use that pointer in an external memory viewer and see the data without having to rely on it being visible to the program and/or debugger.  When you do manage the memory yourself, there are all kinds of advantages you can derive from that which are simply not available when going through the cushy/canned stuff RTL functions provide.  Another really nice characteristic of doing it that way is that, every block of memory is for _one_ and only _one_ type of data. That means all my data is divided into group and every group has its own "bucket".   Contrast that with a heap, if you don't know the address of the one piece of data you'd like to see, you're out of luck and, even if you know, the address, when you look at it in a memory viewer, what you'll see is a "soup" of data.  Data of one kind, followed by data of another kind, followed by yet another kind, etc, etc.  Making sense of data structures (such as linked lists, queues, dictionaries) is significantly more difficult when the elements that make them up are all mixed together. Quote from: Warfley on May 02, 2020, 09:36:06 pm The reason people use memory managers is mostly because they allocate large chunks using VirtualAlloc and divide them into sub chunks. Correct.  That is what I do _and_ the one large chunk is going to be divided into very specific types of data.  Data that belongs together.  That way it's easy to visualize and you always have easy access to it through an external memory viewer. Quote from: Warfley on May 02, 2020, 09:36:06 pmI would guess that you are wasting at least 10x the time instead of using a memory manager. On the contrary. As I've mentioned, there are usually very few calls to VirtualAlloc in the program.  Most of them, at initialization time.  Doing my own block carving makes malloc and getmem look like sedated paraplegic dogs. Quote from: Warfley on May 02, 2020, 09:36:06 pmBesides this I'm reading VirtualAlloc and HeapAlloc, both of those are windows only functions, in fact there is no alternative HeapAlloc in POSIX systems, because there the System can not provide you a heap, meaning there you would need to use a memory manager, which opens up the question again, why not use it in the first place? I am completely Windows centric.  If someone is concerned about making my code run on another O/S, I wish them good luck and, I request they remove my name from the port.   I don't want to be associated with it because the result often doesn't reflect the way I program and, if it doesn't, then my name shouldn't be on it. Regarding another comment you made. I completely agree with @furious programming.  Compilers cannot think, therefore they shouldn't try.  A compiler should do _exactly_ what the programmer told it to do, no less _and_ definitely not more either and, that doesn't preclude doing optimizations. The compiler's job is to find the best way to do what the programmer instructed to do, no more, no less.  Creative compilers are very dangerous critters.  I know a compiler that "thinks" zero is a positive-only quantity.    That's Woodstock stuff... flashbacks...   What would you say if I coded out of alignment... would you except out on me... with a little help from my compiler... Quote from: Martin_fr on May 02, 2020, 09:40:12 pm@440bx: Thanks for explaining your point. You're welcome.  My pleasure. Quote from: Martin_fr on May 02, 2020, 09:40:12 pmActually, about using classes, and being bound to a memory model.... You can override NewInstance/FreeInstance and provide memory for your instance by any means you want (I guess, including dividing a block you got yourself from the OS). I don't want to manage the language.  More or less knowing how the O/S behaves is already a fair amount of work.  From a memory management viewpoint, the language doesn't provide anything I don't already have that is better and more flexible. Quote from: Martin_fr on May 02, 2020, 09:40:12 pmIf you know you need a 1000 instances of TFoo, and you want to avoid mem fragmentation, then you allocate one block to fit all 1000 of them (and if you need more, you allocate a 2nd block and so on), and then all your instances use that block of mem.That's the way to do it but, why would I override some language mechanism when I can use the one provided by the O/S ? ... if I wanted portability, I could create a tiny wrapper around it and I'm good to go instead of wondering if my override of the language's method doesn't get in the way of something else the language does. Quote from: Martin_fr on May 02, 2020, 09:40:12 pmNo problem. It's about choice. I feel the same way.  Every one is absolutely free to choose a different way (and obviously, most have)... no problem, I'm perfectly fine and happy with that but, if someone asks, I answer because I think it is important to show that it isn't just because "I like it this way"... no, there are rock solid reasons for the programming choices I make.    IOW, it _isn't_ a matter of style. While typing this reply, the discussion on objects/classes is raging...  popcorn time ---------------------------------------------------------------------- Warfley · 2020-05-02 22:25 Quote from: 440bx on May 02, 2020, 11:47:49 pm[...] I disagree on your style in about every point, mostly because I'm also using other systems not only windows, and there your strategy of relying on OS specific behaviour is completely unacceptable, because between POSIX system, even between linux kernel versions, there can be a lot of differences, so relying on the quirks of your OS would mean that your program might not even work a year from now on. But on windows this is a different thing because windows never changes. Windows still has features in there that where built into windows 95 because they need the backwards compatibility. But I think you should defenetly get into C++ development. C++ lets you write custom allocators using templates. This allows for highly configurable allocators that could be used for what you are doing in an extremely elegant way. For example: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i template struct TypedAllocator {  typedef T value_type;  static void *memory = null_ptr;   TypedAllocator () {    if (!memory) {      memory = alloc //e.g. via virtual_alloc    }  }   template constexpr TypedAllocator (const TypedAllocator &) noexcept {}   [[nodiscard]] T* allocate(std::size_t n) {    // do your allocation for type T here using memory    return memory;  }  void deallocate(T* p, std::size_t) noexcept {    // Do your deallocation here }};This allocator would allocate one chunk of memory for each possible type, and only allocate things of the same type in this chunk. Of course you can tweak this much more, as you please, you could for example group the memory after the parity of the number of bytes in the requested datatype, etc. And the best thing about this, this is compatible with all C++ language featuers and STL classes and does not add any runtime overhead. C++ does not only allow for your style of programming but is designed to make such programming pretty easy. It would fit your programming style perfectly. QuoteCompilers cannot think, therefore they shouldn't try.Compilers don't think, people developing compilers think. The rust compiler does not think in any way shape or form, it only has a different rule set for how to handle memory, which makes making memory errors impossible. And if this is to restricted you can still "break" it and code unsafe, and if you have some memory error you know it must be from one of the unsafe blocks. It's not magic, it's just different. It's still a hardcoded set of rules everyone can understand easiely. It does so btw, without having to implement Reference counters, it is all compile time, meaning you have 0 overhead. The code will be exactly as efficient if you used manual memory management (maybe even better because the optimizer has a stricter rule set to work with), but memory errors are simply impossible ---------------------------------------------------------------------- jamie · 2020-05-02 23:18 Wow, my scrolling finger is tired  I use the old OBJECT model a lot just because I can , but most of the time the only operation I perform is some sort of initial settings, I don't need to worry about cleanup.. ---------------------------------------------------------------------- 440bx · 2020-05-02 23:25 Quote from: Warfley on May 03, 2020, 12:25:31 amI disagree on your style in about every point, You're in good company. Quote from: Warfley on May 03, 2020, 12:25:31 am so relying on the quirks of your OS I am not relying on quirks at all.   Though, there is one "quirk" that I occasionally use when I feel lazy, which is, causing HeapAlloc to call VirtualAlloc but, I only do it in proof of concept code. Quote from: Warfley on May 03, 2020, 12:25:31 amBut on windows this is a different thing because windows never changes. Windows still has features in there that where built into windows 95 because they need the backwards compatibility.I could use the exact same methods I use in Windows in Linux and it would work perfectly.  The _only_ change required would be the name of the VirtualAlloc function, which I don't recall at this time what it's called in Linux.  Everything else would work exactly as is.  Therefore, as far as memory management goes, if I were interested in porting my code to Linux, most of my programs would take very little work to port because in the great majority of cases, Linux has a function that is fully "parallel" to the Windows function.  Obviously, what I just said does _not_ apply to GUI management and quite a few other things but, memory management would be identical other than different function names. As far as portability goes, I see this way: Windows provides about 13,000 APIs of which I _might_ know reasonably well about 3,000 of them, that's less than a fourth of them and, that's with having assembly listings of the major Windows dlls and a system debugger on call (I still have a Windows XP installation with SoftIce up and running most of time and, as I type this there is a disassembler showing Windows internal code on my screen) and, the one thing all of that has made very clear in my mind is, there is a whole lot more I don't know than what I know.  The bottom line is this: I'd rather know one thing reasonably well (in my case Windows) than have little more than just a vague idea of how things work on multiple O/Ss. Quote from: Warfley on May 03, 2020, 12:25:31 amBut I think you should defenetly get into C++ development. C++ lets you write custom allocators using templates. This allows for highly configurable allocators that could be used for what you are doing in an extremely elegant way.I know you don't say that wishing me harm but, that would be very painful.  Thank you for the offer, I'll kindly pass. Quote from: Warfley on May 03, 2020, 12:25:31 am... people developing compilers think.Yes, some do... it seems that after C was designed someone figured that thinking is a definite plus when writing a compiler.  At least one good thing came out of that language. Quote from: Warfley on May 03, 2020, 12:25:31 am... but memory errors are simply impossible Honestly, I consider that a problem. I put conditionally compiled code to cause errors in order to test the error handlers in the code. I understand people being enthusiastic about compiler features, libraries and other perks that may come with a language.  Myself, my dream compiler would be a high level assembler that knows every trick in the book to produce highly optimized, highly compact code.  Add a good editor and a good debugger and I'm all set. ---------------------------------------------------------------------- PascalDragon · 2020-05-03 14:08 Quote from: Warfley on May 02, 2020, 05:17:09 pmIdea: managed objects: TP style objects are a legacy type. While we do not consider them deprecated as Delphi does we do not add features to them that aren't a falloff of classes (because inside the compiler they're handled very similar). Also as marcov wrote 3.2 has management operators for records. With that and what is already available for advanced records in 3.2 every point of your list except inheritance is covered: Quote from: Warfley on May 02, 2020, 11:43:29 pmBut there are still a few things I think are much better about objects. Most notably: 1. Private fields 2. Properties 3. Parametrized constructors 4. Inheritance And for something like smart pointers for class instances inheritance is not required. ---------------------------------------------------------------------- marcov · 2020-05-03 14:16 Note that Delphi has abandoned its objc smartpointer memory management in the next version ---------------------------------------------------------------------- PascalDragon · 2020-05-03 15:15 I'm not talking about ARC. I was talking about the idea that Maciej had originally presented his management operators for and what Warfley had presented in their first post based on TP style objects (the point “Comming all together”). ---------------------------------------------------------------------- flowCRANE · 2020-05-03 16:18 I think that classic objects are useful and still will be useful in the future. And, at the same time, extending the functionality of basic records does not make much sense. Before the functionality of the records began to be expanded, the division of data structures was clear: record — primitive functionality, only fields supported (with variant record syntax), stack allocated,object — more complex functionality, all above and support of methods, properties, encapsulation, inheritance,class — complex functionality, all above and support of usage interfaces but, heap allocated.But one day someone decided to transfer the functionality of classic objects to standard records. Everything except inheritance, because it is still not supported and probably never will be. What we now have are records that pretend to be old objects, and additionally use class constructions (e.g. class function). What a mess! In my opinion, there is still a point in using classic objects. Firstly, because they provide better functionality compared to extended records, while still being relatively simple structures allocated on the stack, which does not require manual care to allocate and deallocate memory. And secondly, because their use does not require adding compiler directives — they are supported as language standard (and extended records are not). And for these reasons should not be considered legacy. It is rare, but if I need to use a simple structure with methods, I choose classic objects. I treat extended records like an „The Ugly Duckling”, something that developers have failed. And I don't want my code to be ugly. ---------------------------------------------------------------------- 440bx · 2020-05-03 16:54 Quote from: furious programming on May 03, 2020, 06:18:57 pm... extending the functionality of basic records does not make much sense. That's not the case.  Records are the very foundation of OOP.  The functions/procedures that apply to the record are part of the record itself, just like its fields.  In that first step, records are simply static objects.  It is from there that extensions come along, polymorphism: simply add a table of function pointers (the VMT) associated to/with the record. Inheritance, the ability to append more function pointers to the table. Quote from: furious programming on May 03, 2020, 06:18:57 pmBut one day someone decided to transfer the functionality of classic objects to standard records. No.  It's more like someone decided to make it obvious that records are the root of OOP by allowing the functions that apply to it to be included in the record. The bottom line is this: there is nothing new in OOP.  Everything OOP does can be implemented using records that, in addition to the fields, either has a pointer to the function table or it can have it built-in as part of the record itself. OOP is nothing more than a cumbersome and limited way of giving information to the compiler about those function tables and, creating the ultimate expression of spaghetti code by the rampant and completely unchecked overuse and abuse of polymorphism. Quote from: furious programming on May 03, 2020, 06:18:57 pmIn my opinion, there is still a point in using classic objects. ... allocated on the stack, which does not require manual care to allocate and deallocate memory.That might very well be the most important characteristic of old style objects and plain records, which is, the programmer _decides_ where the object resides, not the compiler.  Quote from: furious programming on May 03, 2020, 06:18:57 pmI treat extended records like an „The Ugly Duckling”, something that developers have failed. And I don't want my code to be ugly. The _only_ sort-of OOP feature I ever use is advanced records and, more often than not, there is only one procedure in it, which is Init.  That way, I can just code "MyRecord.Init();" a little syntactic sugar.  That's it. Ignore all of the above... sometimes I just can't help exposing OOP for what it is. ---------------------------------------------------------------------- Warfley · 2020-05-03 18:19 QuoteThe bottom line is this: there is nothing new in OOP.  Everything OOP does can be implemented using records that, in addition to the fields, either has a pointer to the function table or it can have it built-in as part of the record itself. Congrats you found out what "Turing Complete" means. You can do everything you can do in OOP with a classical turing machine, as well as whith a WHILE program, a functional language, a logical language, etc. The difference is what a language paradigm emphasises. For example this is quicksort on Haskell a functional language: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i quicksort []     = []quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)    where        lesser  = filter (< p) xs        greater = filter (>= p) xsThis can be implemented in many other languages like prolog: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i qsort( [], [] ).qsort( [H|U], S ) :- splitBy(H, U, L, R), qsort(L, SL), qsort(R, SR), append(SL, [H|SR], S). % splitBy( H, U, LS, RS )% True if LS = { L in U | L <= H }; RS = { R in U | R > H }splitBy( _, [], [], []).splitBy( H, [U|T], [U|LS], RS ) :- U =< H, splitBy(H, T, LS, RS).splitBy( H, [U|T], LS, [U|RS] ) :- U  > H, splitBy(H, T, LS, RS).or pascal Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Procedure QuickSort (arr: PInteger; Left, Right : LongInt );Var   i, j,  tmp, pivot : Integer;Begin  i:=Left;  j:=Right;  pivot := arr[0]  Repeat  While pivot > arr[i] Do inc(i);    While pivot < arr[j] Do dec(j);    If i<=j Then Begin      tmp:=arr[i];      arr[i]:=arr[j];      arr[j]:=tmp;      dec(j);      inc(i);    End;  Until i>j;  If Left not defined, look in TFoo -> not Defined -> look in TObject. This also has tooling support, so if you simply press Control Click on the .Bar call in lazarus it finds the, top most implementation. The only thing where it gets more complicated is if you don't know which type your object has at a certain point in time, but then again the same problem occurs when you implement polymorphism using procedual programming. Let's say I have the following: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i TSomePolymorphicRecord = record  ClassName: String;  ...end; procedure bar(obj: PSomePolymorphicObject);begin  lookupCall(obj^.ClassName + '.bar')(); // lookup virtual function call hereend; You don't know which type obj has, when bar is called. How is this different than having an OOP class with a virtual function. I think you are complaining that people use too much polymorphism when doing OOP, but thats not the fault of OOP. Any feature can be missused. Take your central lookup table, what if I implement a function that simply looks up a random function and executes it. Is that now the fault of the central lookup table or a fault of me, misusing it? A tool is only as good as it's user, and I fully agree with you, if you misuse OOP it will result in bad code, but that does not mean that OOP is bad. If you don't need virtual functions don't use them. OOP is still a powerfull tool for organization (as all functionality regarding a type are encapsulated in that type, while in procedual programming it can be all over the place) and code reduction (if you have a lot of code shared between different types you can use inheritance to make this a commom base class) QuoteI'd much rather see polymorphism implemented in a procedural language than in OOP and the reason is simple: I can use a lowly text editor to list all the places in the code that modify an entry in the table. In OOP there is exactly one place that can override the VMT and that is the type definition, because it's handeld by the compiler. If you have an external table you can acess it from anywhere you like because it is handled by the code. QuoteIn procedural programming keeping track of what's going on is trivial, in OOP figuring out the same thing requires running the code.  Not to mention all the time that is wasted to determine something that can be done effortlessly in a few seconds in non-OOP code.There are exactly 2 possibilities when you have a virtual function in both OOP and procedual programming 1. You know the type at compiletime. Then looking up what code will be executed is as simple as a Ctrl+Click 2. You don't know the type at compiletime. Then you need to run the code. How is this different from OOP to procedual programming? QuoteWhat is basically is, is a data driven method of producing self- modifying code by altering the pointers to the target code to be executed.What???? If you access the VMT of your objects class you are doing something very very wrong. The VMT is created by the compiler and will not change at any point during the runtime. It's simple, if you know the type you know the function that will be called. If you don't know the type you need to run the Code in a debugger to find out the type. If you manage your VMT by yourself and don't let the compiler do it, it's worse, because then you can access it and change it. Your argument applies, but in the exact opposite direction. By not being able to access the VMT this is something OOP polymorphism can't do, procedual polymorphism can. ---------------------------------------------------------------------- Otto · 2020-05-03 21:27 Quote from: Martin_fr on May 03, 2020, 08:56:17 pmWell when it comes to the Italian cuisine, some people like pizza, others like spaghetti. {$mode Comic Begin} (-: Usually, pizza is considered a first dish like spaghetti; for this reason it is rare to eat pizza and spaghetti during the same meal. Both have flour and water as key ingredients. Both mainly provide carbohydrates as nourishment. However, they are two different foods. :-) {$mode Comic End} Spaghetti Code is a kind of "programming paradigm" more like a low- level programming language, sometimes a little too confusing. OOP is a more rational programming paradigm closer to the way most human beings think. Structured programming is a middle ground and in many cases is the best choice. In addition to these there are many programming paradigms and many others will exist, each has its own advantages and disadvantages over the others. I believe that a multi-paradigm language is the best choice: thanks to it the programmer will be able to use multiple paradigms at the same time. I have seen that the FPC introduces new features in each new version; that's a very positive thing. Perhaps one day it will also become a multi-paradigm language. ---------------------------------------------------------------------- 440bx · 2020-05-03 21:32 First, the most important thing: it's obvious that neither one of us is going to convince the other. That said, I still want to clarify a few things about the claims you make about OOP. Quote from: Warfley on May 03, 2020, 10:13:10 pmI did not say that you have to overuse them, I just said that when you use them it's much easier using OOP than implementing it yourself. Even using that construct "x is whatever" is overuse.  In a non-OOP program the variant type is marked (if needed), therefore: the syntactic construction informs the programmer reading that declaration that the code depends on a field (the tag) to determine the proper course of action.  In an OOP program, there is _no_ indication anywhere in the declaration that the code will need to ascertain the type.  However, it's so common for OOP programs to be dependent on that, that it is the safe thing to do to presume the code depends on it.  It would be very unwise to presume it doesn't. Quote from: Warfley on May 03, 2020, 10:13:10 pmIt's like you are saying I don't like hammers because the last time I tried to use a skrew with them I completely destroyed the wood. Thats why I use a screw driver to hammer my nails in.Not quite.  What I'm saying is that I don't like heavy hammers designed to gravitate towards human fingers.   I strongly prefer hammers that gravitate towards nails and pieces of lumber.  Good hammer!!. Quote from: Warfley on May 03, 2020, 10:13:10 pmHow does polymorphism implemented procedually reduce the amount of controll flow being determined at runtime? The definition of polymorphism is that the execution is runtime dependend. No matter if you do it procedually or using OOP.First, it is correct that a table of function pointers, whether in an OOP or non-OOP program is a potential source of polymorphic behavior.  However, in a non-OOP program, the values in the table are set at compile time and, more often than not, remain constant throughout the duration of the program.   That means, I can go to ONE table - instead of a bunch of classes scattered everywhere - and see exactly where execution is being sent to.   Not so with OOP. Quote from: Warfley on May 03, 2020, 10:13:10 pmWait you have all your virtual functions in one location? They are _not_ virtual.  The roughly equivalent in OOP is a static object.  It is extremely rare to need a virtual function in a correctly designed non-OOP program. Quote from: Warfley on May 03, 2020, 10:13:10 pm So If we take the Lazarus component tree which has hundreds of classes, with dozends of functions, you would have thousands of entries.No and, the reason they wouldn't be there is because they really aren't needed.  They are needed only because that's the OOP way.  In OOP anything that looks like a piece of code is an excuse to have a pointer to it. Quote from: Warfley on May 03, 2020, 10:13:10 pmYou know that functions are only virtual if you declare them as virtual, and they only override if you add the keyword override right? So in the first place you only need to consider the functions that are virtual, so only a rather small subset. And then its a simpel top-down search. Let's say you have an instance of TFooBar which inherits from TFoo which inherits from TObject and you call a function .Bar. Then all you need to do is to look in TFooBar -> not defined, look in TFoo -> not Defined -> look in TObject. This also has tooling support, so if you simply press Control Click on the .Bar call in lazarus it finds the, top most implementation.That's the easy case and it's already more hassle than it should be.  What's quite common is to see classes holding pointers to methods and the value of those pointers are determined at run-time.  There is no tool that is going to tell you what the value of that pointer is going to be at run-time.   Actually, I'll take that back, there is a tool that will tell you, the computer's CPU.    Quote from: Warfley on May 03, 2020, 10:13:10 pmThe only thing where it gets more complicated is if you don't know which type your object has at a certain point in time, but then again the same problem occurs when you implement polymorphism using procedual programming. As stated previously, polymorphism in an non-OOP program is not common at all because in the great majority of the cases, _unklike_ in OOP, it simply isn't needed. Quote from: Warfley on May 03, 2020, 10:13:10 pmYou don't know which type obj has, when bar is called. How is this different than having an OOP class with a virtual function. It's different because in a non-OOP program there will be a _clear_ assignment to the entry that holds the pointer to the function and I can use any text search program to get a list of them.  IOW, I _don't_ need to run the program to determine what possible values that entry may have. Quote from: Warfley on May 03, 2020, 10:13:10 pmI think you are complaining that people use too much polymorphism when doing OOP, but thats not the fault of OOP. It is the fault of OOP and that is clearly seen everywhere.  If polymorphism wasn't abused then programmers could use static objects/classes and, we both know, static objects/classes are comparatively rarely used. Quote from: Warfley on May 03, 2020, 10:13:10 pmTake your central lookup table, what if I implement a function that simply looks up a random function and executes it.   Is that now the fault of the central lookup table or a fault of me, misusing it? And what practical purpose would doing such a thing accomplish ?  generate a random number maybe ?  if that's it, I believe there are other ways of getting that done just as well. You can't use that argument in favor of OOP.  OOP relies heavily on polymorphism. Without polymorphism it's doubtful it would be of much interest to many programmers. Quote from: Warfley on May 03, 2020, 10:13:10 pmOOP is still a powerfull tool for organization (as all functionality regarding a type are encapsulated in that type, Actually, OOP is a powerful tool to create _chaos_ and make organization as difficult as possible.  You can't even decide _where_ the class resides, like Henry Ford would say, any color you want as long as its heap black (which implies maintenance of that heap block whether you wanted it or not.) Quote from: Warfley on May 03, 2020, 10:13:10 pm while in procedual programming it can be all over the place) and code reduction (if you have a lot of code shared between different types you can use inheritance to make this a commom base class) No argument that procedural programming can be used to produce lousy code too, almost as bad as OOP. As far as the code reduction, that's another thing I don't think OOP has gotten right.  It is often the case that OOP code is broken down in so many tiny pieces that figuring out what the _logical_ purpose of all these tiny pieces put together is, ends up being quite a bit of work.  It's not a program, it's jigsaw puzzle. Quote from: Warfley on May 03, 2020, 10:13:10 pmIn OOP there is exactly one place that can override the VMT and that is the type definition, because it's handeld by the compiler. If you have an external table you can acess it from anywhere you like because it is handled by the code. Yes but, every class has its own VMT.  The result, is a significant number of function pointer tables scattered all over the place.  In a well designed program, having even _two_ tables of function pointers is a bit unusual. Quote from: Warfley on May 03, 2020, 10:13:10 pmWhat???? If you access the VMT of your objects class you are doing something very very wrong. You may not be accessing them directly but you _are_ accessing them and changing their targets at runtime.  The real problem is, in OOP all that very undesirable manipulation is hidden and sugar coated by the compiler.  In a non-OOP program it would be clearly seen as an assignment to an entry in the table.  Whether the assignment is justified or not, it is clearly visible and it is visible and deterministic without having to run the program (unlike in OOP.) OOP is the ultimate programming virus.  It's almost always terminal, once infected, there is little hope of finding the road to recovery. Honestly, I don't even know why I am posting about it. I know whatever I say isn't going to make any difference at all.  It hasn't in the past and I doubt it will in the near future.  Long term, I hope it will go the way of spaghetti code which is where it belongs (preferably buried under 2 billion pounds of cheese... like Chernobyl.) ---------------------------------------------------------------------- winni · 2020-05-03 21:42 For the realy perverted: There is also a Spaghetti-Pizza : https://www.wunderweib.de/pizza-spaghetti-ein-traum-aus-pasta-und- pizza-14113.html 10 GOTO NOWHERE ---------------------------------------------------------------------- marcov · 2020-05-03 21:49 Quote from: furious programming on May 03, 2020, 06:18:57 pmI think that classic objects are useful and still will be useful in the future. And, at the same time, extending the functionality of basic records does not make much sense Basically you have the route that C++ goes with an attempt at layering objects over structures, or you go the more modern way where classes are references by default, and not value types.   Basically the disadvantage of the C++ way is that you are fs*cked that way. Or maybe I should say *fscked or &fscked, because for a few cases you have to do a lot of those. And also a lot of . vs ->. If objects are all the same object hierarchy, and you shouldn't need to have to look up its intended usage. That breaks the whole point of unifying records and objects (except maybe some implementation reasons deep in the STL guts) Advanced records mostly came mostly for very small record types (that are so small that by value semantics don't hurt much) like point, rect etc, and to still be able to use codetools/intellisense to find all methods. Some duck typing (for..in) and maybe even generics (though those are from a later version) might also have been a reason. Quote. Before the functionality of the records began to be expanded, the division of data structures was clear: record — primitive functionality, only fields supported (with variant record syntax), stack allocated,object — more complex functionality, all above and support of methods, properties, encapsulation, inheritance,class — complex functionality, all above and support of usage interfaces but, heap allocated. As Pascaldragon said Object is/was legacy, and didn't really belong there. It is not part of the design, it is a leftover. QuoteBut one day someone decided to transfer the functionality of classic objects to standard records. Everything except inheritance, because it is still not supported and probably never will be. So they are still records with methods and not object, since polymorphism is a key OOP aspect  QuoteWhat we now have are records that pretend to be old objects, and additionally use class constructions (e.g. class function). What a mess! Yes, but not a &mess. And normal classes usage is the main use case, and shouldn't be complicated with constantly declaring them as references just to have some form of byvalue objects/records. I don't really know what is best here, but I do know that I don't consider the C++ to be much better. Probably both systems are too organically grown, and one should probably start over if you really want/need a pure design for this aspect. QuoteIn my opinion, there is still a point in using classic objects. Firstly, because they provide better functionality compared to extended records, while still being relatively simple structures allocated on the stack, which does not require manual care to allocate and deallocate memory. Like? That example with  inheritance by passing it to a function with a by ref parameter, while fun is not really a proper motivation for such a major feature that would whole dimensions to the language. QuoteAnd secondly, because their use does not require adding compiler directives — they are supported as language standard (and extended records are not). And for these reasons should not be considered legacy. That's all murky and IMHO. From both sides. Embarcadero seems to have iced many of its "nextgen" plans to rid the compiler of legacy. But TP object usage is very low. Afaik some Lazarus devels liked to use it from time to time, but that all dates from before advanced records. IIRC Mattias said that he just liked them because he could pop up the methods with codetools. But that could be cleaned out I guess.  (if interested, afaik it was TLazRawImage or so that had them) By far the bulk is in the Turbo Vision world. But that isn't exactly the most active part of the project. QuoteIt is rare, but if I need to use a simple structure with methods, I choose classic objects. I treat extended records like an „The Ugly Duckling”, something that developers have failed. And I don't want my code to be ugly. Yeah, we get your sentiment. Just not where it is coming from ---------------------------------------------------------------------- Warfley · 2020-05-03 23:22 Quote from: 440bx on May 03, 2020, 11:32:24 pmFirst, it is correct that a table of function pointers, whether in an OOP or non-OOP program is a potential source of polymorphic behavior.  However, in a non-OOP program, the values in the table are set at compile time and, more often than not, remain constant throughout the duration of the program.   That means, I can go to ONE table - instead of a bunch of classes scattered everywhere - and see exactly where execution is being sent to.   Not so with OOP. Again the VMT of an object does not change during runtime. And why is it a good thing to have one table? In OOP there is exactly one VMT per class. You know exactly where to search. On the other hand, if you have a lookup table with function pointers for all your different types in one place, you always need to search for it, while in OOP you simply know where to look (everything is in the definition of the type) Quote from: Warfley on May 03, 2020, 10:13:10 pmNo and, the reason they wouldn't be there is because they really aren't needed.  They are needed only because that's the OOP way.  In OOP anything that looks like a piece of code is an excuse to have a pointer to it.And how do you create a tree structure (which components will inevitebly form) without pointers? Quote from: Warfley on May 03, 2020, 10:13:10 pmThat's the easy case and it's already more hassle than it should be.  What's quite common is to see classes holding pointers to methods and the value of those pointers are determined at run-time.  There is no tool that is going to tell you what the value of that pointer is going to be at run- time.   Actually, I'll take that back, there is a tool that will tell you, the computer's CPU.This is usually only the case in event based programming. And there you have two options 1. use function pointers, 2. create a big dispatching function. As soon as you need flexibility (e.g. you want to disable a certain event), function pointers win hands down every time. Quote from: Warfley on May 03, 2020, 10:13:10 pmAs stated previously, polymorphism in an non-OOP program is not common at all because in the great majority of the cases, _unklike_ in OOP, it simply isn't needed.Again, why is this an argument against using OOP. Simply use OOP but don't overuse polymorphism. I don't know why you throw a whole tool away because you don't like some of it's usage. In C++ for example polymorphism isn't that common. There most things are handled via templates at compiletime instead. Yes FreePascal and the RTL is heavily relient on polymorphism, but as I said, C++ for example isn't. It's not really an OOP problem at all. Quote from: Warfley on May 03, 2020, 10:13:10 pmIt's different because in a non-OOP program there will be a _clear_ assignment to the entry that holds the pointer to the function and I can use any text search program to get a list of them.  IOW, I _don't_ need to run the program to determine what possible values that entry may have.Yes and in OOP there is also a clear assignment: In an inheritance hierachy the upper most class that overrides the function defines it. Sure it's not a simple text search, but it's not 1980 anymore, we have development tools that do this stuff for us. If I want to check what the implementation of the given type is I simply Ctrl+Click in lazarus. Easy as that. I bet it's faster than you typing your grep command (or what ever searcher you use). Quote from: Warfley on May 03, 2020, 10:13:10 pmIt is the fault of OOP and that is clearly seen everywhere.Except in for example in the C++ community, especially the standard regarding the STL, has a big sentiment of "don't use polymorphism where it isn not needed". This is not an OOP problem, otherwise a highly OO language like C++ would also be "infested" Quote from: Warfley on May 03, 2020, 10:13:10 pmYou can't use that argument in favor of OOP.  OOP relies heavily on polymorphism. Without polymorphism it's doubtful it would be of much interest to many programmers.Again polymorphism is only one of the things OOP does nice. Again C++. Only uses polymorphism in it's STL where it is useful Quote from: Warfley on May 03, 2020, 10:13:10 pmActually, OOP is a powerful tool to create _chaos_ and make organization as difficult as possible.  You can't even decide _where_ the class resides, like Henry Ford would say, any color you want as long as its heap black (which implies maintenance of that heap block whether you wanted it or not.)You can't decide with Pascal classes but you can with Pascal objects, C++ classes or Rust classes. In managed languages like C# or Java this doesn't even matter because there the Heap is a stack anyway, and in scripting languages like JavaScript or Python everything is emulated anyway and even the stack is in the heap. It's not like you are arguing against OOP but more you are arguing about Pascal classes and how they are used by Pascal developers. This whole thread was created because I also dislike these limitations of Pascal classes and would wish for objects to become more sophisticated so I can use them instead of classes in cases where it is appropriate. Quote from: Warfley on May 03, 2020, 10:13:10 pmNo argument that procedural programming can be used to produce lousy code too, almost as bad as OOP. As far as the code reduction, that's another thing I don't think OOP has gotten right.  It is often the case that OOP code is broken down in so many tiny pieces that figuring out what the _logical_ purpose of all these tiny pieces put together is, ends up being quite a bit of work.  It's not a program, it's jigsaw puzzle. Why is this not an argument for me but for you? Your whole argument is that OOP can be used to create lousy code. As I already stated you would be a great fit for the C++ community, because they often have the same sentiment. Only they know it's not about OOP, but about programmers using OOP this way. All you said in this post only fits a rather narrow part of OOP developers especially for Java, C# or Pascal, but is completely invalid for C++ or Rust. Again this is not an OOP thing, otherwise these OOP languages would have the same issues. QuoteYes but, every class has its own VMT.  The result, is a significant number of function pointer tables scattered all over the place.  In a well designed program, having even _two_ tables of function pointers is a bit unusual.They are exactly where it makes sense for them to be. Every VMT is defined by the exact Class that defines them. You are looking for the virtual functions of class TFoo, simple, look in TFoo and look which functions are marked with "virtual" or "override". QuoteYou may not be accessing them directly but you _are_ accessing them and changing their targets at runtime.  The real problem is, in OOP all that very undesirable manipulation is hidden and sugar coated by the compiler.  In a non-OOP program it would be clearly seen as an assignment to an entry in the table.  Whether the assignment is justified or not, it is clearly visible and it is visible and deterministic without having to run the program (unlike in OOP.)No. Simply no. Every instance has a class, each class has a VMT. You can neither change the VMT of a class at runtime (without tricks) nor can you change the type of an instance during runtime. If you disagree, simple, write a code that changes either the VMT or the class of an instance, without(!!!) destroying and creating a new instance. Because I can do the same with records (even easier because I could simply write any memory into it I please) QuoteOOP is the ultimate programming virus.  It's almost always terminal, once infected, there is little hope of finding the road to recovery. Honestly, I don't even know why I am posting about it. I know whatever I say isn't going to make any difference at all.  It hasn't in the past and I doubt it will in the near future.  Long term, I hope it will go the way of spaghetti code which is where it belongs (preferably buried under 2 billion pounds of cheese... like Chernobyl.) Honestly to me it sounds like you have a really narrow view of OOP. Sure what you wrote is true for Pascal (classes and the RTL/LCL), Java, C#, but is not true for a lot of C++ and Rust code. OOP is a paradigm anyone can use how he pleases. It is used extremely diverese, you have languages like Java where everything is virtual and on the other hand Languages like Rust or C++ where virtual functions and polymorphism is only used when needed. Because, procedual programming is a part of OOP. Even if you think that 99% of OOP usage is unessecary, you can still use procedual programming then and use the OOP features for the other 1%. No one is forcing you to write your code like others and disliking a feature because others "misuse" it (in your opinion). It's like you are standing in the supermarket in front of the jam shelf, saying you don't like jam because you don't like strawberry flavor. This is an extremely broad field ---------------------------------------------------------------------- 440bx · 2020-05-04 01:20 Quote from: Warfley on May 04, 2020, 01:22:01 amIn C++ for example polymorphism isn't that common. There most things are handled via templates at compiletime instead.  It's not really an OOP problem at all. OOP has plenty of problems, polymorphism is just one of them. Quote from: Warfley on May 04, 2020, 01:22:01 amIt's not like you are arguing against OOPI am arguing against OOP.  Quote from: Warfley on May 04, 2020, 01:22:01 am but more you are arguing about Pascal classes and how they are used by Pascal developers. Strictly speaking the problem isn't Pascal.  The problem is that the fate of the Pascal language is in the hands of a company in the business of selling gimmicks to make money.  That's the problem. Quote from: Warfley on May 04, 2020, 01:22:01 am This whole thread was created because I also dislike these limitations of Pascal classes and would wish for objects to become more sophisticated so I can use them instead of classes in cases where it is appropriate. I understand that but, be that as it may, you're still arguing in favor of OOP. Quote from: Warfley on May 04, 2020, 01:22:01 amYour whole argument is that OOP can be used to create lousy code. I consider bloated executables to be an indication of code that leaves something to be desired. Quote from: Warfley on May 04, 2020, 01:22:01 amHonestly to me it sounds like you have a really narrow view of OOP.That is likely true to some extent because, as I have stated before, I am not really all that familiar with the C++ implementation.  Therefore, there are OOP programming styles that I am definitely not well versed in but, that doesn't get rid of the problems inherent in OOP. Quote from: Warfley on May 04, 2020, 01:22:01 am use the OOP features for the other 1%. No one is forcing you to write your code like others and disliking a feature because others "misuse" it (in your opinion). The real problem is that, so far, I can always think - with little effort - of a clearly better solution that doesn't use OOP.  The problem in this discussion is that it's all theoretical.  Usually, it's best to compare results.  You mentioned a number of things about OOP, such as code re-use, templates and other things.  Sounds good.  Let's compare results now.  I've attached to this post a little proof of concept program that is not OOP (as expected) and was created with code reuse in mind.  It's a "multiple personality" program.  It's just a little program to test thread synchronization among two processes using mutexes.  Simple stuff. The Delphi 2 version is 37KB (and I could easily shave 5 to 10K off of it, IOW, I didn't code it to be as small as reasonably possible).  The 32bit FPC version is 183KB (I wish it were smaller than that) and the 64bit FPC version weighs in at 236KB.   Run two instances of the program simultaneously and you'll see that one instance is different and behaves differently than the other.  The reason to have it in one program, among many others, is that about 80% of the code among the two programs is the same, because of that, one executable is the perfect solution. There is nothing fancy in the program.  a) it creates a memory mapping.  b) it optionally creates a mutex.  c) the first instance writes to the mapped file.  d) the second instance reads it and writes the value it read in a listbox. If you feel like it, create something roughly equivalent to it.  Use any language you want and any programming paradigm you want (with the exception of assembly code.)  Preferably, I'd like to compare the 32bit versions because Delphi 2 produces reasonably nice and tight code for it.  Let's see if the tools and techniques (I mean OOP of course) you favor can match the result. I don't even care that the program be functional.  As long as it creates a memory mapped file, a mutex, a listbox, a status bar, has the menus, the little dialog box and has code to output something (I don't even care what) that' mimicks the output of the two instances, that's good enough. NOTE: there isn't a single line of assembly code in the program.  IOW, it wasn't coded to be as tight or fast as possible.  Just run of mill proof of concept code meant to test variations of the theme. ---------------------------------------------------------------------- Martin_fr · 2020-05-04 01:56 Just some exe do not proof anything. Not even what you really compare. I can only assume (from other stuff you wrote) that the form and listbox in your small app, are created via calls to the Windows API, without any component library (dcl/lcl)? If the big app uses a component library, then the most part of the difference does not come from OOP. It comes from using a GUI editor + library. And from RTTI. (and side effects of RTTI). The diff may also be affected by different RTLs. And so on. And that is true even for parts that are not OOP... Yes, sure a few bytes may be added by classes. For your chosen example OOP will give no benefits. It's like doing hello world in OOP. Why don't we take a more complex example? Let's say you show how much savings there are, by rewriting fpdebug (the code in the package of that name) entirely in procedural code. fpdebug is OOP, but has not been optimized for minimalism. So you should stand a very good chance there. --------- As for something from an earlier msg of yours: OOP hiding the flow behind the VMT, and supposedly can only be followed by running it.... In procedural code you would then need an "if somevar = x then else", but since I do not know the value of somevar (unless I run the code), I have equal problems finding out what the code would do next.... Of course following code in either format is also majorly affected what you are used to (trained to) look at. So unless you used a lot of OOP, it will be harder to read. Procedural code is probably readable to most OOP users too. But then try functional languages.... And just for background, I learned programming in a time for the waste of a single byte was a punishable offence. And I done my share of procedural in the day. Now I can see and understand, how your coding style works for you, and why you do not personally want to use OOP and certain other stuff. And OOP is not a one shoe fits all. It is good for a great many tasks, real good for a lot, and perfect for some. But for others it may not be the right tool.... What personally bothers me, is not that or why you choose your path. But how you present your dislike as a generalization. Almost branding OOP as the devil. I have no idea what that is supposed to archive? I can tell you what it does archive: My amusement. And for some reason your post keep reminding me of windmills.... (good look fighting them) SCNR ---------------------------------------------------------------------- 440bx · 2020-05-04 03:13 I'm going to reply out of sequence because it will probably convey where I'm coming from better... Quote from: Martin_fr on May 04, 2020, 03:56:53 amAnd for some reason your post keep reminding me of windmills.... (good look fighting them) SCNR I am completely aware that nothing I say is going to change anything but, the reason I say it is because, one thing that does bother me about OOP programmers is that they constantly paint OOP as the best thing since sliced and buttered bread and, that isn't remotely the case.  On the contrary, it is a highly deficient way of programming but, it gives people the _illusion_ of getting something done quickly, which is somewhat true but, the result isn't really all that good.  To make it really good, more effort goes into the product than if it had been coded purely procedurally.  And a lot of really lousy programming is painted as good, even "that's the way to do it" because of OOP.   The worse part is that since it is (painted as) good in OOP then it must be good in non-OOP code.  As a result, it isn't only the OOP code which leaves much to be desired, procedural code gets infected with those bad habits too. Quote from: Martin_fr on May 04, 2020, 03:56:53 amJust some exe do not proof anything. Not even what you really compare. The exe itself doesn't prove anything.  The proof is in the comparison of an exe created one way compared to the exe created another way.   That's where the proof is.  I provided something that allows anyone who wants to claim better results to show them. Quote from: Martin_fr on May 04, 2020, 03:56:53 amI can only assume (from other stuff you wrote) that the form and listbox in your small app, are created via calls to the Windows API, without any component library (dcl/lcl)? That is correct. Quote from: Martin_fr on May 04, 2020, 03:56:53 amIf the big app uses a component library, then the most part of the difference does not come from OOP. It comes from using a GUI editor + library. And from RTTI. (and side effects of RTTI). It does come from OOP because once you go OOP, a whole lot of stuff you don't need gets dragged into the program because of the inheritance and classes/objects containing other classes/objects ad nauseam.  You're making excuses for OOP.  It is quite evident that the bread and butter of OOP programmers is libraries, components, packages and who knows what else.  This reminds me of the TurboPower software libraries.  First there was Turbo Professional, a nice, non-oop library of code. They eventually reworked it into Object Professional.  The result: most executables were close to twice as large and slower but, I'll admit, it required less work on the part of the programmer.  Quote from: Martin_fr on May 04, 2020, 03:56:53 amThe diff may also be affected by different RTLs. And so on. And that is true even for parts that are not OOP... Quite likely but, as soon as an RTL has to support OOP stuff, it's going to be larger.  All those VMTs take space, they are not free nor are all the indirect calls through a function table. Quote from: Martin_fr on May 04, 2020, 03:56:53 amFor your chosen example OOP will give no benefits. It's like doing hello world in OOP. It won't give any benefits in any example.  Hello world or otherwise.  What it will "give" is an executable several times bigger than what it should be and most likely slower (though it would be hard to notice in a hello world program.) Quote from: Martin_fr on May 04, 2020, 03:56:53 amWhy don't we take a more complex example? Let's say you show how much savings there are, by rewriting fpdebug (the code in the package of that name) entirely in procedural code. fpdebug is OOP, but has not been optimized for minimalism. So you should stand a very good chance there.OOP can't do simple ?... if OOP is good then there shouldn't be any problems matching or besting the little program I posted.   I placed no limitations other than not using assembler and, that's because the program I posted doesn't use it, therefore that seems fair.  Other than that, use OOP^2, C++ ^ googleplex, assembler is the only limitation. Quote from: Martin_fr on May 04, 2020, 03:56:53 amIn procedural code you would then need an "if somevar = x then else", but since I do not know the value of somevar (unless I run the code), I have equal problems finding out what the code would do next.... Nice try.  What matters is that the code will go to only one place which is the function or procedure stated in the "then" or "else" depending on the result.  With OOP, regardless of the condition's result when the method has been overriden it is not possible to determine the set of targets without running the program.  It is a run time determined "goto", that's all it is and, there are plenty of those in OOP code.  1960's COBOL ALTER statement on steroids all over again. Quote from: Martin_fr on May 04, 2020, 03:56:53 amWhat personally bothers me, is not that or why you choose your path. But how you present your dislike as a generalization. Almost branding OOP as the devil.I don't hide my dislike of OOP and I justify it very clearly and, it isn't just a way of programming I don't like, it is a provably inferior programming method, which is why I don't like it and, I like it even less that it has become so accepted and widespread.  Unfortunately, there is extremely close to nothing I can do about it in both cases. Quote from: Martin_fr on May 04, 2020, 03:56:53 am I have no idea what that is supposed to archive? I can tell you what it does archive: My amusement. Aside from amusing you, it's quite likely it won't achieve much more than that but, hopefully it will occasionally achieve one thing: to let would be programmers know that OOP isn't that wonderful programming method OOP programmers pretend it is.  It simply _isn't_.  OOP is to programming as what Aristotle was to Physics.   It took about 19 centuries for that to change, it looks like it's going to take a while too to get rid of OOP in programming.  Eventually programmers figured out that spaghetti code wasn't a really good way of programming... eventually, programmers will realize that OOP is just spaghetti of another kind. ---------------------------------------------------------------------- munair · 2020-05-04 06:37 Quote from: 440bx on May 04, 2020, 05:13:50 amIt does come from OOP because once you go OOP, a whole lot of stuff you don't need gets dragged into the program because of the inheritance and classes/objects containing other classes/objects ad nauseam. Correct, but not many care about that these days, because the program "works" and the deadline was reached.  But this problem is not limited to OOP. Pre-compiled libraries usually also drag in a lot of code that a program never uses and the compiler has no way of excluding the dead code. These days, programming is very much led by convenience rather than efficiency. Taking it to the level of OSs, Windows is the best example. It grew from about 2GB with XP to over 15GB in 10. Compare that to Linux that is largely built using C that does not support classes: distro sizes have been fairly stable around 4 GB for years and this includes full packages like office suites (an installation disk still fits a 4.7 DVD). I said it before, Go deliberately does not support classes because inheritance chains can and do break quickly. But Go does support interfaces and objects. Going by my own experience, I used record types a lot and I still use them to group related code. It adds non- trivial structure to the code, but without polymorphism, inheritence and such. How often did I try to add a member to a class that raised a duplicate member definition error because it was already a public member somewhere up the class chain. If you think about it, when using keywords like "inherits" in a constructor, there is no way of knowing exactly what is being inherited. ---------------------------------------------------------------------- JiaXing · 2020-05-04 08:55 @440bx: you have a new convert! I subscribed to your church. Say no to OOP. ---------------------------------------------------------------------- munair · 2020-05-04 11:27 Quote from: JiaXing on May 04, 2020, 10:55:39 am@440bx: you have a new convert! I subscribed to your church. Say no to OOP. I think you're exaggerating big time. ---------------------------------------------------------------------- Martin_fr · 2020-05-04 11:51 Quote from: 440bx on May 04, 2020, 05:13:50 amthe reason I say it is because, one thing that does bother me about OOP programmers is that they constantly paint OOP as the best thing since sliced and buttered bread and, I haven't come across an extraordinary amount of such people yet. I.e., not more than for most other programming paradigms. But I am sure such people exist. I do agree that those who say, OOP is the only way, are quite mislead. But that is about people. It does not taint OOP for me. After all, while maybe uncommon for procedural programming, those people do also exist for other styles such as functional. Quote but, it gives people the _illusion_ of getting something done quickly, which is somewhat true but, the result isn't really all that good.  To make it really good, more effort goes into the product than if it had been coded purely procedurally.  Interesting: For me actually procedural gives me the feeling of archiving something faster initially. But then will evolve into a case of maintenance issues.... Seems that more depends on the individual, than the paradigm? But actually to me it is script languages (perl in the past, javascript today) that give people the feeling of "quick, cheap, and supposedly good". But that is just my opinion. And I mark it as such. QuoteYou're making excuses for OOP.  Not the way you seem to think. Just dividing what actually is OOP, and what is not. IMHO you are pulling in unrelated concepts, and call them OOP, to embolden your point. QuoteIt is quite evident that the bread and butter of OOP programmers is libraries, components, packages and who knows what else.  And with the exception of you, and a few others, none OOP programmers do the exact same. They use ready made code too. QuoteQuite likely but, as soon as an RTL has to support OOP stuff, it's going to be larger.  All those VMTs take space, they are not free nor are all the indirect calls through a function table. I did actually say that, yes with OOP you get a few extra bytes. A lot of the size increase however probably comes from changes that are not OOP. The pulled in framework may be OOP, but if you are comparing pulling in a framework vs not using a framework..... Quote... if OOP is good then there shouldn't be any problems matching or besting the little program I posted. As I state: no one shoe fits all. I never said there are no cases for procedural. But I also say, there is plenty of stuff where OOP is a good think. And yes, maybe you pay a few bytes (by far not what your example suggests) for using OOP. You may gain other advantages. (you may personally not see them as such...) QuoteQuoteIn procedural code you would then need an "if somevar = x then else", but since I do not know the value of somevar (unless I run the code), I have equal problems finding out what the code would do next....Nice try.  What matters is that the code will go to only one place which is the function or procedure stated in the "then" or "else" depending on the result.  With OOP, regardless of the condition's result when the method has been overriden it is not possible to determine the set of targets without running the program.  Nice try, too. In OOP I have a number of subclasses and need to find the correct one. (And I can find them without running the program) In procedural I have a number of if/else and I need to find which one the code enters (So it may be easier to find the referred procedure then, but the problem has only moved to find the conditional block that is used) Yes the search is still a bit different. Not a problem for me, not so far... But the concept of not knowing the state of an app, until you run it.... Not at all an OOP issues. Quote to let would be programmers know that OOP isn't that wonderful programming method OOP programmers pretend it is.  It simply _isn't_.  Well I have no issue with you advertising the pitfalls of OOP. I just think, if your chosen way was less borderline "hatred", it may be more convincing. On the big picture it just looks like you shout at everything that even remotely could be related (or unrelated, but made to appear as if) to OOP. I do not find that bit convincing at all. ---------------------------------------------------------------------- JiaXing · 2020-05-04 12:17 Quote from: munair on May 04, 2020, 01:27:50 pmQuote from: JiaXing on May 04, 2020, 10:55:39 am@440bx: you have a new convert! I subscribed to your church. Say no to OOP. I think you're exaggerating big time. No, I'm just joking. ---------------------------------------------------------------------- BeniBela · 2020-05-04 13:50 Quote from: Martin_fr on May 02, 2020, 05:58:44 pmLots of people (Afaik, especially Delphi users) use undocumented side effects of IInterface, to get refcounted behaviour. However since they relay partly on undocumented behaviour, their code may break with any fpc upgrade. Undocumented behaviour?  I use a lot of interfaces. I would be very angry if a fpc upgrade breaks it Quote from: 440bx on May 02, 2020, 08:53:01 pmI simply allocate a memory block from the O/S (in Windows using VirtualAlloc(Ex) and manage that block myself. Omg, seriously? That sounds really difficult Quote from: Warfley on May 02, 2020, 10:20:14 pmThe variable gets initialized as soon as it is declared and gets finalized as soon as it get's out of scope. Do you really think that is hard to understand? It is hard to know what the scope is. Does it start at begin and ends at end? But some variables cannot be initialized at the begin. Like in C++ you could write File file("filename"); to initialize a file, but in Pascal you cannot, since you cannot call functions at the var declaration. Quote from: Warfley on May 02, 2020, 10:20:14 pmOk, maybe you are simply an insane programmer who is better than the whole development team at Mozilla. I'm not, I will sometimes get problems managing memory. The Mozilla people are not using Pascal. With Pascal they would not have so many memory problems. Quote from: marcov on May 03, 2020, 11:49:05 pmYes, but not a &mess. And normal classes usage is the main use case, and shouldn't be complicated with constantly declaring them as references just to have some form of byvalue objects/records. You do not get a &mess in Pascal, because we have var and const  arguments for functions. Quote from: marcov on May 03, 2020, 11:49:05 pmBut TP object usage is very low. Afaik some Lazarus devels liked to use it from time to time, but that all dates from before advanced records. IIRC Mattias said that he just liked them because he could pop up the methods with codetools. But that could be cleaned out I guess.  (if interested, afaik it was TLazRawImage or so that had them) I am changing all my code to use TP objects. They are much more consistent then classes. Classes were  one of the worst Borland ideas. ---------------------------------------------------------------------- Martin_fr · 2020-05-04 14:00 Quote from: BeniBela on May 04, 2020, 03:50:10 pmQuote from: Martin_fr on May 02, 2020, 05:58:44 pmLots of people (Afaik, especially Delphi users) use undocumented side effects of IInterface, to get refcounted behaviour. However since they relay partly on undocumented behaviour, their code may break with any fpc upgrade. Undocumented behaviour?  I use a lot of interfaces. I would be very angry if a fpc upgrade breaks it Interfaces are documented. But afaik some people use it outside that document range of behaviour. (actually, in that case quite possible a lot of people) I may be wrong on the below, just way down memory lane.... IInterface is ref-counted, and freed when no longer used. Afaik for Delphi, freeing (refcount dec) is (currently) deferred to the end of scope of declaration. Afaik that is not a documented feature, and only implementation detail. Yet some people relay on it. As it (the exact place where dec-ref occurl) is not an actual feature, it may change. It may happen earlier or later. I am not sure where/when it happen in current fpc. ---------------------------------------------------------------------- marcov · 2020-05-04 14:20 Quote from: Thaddy on May 04, 2020, 04:10:27 pmRefCounted interfaces are COM interfaces, so IInterface is not enough, can be CORBA., but the default is COM. IInterface is equal to iunknown (see rtl/inc/objpash.inc),  and iunknown is the root COM interface. ---------------------------------------------------------------------- marcov · 2020-05-04 14:21 Quote from: BeniBela on May 04, 2020, 03:50:10 pmI am changing all my code to use TP objects. They are much more consistent then classes. Try to make a polymorphic list (TList, dyn array), without using pointers. ---------------------------------------------------------------------- 440bx · 2020-05-04 14:56 Quote from: munair on May 04, 2020, 08:37:41 amBut this problem is not limited to OOP. Pre-compiled libraries usually also drag in a lot of code that a program never uses and the compiler has no way of excluding the dead code.True but, OOP tends to make the problem much worse.  In a non-OOP library, I can extract the function I want, compile and the compiler will tell me what I'm missing.  Even for a complex function, it will take only a few minutes to extract the necessary code.  Once that is done, I can customize it as needed. Quote from: munair on May 04, 2020, 08:37:41 amThese days, programming is very much led by convenience rather than efficiency. Definitely true and there are quite a few, not very desirable, consequences to that. Quote from: munair on May 04, 2020, 08:37:41 am If you think about it, when using keywords like "inherits" in a constructor, there is no way of knowing exactly what is being inherited. And that problem gets worse as the number of virtual methods increases, not to mention that if any of those classes use method pointers to something else then grabbing the class may not bring all the code that is actually used.  Welcome to SIGSEGV world. Quote from: Martin_fr on May 04, 2020, 01:51:44 pmQuote from: 440bx on May 04, 2020, 05:13:50 amthe reason I say it is because, one thing that does bother me about OOP programmers is that they constantly paint OOP as the best thing since sliced and buttered bread and, I haven't come across an extraordinary amount of such people yet. I.e., not more than for most other programming paradigms. But I am sure such people exist. I have.  Well over 90% of the Pascal code I read is class/object oriented.  I don't know if that qualifies as "extraordinary" but, it certainly is a very significant percentage.  That picture doesn't change much for other languages that implement objects. Quote from: 440bx on May 04, 2020, 05:13:50 amI do agree that those who say, OOP is the only way, are quite mislead. But that is about people. There are those that see OOP as the only way but, the real problem isn't those people, the real problem is the very significant percentage of people who think and routinely claim that OOP is the _best_ way.  Not only it's not the best way, it is a very poor way of programming. Quote from: Martin_fr on May 04, 2020, 01:51:44 pm It does not taint OOP for me. After all, while maybe uncommon for procedural programming, those people do also exist for other styles such as functional.OOP has a long, long list of problems that are unavoidable.  Some of them could happen in procedural programming but, they would require writing poorly designed code. For instance, with classes, the structure goes on the heap even when it could have been better to have it on the stack.  There is no way around that.  Because of that, the block of memory has to be managed, got to allocate it, got to free it, etc.  Another "wart" in OOP, the fields in a class cannot easily be distinguished from a method's local variable. To "workaround" that problem, someone came up with the convention of prefixing all the class fields with an "F".  That's cheesy.  In reasonably well designed procedural code there is no need for these pedestrian workarounds because the local variables are, more often than not, easily identifiable. OOP needs to use exceptions to go across stack frames because the execution gets trapped in its over-encapsulated implementation, since it is quite common for it to have to communicate something back to the caller, welcome to exceptions (cross stack frames goto-s) which of course means that the code which is going to handle the exception is neither a constant in the program nor is easily identifiable.  The list of problems OOP creates is extremely long and, it seems compilers that support OOP are constantly adding new "features" which are nothing but hacks to workaround the problems inherent in the OOP paradigm.  Another example, since data visibility is not determined by the structure of the code, "modifiers" for "private", "published", "strict", "strict private" and who knows how many more are put into the compiler to synthesize visibility scopes that should be determined by the program structure. Quote from: Martin_fr on May 04, 2020, 01:51:44 pmBut then will evolve into a case of maintenance issues.... Seems that more depends on the individual, than the paradigm? There is no question that the way an individual programs makes a difference no matter the paradigm or the language but, there is very little an individual can do about the deficiencies in a language or paradigm.  Can't blame the individual for that. Quote from: Martin_fr on May 04, 2020, 01:51:44 pmIMHO you are pulling in unrelated concepts, and call them OOP, to embolden your point. OOP has a large number of deficiencies, I alluded to _some_ of them above.  OOP isn't deficient for just one reason, it's a deficient paradigm for _many_ reasons.  As a result, I mention them as they fit in the context of the discussion. Quote from: Martin_fr on May 04, 2020, 01:51:44 pmI did actually say that, yes with OOP you get a few extra bytes. In theory, for one class, it might be a few extra bytes but, when it comes to an entire program coded the OOP way the few extra bytes turn into a few hundred extra kilobytes and even megabytes sometimes. Quote from: Martin_fr on May 04, 2020, 01:51:44 pmA lot of the size increase however probably comes from changes that are not OOP. The pulled in framework may be OOP, but if you are comparing pulling in a framework vs not using a framework..... It is definitely possible to use OOP without a framework or a big library but, those things are part of the OOP way.  Result: packrat executables. Quote from: Martin_fr on May 04, 2020, 01:51:44 pmAs I state: no one shoe fits all. That's a trivial little program.  If OOP can't do that then it's even got more problems than I've seen. Quote from: Martin_fr on May 04, 2020, 01:51:44 pmBut I also say, there is plenty of stuff where OOP is a good think. OOP is a good thing for programmers who are satisfied with programs that work most of the time and can be produced dragging a few things on a "form" (I love the glorified name given to a run of the mill window) and coding "DoIt.Create; DoIt.run(); DoIt.Terminate(); end." Quote from: Martin_fr on May 04, 2020, 01:51:44 pmAnd yes, maybe you pay a few bytes (by far not what your example suggests) for using OOP. You may gain other advantages. (you may personally not see them as such...) "a few bytes" ? ... yes, like like Bill Gates has a "few" millions (only 80,000 of them but, that's such a minor thing) Quote from: Martin_fr on May 04, 2020, 01:51:44 pmIn OOP I have a number of subclasses and need to find the correct one. (And I can find them without running the program) I can find the core pieces of my programs without even opening a single source file. (for real programs, not for proof of concept/test code) Quote from: Martin_fr on May 04, 2020, 01:51:44 pmI just think, if your chosen way was less borderline "hatred", it may be more convincing. I don't think the way I feel about OOP makes much, if any, difference.  I could list every problem with OOP, mathematically prove it is deficient using graphs and, I seriously doubt I would change the views of any significant percentage of OOP programmers. Quote from: Martin_fr on May 04, 2020, 01:51:44 pmI do not find that bit convincing at all. And you are in good company because if I were convincing, OOP would have been left behind decades ago. Quote from: BeniBela on May 04, 2020, 03:50:10 pmOmg, seriously? That sounds really difficult It isn't.  On the contrary, it's so much easier and, if the design is right, everything falls into place naturally.  Debugging and testing are significantly simplified.  The one "disadvantage": it does take a little planning upfront and some more code too but, not a large amount and, the code is often very simple. ---------------------------------------------------------------------- JiaXing · 2020-05-04 15:19 @440bx: From what you said I think you would prefer Oberon style of OOP. Just guessing  BTW, Do you prefer functional programming over OOP? Because it's the most hot trend now. OOP has faded and procedural is always ridiculed as not fit for big project ---------------------------------------------------------------------- winni · 2020-05-04 15:38 Hi! It does not have to do with logic. It is just fashion. In this forum it is just fashion to care about big sets in Pascal. 30 years to late. Oberon was never fashion. It did not step out of the ETH Zürich. And the latest fashion in US: We are searching desperatly Cobol coders. For the payment of the unemployed. It's all coming back .... Winni ---------------------------------------------------------------------- Thaddy · 2020-05-04 16:16 Quote from: winni on May 04, 2020, 05:38:09 pmIn this forum it is just fashion to care about big sets in Pascal. 30 years to late. That's not entirely true: it has come up over at least the past 20 years (maybe 18 or 22, but you get the point) at some point or other. Not only with Freepascal, but also with e.g. Delphi. The subject is like the wind, sometimes it storms, sometimes it is calm. Fashion tends to have a slower cycle... ---------------------------------------------------------------------- marcov · 2020-05-04 16:24 Quote from: winni on May 04, 2020, 05:38:09 pmIn this forum it is just fashion to care about big sets in Pascal. 30 years to late. I do notice with the current level of generics, I use more valuetypes than a decade ago. ---------------------------------------------------------------------- JiaXing · 2020-05-04 17:33 Don't mind my signature. It's just joking. But indeed I have researched a bit about emulating OOP (I called quasi-OOP) on procedural language (all of the implementations are for C, to be clear) and I found they are very error prone and you could easily shoot yourself on the foot. Objective-C is another story, since it's another language, despite being claimed as a superset of C. Why don't use OOP (on an OOP language) directly? You are just wasting time to emulate OOP with your own quasi-OOP code. So how could you say you don't need OOP at all since you are emulating it?  @440bx: QuoteThe list of problems OOP creates is extremely long and, it seems compilers that support OOP are constantly adding new "features" which are nothing but hacks to workaround the problems inherent in the OOP paradigm.  Another example, since data visibility is not determined by the structure of the code, "modifiers" for "private", "published", "strict", "strict private" and who knows how many more are put into the compiler to synthesize visibility scopes that should be determined by the program structure. Might I add some more things to the list? There is "sealed" and "final", "public final" too. ---------------------------------------------------------------------- winni · 2020-05-04 17:37 Hi! After a lot of searching i've got it - not only from memory: September 1978 the things were better than today - for a set. From UCSD_PASCAL_1.5_Manual_Sep78.pdf : Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 2.2.18 IMPLEMENTATION SIZE LIMITS......3. Number of elements in a SET  is 255 * 16 = 4060  The restriction to only 256 elements came with Turbo Pascal. And Pascal hasn't recovered from this until now. Winni ---------------------------------------------------------------------- munair · 2020-05-04 17:58 Quote from: winni on May 04, 2020, 07:37:27 pmHi! After a lot of searching i've got it - not only from memory: September 1978 the things were better than today - for a set. From UCSD_PASCAL_1.5_Manual_Sep78.pdf : Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 2.2.18 IMPLEMENTATION SIZE LIMITS......3. Number of elements in a SET  is 255 * 16 = 4060  The restriction to only 256 elements came with Turbo Pascal. And Pascal hasn't recovered from this until now. Winni Sad. I wonder what that sudden restriction was related to. ---------------------------------------------------------------------- lucamar · 2020-05-04 18:08 Quote from: munair on May 04, 2020, 07:58:03 pmSad. I wonder what that sudden restriction was related to. Memory consumption, most probably; remember that the first Turbo Pascal target was CP/M systems with a minimum of (IIRC) 48K TPA. Also, using sets with more than 255 elements has never been all that common. Except for range-checking indexes, which can easily be done with a couple comparisons. ---------------------------------------------------------------------- 440bx · 2020-05-04 18:12 Quote from: JiaXing on May 04, 2020, 05:19:30 pmBTW, Do you prefer functional programming over OOP? Because it's the most hot trend now. OOP has faded and procedural is always ridiculed as not fit for big project  Like most programmers, I've looked at and played with quite a few languages.  My preference is for languages that I can see in my mind the assembly code the compiler will generate as I type the code.  Functional languages are good for some things and, they definitely have some interesting characteristics but, I cannot see the assembly code as I type, therefore I don't use them.  That said, I do make exceptions to that for throw away code, for instance, I regularly use AWK but, I don't have a single AWK script that I even remember.  I could not care less about what's hot or not.  I care about the results and people can ridicule procedural programming all they want but, when the results are in, they consider their project "big" because their result is BIG (and it wouldn't be if it had been done right.) Quote from: JiaXing on May 04, 2020, 07:33:13 pmDon't mind my signature. It's just joking.I don't.  I think it's funny but, for the record, I don't run a church and, programming isn't a religion though it seems the unqualified allegiance some have for deficient paradigms borders on it. Quote from: JiaXing on May 04, 2020, 07:33:13 pm You are just wasting time to emulate OOP with your own quasi-OOP code. So how could you say you don't need OOP at all since you are emulating it?  Let's be clear.  I am not emulating OOP.   There are _some_ (few!!) commonalities because it's still programming but structurally, it has little to nothing in common with OOP. Quote from: JiaXing on May 04, 2020, 07:33:13 pmMight I add some more things to the list? There is "sealed" and "final", "public final" too. Go ahead... add away. Be my guest. Quote from: munair on May 04, 2020, 07:58:03 pmQuote from: winni on May 04, 2020, 07:37:27 pm3. Number of elements in a SET  is 255 * 16 = 4060 ... The restriction to only 256 elements came with Turbo Pascal. Sad. I wonder what that sudden restriction was related to. Just a guess but, probably related to how much memory would be used.  What I find stranger is the 4060... it's not a power of two... that's a somewhat unusual choice.  Seems 4096 would have been the "natural" number. @Lucamar You posted that will while I was composing my reply.  I concur with your guess as to the reason for limiting the sets to 256 elements. ---------------------------------------------------------------------- Martin_fr · 2020-05-04 18:12 Well, one good think to take home from this. I am really glad for my ignorance and the ability to be really really wrong, which allows me to use (and benefit from) OOP. I am so mistaken that I believe many of the deficiencies listed by 440bx are actually advantages. ---------------------------------------------------------------------- 440bx · 2020-05-04 18:39 Quote from: Martin_fr on May 04, 2020, 08:12:16 pmWell, one good think to take home from this. I am really glad for my ignorance and the ability to be really really wrong, which allows me to use (and benefit from) OOP. I am so mistaken that I believe many of the deficiencies listed by 440bx are actually advantages. ... as far as "advantages", even global variables have advantages (beginners love them) but, those "advantages" have a way of turning into disadvantages. It's such a great "advantage" to have to keep track of umpteen classes residing in the heap... class.create... class.free... of course all that in "try ... finally"(ies) because checking preconditions is too much work... recursion ?... not easy when structures are kept in the heap... not to mention all the scoping "advantages" ... public, private, strict, strict private and on and on... (that's such an "advantage" over having the structure in the stack where its scope and visibility is simply determined by its location)... polymorphic calls like "Shape.Draw()", just by reading that the programmer knows instantly it's going to be a circle.... oh wait... why is a tetrahedron there ?... (probably because of the untimely death of a loxodrome and someone inherited from it) ...  property needs to send a return code to the caller ?...  no problem, we have exceptions for that... and it's such an "advantage" that the exception handler that got the notification wasn't the target or had no clue how to handle that problem but... wait... there is another "advantage", just re- raise the exception and pass the buck... that sure is a great "advantage" when a programmer has to figure out what code will ultimately handle what. and on and on and on... That stuff makes spaghetti code look like a desirable "paradigm". With all of those advantages, I wonder why none of those who benefit from them has attempted to replicate the behavior of the little program I posted.  It must be because it is small... OOP doesn't do small.  It's beneath OOP.  Must be. ---------------------------------------------------------------------- lucamar · 2020-05-04 18:43 Quote from: 440bx on May 04, 2020, 08:12:04 pmYou posted that will I was composing my reply.  I concur with your guess as to the reason for limiting the sets to 256 elements. It should also be noted that UCSD Pascal was quite apart in this respect. Most "personal" Pascal compilers (say, Pascal MT+) limited sets in this way too; after all, 32 bytes are 32 bytes! Quote from: 440bx on May 04, 2020, 08:12:04 pmWhat I find stranger is the 4060... it's not a power of two... that's a somewhat unusual choice.  Seems 4096 would have been the "natural" number. It's probably a typo; I haven't used UCSD much but IIRC you could have a set [0..4095], which fits nicely in the max. 16 * 256 ---------------------------------------------------------------------- Warfley · 2020-05-04 18:50 Quote from: 440bx on May 04, 2020, 03:20:53 amI consider bloated executables to be an indication of code that leaves something to be desired.This is so easiely disprovable using hello world: C (procedual): Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include int main(int argc, char **argv) {  std::printf("Hello %s\n", argv[1]);  return 0;}C++ (OOP): Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include class Greeter {  private:  char *name;  public:  Greeter(char *aname): name(aname) {}  void greet() {    std::cout << "Hello " << name << "\n";  }}; int main(int argc, char **argv) {  Greeter g{argv[1]};  g.greet();  return 0;} Both compiled with the exact same command: Code: Bash  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i $> g++ -O3 test.c -o ctest$> g++ -O3 test.cpp -o cpptestSize: Code: Bash  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i $> ls -lh[...]-rwxr-xr-x 1 frederic Kein 318K  4. Mai 18:16 cpptest.exe- rwxr-xr-x 1 frederic Kein 512K  4. Mai 18:16 ctest.exe so to put it simply, your argument is invalid, OOP does not "bloat" the executable at all, it is even smaller than the non OOP example. Your argument is simply wrong. QuoteThe real problem is that, so far, I can always think - with little effort - of a clearly better solution that doesn't use OOP.  I work with both C and C++ on a daily basis, and I can only say that from all I have seen OOP wins at least in regards of readability and maintainability always. Simply the fact that in procedual programming your functions can be all over the place while in OOP they are grouped with the data they work on massively improves readability. Forgett everything else about OOP, the fact alone that to find out which functions change values of your object you only need to look into the object definition is a massive improvement over procedual programming. Especially in pascal where your type definition is basically a list that tells you everything about that type, including all ways to interact with it. In procedual programming I can change the values of any record freely from any point in the code. In OOP I can organize my classes so that every interaction with the data will only occur inside the methods of my class. QuoteThe Delphi 2 version is 37KB (and I could easily shave 5 to 10K off of it, IOW, I didn't code it to be as small as reasonably possible).  The 32bit FPC version is 183KB (I wish it were smaller than that) and the 64bit FPC version weighs in at 236KB.   Run two instances of the program simultaneously and you'll see that one instance is different and behaves differently than the other.  The reason to have it in one program, among many others, is that about 80% of the code among the two programs is the same, because of that, one executable is the perfect solution. And how to benchmark this? I mean file size is pretty much the least important metric to judge an executable, at least as long as it will run on a modern PC. I have 32 gigs of ram, 1.5 TB SSD and a download speed of many megabytes per second. Why should I care about file size? As long as it does not get to massive (the largest programm I've written had less than 200mb, this was including graphics, without it's less than 100 megs) filesize is the least important metric. Especially if we consider that there more often than not is a time-memory tradeoff. For example inlining of functions which are called more often than once will inevitebly increase the file size, but will also increase the performance. Other example jumping tables, an if-then- else for ranges is much smaller in code size, but checking if none of the values fit takes a linear time with the size of the if. A jumping table instead has always a constant time, but scales linear in size with the number of values that are covered. So let's assess what is more important speed or memory (on a usual desktop PC like the one I'm having). To upgrade my PC to 64 gigs of ram it would cost me about 100€-200€ or so. To upgrade my CPU from 12 cores at 3.5 GHz to a CPU with a. double the cores or b. double the clock speed, would cost me a. 500€ b. be impossible because there is no 7 GHZ 12 core CPU available. Your programm is a GUI programm, meaning profiling it performance wise does not make any sense. Also I'm more of a POSIX developer, so why don't we make something that makes more sense to compare, something where the architecture will also be completely different. And it should be doable without any external libraries (like for example the Windows API. You can use it if you want, but it should be doable with only FPCs system unit). I would suggest the following as a compromise of being easy but still a practically relevant piece of code: A programm that takes from stdin a script formatted as followed: 1. line an S-Expression forming an arithmetic tree using integers and variables, and in the following lines queries to that assigning variables. E.g. Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i (add (mul 2 x) y)x=2,y=3x=5,y=4The output should than compute the result, in this example it should compute 2 * 2 + 3 and 2 * 5 + 4. Then we can compare 1. runtime on a large input, 2. exec size, 3. code size. ---------------------------------------------------------------------- winni · 2020-05-04 18:55 Quote from: lucamar on May 04, 2020, 08:08:23 pm Memory consumption, most probably; remember that the first Turbo Pascal target was CP/M systems with a minimum of (IIRC) 48K TPA. Indeed in the late 70s there were CP/M systems with 48k. But in the  early 80s everybody had a mimimum of 64k. Turbo Pascal 1.0 came 1983. 6 years  before that a set in UCSD allowed 4060 elements. And that version could not use more than 64k. So it is either lazyness. Or a design fault.  Blame Anders Hejlsberg. Winni ---------------------------------------------------------------------- Martin_fr · 2020-05-04 18:59 Quote from: 440bx on May 04, 2020, 08:39:07 pm no problem, we have exceptions for that... Exceptions are OOP ?? really? WOW. And that is not the first bit of FUD that you mixed in. Sadly though, since as I already admitted, here and there you actually had a point. (small ones, but real ones) I just learned something new. Not about OOP, but about your beliefs. (SCNR) Now what do you want me to believe, if you mix up things like that? 1) You do not know what the diff between OOP and other stuff is? Then why should your opinion on OOP matter? Now I do give you the benefit of the doubt that you do know the diff. That leaves 2) You pull in unrelated staff, so that your point looks much much bigger than it actually is? If your own confidence in the core bit of your issues is that low, again why believe you? 3? your explanation? ---------------------------------------------------------------------- marcov · 2020-05-04 19:03 Quote from: munair on May 04, 2020, 07:58:03 pmSad. I wonder what that sudden restriction was related to. Probably keep elementsize/index a byte, loading a value > buswidth required more cycles, and the compiler had to fit in about 500k and still have enough memory to compile. So making exceptions or multiple tracks was hard. Then by the time of Delphi, the focus has shifted to more modern features, and old underpinnings were neglected. Actually I think we even had troubles in the compiler because of this, when an enum got to large, and sets of it no longer worked. ---------------------------------------------------------------------- munair · 2020-05-04 19:13 Quote from: marcov on May 04, 2020, 09:03:36 pmActually I think we even had troubles in the compiler because of this, when an enum got to large, and sets of it no longer worked. And simply leaving out sets in FPC wasn't an option because of the level of compatibility that had to be reached, I guess. ---------------------------------------------------------------------- munair · 2020-05-04 19:21 Quote from: Warfley on May 04, 2020, 08:50:49 pmThis is so easiely disprovable using hello world: C (procedual): Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include int main(int argc, char **argv) {  std::printf("Hello %s\n", argv[1]);  return 0;}C++ (OOP): Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include class Greeter {  private:  char *name;  public:  Greeter(char *aname): name(aname) {}  void greet() {    std::cout << "Hello " << name << "\n";  }}; int main(int argc, char **argv) {  Greeter g{argv[1]};  g.greet();  return 0;} Both compiled with the exact same command: It would be a fair comparison to also include a C++ version without OOP. I bet it is also smaller than the C version and even smaller than the C++ OOP version. Ultimately, it very much depends on the compiler(s) used. ---------------------------------------------------------------------- Warfley · 2020-05-04 19:27 Quote from: munair on May 04, 2020, 09:21:37 pmIt would be a fair comparison to also include a C++ version without OOP. I bet it is also smaller than the C version and even smaller than the C++ OOP version. Ultimately, it very much depends on the compiler(s) used. As C is a subset of C++ I used g++ for both, so it's not a compiler difference (actually the first one is not even C but C++ without OOP). The difference is that the oldschool function printf is really bloated, while the C++ cin class is really lightwight. If i replace cin... with printf, it has to the byte the exact same size, meaning the OOP "overhead" is literally 0. But I put this example in here because the reason cin is so much more efficent than printf is because of it's use of templates. The function to print numbers is only generated on compile time when actually numbers are printed. If only strings are printed, the cin class will only provide functionality to print strings. In comparison to this printf needs to be able to print everything at any point in time, which is really complicated ---------------------------------------------------------------------- marcov · 2020-05-04 19:28 Quote from: munair on May 04, 2020, 09:13:17 pmQuote from: marcov on May 04, 2020, 09:03:36 pmActually I think we even had troubles in the compiler because of this, when an enum got to large, and sets of it no longer worked. And simply leaving out sets in FPC wasn't an option because of the level of compatibility that had to be reached, I guess. Before the change to unicode, sets were immensely heavily used in string routines. Still are to a degree. I also don't think removing was ever suggested. But personally I hate this limit. It makes using enums and sets for statemachines less elegant because it doesn't scale, and go the manual C way. Same for bitfields in streamed datastructures (I have several at work). That's why I was looking for the large set generic (see large set thread) ---------------------------------------------------------------------- munair · 2020-05-04 19:29 Also, I do not know what the criterium is for a "hello world" program, but compiling it here on Linux (without OOP) results in a mere 40kb executable. ---------------------------------------------------------------------- munair · 2020-05-04 19:34 And I can do even better than that! Compiling this in Geany: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include int main() {   // printf() displays the string inside quotation   printf("Hello, World!");   return 0;} results in a mere 16 kb executable. What bloated tools produce 300+ kb??? ---------------------------------------------------------------------- winni · 2020-05-04 19:37 Quote from: marcov on May 04, 2020, 09:03:36 pmQuote from: munair on May 04, 2020, 07:58:03 pmSad. I wonder what that sudden restriction was related to. Probably keep elementsize/index a byte, loading a value > buswidth required more cycles, and the compiler had to fit in about 500k and still have enough memory to compile. So making exceptions or multiple tracks was hard. Then by the time of Delphi, the focus has shifted to more modern features, and old underpinnings were neglected. Actually I think we even had troubles in the compiler because of this, when an enum got to large, and sets of it no longer worked. The size of the compiler could not be the problem. I just started UCSD Pascal - the DOS hosted version. It is Version 4.2.2 and so "bigger" than the above mentioned. The System.Compiler has the size of 58.5 kB. And that the sets in Delphi were neglected: The one reason that one of the developers was again Anders Hejlsberg. And the other reason: There was a new fashion in town. Winni ---------------------------------------------------------------------- Warfley · 2020-05-04 19:38 Quote from: munair on May 04, 2020, 09:34:46 pmresults in a mere 16 kb executable. What bloated tools produce 300+ kb??? Simple, on linux distros the libc is shipped with the system, so it is linked dynamically. On windows however the compiler needs to link statically because windows does not provide the libc, which means your code does not contain the printf code. That means the C++ cin example should also not be so much smaller anymore, because there the stdlib is also provided by the system. This is also the reason why fpc programs are so much larger than gcc programs on linux. It's simply that the fpc needs to pack the system unit into your application while the libc is provided by your system ---------------------------------------------------------------------- marcov · 2020-05-04 19:47 Quote from: munair on May 04, 2020, 09:29:39 pmAlso, I do not know what the criterium is for a "hello world" program, but compiling it here on Linux (without OOP) results in a mere 40kb executable. Statically linked ? ---------------------------------------------------------------------- munair · 2020-05-04 19:51 Quote from: Warfley on May 04, 2020, 09:38:55 pmQuote from: munair on May 04, 2020, 09:34:46 pmresults in a mere 16 kb executable. What bloated tools produce 300+ kb??? Simple, on linux distros the libc is shipped with the system, so it is linked dynamically. On windows however the compiler needs to link statically because windows does not provide the libc, which means your code does not contain the printf code. That means the C++ cin example should also not be so much smaller anymore, because there the stdlib is also provided by the system. This is also the reason why fpc programs are so much larger than gcc programs on linux. It's simply that the fpc needs to pack the system unit into your application while the libc is provided by your system But the printf code is not a measure for comparing OOP vs non-OOP. If I were to wrap the code in a class, naturally it would produce more code. ---------------------------------------------------------------------- Warfley · 2020-05-04 20:02 Quote from: munair on May 04, 2020, 09:51:14 pmBut the printf code is not a measure for comparing OOP vs non-OOP. If I were to wrap the code in a class, naturally it would produce more code. Actually wrapping the same programm into a class creates, at least in C++ if you don't use RTTI, 0 overhead. They are simply syntactic sugar and fully get optimized away even in O1. Take this code: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     #include         class Greeter {      private:      char *name;      public:      Greeter(char *aname): name(aname) {}      void greet() {        printf("Hello %n\n", name);      }    };       int main(int argc, char **argv) {      Greeter g{argv[1]};      g.greet();      return 0;    }This is basically syntactic sugar for: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include struct Greeter {  char *name;} void Greeter_greet(Greeter &self) {  printf("Hello %s\n", self.name);} int main(int argc, char **argv) {  Greeter g  Greeter_greet(g);  return 0;}Which will then be inlined: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include int main(int argc, char **argv) {  printf("Hello %s\n", argv[1]);  return 0;}resulting in the exact same code as using C. To a more comparable code in C would be: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include  void greet(char *name) {  printf("Hello %s\n", name);}int main(int argc, char **argv) {  char *name = argv[1];  greet(name);  rerturn 0;}The thing about C++ is, using stack local classes that don't have virtual functions, will be completely optimized away. It's the same as using local variables and functions in C, adding absolutely no overhead. The only time overhead through classes is generated if you have virtual functions (which most classes don't need) or you use RTTI (which will also only be generated if it is needed). If you don't need any of that C++ classes will add absolutely no overhead. Also I used std::cin because this is the C++ alternative to printf. Actually in C++ it is heavily discuraged to use printf but rather to use the new stream classes (of which cin is one), because they only have the respected code when it is needed, i.e. the required functions are generated at compiletime, meaning if you don't need integers the cin class will not contain functionality to print integers ---------------------------------------------------------------------- munair · 2020-05-04 20:09 Yes, but with larger, more complicated programs OO stuff won't be optimized away like that. IOW, compilers are smart enough to see the difference and providing a stack based class example doesn't prove anything. Also, C++ compilers may be among the smartest on the planet. It would be interesting to compare similar code in other languages. ---------------------------------------------------------------------- Warfley · 2020-05-04 20:11 Quote from: munair on May 04, 2020, 10:09:01 pmYes, but with larger, more complicated programs OO stuff won't be optimized away like that. IOW, compilers are smart enough to see the difference and providing a stack based class example doesn't prove anything. No you don't get my point, it's not about the inlining, it's about the overhead of the class itself. A stacklocal class has no more overhead than calling functions. Having a class Greeter with a function greet and a name, has not more overhead than having a function greet that get's a name as parameter. Therefore *any* procedual program cann be implemented using C++ classes without any overhead, meaning classes (and thereby OOP in general) does not add any overhead ---------------------------------------------------------------------- Warfley · 2020-05-04 20:18 Quote from: munair on May 04, 2020, 10:09:01 pmAlso, C++ compilers may be among the smartest on the planet. It would be interesting to compare similar code in other languages. If you want to level the playing field use LLVM. Swift, Go, Rust, C++ and even FPC can compile to LLVM making use of the same optimizations. But all these languages are also quite different with regards to optimization, e.g. in swift pointer in generall can't be null (or point to an invalid object), if you want to have a pointer to be null you need to mark it specifically as such. This gives a massive advantage for optimization, which is why C++ also implements this as their reference type (It also implies that the object the pointer points to will live at least as long as the pointer). In rust you have a strict ownership enforcement, meaning at any point in time each object is owned by exactly one owner who is allowed to write (you can grant writing rights, but only one participant can have writing rights at a time). Meaning an instance of an object can simply be referenced as long as no one has writing rights, meaning many copy instructions can be replaced by referencing the object. Thats also the reason why for example Firefox is currently being rewritten in Rust, it allows for great Optimizations, producing code that is not less efficient than C or C++, while also being 100% memory safe (mathematically provable. The compiler does not compile if it can't automatically proove that you are following the ownership enforcement). ---------------------------------------------------------------------- munair · 2020-05-04 20:20 Quote from: Warfley on May 04, 2020, 10:11:41 pmNo you don't get my point, it's not about the inlining, it's about the overhead of the class itself. A stacklocal class has no more overhead than calling functions. I wasn't talking about inlining. Normally, a class produces more code because of the inherent references. When a compiler is smart enough to optimize all that away, naturally you get the same result. But you're now speaking specifically of the C++ compiler. Many compilers are not equally smart, and a programmer should not automatically assume that the compiler he works with provides the same quality. ---------------------------------------------------------------------- munair · 2020-05-04 20:24 Quote from: Warfley on May 04, 2020, 10:18:51 pmIf you want to level the playing field use LLVM. Swift, Go, Rust, C++ and even FPC can compile to LLVM making use of the same optimizations. Go doesn't support classes. Languages are not so easy to compare in this respect. ---------------------------------------------------------------------- Warfley · 2020-05-04 20:28 Quote from: munair on May 04, 2020, 10:20:26 pmI wasn't talking about inlining. Normally, a class produces more code because of the inherent references. When a compiler is smart enough to optimize all that away, naturally you get the same result. But you're now speaking specifically of the C++ compiler. Most other compilers are not equally smart, and a programmer should not automatically assume that the compiler he works with provides the same quality. Thats not the case for stack classes, only for heap classes. If you have a stack class it is literally the same as simply having a record containing your data and calling a function with that record as an argument. So every time you use a record in procedual programming, having a class is in C++ exactly as efficient. Sure in this exact example there is no need for a record in the C program because there is only one member (name), but then there is also no need for a class. The thing about OOP vs procedual, at least with regards to C++ is, in procedual programming as soon as you combine your data into records, you could also use a C++ class without any overhead. Sure if you don't use records using classes would result in overhead, but I don't know of a single non-trival procedual program that doesn't use records. And if it exists, maintaining the code must be horrible ---------------------------------------------------------------------- munair · 2020-05-04 20:41 Quote from: Warfley on May 04, 2020, 10:28:41 pmQuote from: munair on May 04, 2020, 10:20:26 pmI wasn't talking about inlining. Normally, a class produces more code because of the inherent references. When a compiler is smart enough to optimize all that away, naturally you get the same result. But you're now speaking specifically of the C++ compiler. Most other compilers are not equally smart, and a programmer should not automatically assume that the compiler he works with provides the same quality. Thats not the case for stack classes, only for heap classes. If you have a stack class it is literally the same as simply having a record containing your data and calling a function with that record as an argument. So every time you use a record in procedual programming, having a class is in C++ exactly as efficient. Sure in this exact example there is no need for a record in the C program because there is only one member (name), but then there is also no need for a class. The thing about OOP vs procedual, at least with regards to C++ is, in procedual programming as soon as you combine your data into records, you could also use a C++ class without any overhead. Sure if you don't use records using classes would result in overhead, but I don't know of a single non-trival procedual program that doesn't use records. And if it exists, maintaining the code must be horrible Procedural programming is not necessarily horrible. The difference is that the programmer must provide the structure himself by choosing the right naming. I have done this hundreds of times using procedural languages. And even today I often don't go much further than UDTs or records as you call them because they are less complicated than classes. But in the end it is just a more convenient way of grouping related code. Classes can also make programs difficult to maintain. Changing something up the inheritance chain can cause nasty bugs. This is a reason why Go did not implement classes. ---------------------------------------------------------------------- 440bx · 2020-05-04 20:53 Quote from: Warfley on May 04, 2020, 08:50:49 pm-rwxr-xr-x 1 frederic Kein 318K  4. Mai 18:16 cpptest.exe -rwxr-xr-x 1 frederic Kein 512K  4. Mai 18:16 ctest.exe[/code] so to put it simply, your argument is invalid, OOP does not "bloat" the executable at all, it is even smaller than the non OOP example. Your argument is simply wrong. Simply, No.  Both executables are bloated, one more than other but, both are. To put this into perspective, your executables use 318K and 512K just to output "hello". Have a look at this program I wrote https://forum.lazarus.freepascal.org/index.php?topic=46617.0  it is a fairly complete PE viewer - it does a _lot_ more than put "hello" on the console - and, if memory serves, it is in the ballpark of 250K.  There it is, your cpptest used about 70K more code to display "hello" on a console than a fairly complete PE viewer.  NOTE: there _isn't_ a single of assembly code in that program, IOW, it isn't programmed to be as small as possible. The executables you produced make my point, whether C or C++, there is always a pile of junk in the executable that doesn't have any business being there.  I'll grant you that the result you show indicates that C++ is better at not putting as much junk as C but, 318K to output "hello" ??? ... I cannot help but consider that _way_ more than anything reasonably justifiable. Quote from: Warfley on May 04, 2020, 08:50:49 pm Simply the fact that in procedual programming your functions can be all over the place while in OOP they are grouped with the data they work on massively improves readability. That's the case only if the program is poorly written or if the language doesn't support nested functions/procedures.  In a well written procedural language that supports nested functions/procedures, the result is vastly superior to what can be produced with OOP. Quote from: Warfley on May 04, 2020, 08:50:49 pm In procedual programming I can change the values of any record freely from any point in the code. Only if the record is a global variable - which would be a design problem - otherwise that is not true. Quote from: Warfley on May 04, 2020, 08:50:49 pm In OOP I can organize my classes so that every interaction with the data will only occur inside the methods of my class. Same thing can be done using nested functions/procedures.  OOP isn't bringing anything to the table that wasn't already there (except in the case of C since supporting nested functions is a "novelty" for C.) Quote from: Warfley on May 04, 2020, 08:50:49 pmI mean file size is pretty much the least important metric to judge an executable, at least as long as it will run on a modern PC.Not the case at all.   Every instruction in an executable is a potential source of bugs.  People now like to downplay the size of the executable because the tools/compilers they use generate bloat instead of quality.   Because of that, quality, which is reflected in code size is supposedly not important anymore.  Quote from: Warfley on May 04, 2020, 08:50:49 pmWhy should I care about file size? Paragraph above answers that question. Quote from: Warfley on May 04, 2020, 08:50:49 pmfilesize is the least important metric. That may be true for programmers addicted to bloat generators. Quote from: Warfley on May 04, 2020, 08:50:49 pmEspecially if we consider that there more often than not is a time-memory tradeoff. For example inlining of functions which are called more often than once will inevitebly increase the file size, but will also increase the performance.We might have something to agree on as far as time-memory trade off.  I will almost always choose a simpler, easier to understand algorithm over another one that is more memory efficient.  As you said, memory is cheap, human time spent to understand complex algorithms isn't, not to mention that the more complex the algorithm, the more likely there is a subtle bug in it. As far as speed goes, design for parallelism.  Take advantage of the ever increasing number of cores.  I'd much rather have a somewhat slower algorithm that can easily be parallelized than a faster one that may not be parallelizable or may be but with significant effort (which implies a higher likeliness of bugs.) Quote from: Warfley on May 04, 2020, 08:50:49 pmSo let's assess what is more important speed or memory (on a usual desktop PC like the one I'm having). Both are and both should be "reasonable", which in this case means, fast enough that the program can flow with the user's actions and memory consumption that is justified given what it does.  That last one means, 320K to put "hello" on a console ?... that's neither reasonable nor justified. Quote from: Warfley on May 04, 2020, 08:50:49 pmYour programm is a GUI programm, meaning profiling it performance wise does not make any sense. I didn't submit it claiming it was faster than something else.  That program isn't about speed, it is about code re-use. There are two programs in one executable, since the two programs share about 80% of the code, instead of producing two executables, produce just one.  Much simpler and, there is another BIG advantage to the method - which is _not_ related to size - when distributed, there aren't two programs to compile and keep in synch, there aren't two programs to install, there aren't two programs that may fail, the user won't delete one because he/she doesn't realize the other program needs it... etc, etc. Let's see OOP do that and compare the resulting executables. Quote from: Warfley on May 04, 2020, 08:50:49 pmAnd it should be doable without any external libraries (like for example the Windows API. You can use it if you want, but it should be doable with only FPCs system unit). Just for the record, any program I write that uses the compiler's RTL is either proof of concept/test or throw away code.  No program I write which I intend to use on regular basis uses any of the compiler's RTL.  One of the reasons I'm using Pascal - not the only one - is because it's become ever harder to have C/C++ compiler _not_ use their RTL.  It used to be easy... write the code the right way... fiddle with linker switches and that was it... now, getting compilers to _not_ use their RTL is real work.   I work to produce code... not to get rid of code.... if I didn't ask for it... it has no reason to be there. Quote from: Warfley on May 04, 2020, 08:50:49 pmI would suggest the following as a compromise of being easy but still a practically relevant piece of code: A programm that takes from stdin a script formatted as followed: 1. line an S-Expression forming an arithmetic tree using integers and variables, and in the following lines queries to that assigning variables. E.g. Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i (add (mul 2 x) y)x=2,y=3x=5,y=4The output should than compute the result, in this example it should compute 2 * 2 + 3 and 2 * 5 + 4. Then we can compare 1. runtime on a large input, 2. exec size, 3. code size. I'm somewhat concerned about your desire to compare speed.  The reason is, C/C++ compilers usually optimize better than Pascal compilers.  That means, it isn't OOP versus procedural that is being tested.  What's tested in that case are the compiler's abilities to optimize code and, we both know that FPC is ok in that area but, is usually no match for C/C++. Executable size, I have no problem comparing that. About the code size, I presume you mean lines of code. I place a lot more importance on ease of understanding than on how many lines of code the implementation takes.  I'd much rather deal with 1,000 lines of easy to understand code than 100 lines of subtle very hard to understand code - which is quite common in C and C++. Question for you ... since you offer that program as a compromise ... do you already have it written (or something very close to it) ? Another question: would you consider comparing a very limited PE viewer, one done in Pascal and the other one in C++.  The reason I ask is very obvious, I already wrote one (which is not limited) and its size is about 250K.  I'm willing to compare that to a version in C++ that dumps a PE file _only_ up to and including the OPTIONAL_HEADER.  I suspect my 250K PE viewer will be smaller and quite likely faster than a limited one written in C++. Quote from: Martin_fr on May 04, 2020, 08:59:24 pmExceptions are OOP ?? really? WOW. WOW... you know just as well as I do that exceptions are _not_ OOP but, you also know just as well as I do, that exceptions in Pascal have been "OOP-ified", IOW, an exception in FPC is an object.  One that is _grossly_ abused and misused as a workaround for the undesirable situations OOP puts a programmer in. Quote from: Martin_fr on May 04, 2020, 08:59:24 pmAnd that is not the first bit of FUD that you mixed in. Talk about FUD.  You're the one "fudding".  You know what I stated above is a fact. Quote from: Martin_fr on May 04, 2020, 08:59:24 pmI just learned something new. Not about OOP, but about your beliefs. (SCNR) Beliefs ?? seems like you're reaching for straws... Quote from: Martin_fr on May 04, 2020, 08:59:24 pmNow what do you want me to believe, if you mix up things like that? I want you to believe what you already know, that exceptions in FPC are objects and that they are grossly misused and abused. Quote from: Martin_fr on May 04, 2020, 08:59:24 pm1) You do not know what the diff between OOP and other stuff is? Then why should your opinion on OOP matter? Since you haven't defined what "other stuff" means, I don't have an opinion at all.  Define what "other stuff" means and I might have an opinion about it. Quote from: Martin_fr on May 04, 2020, 08:59:24 pmNow I do give you the benefit of the doubt that you do know the diff. Very kind of you.  Thank you. Quote from: Martin_fr on May 04, 2020, 08:59:24 pm2) You pull in unrelated staff, so that your point looks much much bigger than it actually is? If your own confidence in the core bit of your issues is that low, again why believe you? 3? your explanation? My explanation is that you have to define what "stuff" means to you.  After you do that, I might be able to provide an explanation that addresses the "stuff".  SCNR. ---------------------------------------------------------------------- munair · 2020-05-04 21:13 Quote from: marcov on May 04, 2020, 09:47:46 pmQuote from: munair on May 04, 2020, 09:29:39 pmAlso, I do not know what the criterium is for a "hello world" program, but compiling it here on Linux (without OOP) results in a mere 40kb executable. Statically linked ? Remind me not to use Windows as my daily OS. ---------------------------------------------------------------------- 440bx · 2020-05-04 21:21 Quote from: munair on May 04, 2020, 11:13:14 pmRemind me not to use Windows as my daily OS. That's probably not what anyone should be reminded of... a better thing to remind someone of is that the result depends on the compiler... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program HelloWorld;begin  writeln('Hello World');end. Using Delphi 2:QuoteDelphi for Win32  Version 9.0  Copyright (c) 1983,96 Borland International HelloWorld.lpr(4) 5 lines, 0.00 seconds, 3020 bytes code, 1224 bytes data.  5/04/2020  17:15           7,168  HelloWorld.exeThat's still way bigger than it should be but, at least it's not 320K (I believe that was on a Linux box... but not sure) ---------------------------------------------------------------------- munair · 2020-05-04 21:29 You cannot compare 32 bits and 64 bits programs. See my previous example of a 64 bits "hello world". On Linux it's 16 kb. On Windows it links statically, resulting in 300+ kb. ---------------------------------------------------------------------- BeniBela · 2020-05-04 21:32 Quote from: marcov on May 04, 2020, 04:21:22 pmTry to make a polymorphic list (TList, dyn array), without using pointers. I avoid polymorphism. But pointers to TP objects go, too Quote from: Warfley on May 04, 2020, 10:18:51 pmIn rust you have a strict ownership enforcement, meaning at any point in time each object is owned by exactly one owner who is allowed to write (you can grant writing rights, but only one participant can have writing rights at a time). Meaning an instance of an object can simply be referenced as long as no one has writing rights, meaning many copy instructions can be replaced by referencing the object. Thats also the reason why for example Firefox is currently being rewritten in Rust, it allows for great Optimizations, producing code that is not less efficient than C or C++, while also being 100% memory safe (mathematically provable. The compiler does not compile if it can't automatically proove that you are following the ownership enforcement). Although Rust cannot use all those optimization, because LLVM cannot handle it properly. Quote from: munair on May 04, 2020, 09:29:39 pmAlso, I do not know what the criterium is for a "hello world" program, but compiling it here on Linux (without OOP) results in a mere 40kb executable. 40kb for a hello world Btw, today is Star Wars day.  I have a 40kb Star Wars animation. Compiled with Delphi 4, creates a window, initializes OpenGL, contains music, textures, and space ship models. Although it is a MIDI music, so it needs a library which I do not know if it still exists. ---------------------------------------------------------------------- marcov · 2020-05-04 21:42 Quote from: winni on May 04, 2020, 09:37:17 pmI just started UCSD Pascal - the DOS hosted version. It is Version 4.2.2 and so "bigger" than the above mentioned. The System.Compiler has the size of 58.5 kB. Native compiled, statically linked? Or bytecode? Older bytecode is tighter than binary code, but requires interpreter + libraries to execute. QuoteAnd that the sets in Delphi were neglected: The one reason that one of the developers was again Anders Hejlsberg. I don't know much about that. BP7 is 1992, D1 is 1995, so there must have been at least some continuity. ---------------------------------------------------------------------- munair · 2020-05-04 21:56 While we're at it: "Hello world" in Quick Pascal on DOS 7: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program hello_world;beginwriteln('Hello World!');end. - > 3180 bytes. ---------------------------------------------------------------------- Martin_fr · 2020-05-04 22:04 I really did not want to reply any further, but its to good to ignore.... Quote from: 440bx on May 04, 2020, 10:53:12 pmQuote from: Martin_fr on May 04, 2020, 08:59:24 pmExceptions are OOP ?? really? WOW. WOW... you know just as well as I do that exceptions are _not_ OOP Yes that's what I said. Exactly what I said. Quote but, you also know just as well as I do, that exceptions in Pascal have been "OOP-ified" And the point is? Exceptions are still not OOP. You can use OOP in exceptions. That does not change the concept of Exceptions. You can use and abuse exceptions. This use and abuse can be done in OOP code as well as none OOP code. As for what you may have referred to (I can only guess, sorry if I guess wrong): "properties returning exceptions" => you mean. TList.Item throwing out of bounds? 1) Yes that is horrible, if used for production. But that is not OOP. It is a procedure checking its inputs.   In the same way as the none OOP StrToInt throws an excecpion...   In both cases a question of design. StrToInt has a none throwing equivalent. An TList could have an OOP style function with an out param, in case of invalid input. (IMHO it should not need it, the caller should make sure correctness before). But I digress on general design. Point is: None of those Exception have anything to do with OOP. QuoteI want you to believe what you already know, that exceptions in FPC are objects If you mean exceptions throw objects, then I never said anything to the contrary. The concept of exceptions has nothing to do with OOP at all. I am personally not a friend of exception based programming, but exception based programming exists entirely independent of OOP. As for what I guess is your claim that in procedural code there is less of a need for exceptions, I can not see where such a claim comes from. Someone who can not design OOP without exception, by all likelihood can also not design procedural without exception. So there is no difference between OOP and procedural with regards  to exceptions (well procedural has to throw a struct/record instead of an object, but that really is not the point). Quote from: 440bx on May 04, 2020, 08:39:07 pm property needs to send a return code to the caller ?...  no problem, we have exceptions for that... As I wrote above method or plain functions, such design is found in procedural code exactly as in OOP (Only in procedural programming its a procedure or function that "needs" to return the exception). Such design has nothing to do with OOP. Quoteand it's such an "advantage" that the exception handler that got the notification wasn't the target or had no clue how to handle that problem but... wait... there is another "advantage", just re-raise the exception and pass the buck... that sure is a great "advantage" when a programmer has to figure out what code will ultimately handle what. Your personal coding style may differ, but most procedural code I have seen is at least as deeply nested as OOP. Pass on the buck, is the exact same game in procedural code. Again nothing that is made any different by OOP. Quote from: 440bx on May 04, 2020, 04:56:48 pmOOP needs to use exceptions to go across stack frames because the execution gets trapped in its over-encapsulated implementation, since it is quite common for it to have to communicate something back to the caller, welcome to exceptions Same answer. High level of nested callers happens in procedural code too. Well to be exact, in both OOP or procedural, that may depend a lot on how much you like to pack into a single subroutine. I prefer to keep subroutine smaller, and factor code into further subroutine that I can call. You may prefer a different style. But the point is a decision on that style is not bound to OOP or procedural. ---------------------------------------------------------------------- 440bx · 2020-05-04 22:08 Quote from: munair on May 04, 2020, 11:29:28 pmYou cannot compare 32 bits and 64 bits programs. See my previous example of a 64 bits "hello world". On Linux it's 16 kb. On Windows it links statically, resulting in 300+ kb. Fair enough but, unless I missed it I didn't see in your post an indication of the program's bitness. Compiled for 64 bitQuote 5/04/2020  18:06          43,008  HelloWorld.exe ---------------------------------------------------------------------- marcov · 2020-05-04 22:12 Quote from: 440bx on May 05, 2020, 12:08:12 amQuote from: munair on May 04, 2020, 11:29:28 pmYou cannot compare 32 bits and 64 bits programs. See my previous example of a 64 bits "hello world". On Linux it's 16 kb. On Windows it links statically, resulting in 300+ kb. Fair enough but, unless I missed I didn't see in your post an indication of the program's bitness. Compiled for 64 bitQuote 5/04/2020  18:06          43,008  HelloWorld.exe (size freaks should go for 16-bits .COMs) ---------------------------------------------------------------------- winni · 2020-05-04 22:17 Quote from: marcov on May 04, 2020, 11:42:16 pm Native compiled, statically linked? Or bytecode? Older bytecode is tighter than binary code, but requires interpreter + libraries to execute. Yes - the UCSD system was always a P-code machine, later called Bytecode. I made a list of a necessary files which are needed to compile and execute a file. The interpreter is not necessary to compile. System.Pme.86    16.0 kB   - the Interpreter for DOS System.Library   52.5 kB   - the Library System.Syntax    8.0 kB  - the Compiler error messages (ASCII) System.Compiler  58.5 kB  - the Compiler Total           135.0 kB In Version 1.x and 2.x you had only 64 k RAM. In Version 4.x you had 64 k for Stack and Heap and 128 k for the Codepool. In the DOS-hosted version you got still 64 k for Stack/Heap but amazing 256 kB for the Codepool. When coding was simple and RAM was expensive .... Winni ---------------------------------------------------------------------- 440bx · 2020-05-04 22:36 Quote from: Martin_fr on May 05, 2020, 12:04:45 amAnd the point is? Exceptions are still not OOP. But, the point you're bending over backwards to avoid is that the OOP mindset results in "OOP-ing" everything, including exceptions.  Once exceptions have been turned into objects/classes, they are used in a very cavalier manner because they are seen as "just another object". Quote from: Martin_fr on May 05, 2020, 12:04:45 amYou can use and abuse exceptions. This use and abuse can be done in OOP code as well as none OOP code. True but, it is much more likely to be abused in OOP code than in procedural code (though Borland has encouraged their misuse by providing rather poor examples.) Quote from: Martin_fr on May 05, 2020, 12:04:45 amAs for what you may have referred to (I can only guess, sorry if I guess wrong): "properties returning exceptions" => you mean. TList.Item throwing out of bounds? 1) Yes that is horrible, if used for production. But that is not OOP. It is a procedure checking its inputs.   In the same way as the none OOP StrToInt throws an excecpion...   In both cases a question of design. StrToInt has a none throwing equivalent. An TList could have an OOP style function with an out param, in case of invalid input. (IMHO it should not need it, the caller should make sure correctness before). But I digress on general design. Point is: None of those Exception have anything to do with OOP. Yes, it is OOP because the OOP paradigm creates a mindset in the programmer that promotes very poorly thought out and structured code.  IOW, why "bother" doing it the right way when the code can throw an exception which is "just another object" ? Quote from: Martin_fr on May 05, 2020, 12:04:45 amThe concept of exceptions has nothing to do with OOP at all. Yes, that is true but, because exceptions have been turned into objects they are used as commonly as any other object and _that_ is another one of bad things about OOP: it encourage very poor programming.  Why design when exceptions can be thrown around as if they were another TLabel ? Quote from: Martin_fr on May 05, 2020, 12:04:45 amAs for what I guess is your claim that in procedural code there is less of a need for exceptions, I can not see where such a claim comes from. The great of majority of code doesn't "need" exceptions but, again, OOP has encouraged their misuse.  One and, not the only one, way it does that is by cornering the programmer into situations where there is no way to inform the caller of a problem.  Properties are an example of that and, properties are most definitely OOP stuff. Quote from: Martin_fr on May 05, 2020, 12:04:45 amSomeone who can not design OOP without exception, by all likelihood can also not design procedural without exception. So there is no difference between OOP and procedural with regards  to exceptions (well procedural has to throw a struct/record instead of an object, but that really is not the point). You refuse to acknowledge that OOP leads to poor programming habits.  The overuse of exceptions is one of them. Quote from: Martin_fr on May 05, 2020, 12:04:45 amYour personal coding style may differ, but most procedural code I have seen is at least as deeply nested as OOP. I'm not sure about that one.  Maybe but, in both cases, they are simply poor design. Quote from: Martin_fr on May 05, 2020, 12:04:45 amPass on the buck, is the exact same game in procedural code. Again nothing that is made any different by OOP. No.  Not the same because in procedural code, it is the caller that will be notified of the problem not some exception handler that may be anywhere and transfer control anywhere another time.  IOW, in procedural programming, it's easy to follow the error handling chain - it often doesn't go past the caller - whereas in the case of OOP, because of the use of exceptions, following the error handling chain is often not possible without running the program. Quote from: Martin_fr on May 05, 2020, 12:04:45 amSame answer. High level of nested callers happens in procedural code too. Yes but, you can easily follow the chain, not so in OOP. ---------------------------------------------------------------------- marcov · 2020-05-04 22:46 Quote from: winni on May 05, 2020, 12:17:15 amQuote from: marcov on May 04, 2020, 11:42:16 pmNative compiled, statically linked? Or bytecode? Older bytecode is tighter than binary code, but requires interpreter + libraries to execute. Yes - the UCSD system was always a P-code machine, later called Bytecode. I made a list of a necessary files which are needed to compile and execute a file. The interpreter is not necessary to compile. System.Pme.86    16.0 kB   - the Interpreter for DOS System.Library   52.5 kB   - the Library System.Syntax    8.0 kB  - the Compiler error messages (ASCII) System.Compiler  58.5 kB  - the Compiler Total           135.0 kB If I compile bytecode compiler P6 http://wirth-dijkstra-langs.org/ to native exe with FPC 32-bit it is 149.504 bytes. So FPC, which is not particularly size optimized has an 10kb increase in 40 years which proves AGAIN that the whole size discussion is mostly just windmills stuff. If you factor in that it is 32-bit code and has 2k or so worth of PE header, it might be considered more tight even for the functionality it delivers. Ah, the days of yonder, when the binaries were bloated and the interpreters inefficient.... ---------------------------------------------------------------------- Martin_fr · 2020-05-05 00:23 Quote from: 440bx on May 05, 2020, 12:36:06 amYou refuse to acknowledge that OOP leads to poor programming habits.  The overuse of exceptions is one of them. Yes, that I "refuse"... Or rather according to the statistical sample of people to whom I have access, that is not the case. I can only assume, that with the range of people you know, the statistics show a coincidence? I do not know the size of that sample. Nor do I know how "random" the choice actually is. But statistics away, I can also not see anything in the OOP paradigm, that would lead to exception usage. I am a big fan of OOP, but no fan of Exceptions at all. (Well for testcase, in form of "assert" they are ok, but that is a different matter, and again that applies for procedural testcases too) Also any claim that OOP makes exception easier to use (or more attractive) seems questionable. OOP has added nothing that you could not have had before. - returning an object as exception => procedural: return a struct/record. The "class" hardly matters, you can add a "ExceptionClass:enum" field to the struct. QuoteQuote from: Martin_fr on May 05, 2020, 12:04:45 amPass on the buck, is the exact same game in procedural code. Again nothing that is made any different by OOP. No.  Not the same because in procedural code, it is the caller that will be notified of the problem not some exception handler that may be anywhere and transfer control anywhere another time. In OOP the "try except end" block is also in the chain of callers. I know no language where that is different? In either case the "except end" can call any method it wants and pass the exception info on. And since "pointer to procedure" is avail in procedural code too, the handle may pass it to some event callback. There is no difference at all. QuoteYes, it is OOP because the OOP paradigm creates a mindset in the programmer that promotes very poorly thought out and structured code."the mindset of an OOP person": That is the only claim I can not disprove. But neither have you proven it.  And neither have I read anything from you that makes that even only remotely likely. Also, there are a great many different mindsets of OOP coders. And I would even go as for and claim that OOP actually educates people to more structured and thought through code. ---------------------------------------------------------------------- 440bx · 2020-05-05 02:03 @Martin, Obviously, we are not going to convince each other of anything regarding OOP and, I seriously doubt I am going to convince anyone at all here but, I hope the things I noted provides some food for thought to some. I agree to almost entirely disagree with you.   The "almost" is because it's quite obvious that I am not a fan of exceptions at all, except (pun not completely unintended) when a program is dealing with resources it doesn't own, other than that, exceptions don't belong in a program. ---------------------------------------------------------------------- eljo · 2020-05-05 02:10 Quote from: 440bx on May 05, 2020, 04:03:29 am @Martin, Obviously, we are not going to convince each other of anything regarding OOP and, I seriously doubt I am going to convince anyone at all here but, I hope the things I noted provides some food for thought to some. I agree to almost entirely disagree with you.   The "almost" is because it's quite obvious that I am not a fan of exceptions at all, except (pun not completely unintended) when a program is dealing with resources it doesn't own, other than that, exceptions don't belong in a program. Given the fact that in a modern OS your program doesn't own any resources you are saying that we can't leave with out exceptions? So you love exceptions? ---------------------------------------------------------------------- munair · 2020-05-05 05:36 Quote from: 440bx on May 04, 2020, 10:53:12 pmSimply, No.  Both executables are bloated, one more than other but, both are. That's because they were compiled on Windows, if I'm not mistaken. As I said before, Windows has grown from some 2 GB to a whopping 15 GB in less than 15 years. If you're really against bloat software, don't use Windows. Use a Unix derived or related OS instead. ---------------------------------------------------------------------- munair · 2020-05-05 05:44 Does FPC have a switch to leave out the debug_frame? Code: ASM  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i         .file "hw.pas"# Begin asmlist al_procedures .section .text.n_main      .balign 16,0x90.globl  PASCALMAIN        .type   PASCALMAIN,@functionPASCALMAIN:.globl  main        .type   main,@functionmain:.Lc1:# Temps allocated between rbp-8 and rbp+0# [hw.pas]# [3] begin        pushq   %rbp.Lc3:.Lc4:        movq    %rsp,%rbp.Lc5:        leaq    -16(%rsp),%rsp        movq    %rbx,-8(%rbp)        call    FPC_INITIALIZEUNITS@PLT# [4] writeln('hello world');        call    fpc_get_output@PLT        movq    %rax,%rbx        movq    _$HELLO_WORLD$_Ld1@GOTPCREL(%rip),%rdx      movq    %rbx,%rsi        movl    $0,%edi        call    fpc_write_text_shortstr@PLT        call    FPC_IOCHECK@PLT        movq    %rbx,%rdi        call    fpc_writeln_end@PLT        call    FPC_IOCHECK@PLT# [5] end.        call    FPC_DO_EXIT@PLT        movq  -8(%rbp),%rbx        leave        ret.Lc2:.Le0:        .size   main, .Le0 - main .section .text# End asmlist al_procedures# Begin asmlist al_globals .section .data.rel.n_INITFINAL        .balign 8.globl  INITFINAL        .type   INITFINAL,@objectINITFINAL:        .quad   1,0        .quad   INIT$_$SYSTEM        .quad   0# [6] .Le1:        .size   INITFINAL, .Le1 - INITFINAL .section .data.rel.n_FPC_THREADVARTABLES        .balign 8.globl  FPC_THREADVARTABLES        .type   FPC_THREADVARTABLES,@objectFPC_THREADVARTABLES:        .long   1      .quad   THREADVARLIST_$SYSTEM.Le2:        .size   FPC_THREADVARTABLES, .Le2 - FPC_THREADVARTABLES .section .data.rel.n_FPC_RESOURCESTRINGTABLES        .balign 8.globl  FPC_RESOURCESTRINGTABLES        .type   FPC_RESOURCESTRINGTABLES,@objectFPC_RESOURCESTRINGTABLES:        .quad   0.Le3:        .size   FPC_RESOURCESTRINGTABLES, .Le3 - FPC_RESOURCESTRINGTABLES .section .data.rel.n_FPC_WIDEINITTABLES      .balign 8.globl  FPC_WIDEINITTABLES        .type   FPC_WIDEINITTABLES,@objectFPC_WIDEINITTABLES:        .quad   0.Le4:      .size   FPC_WIDEINITTABLES, .Le4 - FPC_WIDEINITTABLES .section .data.rel.n_FPC_RESSTRINITTABLES        .balign 8.globl  FPC_RESSTRINITTABLES        .type   FPC_RESSTRINITTABLES,@objectFPC_RESSTRINITTABLES:        .quad   0.Le5:        .size   FPC_RESSTRINITTABLES, .Le5 - FPC_RESSTRINITTABLES .section .fpc.n_version        .balign 8        .ascii  "FPC 3.0.4 [2019/05/13] for x86_64 - Linux" .section .data.rel.n___stklen        .balign 8.globl  __stklen        .type   __stklen,@object__stklen:        .quad   8388608 .section .data.rel.n___heapsize        .balign 8.globl  __heapsize        .type   __heapsize,@object__heapsize:        .quad   0 .section .data.rel.n___fpc_valgrind.globl  __fpc_valgrind        .type   __fpc_valgrind,@object__fpc_valgrind:        .byte   0 .section .data.rel.n_FPC_RESLOCATION        .balign 8.globl  FPC_RESLOCATION      .type   FPC_RESLOCATION,@objectFPC_RESLOCATION:        .quad   0# End asmlist al_globals# Begin asmlist al_typedconsts .section .data.rel.n__$HELLO_WORLD$_Ld1        .balign 8.globl  _$HELLO_WORLD$_Ld1_$HELLO_WORLD$_Ld1:        .ascii  "\013hello world\000"# End asmlist al_typedconsts# Begin asmlist al_dwarf_frame .section .debug_frame.Lc6:        .long   .Lc8-.Lc7.Lc7:        .long   -1        .byte   1        .byte   0      .uleb128        1        .sleb128        -4        .byte   16      .byte   12        .uleb128        7        .uleb128        8        .byte   5        .uleb128        16        .uleb128        2        .balign 4,0.Lc8:        .long   .Lc10-.Lc9.Lc9:        .quad   .Lc6      .quad   .Lc1        .quad   .Lc2-.Lc1        .byte   4        .long   .Lc3-.Lc1        .byte   14        .uleb128        16        .byte   4        .long   .Lc4-.Lc3        .byte   5        .uleb128      6        .uleb128        4        .byte   4        .long   .Lc5-.Lc4        .byte   13        .uleb128        6        .balign 4,0.Lc10:# End asmlist al_dwarf_frame.section .note.GNU- stack,"",%progbits ---------------------------------------------------------------------- Thaddy · 2020-05-05 06:07 FPC_IOCHECK@PLT disappears when compiled in {$I-} state ( or {$IOCHECKS OFF} ) If that is what you mean.. I usually do that after debugging. ---------------------------------------------------------------------- munair · 2020-05-05 06:21 Quote from: Thaddy on May 05, 2020, 08:07:16 am FPC_IOCHECK@PLT disappears when compiled in {$I-} state ( or {$IOCHECKS OFF} ) If that is what you mean.. I usually do that after debugging. Nope, frame is still there. A quick google only gave a recent bug that mentions the debug_frame. ---------------------------------------------------------------------- Thaddy · 2020-05-05 06:31 Does 3.20 expose the same behavior? ---------------------------------------------------------------------- JiaXing · 2020-05-05 06:58 Quote from: munair on May 05, 2020, 07:36:01 amQuote from: 440bx on May 04, 2020, 10:53:12 pmSimply, No.  Both executables are bloated, one more than other but, both are. That's because they were compiled on Windows, if I'm not mistaken. As I said before, Windows has grown from some 2 GB to a whopping 15 GB in less than 15 years. If you're really against bloat software, don't use Windows. Use a Unix derived or related OS instead. That is obviously wrong. Windows used more and more space because they included more and more features and the old ones mostly can't be removed because of compatibility. They also keep Windows Updates files, MSI packages... It's the reason why they could roll back updates since the installation packages still there. When you said Windows, it already means Service Pack included. For Windows 7 it means Service Pack 1. A standard Windows 7 32 bit installation is 11.5 GB including pagefile.sys. If you strip every unnecessary things the finally system is not much bloated from a standard Linux installation. People have do that for a long time. There are many Windows Lite mods. Also keep in mind an Linux desktop installation is not just the kernel but all other stuffs pulled in to have a working desktop system. Windows = Linux + X11 + DE + Firefox + VLC + A bunch of small utilities. Let be fair, man. FPC is indeed GNU binutils based and binutils based compiler always generate bloated binary on Windows. Comparing Pelles C and MinGW-GCC and you will see the different. Don't blame Windows just because you don't like it. I don't like it, too, because I don't like the telemetry and the way M$ is making Windows a massive Spyware. So I use Linux. Also note people also implemented many kinds of telemetry Spyware and tracking tools on Linux, too. That's the reason why I avoid Ubuntu based distributions. ---------------------------------------------------------------------- munair · 2020-05-05 07:24 Quote from: JiaXing on May 05, 2020, 08:58:14 amAlso keep in mind an Linux desktop installation is not just the kernel but all other stuffs pulled in to have a working desktop system. Windows = Linux + X11 + DE + Firefox + VLC + A bunch of small utilities. Let be fair, man. Yeah, let's be fair. I was not referring to just the Linux kernel. That wouldn't be a fair comparison. I meant a complete distro, which usually also includes a full office suite, DVD burning software etc. The size of these distro's vary somewhat depending on the desktop installed, but it has been fairly stable for years, and it also includes older libraries such as GTK2 to maintain compatibility with older software. Windows tends to use resources a lot. The paging file by default is quite big and next to that there is the system volume information and the MFT which has also grown exponentially. I know Windows users generally don't like it, but Linux OSs (not just the kernel) are much more efficient and can usually be installed on much older hardware. I can easily install a Debian 64 bits OS on a 15 years old AMD 64 machine. Try to do that with Windows! QuoteAlso note people also implemented many kinds of telemetry Spyware and tracking tools on Linux, too. That's the reason why I avoid Ubuntu based distributions. There are many other distros to choose from that are clean of tracking stuff. ---------------------------------------------------------------------- JiaXing · 2020-05-05 08:09 Quote from: munair on May 05, 2020, 09:24:48 amWindows tends to use resources a lot. The paging file by default is quite big and next to that there is the system volume information and the MFT which has also grown exponentially. I know Windows users generally don't like it, but Linux OSs (not just the kernel) are much more efficient and can usually be installed on much older hardware. I can easily install a Debian 64 bits OS on a 15 years old AMD 64 machine. Try to do that with Windows! Please note that Linux ext4 also uses a lot of space for metadata. It's much much more than Windows. For my 1TB drive with a single ext4 file system it use 1.94 GB by default and when the file system is mounted it's increased to somewhat 5 GB but reduced back to 1.94 GB when unmounted. Ext4 is still the better file system, though. MFT size growing is not important, but MFT fragmentation is. It's a known problem for NTFS. If you applied all the necessary tweak, I got my Windows 7 64 bit RAM usage on startup about 514 MB. Turn off superfetch reduced much of the RAM usage. It's not any more bloated than Linux. Windows' DE is heavy. I used full Aero effect. So comparing Windows' DE to something like XFCE is unfair. It should be compared with KDE5 Plasma or GNOME3. And then you will see they are almost the same. Also keep in mind Windows is not optimized for specific customers as much as Linux. Yes, you don't hear it wrong. Windows is more generic about setting. They use a balanced performance profile that fitted for almost everyone by default. Linux distro maintainer, on the other hand, tweak their system heavily for the needs of specific customers. Comparing untweaked Windows with a Linux distro (already heavily tweaked) is unfair. An obvious example for this: Linux usually included the GPU driver by default. On my system it's MESA. And they tweaked it a lot to make it work well. On more server oriented distro they keep the default settings so it's tearing like hell, not as smooth as the distro I'm using. And with Windows, I'm not said about Windows 10, I have to download the Integrated Graphic Driver directly from Intel to make it use the native resolution of my monitor. The default included drivers of Windows are always outdated. This is the reason for the need of driver updating tools like Driver Booster. And it's about resource usage (bloatness) but not hardware support. Hardware support has more to do with drivers than resource usage. They patched Windows XP to include SATA driver and have it installed on modern system. They also have Windows 7 patched to run on a smartwatch or an emulator like Bochs on an Android device. If you used qemu without kvm (hardware acceleration) you should know how slow hardware emulation is, but it's still possible to run Windows. It's all about drivers and tweaks. The default Windows provided by M$ doesn't have the necessary drivers and tweaks to run on these hardwares. And if I'm M$ I also has no reason to support these hardwares. Linux in the other hand is an opensource software. People are free to contribute the missing bits they need. The supports are still there (even if unmaintained for a long time) until people decided to remove it because it's no longer worth to keep (no longer work well with modern linux version and it's a lot of efforts to keep linux to work with these old hardwares). It's the different between closed source commercial software and opensource software. Hope you get it. And I think we should stop being off topic. Let's give the thread back to 440bx. From what I observed I think I shouldn't engaged in discussing with you. You are too biased. Your statement about Windows bloatness is nothing but an personal attack to 440bx. ---------------------------------------------------------------------- JiaXing · 2020-05-05 08:37 @440bx: You didn't answer my question about if you prefered the OOP style of Oberon. I think it's very similar to what you are currently using ---------------------------------------------------------------------- PascalDragon · 2020-05-05 08:50 Quote from: Warfley on May 04, 2020, 09:38:55 pmQuote from: munair on May 04, 2020, 09:34:46 pmresults in a mere 16 kb executable. What bloated tools produce 300+ kb??? Simple, on linux distros the libc is shipped with the system, so it is linked dynamically. On windows however the compiler needs to link statically because windows does not provide the libc, which means your code does not contain the printf code. That means the C++ cin example should also not be so much smaller anymore, because there the stdlib is also provided by the system. On Windows one can link dynamically as well. At least MSVC can. Here are the example programs compiled with Visual Studio 2019 (32-bit) once as dynamic and once as static: Code: [Select]05.05.2020  10:02             8.192 hello-c-dyn.exe 05.05.2020  09:59           101.888 hello-c-static.exe 05.05.2020  10:01            11.264 hello-cpp-dyn.exe 05.05.2020  09:59           183.808 hello-cpp-static.exe And here the same with the 64-bit compiler: Code: [Select]05.05.2020  10:06             9.728 hello-c-dyn.exe 05.05.2020  10:06           119.296 hello-c-static.exe 05.05.2020  10:07            12.288 hello-cpp-dyn.exe 05.05.2020  10:07           235.520 hello-cpp-static.exe Oh and just for the fun of it: a simple helloworld compiled with FPC once statically and once with dynamic packages for i386-win32: Code: [Select]-a----       05.05.2020     10:21           6815 hello- dyn.exe -a----       05.05.2020     10:22          70363 hello-static.exe Obviously the rtl library is a bit bigger then Code: [Select]-a----       05.05.2020     10:14        2796891 rtl.dll Quote from: JiaXing on May 05, 2020, 08:58:14 amFPC is indeed GNU binutils based and binutils based compiler always generate bloated binary on Windows. Comparing Pelles C and MinGW-GCC and you will see the different. By default FPC uses its own, internal linker on Windows, because it is faster than ld. The problem of FPC compared with Delphi is that FPC's System unit has more dynamically built in due to its cross platform nature (thread manager, WideString/UnicodeString manager, Variant manager) that can't easily be linked away if it isn't used by the program cause it's at least initialized in the startup code. Quote from: munair on May 05, 2020, 09:24:48 amWindows tends to use resources a lot. The paging file by default is quite big and next to that there is the system volume information and the MFT which has also grown exponentially. I know Windows users generally don't like it, but Linux OSs (not just the kernel) are much more efficient and can usually be installed on much older hardware. I can easily install a Debian 64 bits OS on a 15 years old AMD 64 machine. Try to do that with Windows! The MFT is the metafile on NTFS that contains information about all other files. Of course it grows if the file system contains more file objects. The inode structure of Ext and Co. filesystems is simply not visible to the user, but it's there as well. ---------------------------------------------------------------------- munair · 2020-05-05 09:17 Quote from: JiaXing on May 05, 2020, 10:09:03 amIf you applied all the necessary tweak, I got my Windows 7 64 bit RAM usage on startup about 514 MB. The average Windows user doesn't know how to 'tweak' it and there shouldn't be the need for much tweaking after a fresh install. Installing and tweaking Windows is a lot more work, if you consider unnecessary /unneeded processes/services and all additional software/drivers that need to be installed. QuoteWindows' DE is heavy. I used full Aero effect. So comparing Windows' DE to something like XFCE is unfair. It's not. If you turn compositing on in XFCE (it usually is by default) you have the same transparent effects as with Aero and on top of that there are a lot more tweaking options. QuoteAlso keep in mind Windows is not optimized for specific customers as much as Linux. Yes, you don't hear it wrong. Windows is more generic about setting. They use a balanced performance profile that fitted for almost everyone by default. Linux distro maintainer, on the other hand, tweak their system heavily for the needs of specific customers. Comparing untweaked Windows with a Linux distro (already heavily tweaked) is unfair. That is a whole load of nonsense. Popular distros are just as generally tweaked as Windows, for the average user that uses an internet browser, mail client and office suite. Some like Manjaro even distribute their OS on machines for the average user. But indeed, Windows doesn't come with a office suite pre-installed, if that's the 'tweaking' you were referring to. QuoteAnd if I'm M$ I also has no reason to support these hardwares. Of course, M$ has no reason to keep support for older hardware. But there is a difference between keeping drivers for older hardware and deliberately removing them to force customers to upgrade their hardware, which is another reason not to use Windows as a daily OS. Adobe is even worse by claiming that an Air package is "damaged" until you turn back the clock one or two years before installation, the "damage" is suddenly gone. These companies use all kinds of tricks to keep the money flow going beyond proportions. QuoteAnd I think we should stop being off topic. Let's give the thread back to 440bx. I wasn't aware this thread belonged to 440bx. If I'm not mistaken the thread already was way off-topic. If you don't like the subject then simply don't respond to it. ---------------------------------------------------------------------- marcov · 2020-05-05 09:33 Quote from: JiaXing on May 05, 2020, 08:58:14 amFPC is indeed GNU binutils based and binutils based compiler always generate bloated binary on Windows. Sigh. Wanting to argue so badly, but so little knowledge. FPC has had an internal linker for over 10 years. I'm really happy with these minimalist discussions. It will be good to get more testers and users for 16-bit msdos. ---------------------------------------------------------------------- munair · 2020-05-05 09:37 Quote from: marcov on May 05, 2020, 11:33:09 amI'm really happy with these minimalist discussions. It will be good to get more testers and users for 16-bit msdos. How many users use FPC on DOS these days. I honestly wonder if it is still worth the effort to maintain 16 bits. No offence, just my opinion. ---------------------------------------------------------------------- Thaddy · 2020-05-05 09:48 Quote from: munair on May 05, 2020, 11:37:15 amHow many users use FPC on DOS these days. I honestly wonder if it is still worth the effort to maintain 16 bits. No offence, just my opinion. Actually it was fairly recently  (re-?)introduced, because a developer wished to do so. It is not a dead platform by any means. E.g. game emulaters, dosbox code, 8086 embedded systems and legacy desktop machines etc. Ok it is a niche, but a nice niche. We have more like that e.g. GameBoy, Wii and the likes. Good to have. I used the Wii compiler a lot to make it do things it wasn't supposed to do and also use the Dos compiler now and then. ---------------------------------------------------------------------- PascalDragon · 2020-05-05 09:55 Quote from: munair on May 05, 2020, 11:37:15 amQuote from: marcov on May 05, 2020, 11:33:09 amI'm really happy with these minimalist discussions. It will be good to get more testers and users for 16-bit msdos. How many users use FPC on DOS these days. I honestly wonder if it is still worth the effort to maintain 16 bits. No offence, just my opinion. Please note that we're talking about two different things here. The DOS target that FPC supported from basically its beginning is a 32-bit target based on the GO32v2 DOS Extender (originally it was the GO32v1 DOS Extender, but that was changed to v2 long ago). That target is still actively used and at least the downloads from SourceForge can be seen though it is also distributed within FreeDOS. The 16-bit target is a relatively new development which was only introduced during 2.7.1 and became an official release with 3.0.0. For statistics for this you need to look for example at the Windows to MS- DOS cross compiler here or from Linux to MS-DOS here (it's much more fragmented as it's only a cross compiler). The development for i8086 however was an important point on the way to better AVR support. And maintaining it does not lead to more effort than any of the other targets we support as the code generator is rather well separated and new features that rely on platform functionality need to be implemented for each platform anyway (or are simply stubbed like TThread.NameThreadForDebugging which was only recently implemented for Windows, Linux and Android). Also the releases are generated by persons who care about those platforms. As long as someone cares about a target platform it will be supported. ---------------------------------------------------------------------- munair · 2020-05-05 10:08 Quote from: PascalDragon on May 05, 2020, 11:55:07 amQuote from: munair on May 05, 2020, 11:37:15 amQuote from: marcov on May 05, 2020, 11:33:09 amI'm really happy with these minimalist discussions. It will be good to get more testers and users for 16-bit msdos. How many users use FPC on DOS these days. I honestly wonder if it is still worth the effort to maintain 16 bits. No offence, just my opinion. Please note that we're talking about two different things here. The DOS target that FPC supported from basically its beginning is a 32-bit target based on the GO32v2 DOS Extender (originally it was the GO32v1 DOS Extender, but that was changed to v2 long ago). That target is still actively used and at least the downloads from SourceForge can be seen though it is also distributed within FreeDOS. The 16-bit target is a relatively new development which was only introduced during 2.7.1 and became an official release with 3.0.0. For statistics for this you need to look for example at the Windows to MS- DOS cross compiler here or from Linux to MS-DOS here (it's much more fragmented as it's only a cross compiler). The development for i8086 however was an important point on the way to better AVR support. And maintaining it does not lead to more effort than any of the other targets we support as the code generator is rather well separated and new features that rely on platform functionality need to be implemented for each platform anyway (or are simply stubbed like TThread.NameThreadForDebugging which was only recently implemented for Windows, Linux and Android). Also the releases are generated by persons who care about those platforms. As long as someone cares about a target platform it will be supported. Thank you for your explanation. Quote from: Thaddy on May 05, 2020, 11:48:13 amActually it was fairly recently  (re-?)introduced, because a developer wished to do so. It is not a dead platform by any means. E.g. game emulaters, dosbox code, 8086 embedded systems and legacy desktop machines etc. No argument there. ---------------------------------------------------------------------- marcov · 2020-05-05 10:19 Quote from: munair on May 05, 2020, 11:37:15 amQuote from: marcov on May 05, 2020, 11:33:09 amI'm really happy with these minimalist discussions. It will be good to get more testers and users for 16-bit msdos. How many users use FPC on DOS these days. I honestly wonder if it is still worth the effort to maintain 16 bits. No offence, just my opinion. How many people dedicate their life to binary sizes these days? I thought since your goals are parallel, you could help eachother. It seems a match made in heaven. ---------------------------------------------------------------------- munair · 2020-05-05 10:25 Quote from: marcov on May 05, 2020, 12:19:28 pmHow many people dedicate their life to binary sizes these days? I thought since your goals are parallel, you could help eachother. It seems a match made in heaven. LOL. There is a difference between code optimization for 32 and 64 bits flat memory models and 16 bits segmented models. If I were to put efforts in 16 bits programming, it would be for specific devices, not because I like small sized DOS executables. ---------------------------------------------------------------------- JiaXing · 2020-05-05 11:40 Quote from: munair on May 05, 2020, 11:17:12 amQuoteAlso keep in mind Windows is not optimized for specific customers as much as Linux. Yes, you don't hear it wrong. Windows is more generic about setting. They use a balanced performance profile that fitted for almost everyone by default. Linux distro maintainer, on the other hand, tweak their system heavily for the needs of specific customers. Comparing untweaked Windows with a Linux distro (already heavily tweaked) is unfair. That is a whole load of nonsense. Popular distros are just as generally tweaked as Windows, for the average user that uses an internet browser, mail client and office suite. Some like Manjaro even distribute their OS on machines for the average user. But indeed, Windows doesn't come with a office suite pre-installed, if that's the 'tweaking' you were referring to. No. There are much more than Manjaro. And even this distro does it own tweaking, not just pulls everything from Arch. You only quote a portion of my post but not my example because it will prove that you are obviously wrong. You said you installed Debian 64 bit, didn't you? So you must notice the video performance on standard Debian is much much worse and when watching videos it's tearing like hell, don't you? You also must know that desktop environments installed from apt are bare metal and ugly looking, don't you? Compare it with Linux Mint Debian (LMDE) and Ubuntu and you will not notice any screen tearing and you would know how smooth and good looking everything is. People rarely use base distributions like Debian or Arch, which only served as a base for other to build their distributions up on. Yes, Debian and Arch are as generic as Windows. But what I refer to is the beginner user friendly distritbutions like Ubuntu, Mint. They are obviously more tweaked and optimized out of the box than an out of the box Windows. Ignorant people never admit that they are wrong and always ridicule other people without any real counter arguments. So ignorant always goes with arrogant. Yes, I'm obviously have less knowledge about programming and fpc itself than you. But about this subject, I definitely know more than you  Quote from: munair on May 05, 2020, 11:17:12 amQuoteAnd if I'm M$ I also has no reason to support these hardwares. Of course, M$ has no reason to keep support for older hardware. But there is a difference between keeping drivers for older hardware and deliberately removing them to force customers to upgrade their hardware, which is another reason not to use Windows as a daily OS. Adobe is even worse by claiming that an Air package is "damaged" until you turn back the clock one or two years before installation, the "damage" is suddenly gone. These companies use all kinds of tricks to keep the money flow going beyond proportions. And I see nothing wrong with it. There are people still using XP and never upgrade. First, laptop manufactures will not earn anything. Microsoft themselves, will not earn anything. Since Windows XP is an aged technology and the maintenance efforts will be more than it worths. Upgrading to a newer platform not only give the user better experience but also help the developer. Yes, they can also charge the user for long term support like what they are currently doing with corporate customer. But remember most of the users don't buy this subscription and even not bought the software (they use cracked version). And they complain that Windows sucks yet most of them, also do not update their Windows. And their opponents will run a campaign against them, saying: "Oh, Windows sucks and is a security nightmare! Switch to Linux now!". What would you do if you are them, I wonder? Don't tell me that you will open source Windows and utilize the help of the community  Adobe is another story, though. I don't use anything commercial from them  Quote from: munair on May 05, 2020, 11:17:12 amQuoteAnd I think we should stop being off topic. Let's give the thread back to 440bx. I wasn't aware this thread belonged to 440bx. If I'm not mistaken the thread already was way off-topic. If you don't like the subject then simply don't respond to it. Yes, I was wrong when said 440bx is the OP. OK, fine. The OP is a clueless ignorant. He can't even distinguish between a C++ program that uses C header functions and a pure C program! It's only a waste of time to talk with this fool. And how could you know if I'm interested in the subject or not, I wonder? ---------------------------------------------------------------------- JiaXing · 2020-05-05 11:47 Quote from: marcov on May 05, 2020, 11:33:09 amQuote from: JiaXing on May 05, 2020, 08:58:14 amFPC is indeed GNU binutils based and binutils based compiler always generate bloated binary on Windows. Sigh. Wanting to argue so badly, but so little knowledge. FPC has had an internal linker for over 10 years. I'm really happy with these minimalist discussions. It will be good to get more testers and users for 16-bit msdos. Yes, I'm wrong. And no, I didn't want to argue with him. I only found his post about Windows too smelly and I think I must correct it. It's just his plain hate for Windows but no real arguments! Do you found any add foe and add to ignore list option? I don't want to talk with this guy anymore. Other forums definitely have this option. I found none on this forum. So even hate someone is forbidden here? ---------------------------------------------------------------------- munair · 2020-05-05 12:00 Quote from: JiaXing on May 05, 2020, 01:47:11 pmYes, I'm wrong. And no, I didn't want to argue with him. I only found his post about Windows too smelly and I think I must correct it. It's just his plain hate for Windows but no real arguments! Do you found any add foe and add to ignore list option? I don't want to talk with this guy anymore. Other forums definitely have this option. I found none on this forum. So even hate someone is forbidden here? Nowhere did I state that I hate Windows. There's no need to jump to conclusions. What I did say is that it wouldn't be my first choice as daily OS for the obvious reasons I stated.  Funny how you easily make fun of other people (read: I'm subscribed to the church of 440bx. Say no to OOP.) but that you have difficulty engaging in serious discussions. ---------------------------------------------------------------------- marcov · 2020-05-05 12:00 Quote from: munair on May 05, 2020, 12:25:25 pmQuote from: marcov on May 05, 2020, 12:19:28 pmHow many people dedicate their life to binary sizes these days? I thought since your goals are parallel, you could help eachother. It seems a match made in heaven. LOL. There is a difference between code optimization for 32 and 64 bits flat memory models and 16 bits segmented models. If I were to put efforts in 16 bits programming, it would be for specific devices, not because I like small sized DOS executables. Ok, so now we are making progress, thats good    Binary size is not everything, and features matter too ---------------------------------------------------------------------- munair · 2020-05-05 12:02 Quote from: marcov on May 05, 2020, 02:00:22 pmQuote from: munair on May 05, 2020, 12:25:25 pmQuote from: marcov on May 05, 2020, 12:19:28 pmHow many people dedicate their life to binary sizes these days? I thought since your goals are parallel, you could help eachother. It seems a match made in heaven. LOL. There is a difference between code optimization for 32 and 64 bits flat memory models and 16 bits segmented models. If I were to put efforts in 16 bits programming, it would be for specific devices, not because I like small sized DOS executables. Ok, so now we are making progress, thats good    Binary size is not everything, and features matter too Never claimed anything to the contrary. ---------------------------------------------------------------------- 440bx · 2020-05-05 12:07 Quote from: JiaXing on May 05, 2020, 10:37:24 am@440bx: You didn't answer my question about if you prefered the OOP style of Oberon. I think it's very similar to what you are currently using  My apologies, I wasn't ignoring you.   The problem is, while I have had a _casual_ look at Oberon, I really do not have a reasonable enough amount of knowledge about it to even state a preference.  That means, I would be unable to justify a preference, therefore I cannot have one. Quote from: JiaXing on May 05, 2020, 01:40:45 pmThe OP is a clueless ignorant. Calm down... switch to decaf.     One of the nice things in this forum is that we can get to disagree and make our points strongly but, most of the time at least, we _try_ to do it respectfully. The best way to reinforce an argument isn't with an angry face, it's with a better argument. If you manage to do that then, it's the other guy that will have an angry face... much better than you having an angry face @Munair About the Windows bloat, I pretty much agree with JiaXing.  There are a fair number of Linux distributions and, one of the reasons it's that way is because, since its open source, it can be tailored to fit particular requirements. As JiaXing stated, the desktop Windows O/S is a "general" type of beast which means it's not as finely customized for different and, specific uses, than Linux distros are in general.  In addition to that, as you pointed out, the average Windows user probably has to make an effort to tell an O/S from a bar of soap.  Given that, there is little chance of the user making any customizations to trim away features he/she doesn't need.   The average Linux user tends to be a very different type of user than the average Windows user.  I don't see the average Windows user recompiling Windows.  (quite likely the majority of them would as say "compile ?... what does that mean ?... C ?... what's C ?... and so on) Quote from: marcov on May 05, 2020, 11:33:09 amI'm really happy with these minimalist discussions. It will be good to get more testers and users for 16-bit msdos. Code/library size isn't about the amount of memory it occupies.  It's about the amount of code that is nothing but potential for bugs.   It is also about how well the compiler and linker generate an executable.  Large executables mean there are a number of things the compiler and linker could do better and, that is what is really important.  People who downplay the executable's size are simply trying to hide quality problems under the rug. ---------------------------------------------------------------------- Warfley · 2020-05-05 12:11 Quote from: 440bx on May 04, 2020, 10:53:12 pmSimply, No.  Both executables are bloated, one more than other but, both are. To put this into perspective, your executables use 318K and 512K just to output "hello". Sorry for using a linux compiler on windows.  If I done this example on linux or using MSVC++ it would have been much smaller. Also this code was optimized for speed, not for size. Using linux with -Os (optimize size) both executables are 16k big. QuoteHave a look at this program I wrote https://forum.lazarus.freepascal.org/index.php?topic=46617.0  it is a fairly complete PE viewer - it does a _lot_ more than put "hello" on the console - and, if memory serves, it is in the ballpark of 250K.  There it is, your cpptest used about 70K more code to display "hello" on a console than a fairly complete PE viewer.  NOTE: there _isn't_ a single of assembly code in that program, IOW, it isn't programmed to be as small as possible. The executables you produced make my point, whether C or C++, there is always a pile of junk in the executable that doesn't have any business being there.  I'll grant you that the result you show indicates that C++ is better at not putting as much junk as C but, 318K to output "hello" ??? ... I cannot help but consider that _way_ more than anything reasonably justifiable.Comparing a g++ program under windows with a delphi programm under windows is not a fair comparison. Because your code is using the Windows API, which is not included in your figure or is it? If you want to compare this, you could compare the g++ built for windows against a delphi built for windows including wine. QuoteThat's the case only if the program is poorly written or if the language doesn't support nested functions/procedures.  In a well written procedural language that supports nested functions/procedures, the result is vastly superior to what can be produced with OOP.So people misusing OOP is a problem inherent to OOP, people misusing procedual programming is a problem of the people using it. Nice double standard. OOP enforces code seperation through binding functionality do data and having access guards like private fields. In procedual programming you need to pray that everyone on your team does that by himself. QuoteOnly if the record is a global variable - which would be a design problem - otherwise that is not true.So you never passed a record to another function as pointer? I'm curios because the Linux kernel, famously written in C, does this all the time. QuoteSame thing can be done using nested functions/procedures.  OOP isn't bringing anything to the table that wasn't already there (except in the case of C since supporting nested functions is a "novelty" for C.)Nested functions in C are different than in for example pascal because there the code is placed on the stack and the instruction pointer jumps to that stack location. They are not comparable in any form with pascal nested functions. Also again, as soon as you pass a record (or a pointer to a record) to any function, this function can do with that record as it pleases. In OOP you can guard every single data field by having to access it through a property. Maybe you are not passing records or pointer to records to functions at all, but than you are an exception. QuoteNot the case at all.   Every instruction in an executable is a potential source of bugs.  People now like to downplay the size of the executable because the tools/compilers they use generate bloat instead of quality.   Because of that, quality, which is reflected in code size is supposedly not important anymore.  Now you are pulling things out of your rear bottom. Please, it is well known that the FPC creates larger executables than (older) Delphi versions. Simply write a correct Delphi program that produces bugs when compiled with FPC because of the bloat. If you can't, what you just wrote is simply bullocks. QuoteWe might have something to agree on as far as time-memory trade off.  I will almost always choose a simpler, easier to understand algorithm over another one that is more memory efficient.  As you said, memory is cheap, human time spent to understand complex algorithms isn't, not to mention that the more complex the algorithm, the more likely there is a subtle bug in it.It's not about algorithms, I talked about jumping tables and inlining because these are optimization techniques. Nothing you as a developer should do but simply things an optimizer does which will increase the performance for trading in file-size. If one compiler creates larger code than another, it could be that the compiler simply bloats the executable with unnecessary things, or it could be that it is simply better at optimizing. Thats why gcc has the Option -Os to optimize for size. Also that said, if you have ever wondered why modern compilers usually create larger executables, there is more to it. For example stack canaries are used to check if you had a buffer overflow in your program. It's a security feature in modern compiler, that simply hasn't existed 20 years ago. Fetishizing filesize does not give you any inherent advantage. More often than not you are scrificing speed or security for it. QuoteAs far as speed goes, design for parallelism.  Take advantage of the ever increasing number of cores.  I'd much rather have a somewhat slower algorithm that can easily be parallelized than a faster one that may not be parallelizable or may be but with significant effort (which implies a higher likeliness of bugs.)Yes and some problems simply can't be parallelized. I've had to work with such problems in the past. QuoteBoth are and both should be "reasonable", which in this case means, fast enough that the program can flow with the user's actions and memory consumption that is justified given what it does.  That last one means, 320K to put "hello" on a console ?... that's neither reasonable nor justified.You still haven't given any reason why the 320k for "hello" is bad. Ok let's say there wouldn't be a reason for this (there is, see above), and the gcc simply adds 300k of memory junk because it is bored. Whats the deal? There is only one real implication, that is that it takes longer to load the executable at the initial startup. But as a startup takes even for the smalleset executable 1ms *at least* the difference due to 300k is absolutely neligable (which will be orders of magnitude faster than the 1 ms). If I take a program and add a lot of unreachable junk simply at the end of the CODE section, how does this impact the runtime behavior of a program on a modern machine? QuoteI didn't submit it claiming it was faster than something else.  That program isn't about speed, it is about code re-use. There are two programs in one executable, since the two programs share about 80% of the code, instead of producing two executables, produce just one.  Much simpler and, there is another BIG advantage to the method - which is _not_ related to size - when distributed, there aren't two programs to compile and keep in synch, there aren't two programs to install, there aren't two programs that may fail, the user won't delete one because he/she doesn't realize the other program needs it... etc, etc. Why would I want to have two programs in one executable? Code reuse does not mean reusing the assembly. If you want to do that there are dynamic libraries for this. Code reuse means source code reuse. There is no advantage in having two applications in the same executable because you simply want to share code. Libraries are made for that. And to your big advantage, there are three options: 1. the programs are dependend on onather, so you manage them together, they are located in the same folder, if the user wants to delete them, simply delete the folder. If you want to update them, simply update the folder. Or even better, write a third executable for this, an updater. 2. the programs are independent but share the same code base. Then use a library and updating the library will update both programs simultaniously 3. the programs are completely independend, no need to have them in one exec. It's even worse if you think about it, because updating one functionality will update both executables, possible introducing bugs into both functionalities. If you have them separated you can change one application as much as you like without interferring with the other. QuoteLet's see OOP do that and compare the resulting executables.Why should I wan't to write something that I think is completely useless? Even if procedual programming is better at that, it's something I don't even want to use. QuoteJust for the record, any program I write that uses the compiler's RTL is either proof of concept/test or throw away code.I was talking about your example, which is clearly using some form of library, e.g. the Windows API. Otherwise you couldn't create a GUI. QuoteNo program I write which I intend to use on regular basis uses any of the compiler's RTL.  One of the reasons I'm using Pascal - not the only one - is because it's become ever harder to have C/C++ compiler _not_ use their RTL.  It used to be easy... write the code the right way... fiddle with linker switches and that was it... now, getting compilers to _not_ use their RTL is real work.   I work to produce code... not to get rid of code.... if I didn't ask for it... it has no reason to be there. Thats because of the design of C. C is standardized together with it's standard lib. These things belong together. QuoteI'm somewhat concerned about your desire to compare speed.  The reason is, C/C++ compilers usually optimize better than Pascal compilers.  That means, it isn't OOP versus procedural that is being tested.  What's tested in that case are the compiler's abilities to optimize code and, we both know that FPC is ok in that area but, is usually no match for C/C++.Yeah I would want to compare an FPC OOP implementation (both with classes and objects) against a fpc procedual implementation, because this is actually quite interesting I think. QuoteAbout the code size, I presume you mean lines of code. I place a lot more importance on ease of understanding than on how many lines of code the implementation takes.  I'd much rather deal with 1,000 lines of easy to understand code than 100 lines of subtle very hard to understand code - which is quite common in C and C++. Sure, but I think it still is somewhat of a good indicator, especially when using the same language. But we can also simply try to read the code of the other, sure this is no measurable metric, but I would really like to compare the approach of you and me to such a problem QuoteQuestion for you ... since you offer that program as a compromise ... do you already have it written (or something very close to it) ?It's something I've needed for work in the past a lot thats why I thought about it. I don't have one specifically for this purpose right now, but I think it should be doable in less than an hour so I thought it would be a nice little program. And I'm actually interested how OOP compares to something like this, because this is something I always use OOP for. QuoteAnother question: would you consider comparing a very limited PE viewer, one done in Pascal and the other one in C++.  The reason I ask is very obvious, I already wrote one (which is not limited) and its size is about 250K.  I'm willing to compare that to a version in C++ that dumps a PE file _only_ up to and including the OPTIONAL_HEADER.  I suspect my 250K PE viewer will be smaller and quite likely faster than a limited one written in C++.I'm not going to write a GUI programm in C++, this is an absolute pain (you either have to use QT, GTK or windows with the winAPI and all three options I quite dislike). I would rather have something that is command line only because then it is easy to write something in pascal and C++ (and even C), so it is easy to compare. Especially because this is pretty much platform independent, and when using C++ I usually use Linux (I'm not a fan of visual c++ and visual studio as IDE) ---------------------------------------------------------------------- PascalDragon · 2020-05-05 13:24 Quote from: Warfley on May 05, 2020, 02:11:45 pmQuote from: 440bx on May 04, 2020, 10:53:12 pmSimply, No.  Both executables are bloated, one more than other but, both are. To put this into perspective, your executables use 318K and 512K just to output "hello". Sorry for using a linux compiler on windows.  If I done this example on linux or using MSVC++ it would have been much smaller. Also this code was optimized for speed, not for size. Using linux with -Os (optimize size) both executables are 16k big. For an example with MSVC see my earlier post. Quote from: Warfley on May 05, 2020, 02:11:45 pmQuoteSame thing can be done using nested functions/procedures.  OOP isn't bringing anything to the table that wasn't already there (except in the case of C since supporting nested functions is a "novelty" for C.)Nested functions in C are different than in for example pascal because there the code is placed on the stack and the instruction pointer jumps to that stack location. They are not comparable in any form with pascal nested functions. Now you're talking nonsense. In modern operating systems the stack area is Read/Write, but not Executable. Just like in FPC a nested function in GCC is a separate part of code in the code section that is called. The difference to FPC is that captured variables are passed as hidden parameters and the function has its own stackframe instead of passing the frame pointer like FPC does and reusing the stackframe of the caller. Look at this (based on the example in the GCC docs): Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i int foo (int a, int b){        int offset = a + b;         int square (int z) { return z * z + offset; }         return square (a) + square (b);} int main(){        return foo(2, 3);} This is the generated assembly code: Code: ASM  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i         .file   "nested.c"        .text        .type   square.1836, @functionsquare.1836:.LFB1:        .cfi_startproc        pushq   %rbp        .cfi_def_cfa_offset 16        .cfi_offset 6, -16        movq    %rsp, %rbp        .cfi_def_cfa_register 6        movl    %edi, -4(%rbp)        movq    %r10, %rcx        movq    %r10, -16(%rbp)      movl    -4(%rbp), %eax        imull   -4(%rbp), %eax        movl    %eax, %edx        movl    (%rcx), %eax        addl    %edx, %eax      popq    %rbp        .cfi_def_cfa 7, 8        ret        .cfi_endproc.LFE1:        .size   square.1836, .-square.1836        .globl  foo        .type   foo, @functionfoo:.LFB0:        .cfi_startproc        pushq   %rbp        .cfi_def_cfa_offset 16      .cfi_offset 6, -16        movq    %rsp, %rbp        .cfi_def_cfa_register 6        pushq   %rbx        subq    $40, %rsp      .cfi_offset 3, -24        movl    %edi, -36(%rbp)        movl    %esi, -40(%rbp)        movq    %fs:40, %rax        movq    %rax, -24(%rbp)        xorl    %eax, %eax        movl    -36(%rbp), %edx      movl    -40(%rbp), %eax        addl    %edx, %eax        movl    %eax, -32(%rbp)        movl    -36(%rbp), %eax        leaq    -32(%rbp), %rdx        movq    %rdx, %r10        movl    %eax, %edi      call    square.1836        movl    %eax, %ebx        movl    -40(%rbp), %eax        leaq    -32(%rbp), %rdx        movq    %rdx, %r10        movl    %eax, %edi        call    square.1836        addl    %ebx, %eax        movq    -24(%rbp), %rcx        xorq    %fs:40, %rcx        je      .L5        call    __stack_chk_fail.L5:        addq    $40, %rsp        popq    %rbx        popq    %rbp        .cfi_def_cfa 7, 8        ret        .cfi_endproc.LFE0:        .size   foo, .-foo        .globl  main        .type   main, @functionmain:.LFB2:        .cfi_startproc        pushq   %rbp        .cfi_def_cfa_offset 16        .cfi_offset 6, -16        movq    %rsp, %rbp        .cfi_def_cfa_register 6        movl    $3, %esi        movl    $2, %edi        call    foo        popq    %rbp        .cfi_def_cfa 7, 8        ret        .cfi_endproc.LFE2:        .size   main, .-main        .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"        .section        .note.GNU-stack,"",@progbits As you can see the code is part of a .text section and in lines 52 and 58 you can see the call of the square function and in there at the top you can see that it sets up a stackframe, does its calculation and returns, just like a regular function. The only difference is that offset is passed in r10 as second, hidden parameter (according to the Sys V ABI). ---------------------------------------------------------------------- serbod · 2020-05-05 13:33 According to Internal Data Formats (Delphi) difference between "record" and "class" is very small: class type = record, contains VMT, Virtual method Tableclass instance = record, contains fields and pointer to VMT recordclass variable = pointer to class instance So, technically "object" type can be class instance, that resides on stack. How about that syntax: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  OStringList = object(TStringList); var  StringList: OStringList;begin  StringList.LoadFromFile('some.txt');  WriteLn(StringList.DelimitedText);end;  No need to Create/Destroy! With help of compiler, type object(Class) can be smartpointer, like "string" or "array of". ---------------------------------------------------------------------- munair · 2020-05-05 13:34 Quote from: 440bx on May 05, 2020, 02:07:27 pm@Munair About the Windows bloat, I pretty much agree with JiaXing.  There are a fair number of Linux distributions and, one of the reasons it's that way is because, since its open source, it can be tailored to fit particular requirements. As JiaXing stated, the desktop Windows O/S is a "general" type of beast which means it's not as finely customized for different and, specific uses, than Linux distros are in general.  In addition to that, as you pointed out, the average Windows user probably has to make an effort to tell an O/S from a bar of soap.  Given that, there is little chance of the user making any customizations to trim away features he/she doesn't need.   The average Linux user tends to be a very different type of user than the average Windows user.  I don't see the average Windows user recompiling Windows.  (quite likely the majority of them would as say "compile ?... what does that mean ?... C ?... what's C ?... and so on) I wasn't really talking about capabilities per OS, but rather size and performance. I have experience with both Windows (3.1 to 10) and Linux (since SuSE 6.4). Compared to GNU/Linux OSs (i.e. not just the kernel), Windows has grown much more in size in the last 20 years, and its hardware requirements have grown proportionally. The best way to measure the difference is by comparing hardware requirements and performance. Windows 10 won't install on older machines. I have not tested the minimum age nor the performance on the oldest possible machine. However, I successfully installed modern distros on 17 years old computers. Just recently I installed a Debian 10 server on a Hp-Compaq from 2003. Performance is excellent and I did not have to strip down or tailor anything to do that. FYI the SharpBASIC website is running on that server. Granted, the server doesn't need a desktop, but it would easily install XFCE or MATE and still perform like XP at the time. A few weeks ago I successfully installed the latest Manjaro on a 13 years old laptop (64 bits). The owner, who is very much an average user,  knows how to navigate a desktop, be it Windows or Linux, but has no technical expertise regarding software or hardware. Manjaro worked out of the box and no additional tweaking or installation was necessary. Granted, Linux is largely a community effort, although companies have also contributed to the kernel and are actively involved. But no matter the reason, be it commercial or otherwise, Linux based OSs outperform Windows on nearly every level. Windows machines need a lot more maintenance and still get slower over time. By comparison, I run Linux computers for several years and performance remains the same. The system never feels bloated or sluggish. Sure with the right tools it is possible to write efficient Windows software, but commercial packages are usually bloated, and this has probably a lot to do with the fact that software companies are eager to get their latest products on the market as soon as possible, without taking size or memory usage into consideration all that much (because hardware resources are abundant anyway these days). Linux not being commercial has definitely an advantage IMHO. ---------------------------------------------------------------------- marcov · 2020-05-05 13:41 Quote from: PascalDragon on May 05, 2020, 03:24:24 pmNow you're talking nonsense. In modern operating systems the stack area is Read/Write, but not Executable. Just like in FPC a nested function in GCC is a separate part of code in the code section that is called. The difference to FPC is that captured variables are passed as hidden parameters and the function has its own stackframe instead of passing the frame pointer like FPC does and reusing the stackframe of the caller. (I think he means function pointers of nested functions, for which GCC afaik uses/used trampolines?) ---------------------------------------------------------------------- marcov · 2020-05-05 14:02 Quote from: 440bx on May 05, 2020, 02:07:27 pmQuote from: marcov on May 05, 2020, 11:33:09 amI'm really happy with these minimalist discussions. It will be good to get more testers and users for 16-bit msdos. Code/library size isn't about the amount of memory it occupies.  It's about the amount of code that is nothing but potential for bugs.   It is also about how well the compiler and linker generate an executable.  Large executables mean there are a number of things the compiler and linker could do better And library architecture. Quoteand, that is what is really important.  People who downplay the executable's size are simply trying to hide quality problems under the rug. The problem is that the generalization implies that  not being able to scale all the way down to zero (smallest binaries) means that something is wrong on the more general level too. And proof for that correlation to is scarce to non-existent. And if so, why don't simply argue those general problems directly, instead of coating it with a lot of confusing minimalist sentiment. ---------------------------------------------------------------------- PascalDragon · 2020-05-05 14:31 Quote from: marcov on May 05, 2020, 03:41:35 pmQuote from: PascalDragon on May 05, 2020, 03:24:24 pmNow you're talking nonsense. In modern operating systems the stack area is Read/Write, but not Executable. Just like in FPC a nested function in GCC is a separate part of code in the code section that is called. The difference to FPC is that captured variables are passed as hidden parameters and the function has its own stackframe instead of passing the frame pointer like FPC does and reusing the stackframe of the caller. (I think he means function pointers of nested functions, for which GCC afaik uses/used trampolines?) That doesn't change that the code is not jumping into the stack. Quote from: serbod on May 05, 2020, 03:33:11 pmAccording to Internal Data Formats (Delphi) difference between "record" and "class" is very small: class type = record, contains VMT, Virtual method Tableclass instance = record, contains fields and pointer to VMT recordclass variable = pointer to class instance So, technically "object" type can be class instance, that resides on stack. How about that syntax: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  OStringList = object(TStringList); var  StringList: OStringList;begin  StringList.LoadFromFile('some.txt');  WriteLn(StringList.DelimitedText);end;  No need to Create/Destroy! With help of compiler, type object(Class) can be smartpointer, like "string" or "array of". object and class are not compatible, they have different internal structuresthe compiler does not call constructors/destructors for objects on the stackmany of the classes in the RTL have parameters in their constructors and using the default TObject constructor would leave them in an invalid stateobjects are assigned using copy, for a class this would lead to memory leaksfor smart pointers you need to keep track of the number of references, thus a class instance converted to an object is  not suitable for this ---------------------------------------------------------------------- Warfley · 2020-05-05 14:32 Quote from: PascalDragon on May 05, 2020, 03:24:24 pmNow you're talking nonsense. In modern operating systems the stack area is Read/Write, but not Executable. Just like in FPC a nested function in GCC is a separate part of code in the code section that is called. The difference to FPC is that captured variables are passed as hidden parameters and the function has its own stackframe instead of passing the frame pointer like FPC does and reusing the stackframe of the caller.Then this was changed in GCC. Because there once was the problem when Linux (or some other Unix system) switched to stack protection by default that many old GCC applications didn't run anymore because of that. That said, nested functions are not standard C and only an extension and could be vastly different on different compilers (syntacticly and semanticly) ---------------------------------------------------------------------- serbod · 2020-05-05 14:53 Quote from: PascalDragon on May 05, 2020, 04:31:05 pm object and class are not compatible, they have different internal structuresthe compiler does not call constructors/destructors for objects on the stackmany of the classes in the RTL have parameters in their constructors and using the default TObject constructor would leave them in an invalid stateobjects are assigned using copy, for a class this would lead to memory leaksfor smart pointers you need to keep track of the number of references, thus a class instance converted to an object is  not suitable for this It's already working for "interface" and 'variant' type variables. And can be constructed automatically for invocable objects. ---------------------------------------------------------------------- winni · 2020-05-05 15:26 Quote from: marcov on May 05, 2020, 12:46:35 am If I compile bytecode compiler P6 http://wirth-dijkstra-langs.org/ to native exe with FPC 32-bit it is 149.504 bytes. So FPC, which is not particularly size optimized has an 10kb increase in 40 years which proves AGAIN that the whole size discussion is mostly just windmills stuff. If you factor in that it is 32-bit code and has 2k or so worth of PE header, it might be considered more tight even for the functionality it delivers. Ah, the days of yonder, when the binaries were bloated and the interpreters inefficient....  So we finish the discussion about the sets: The smaler and very much older compiler has a set with 4060 Elements. The bigger and newer compiler has a set with 256 elements. W$inni ---------------------------------------------------------------------- 440bx · 2020-05-05 15:32 Quote from: Warfley on May 05, 2020, 02:11:45 pmSorry for using a linux compiler on windows. No problem.  The tools you use are your choice to make, not mine. Quote from: Warfley on May 05, 2020, 02:11:45 pmComparing a g++ program under windows with a delphi programm under windows is not a fair comparison. It's not a Delphi program.  That program is compiled with FPC v3.0.4 and it wouldn't compile "as-is" with any version of Delphi.  Also, that program is my _first_ FPC program, it's a small program but, I believe its large enough to deserve to be called a program.  The reason I mention it was my first is because, it was a way to get acquainted with FPC's various capabilities.  That program is _far_ from optimized and, from a programming viewpoint, I consider the implementation just "decent" but, it could be improved in a good number of ways (particularly for consistency - there are multiple ways of doing the same thing in there because I wanted to see what FPC would do and the code it would generate.)  Additionally, that executable is compiled with -O1, not even -O3. IOW, it's a program written by an FPC beginner.  Quote from: Warfley on May 05, 2020, 02:11:45 pmBecause your code is using the Windows API, which is not included in your figure or is it? Yes, the code uses the Windows API.  An O/S is there to use its services not to ignore them but, it's important to state that in spite of the fact that the program doesn't rely in any way on the compiler's RTL, the RTL is still in there.  If I removed it, the program would be about 40K smaller.  I've been meaning to remove it for a while now, I'll get to it someday. Quote from: Warfley on May 05, 2020, 02:11:45 pmSo people misusing OOP is a problem inherent to OOP, To a great extent it is.  The reason I say that is because, whenever I program in C for any extended period of time and then go back to programming in Pascal, that's when I realize all the _bad_ programming habits I acquired while using C.  OOP is that way.  The OOP way literally contaminates the programmer's mind, just as C does.  It's when you go back to using something that won't accept most of those poor constructions that you realize what happened. That's the very reason why there is no way to show an OOP programmer how poor that paradigm is, the poor design is ingrained in their minds.  It's exactly what happens with C.  Explaining to a C programmer why C is an _atrocity_ is about as fruitful as explaining number theory to a wall and, in that case, the wall might be more receptive, at least it won't argue. Quote from: Warfley on May 05, 2020, 02:11:45 pm people misusing procedual programming is a problem of the people using it. Nice double standard. No.  Not a double standard at all.  Yes, people misuse procedural programming, particularly at the beginning but, it is quite common that the individual learns how to do it right because when it's wrong it's usually fairly obvious.   OOP is the opposite and, in that regard it's just like C, the more people use it, the most commonly observed result is, the code gets worse and worse.  IOW, they were better programmers when they were beginners than when they became "experts".  All that expertise is used to produce atrocious code (just like in C, examples of that are everywhere to be found, many even take pride in being able to write unintelligible code - they even have contests for it - what a great language design!.) Quote from: Warfley on May 05, 2020, 02:11:45 pmOOP enforces code seperation through binding functionality do data and having access guards like private fields. In procedual programming you need to pray that everyone on your team does that by himself.Prayers are not what's needed, what's needed is good design.   A well designed procedural program can provide everything OOP provides and do it better.   Just like "don't drink and drive", there should be "don't pray and code", neither works, the results are very rarely desirable. Quote from: Warfley on May 05, 2020, 02:11:45 pmSo you never passed a record to another function as pointer? I'm curios because the Linux kernel, famously written in C, does this all the time.Of course I have, bread and butter of programming but, you made it sound different than that. Quote from: Warfley on May 05, 2020, 02:11:45 pmAlso again, as soon as you pass a record (or a pointer to a record) to any function, this function can do with that record as it pleases. In OOP you can guard every single data field by having to access it through a property. Properties... one of my favorite OOP gizmos.  When something goes wrong with one of those, it's usually "exception time" because the property (at least in FPC) has no way to inform the caller that something went wrong.  There is this "old-fashioned" thing called "pre-conditions" and "post-conditions", those are classics in programming and it would nice if OOP programmers used those a little more often instead of being casual and every time something goes wrong jump through the exception window to get out of mess they got themselves into. Quote from: Warfley on May 05, 2020, 02:11:45 pmPlease, it is well known that the FPC creates larger executables than (older) Delphi versions. I never said otherwise and I don't think anything I said previously implied that. Quote from: Warfley on May 05, 2020, 02:11:45 pmSimply write a correct Delphi program that produces bugs when compiled with FPC because of the bloat. If you can't, what you just wrote is simply bullocks. I don't have an example that is directly caused by bloat but, I do have an example of a correct Delphi program that produces bugs when compiled with FPC.  I also have an example of the opposite, a correct FPC program that produces bugs when compiled with Delphi.  Since it's quite likely you're curious about what those are, here they are: Delphi produces correct code for an array element access with a negative index when the low bound of the array is zero, FPC does not.   FPC produces correct code when passing a pointer to single character, Delphi does not (a fairly common thing to do when sending a single character to a listbox for instance.) Quote from: Warfley on May 05, 2020, 02:11:45 pmIf one compiler creates larger code than another, it could be that the compiler simply bloats the executable with unnecessary things, or it could be that it is simply better at optimizing. Thats why gcc has the Option -Os to optimize for size. Unnecessary things... quite common when doing OOP programming.  Not entirely eliminated (without some configuration effort) with procedural programming but, with decent code, quite a bit less than with OOP. Quote from: Warfley on May 05, 2020, 02:11:45 pmAlso that said, if you have ever wondered why modern compilers usually create larger executables, there is more to it. For example stack canaries are used to check if you had a buffer overflow in your program. It's a security feature in modern compiler, that simply hasn't existed 20 years ago. When there is a good reason for the additional code, I don't have anything against it.  On the contrary, I welcome it.  A "good reason" isn't including the kitchen sink in the executable to cater to programmers who are more interested in instant gratification than quality. Quote from: Warfley on May 05, 2020, 02:11:45 pmFetishizing filesize does not give you any inherent advantage. More often than not you are scrificing speed or security for it. You're attempting to avoid the point.  Filesize is an indicator of the quality of the code the compiler produces and, myself, I believe a programmer should care about that just as he/she should care about the quality of his code.  A good compiler with a good programmer = good results.  A deficiency in either and the results are "not so good" anymore. Quote from: Warfley on May 05, 2020, 02:11:45 pmYes and some problems simply can't be parallelized. I've had to work with such problems in the past. So have I but, that doesn't mean a programmer shouldn't be looking for ways to parallelize the algorithms applicable to solving a problem. Quote from: Warfley on May 05, 2020, 02:11:45 pmYou still haven't given any reason why the 320k for "hello" is bad.If the reason isn't obvious, I probably cannot give one.  A 320k executable is bad for the same reason that a 5MB executable for "hello" is bad.  In both cases, it should be quite obvious that there is a whole lot of room for improvement which means the quality of the result leaves a great deal to be desired. Quote from: Warfley on May 05, 2020, 02:11:45 pmthe gcc simply adds 300k of memory junk because it is bored. Whats the deal? Poor compiler is bored... I guess I should take the compiler to Disneyland to get better code.  No one mentioned that to me before.  Maybe I'll try it someday... sounds like fun. Quote from: Warfley on May 05, 2020, 02:11:45 pm There is only one real implication, that is that it takes longer to load the executable at the initial startup. Not true.  That is _not_ the only implication.  The _fact_ is, there is a bunch of code that doesn't belong there and, that code can contain bugs.  For those two reasons, it shouldn't be there. Quote from: Warfley on May 05, 2020, 02:11:45 pmIf I take a program and add a lot of unreachable junk That's wishful thinking.  What makes you think that code is "unreachable" ?... it would be nice if it were but, you have no assurance of that.  Additionally, if it really is unreachable, I expect the compiler (and/or linker) to figure that out and _not_ place it in the executable since, as unreachable, it does not perform any useful function.  Quote from: Warfley on May 05, 2020, 02:11:45 pmWhy would I want to have two programs in one executable? I stated the reason in the post you quoted but, I'll restate the one that may be the most important one, because in that way when a change is made, it is _not_ necessary to recompile _two_ programs instead of _one_ to ensure they are in synch.  Simple way of ensuring two programs are _always_ in synch. Quote from: Warfley on May 05, 2020, 02:11:45 pmThere is no advantage in having two applications in the same executable because you simply want to share code. Not true.  Reason clearly stated in the paragraph above.  Quote from: Warfley on May 05, 2020, 02:11:45 pmLibraries are made for that. Libraries are good to gather code that is common and, general in nature (e.g, a sort routine) to _many_ programs, not just two programs that need to be kept in synch which use code that is not general. Quote from: Warfley on May 05, 2020, 02:11:45 pmOr even better, write a third executable for this, an updater. Not two but three now.  Who keeps all that stuff in synch ? ... prayers don't. Quote from: Warfley on May 05, 2020, 02:11:45 pm2. the programs are independent but share the same code base. Then use a library and updating the library will update both programs simultaniously That's how the Flinstones do it.  That resembles their car engines but, they did have their advantages, among them: low carbon monoxide footprint (literally.) Quote from: Warfley on May 05, 2020, 02:11:45 pmIt's even worse if you think about it, because updating one functionality will update both executables, possible introducing bugs into both functionalities. If you have them separated you can change one application as much as you like without interferring with the other. I can do that with less management overhead by having them be a single executable. Looks to me, you're trying to find imagined problems with the method because you can't do it in OOP.  For the record and, to emphasize an important point, I stated that I don't even care that your OOP rendition be _functional_, all I care about is that it has to carry out the same actions, i.e, open a file, mapped the file, create a mutex, have a little dialog box, a status bar, etc. That way we can compare what your OOP version weighs in to my procedural version.  Of course, if it cannot be done with OOP then, there won't anything to compare.  Just another unfortunate occurrence (which - obviously - cannot have anything to do with OOP.) Quote from: Warfley on May 05, 2020, 02:11:45 pmWhy should I wan't to write something that I think is completely useless? It wouldn't be completely useless, it would prove your claim that OOP introduces no overhead in the executable.  It would show you have a valid point, that's not useless. Quote from: Warfley on May 05, 2020, 02:11:45 pm Even if procedual programming is better at that, it's something I don't even want to use. I don't really use the little program I posted.  I "use" it only when I want to test how Windows behaves in certain cases.  Other than that, it performs no useful function. Quote from: Warfley on May 05, 2020, 02:11:45 pmI was talking about your example, which is clearly using some form of library, e.g. the Windows API. Otherwise you couldn't create a GUI. And why would that be a problem ? can't OOP use the Windows API ?... I am under the impression it can. Quote from: Warfley on May 05, 2020, 02:11:45 pmThats because of the design of C. C is standardized together with it's standard lib. These things belong together. They may belong together but, if a program doesn't use the standard lib, belonging together is _not_ a good reason to have it in the executable.  My executables aren't Rome, IOW, they are not a tourist destination for compiler code. Quote from: Warfley on May 05, 2020, 02:11:45 pmYeah I would want to compare an FPC OOP implementation (both with classes and objects) against a fpc procedual implementation, because this is actually quite interesting I think.It's probably quite obvious by now that I am _not_ the person who is going to write an OOP implementation of anything in FPC or any other language.   Maybe someone else will take you up on that. Quote from: Warfley on May 05, 2020, 02:11:45 pmSure, but I think it still is somewhat of a good indicator, especially when using the same language. But we can also simply try to read the code of the other, sure this is no measurable metric, but I would really like to compare the approach of you and me to such a problem ... out of sequence... It's something I've needed for work in the past a lot thats why I thought about it. I don't have one specifically for this purpose right now, but I think it should be doable in less than an hour so I thought it would be a nice little program. And I'm actually interested how OOP compares to something like this, because this is something I always use OOP for. I see your point and I see the value.  Also, I also have some expression evaluators I wrote laying around but, the thought of writing a little scanner and parser just to feed the evaluator isn't on my list of fun things to do.  Plus, as you mentioned in a previous paragraph, that would be useless to me since I already have code that makes my point.   Choose to replicate the little GUI program or just the little subset I mentioned of that PE viewer.  If you choose the subset of the PE viewer, you'll have a useful little utility coded _your_ way. I challenge you to use OOP to produce the output of that PE viewer, just up to and including the OPTIONAL_HEADER and, I believe that my FPC program (not Delphi) in its entirety will be smaller and _faster_ than your OOP implementation.  Choose any C compiler you want.  The restrictions are: 1. no assembly code since there isn't any in mine and 2. it must be 64bit because mine is 64 bit as well.  That way we can compare oranges to oranges and see who's got the smaller but juicer orange. Quote from: Warfley on May 05, 2020, 02:11:45 pmI'm not going to write a GUI programm in C++, this is an absolute pain (you either have to use QT, GTK or windows with the winAPI and all three options I quite dislike).  I would rather have something that is command line only because then it is easy to write something in pascal and C++ (and even C), so it is easy to compare. Especially because this is pretty much platform independent, and when using C++ I usually use Linux (I'm not a fan of visual c++ and visual studio as IDE)My PE viewer isn't GUI, it's pure console, strictly command line (not that it matters since it doesn't accept any switches... it's a whatever you want as long as it's the whole thing.) There is another advantage to using that program as a yardstick, which is, the output it generates is the specification of what your implementation should match.  That way there can be no differences because the programs being compared don't quite implement the same features. ---------------------------------------------------------------------- 440bx · 2020-05-05 15:33 Quote from: munair on May 05, 2020, 03:34:54 pmI wasn't really talking about capabilities per OS, but rather size and performance. But the point is, depending on the goal of the Linux distribution, the "bloat" will vary.  That said, the linux kernel is smaller than the Windows one but, Windows caters to just about everything under the sun, Linux doesn't. If a Linux distribution tried to match Windows feature for feature, it might still be smaller because of its kernel but, I doubt it would be significantly smaller. Quote from: munair on May 05, 2020, 03:34:54 pmWindows has grown much more in size in the last 20 years, and its hardware requirements have grown proportionally. Yes but, that is mostly due to Windows catering to "Joe average" and also catering to manufacturers that want to "personalize" in some ways their distribution while MS doesn't give the source code.  The result: Windows has to include code for personalization mechanisms that Linux doesn't.  In Linux, modify the code according to your wishes, recompile and you've got your "personal"/customized Linux. Quote from: munair on May 05, 2020, 03:34:54 pmThe best way to measure the difference is by comparing hardware requirements and performance. Windows 10 won't install on older machines. That's true but, _one_ (far from the only one) reason is that Windows is also a mechanism to create a need for more memory, more hard drive, more and more of everything.  Linux isn't playing that game (which is a very nice thing about Linux.)  Manufacturers use Windows... MS helps create a need for what the manufacturers sell... they're scratching each other's back and the customer pays.  Windows is probably as much a money mover as it is an O/S. Quote from: munair on May 05, 2020, 03:34:54 pmSure with the right tools it is possible to write efficient Windows software, but commercial packages are usually bloated, and this has probably a lot to do with the fact that software companies are eager to get their latest products on the market as soon as possible, without taking size or memory usage into consideration all that much (because hardware resources are abundant anyway these days).True. Quote from: munair on May 05, 2020, 03:34:54 pmLinux not being commercial has definitely an advantage IMHO. No question about it.  It does. Quote from: marcov on May 05, 2020, 04:02:35 pmAnd if so, why don't simply argue those general problems directly, instead of coating it with a lot of confusing minimalist sentiment.I don't know how much more directly I could be.  There is no sugar coating anywhere. The problems associated with bloated executables are simple: 1. they are good indicator of "less than optimal" code quality and 2. that bloat contains bugs. ---------------------------------------------------------------------- munair · 2020-05-05 16:10 Quote from: 440bx on May 05, 2020, 05:33:34 pmYes but, that is mostly due to Windows catering to "Joe average" and also catering to manufacturers that want to "personalize" in some ways their distribution while MS doesn't give the source code.  The result: Windows has to include code for personalization mechanisms that Linux doesn't.  In Linux, modify the code according to your wishes, recompile and you've got your "personal"/customized Linux. The idea that Linux is not for "Joe average" dates back to the early days, but no longer applies. As I said - and this seems to simple be ignored here - I have installed Linux on (older) machines, laptops, desktops for people who had no more experience than moving a mouse on Windows. They had no difficulty finding their way. And if it comes to personalization, by default Linux offers way more options to customize the look and feel than Windows,without having to modify or recompile any code. Sure, everything in Linux can be customized and even hacked down to the core, but the idea that average people cannot customize the desktop as easily as on Windows belongs to the realm of fiction. ---------------------------------------------------------------------- marcov · 2020-05-05 16:32 Quote from: 440bx on May 05, 2020, 05:33:34 pmQuote from: marcov on May 05, 2020, 04:02:35 pmAnd if so, why don't simply argue those general problems directly, instead of coating it with a lot of confusing minimalist sentiment.I don't know how much more directly I could be.  There is no sugar coating anywhere. The problems associated with bloated executables are simple: 1. they are good indicator of "less than optimal" code quality and 2. that bloat contains bugs. 1. No they are not. Without looking at it in detail you don't know if it bloated code generation, lacking optimizationproblem with the linker(smartlinking)A matter of library architecture And since I haven't seen any numbers from somebody that has filleted the RTL, I've no indication that somebody studied the library architecture angle. Wouldn't be too hard. Just cut down rtl, compile demo app with map file, look at results, rinse, repeat. And even IF I would assume it were true, that indication doesn't mean that thus attention should go to getting  the minimal size down. (since those might not be major factors where binary size in normal applications could be fixed). It will only lead developers into a quagmire of reducing functionality of system for no significant benefit for nobody. ---------------------------------------------------------------------- JiaXing · 2020-05-05 16:45 Quote from: munair on May 05, 2020, 06:10:05 pmQuote from: 440bx on May 05, 2020, 05:33:34 pmYes but, that is mostly due to Windows catering to "Joe average" and also catering to manufacturers that want to "personalize" in some ways their distribution while MS doesn't give the source code.  The result: Windows has to include code for personalization mechanisms that Linux doesn't.  In Linux, modify the code according to your wishes, recompile and you've got your "personal"/customized Linux. The idea that Linux is not for "Joe average" dates back to the early days, but no longer applies. As I said - and this seems to simple be ignored here - I have installed Linux on (older) machines, laptops, desktops for people who had no more experience than moving a mouse on Windows. They had no difficulty finding their way. And if it comes to personalization, by default Linux offers way more options to customize the look and feel than Windows,without having to modify or recompile any code. Sure, everything in Linux can be customized and even hacked down to the core, but the idea that average people cannot customize the desktop as easily as on Windows belongs to the realm of fiction. This time I have to agree. Some Linux even more user friendly than Windows. But overall, his argument stands. As people don't use Linux in the first place, they mostly migrated from Windows. You don't know how bad average Windows user is. To be able to install Linux, even if the installer is user friendly and self explain, people usually watch a video or read a tutorial. Even this alone is far better the average Windows user. I'm an IT helpdesk. I make a living by installing Windows or Linux (Ubuntu or Linux Mint) for people. So I know about this. And finally I hope you to stop this meaningless discussion about Windows or Linux is better and get back to the real problem about OOP. You are obviously a Linux fanboy and your arguments about Windows vs Linux finally just to do an personal attack to 440bx: he doesn't like bloated, Windows is bloated, he's using Windows, he's self conflict, so he must be wrong. It's totally nonsense. ---------------------------------------------------------------------- JiaXing · 2020-05-05 16:50 Quote from: marcov on May 05, 2020, 06:32:39 pmAnd even IF I would assume it were through, that indication doesn't mean that thus attention should go to getting  the minimal size down. (since those might not be major factors where binary size in normal applications could be fixed). It will only lead developers into a quagmire of reducing functionality of system for no significant benefit for nobody. In short, it's just about ease of development. ---------------------------------------------------------------------- JiaXing · 2020-05-05 16:51 Quote from: 440bx on May 05, 2020, 02:07:27 pmQuote from: JiaXing on May 05, 2020, 10:37:24 am@440bx: You didn't answer my question about if you prefered the OOP style of Oberon. I think it's very similar to what you are currently using  My apologies, I wasn't ignoring you.   The problem is, while I have had a _casual_ look at Oberon, I really do not have a reasonable enough amount of knowledge about it to even state a preference.  That means, I would be unable to justify a preference, therefore I cannot have one. Keep in mind the different between Oberon-2 and Oberon-07. It's there: https://en.wikipedia.org/wiki/Oberon_(programming_language)#Object_ori entation there: http://ssw.jku.at/Research/Books/Oberon2.pdf and there: https://miasap.se/obnc/data-abstraction.html#class BTW, I failed to do the same kind of OOP on Free Pascal. Quote from: 440bx on May 05, 2020, 02:07:27 pmQuote from: JiaXing on May 05, 2020, 01:40:45 pmThe OP is a clueless ignorant. Calm down... switch to decaf.     One of the nice things in this forum is that we can get to disagree and make our points strongly but, most of the time at least, we _try_ to do it respectfully. The best way to reinforce an argument isn't with an angry face, it's with a better argument. If you manage to do that then, it's the other guy that will have an angry face... much better than you having an angry face I know how passionate you are when you quoted and addressed their arguments point by point. I don't have such patient. I think I should quit the discussion to keep myself from insulting anyone. ---------------------------------------------------------------------- Warfley · 2020-05-05 17:08 Quote from: 440bx on May 05, 2020, 05:32:25 pmYes, the code uses the Windows API.  An O/S is there to use its services not to ignore them but, it's important to state that in spite of the fact that the program doesn't rely in any way on the compiler's RTL, the RTL is still in there.  If I removed it, the program would be about 40K smaller.  I've been meaning to remove it for a while now, I'll get to it someday.The thing why I mention this is that POSIX systems (for which the GCC is built) provide the libc in the same way windows provides the windows API. That is why a comparison of a program using the Windows API to a program having to be statically linked against the libc is unfair. QuoteTo a great extent it is.  The reason I say that is because, whenever I program in C for any extended period of time and then go back to programming in Pascal, that's when I realize all the _bad_ programming habits I acquired while using C.  OOP is that way.  The OOP way literally contaminates the programmer's mind, just as C does.  It's when you go back to using something that won't accept most of those poor constructions that you realize what happened. That's the very reason why there is no way to show an OOP programmer how poor that paradigm is, the poor design is ingrained in their minds.  It's exactly what happens with C.  Explaining to a C programmer why C is an _atrocity_ is about as fruitful as explaining number theory to a wall and, in that case, the wall might be more receptive, at least it won't argue. If you want to show someone how bad C is, simply show them the function printf. This is by far the worst thing ever created by a programmer. QuoteNo.  Not a double standard at all.  Yes, people misuse procedural programming, particularly at the beginning but, it is quite common that the individual learns how to do it right because when it's wrong it's usually fairly obvious.   OOP is the opposite and, in that regard it's just like C, the more people use it, the most commonly observed result is, the code gets worse and worse.  IOW, they were better programmers when they were beginners than when they became "experts".  All that expertise is used to produce atrocious code (just like in C, examples of that are everywhere to be found, many even take pride in being able to write unintelligible code - they even have contests for it - what a great language design!.)As someone who writes both OOP and procedual code on a daily basis, from my experience I can't disagree more. QuotePrayers are not what's needed, what's needed is good design.   A well designed procedural program can provide everything OOP provides and do it better.This might be true when you are writing your code alone. But lets say you are part of a team with 3 people, and you call on of their functions with a reference to your record. Whats stopping them from skrewing up all your data? In OOP you can build guards to not allow them to mess around with it. Even more so when you are using and writing libraries for others. The thing about OOP is that it can enforce such things as access control, which you simply can't in procedual programming. QuoteOf course I have, bread and butter of programming but, you made it sound different than that.If you pass a record (reference) to a function, anyone can do with it what they please. In OOP you have a very granular way of granting access and placing guards. At my work we have a motivational poster that says something like: You should always write code as if it would be the code-base for a psychopath who knows where you live QuoteProperties... one of my favorite OOP gizmos.  When something goes wrong with one of those, it's usually "exception time" because the property (at least in FPC) has no way to inform the caller that something went wrong.  There is this "old-fashioned" thing called "pre-conditions" and "post-conditions", those are classics in programming and it would nice if OOP programmers used those a little more often instead of being casual and every time something goes wrong jump through the exception window to get out of mess they got themselves into.You can use pre-and postconditions in OOP. It is actually heavily used with OCL, where you use automated testing to enforce that the pre-and postcondition hold true in any case. That said, thats exactly what exceptions are there for. Because when doing programming without them you often have to add massive amounts of output parameters to check for errors. E.g. https://linux.die.net/man/3/strtol where you have to write code like this: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i int i = strtoll(...);if (errno == ERANGE) {  if (i == INT_MAX) {    // handle overflow  } else if (i == INT_MIN) {    // handle underflow  }} Exceptions massively clean up the code, as you can have many lines of code that can throw all throw exceptions and then only one handler (e.g. if on exception you need to return). Simply look at page 32 in http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf It's not only about properties, in the very most cases exceptions clean up the code. For example you write a websocket server. The protocol basically defines if anything unexpected happens you need to directly shut down the connection. With exceptions easy, simply throw an exception and catch it in the outer most connection handling loop. Without you need to pass the information manually up the stack frames. QuoteI never said otherwise and I don't think anything I said previously implied that.You said QuoteEvery instruction in an executable is a potential source of bugs.  People now like to downplay the size of the executable because the tools/compilers they use generate bloat instead of quality.If you don't want to imply that, don't put two sentences right after another that together imply that. Still you didn't argue how size effects the quality of your code. If I have an executable that is 100k big and I add another 100k of usless junk that is never reached. How does that decrease the quality of the application. Except maybe for a 1% longer loading time I don't see anything QuoteI don't have an example that is directly caused by bloat but, I do have an example of a correct Delphi program that produces bugs when compiled with FPC.  I also have an example of the opposite, a correct FPC program that produces bugs when compiled with Delphi.  Since it's quite likely you're curious about what those are, here they are: Delphi produces correct code for an array element access with a negative index when the low bound of the array is zero, FPC does not.   FPC produces correct code when passing a pointer to single character, Delphi does not (a fairly common thing to do when sending a single character to a listbox for instance.)What are you talking about? It's simple you claimed: More bloat -> more potential for bugs. So if thats a problem, you must have some examples. QuoteUnnecessary things... quite common when doing OOP programming.  Not entirely eliminated (without some configuration effort) with procedural programming but, with decent code, quite a bit less than with OOP.What? Optimization is unnecessary? Inlining is the most neccessary optimization to have, because without it your code would look terrible, because you would have functions with hundreds of lines of code. The whole point behind inlining is that it makes the use of non recursive functions free. This massively increases readability, but will inevitebly increase size. QuoteWhen there is a good reason for the additional code, I don't have anything against it.  On the contrary, I welcome it.  A "good reason" isn't including the kitchen sink in the executable to cater to programmers who are more interested in instant gratification than quality.Yes but there is no good reson to have small executables. There is nothing gained from having a few kilobytes less in your programm. QuoteYou're attempting to avoid the point.  Filesize is an indicator of the quality of the code the compiler produces and, myself, I believe a programmer should care about that just as he/she should care about the quality of his code.  A good compiler with a good programmer = good results.  A deficiency in either and the results are "not so good" anymore.No it's not. Take this simple calculator: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program calc;begin  WriteLn(42);end;It's really small, but it's a terrible calculator. If I take a C program and use -O3 vs -Os, the -Os variant will be much smaller, but the O3 variant will be much faster. You are making the claim that executable size is an indicator of code quality, but all you did is claim that. Prove it. I bet for every program you write I can write a worse program thats smaller QuoteIf the reason isn't obvious, I probably cannot give one.Ok, then there is none. "Obvious" is not an argument period. QuoteA 320k executable is bad for the same reason that a 5MB executable for "hello" is bad.  In both cases, it should be quite obvious that there is a whole lot of room for improvement which means the quality of the result leaves a great deal to be desired.It's bad because it leaves something to be desired is a circular argument. You are saying it's bad because It's bad. I can tell you when it is bad (at least to me). When runtime is massively impared (e.g. when the exec is so large it takes a long time to load) or the memoryconsumption is unreasonable for the amount of storage available (e.g. 10 GB on a 1TB drive takes 1% of available space, this would be unreasonable. But if I had a 1PT drive this would be different). QuoteThe _fact_ is, there is a bunch of code that doesn't belong there and, that code can contain bugs.  For those two reasons, it shouldn't be there.So you are assuming that the code there will 1. be executed and 2. contain bugs. Feel free to argue why they are true. For example if you are using inlining, this increases the size of the executable, but does not introduce new bugs. RTTI information for example is only data, it can neither be executed nor contain bugs QuoteThat's wishful thinking.  What makes you think that code is "unreachable" ?... it would be nice if it were but, you have no assurance of that.  Additionally, if it really is unreachable, I expect the compiler (and/or linker) to figure that out and _not_ place it in the executable since, as unreachable, it does not perform any useful function.  You know unreachable code is a thing? Thats why optimizers do reachability analysis right? But unreachibility analysis is computationally not decidable. Yes it's the job of the compiler and linker to find out what is not needed, but it is not always possible. QuoteLibraries are good to gather code that is common and, general in nature (e.g, a sort routine) to _many_ programs, not just two programs that need to be kept in synch which use code that is not general.Why not? if two programms require the same code base and you need to sync it, using libraries is the better alternative than having one exec. QuoteNot two but three now.  Who keeps all that stuff in synch ? ... prayers don't.The updater... that's its job QuoteI can do that with less management overhead by having them be a single executable.Yes you can break two applications at once with less overhead... Nice, why don't you compile your own OS where all your apllications are one with the kernel? QuoteLooks to me, you're trying to find imagined problems with the method because you can't do it in OOP.  For the record and, to emphasize an important point, I stated that I don't even care that your OOP rendition be _functional_, all I care about is that it has to carry out the same actions, i.e, open a file, mapped the file, create a mutex, have a little dialog box, a status bar, etc.You can do everything in OOP you can do with procedual programming simple as that. Turing complete is the magic word. QuoteThat way we can compare what your OOP version weighs in to my procedural version.  Of course, if it cannot be done with OOP then, there won't anything to compare.  Just another unfortunate occurrence (which - obviously - cannot have anything to do with OOP.)Again, we can also compare two cars on how well they burn. You are still insisting to measure a useless metric on a programm that has absolutely no use and is the most poorly designed thing I have ever come across. QuoteIt wouldn't be completely useless, it would prove your claim that OOP introduces no overhead in the executable.  It would show you have a valid point, that's not useless. I've already shown that with my C and C++ hello world example. Nothing more needed to show QuoteAnd why would that be a problem ? can't OOP use the Windows API ?... I am under the impression it can.Yes it can even better (COM interfaces), but the thing is I'm not using the Windows API, simple as that. QuoteThey may belong together but, if a program doesn't use the standard lib, belonging together is _not_ a good reason to have it in the executable.  My executables aren't Rome, IOW, they are not a tourist destination for compiler code.It will not be in your executable if you don't use it QuoteIt's probably quite obvious by now that I am _not_ the person who is going to write an OOP implementation of anything in FPC or any other language.   Maybe someone else will take you up on that. No the idea was you write your procedual version and I the OOP version... QuoteI challenge you to use OOP to produce the output of that PE viewer, just up to and including the OPTIONAL_HEADER and, I believe that my FPC program (not Delphi) in its entirety will be smaller and _faster_ than your OOP implementation.  Choose any C compiler you want.  The restrictions are: 1. no assembly code since there isn't any in mine and 2. it must be 64bit because mine is 64 bit as well.  That way we can compare oranges to oranges and see who's got the smaller but juicer orange. I will take a look into that, but that said, I have absolutely no idea how to write a PE viewer. Thats why I suggested something that is really easy for both of us (I mean parsing S expressions should be doable in 30 minutes to an hour) ---------------------------------------------------------------------- Thaddy · 2020-05-05 17:56 Well said, well said, I like informed replies... ---------------------------------------------------------------------- munair · 2020-05-05 18:50 Quote from: JiaXing on May 05, 2020, 06:45:52 pmYou don't know how bad average Windows user is. How do you know what I know? If there is one thing in a discussion that is meaningless, it is these ridiculous assumptions.That's where the problem starts. No one should assume anything about someone without knowing that someone. I will leave it at that. ---------------------------------------------------------------------- 440bx · 2020-05-05 19:23 Quote from: munair on May 05, 2020, 06:10:05 pmThe idea that Linux is not for "Joe average" dates back to the early days, but no longer applies. Maybe some distributions are better suited to Joe Average.  I honestly don't know, I don't use Linux and, I _occasionally_ install it just to have a quick look at it to satisfy my curiosity then delete it.  Because of that, I'll take your word for it that, some distributions, may be "Joe" friendly. Quote from: marcov on May 05, 2020, 06:32:39 pm1. No they are not. Without looking at it in detail you don't know if it bloated code generation, lacking optimizationproblem with the linker(smartlinking)A matter of library architecture And since I haven't seen any numbers from somebody that has filleted the RTL, I've no indication that somebody studied the library architecture angle. Wouldn't be too hard. Just cut down rtl, compile demo app with map file, look at results, rinse, repeat. And even IF I would assume it were through, that indication doesn't mean that thus attention should go to getting  the minimal size down. (since those might not be major factors where binary size in normal applications could be fixed). It will only lead developers into a quagmire of reducing functionality of system for no significant benefit for nobody.  It's really surprising that you deny _fact_.  FACT: I can compile a 32bit program with Delphi 2 and with FPC (both in 32bit of course) and, so far, I am yet to see a single case where FPC would match Delphi's executable size. It's _not_ about reducing functionality, it is about increasing _quality_, where ever it's needed, be it the compiler in general, its optimizer specifically, the linker or whatever else is involved in the production of the final executable. The reasons only matter to the extent that they should be the targets of improvements but, the bottom line is: the compiler and the tools (if any) involved in the production of the final code should be continuously improved.  That's approach is much more likely to result in superb compiler than continuously adding more features, many of somewhat dubious value, to it. Polish the product.  That's how desirable results are obtained and, that includes well-optimized executables that are _not_ code packrats. Quote from: Warfley on May 05, 2020, 07:08:43 pmThe thing why I mention this is that POSIX systems (for which the GCC is built) provide the libc in the same way windows provides the windows API. That is why a comparison of a program using the Windows API to a program having to be statically linked against the libc is unfair. There is nothing unfair about it. There is an operating system that provides services.  I use the services, that's why they are there for, to be used.   Because _you_ choose bloat and someone else doesn't, doesn't make it unfair. Quote from: Warfley on May 05, 2020, 07:08:43 pmIf you want to show someone how bad C is, simply show them the function printf. This is by far the worst thing ever created by a programmer.I don't know if it's the worst but, it's up there.  We agree there. Quote from: Warfley on May 05, 2020, 07:08:43 pmThis might be true when you are writing your code alone. But lets say you are part of a team with 3 people, Team of 3 ? ... try over a hundred.  That's a project. Quote from: Warfley on May 05, 2020, 07:08:43 pmand you call on of their functions with a reference to your record. Whats stopping them from skrewing up all your data? In OOP you can build guards to not allow them to mess around with it. Even more so when you are using and writing libraries for others. You can pass the record as "constref", that will prevent most attempts to modify the record.   There is no difference there with OOP, _every_ field that is in the scope of the method can be trashed by the callee.  There is _nothing_ in OOP or any paradigm that prevents code that has write access to a field from messing it up. As far as all those guards you're talking about, if the callee only needs access to _some_ of the fields in the record then, only those fields should be passed by reference, not the entire record. Quote from: Warfley on May 05, 2020, 07:08:43 pmThe thing about OOP is that it can enforce such things as access control, which you simply can't in procedual programming. I can do better and much simpler in procedural programming than all the scope _junk_ compilers have added to mitigate all the problems of object/classes fields which are nothing more than object/class global variables and, it is for that reason that all that scoping junk is necessary.    In well designed procedural code none of that stuff is needed, the structure of the program determines scope and visibility not a bunch of junky keywords added as a hack to alleviate a problem that shouldn't exist if the paradigm was worth anything. Quote from: Warfley on May 05, 2020, 07:08:43 pmIn OOP you have a very granular way of granting access and placing guards. A highly deficient method that would be completely unnecessary in a well designed procedural program. Quote from: Warfley on May 05, 2020, 07:08:43 pmYou can use pre-and postconditions in OOP. It is actually heavily used with OCL, where you use automated testing to enforce that the pre-and postcondition hold true in any case. I have no doubt pre and post conditions can be used in OOP but,  they are almost as common as seeing a unicorn in New York. Quote from: Warfley on May 05, 2020, 07:08:43 pmThat said, thats exactly what exceptions are there for. Because when doing programming without them you often have to add massive amounts of output parameters to check for errors. E.g. https://linux.die.net/man/3/strtol where you have to write code like this: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i int i = strtoll(...);if (errno == ERANGE) {  if (i == INT_MAX) {    // handle overflow  } else if (i == INT_MIN) {    // handle underflow  }}I understand doing it right is just too much work.  Quote from: Warfley on May 05, 2020, 07:08:43 pmExceptions massively clean up the code, as you can have many lines of code that can throw all throw exceptions and then only one handler (e.g. if on exception you need to return). When a programmer needs exceptions, it is often an indication of exceptionally bad code.  Of course, there are exceptions (pun intended) to that. The last time I used an exception in my code was as a workaround to a bug in the FPC compiler that caused it to access a word instead of a byte.  Fortunately Martin_fr came up with a very nice workaround that didn't require using an exception handler, therefore I had the pleasure of getting rid of it.  That said, I routinely use the Windows API functions to validate readability and/or writeability of memory areas (most commonly parameters) and those APIs implement the exception handlers.  That keeps my code clean and working as it should _without_ exceptions. Quote from: Warfley on May 05, 2020, 07:08:43 pmWithout you need to pass the information manually up the stack frames. What a terrible thing!  have to check results and pass them back to the proper handler in a predictable manner.  That's really terrible. Quote from: Warfley on May 05, 2020, 07:08:43 pmStill you didn't argue how size effects the quality of your code. If I have an executable that is 100k big and I add another 100k of usless junk that is never reached. How does that decrease the quality of the application. Except maybe for a 1% longer loading time I don't see anythingFine!... do you keep 500 pounds of useless, unreachable junk in the trunk of your car ?... probably not.  And you are still making the totally unproven assumption that all that junk is unreachable.  You have no proof of that, just wishful thinking.  OTH, if it's not there then, it is a _fact_ it is unreachable. Quote from: Warfley on May 05, 2020, 07:08:43 pmIt's simple you claimed: More bloat -> more potential for bugs. So if thats a problem, you must have some examples. And I stand by that claim.  The more code there is in a program, the more likely the program is to have a bug, simply because there is more code.  Can a compiler produce and _infinite_ amount of bug free code ?... rather unlikely (to put it very kindly.) Quote from: Warfley on May 05, 2020, 07:08:43 pmWhat? Optimization is unnecessary?Optimization is necessary and, I am under the impression that optimization includes removing code that is not used.  Am I mistaken about that ? Quote from: Warfley on May 05, 2020, 07:08:43 pmYes but there is no good reson to have small executables. There is nothing gained from having a few kilobytes less in your programm.Not true.  A smaller executable has less code, therefore there are fewer instructions that may be logically incorrect. Quote from: Warfley on May 05, 2020, 07:08:43 pmYou are making the claim that executable size is an indicator of code quality, but all you did is claim that. Prove it. I bet for every program you write I can write a worse program thats smallerOk.  It's really easy, if something _can_ happen then it is only a matter of time before it happens.  The same thing applies to code, any instruction in a program can be the cause of bug, the more instructions the greater the probability.  Take the limit when the number of instructions tends to infinity and the result is 1.  IOW, absolute certainty.    Unless you care to claim that bugs in a program are not an indicator of a quality problem then, the more unnecessary code, the lower the quality due to an ever increasing probability that the unnecessary code may be the source of a bug. Quote from: Warfley on May 05, 2020, 07:08:43 pmOk, then there is none. "Obvious" is not an argument period. Well... should I also prove that 0 + 0 = 0 ? Quote from: Warfley on May 05, 2020, 07:08:43 pmIt's bad because it leaves something to be desired is a circular argument. You are saying it's bad because It's bad. The only one presenting a circular argument here is _you_ and you have offered nothing to validate your claim that executable size does not matter because you _choose_ to _believe_ the code is unreachable.  Your argument so far is based on unproven claims solidly resting on a completely unfounded assumption.  Other than that, it's a good argument. Quote from: Warfley on May 05, 2020, 07:08:43 pmSo you are assuming that the code there will 1. be executed and 2. contain bugs. Feel free to argue why they are true.No problem.  Most important and the crux of the fallacy you want to slide by: I am not assuming that code will _not_ be executed as you are doing.  My claim is: since the code is there, it can/may be executed and, since it is there, it can be the source of bugs. Additionally, if that code really isn't executed, don't you think it reflects on the quality of the tools that included it in there ?  If your answer is "no" then, you should have no problem with your neighbor putting 2000 pounds of junk he/she doesn't want anymore in the trunk of you car.  I believe (maybe wrongly) you'd consider that a problem but, if the compiler puts a bunch of useless junk code in your executable, that's not a problem... since "obvious" is a word you don't like, I'll say, I "suspect" there may be a contradiction in the proper evaluation of the events on your part. All that said, if you think it's perfectly ok for your neighbor to load your car's trunk with a bunch of junk he/she doesn't need anymore then, in that case, that would weaken my argument. Quote from: Warfley on May 05, 2020, 07:08:43 pmYou know unreachable code is a thing? Thats why optimizers do reachability analysis right? But unreachibility analysis is computationally not decidable. Yes it's the job of the compiler and linker to find out what is not needed, but it is not always possible.Whether it's decidable or not depends on how the program is written.  What seems a bit strange is that "unreachability" seems to have grown significantly in the past few years.  It must be a coincidence that its growth seems to be greater (temporarily presuming your unreachability assumption is valid) in OOP code than in procedural code.  Pure coincidence, of course. Quote from: Warfley on May 05, 2020, 07:08:43 pmWhy not? if two programms require the same code base and you need to sync it, using libraries is the better alternative than having one exec.What a wonderful solution.  Now there are three (3) programs to recompile, manage, install, distribute, support, etc instead of just one (1).  I can see that's a significantly better solution if the goal is to minimize unemployment. Quote from: Warfley on May 05, 2020, 07:08:43 pmYes you can break two applications at once with less overhead... Nice, why don't you compile your own OS where all your apllications are one with the kernel?As I stated in the previous post.  Libraries are good solutions when it is necessary to provide functionality that is common to many programs.  One of the functions an O/S has to fulfill is to be a library of services available to any program that may be installed at any time.  For that reason, it makes no sense to compile applications into the operating system.  I won't say it's obvious, I know you don't like that word but, I'll say that it _might_ be common sense. Quote from: Warfley on May 05, 2020, 07:08:43 pmYou can do everything in OOP you can do with procedual programming simple as that. I never claimed otherwise. I claimed and still claim, that _anything_ OOP can do can be done better with pure procedural programming.    Very important: note that I am _not_ claiming it can be done faster, it often cannot.   That last part, just to make things clear. Quote from: Warfley on May 05, 2020, 07:08:43 pmAgain, we can also compare two cars on how well they burn. You are still insisting to measure a useless metric on a programm that has absolutely no use and is the most poorly designed thing I have ever come across.In that case, you should find it easy to show how OOP can do better.  Quote from: Warfley on May 05, 2020, 07:08:43 pmI've already shown that with my C and C++ hello world example. Nothing more needed to show and you talk about useless programs... that "hello" program is so useful, someone should send it to Washington, it might solve the national debt problem (or if it can do that, to Greece.) Quote from: Warfley on May 05, 2020, 07:08:43 pmYes it can even better (COM interfaces), but the thing is I'm not using the Windows API, simple as that.Let's be clear, AFAIC, you can use whatever you want.  Quote from: Warfley on May 05, 2020, 07:08:43 pmI will take a look into that, but that said, I have absolutely no idea how to write a PE viewer. A PE viewer is little more than "hello world" about a 100 times.  Format field, output field.  The PE specification is reasonably well documented and the program I have offers a crystal clear specification of what the program should do. You'd end up with something useful instead of a very limited calculator. (instead of other item to send to Greece to help ease the national debt problem.) ---------------------------------------------------------------------- Thaddy · 2020-05-05 20:09 The difference between a programmer and a professor is obvious. Et requium meam. What rests? (explained as give a proper example, otherwise the matter is closed) ---------------------------------------------------------------------- marcov · 2020-05-05 20:21 Quote from: JiaXing on May 05, 2020, 06:50:06 pmQuote from: marcov on May 05, 2020, 06:32:39 pmAnd even IF I would assume it were through, that indication doesn't mean that thus attention should go to getting  the minimal size down. (since those might not be major factors where binary size in normal applications could be fixed). It will only lead developers into a quagmire of reducing functionality of system for no significant benefit for nobody. In short, it's just about ease of development. It is about lack of people actually doing something about it (and even if they can't fix it, try to really nail the issues). Anything other than gratuitous ranting on the fora. ---------------------------------------------------------------------- howardpc · 2020-05-05 22:26 Quote from: 440bx on May 05, 2020, 09:23:16 pmQuote from: marcov on May 05, 2020, 06:32:39 pm1. No they are not. Without looking at it in detail you don't know if it bloated code generation, lacking optimizationproblem with the linker(smartlinking)A matter of library architectureAnd since I haven't seen any numbers from somebody that has filleted the RTL, I've no indication that somebody studied the library architecture angle. Wouldn't be too hard. Just cut down rtl, compile demo app with map file, look at results, rinse, repeat. And even IF I would assume it were through, that indication doesn't mean that thus attention should go to getting  the minimal size down. (since those might not be major factors where binary size in normal applications could be fixed). It will only lead developers into a quagmire of reducing functionality of system for no significant benefit for nobody.  It's really surprising that you deny _fact_.  FACT: I can compile a 32bit program with Delphi 2 and with FPC (both in 32bit of course) and, so far, I am yet to see a single case where FPC would match Delphi's executable size. It's _not_ about reducing functionality, it is about increasing _quality_, where ever it's needed, be it the compiler in general, its optimizer specifically, the linker or whatever else is involved in the production of the final executable. To some extent you are comparing an apple to an orange. The Delphi 2 compiler is a single-platform compiler honed from the TurboPascal era onwards by a team of professionals to target Windows only. I don't know how many people were involved over the years in producing that compiler, but some were paid to work on it full time, most likely more than one person, at perhaps 35 hours a week for years; and others like Anders, Chuck and Danny worked on it from time to time as part of their Delphi development work. FPC has been cross-platform from the outset. AFAIK it has never had a goal of producing the smallest Windows binaries possible, since that would constrain its cross-platform vision too much. For many years FPC relied on a cross-platform linker, and only got a dedicated Windows linker a few years ago. This reflects the fact that it is developed by volunteers in their spare time, scratching their particular itch (as well as doing the grunt work that no one really wants to do, but is needed nevertheless). Dedicated single-platform tools are almost bound to outperform equivalent cross-platform tools in most  areas, since they can take shortcuts and perform custom optimizations that are not possible for cross-platform tools to do without incurring unacceptable speed costs. I also think it is questionable whether the equation   smaller executable size = better quality code always holds true. As a generalisation in broad terms comparative size is clearly a  guide to quality of code generation. But the two are not identical. It is possible that differences in size might be largely down to chunks of zero bytes present in the larger executable. ---------------------------------------------------------------------- 440bx · 2020-05-05 22:59 @howardpc, I think you make a number of valid points and you take into consideration a number of things that must be considered but, I also think that there are a few important considerations missing. Quote from: howardpc on May 06, 2020, 12:26:12 amThe Delphi 2 compiler is a single-platform compiler honed from the TurboPascal era onwards by a team of professionals to target Windows only. I don't know how many people were involved over the years in producing that compiler, but some were paid to work on it full time, most likely more than one person, at perhaps 35 hours a week for years; and others like Anders, Chuck and Danny worked on it from time to time as part of their Delphi development work. FPC has been cross-platform from the outset. All that is true but, it should also be considered that FPC has been under development since 1993.  That's a long time.  That seems to be a very reasonable amount of time to address the areas that need improvement. As far as the cross platform point, that is definitely something that enters into the equation but, the algorithms to determine if some piece of code is or is not used aren't (or at least, shouldn't be) platform dependent.  My point is that 24 years seems to be enough time to polish them.  Quote from: howardpc on May 06, 2020, 12:26:12 amAFAIK it has never had a goal of producing the smallest Windows binaries possible, since that would constrain its cross-platform vision too much.I think producing small and fast code is an objective in all compilers.  I wouldn't ask for "smallest" but, I think the compiler should be capable enough to produce code organized in such a way that removing unused code isn't too difficult or maybe even impossible.  I don't believe that would significantly constrain the cross platform objective. Additionally, as far as cross platform, the two most common platforms are Windows and Linux and from a CPU viewpoint, Intel/AMD.  Those platforms are the ones used by the majority of users, it seems logical and reasonable to optimize for those, IOW, optimize the common case. Quote from: howardpc on May 06, 2020, 12:26:12 amFor many years FPC relied on a cross-platform linker, and only got a dedicated Windows linker a few years ago. This reflects the fact that it is developed by volunteers in their spare time, scratching their particular itch (as well as doing the grunt work that no one really wants to do, but is needed nevertheless). Dedicated single-platform tools are almost bound to outperform equivalent cross-platform tools in most  areas, since they can take shortcuts and perform custom optimizations that are not possible for cross-platform tools to do without incurring unacceptable speed costs.I understand that but, as I mentioned previously, roughly 24 years to produce custom algorithms to optimize for the common platforms seems an adequate amount of time.  Quote from: howardpc on May 06, 2020, 12:26:12 amI also think it is questionable whether the equation   smaller executable size = better quality code always holds true. I concur. I don't think it holds true in all cases but, when the additional size is a result of a lack of capabilities in the compiler then, in those cases, it is true. Quote from: howardpc on May 06, 2020, 12:26:12 amAs a generalisation in broad terms comparative size is clearly a  guide to quality of code generation. But the two are not identical. I agree with that. Quote from: howardpc on May 06, 2020, 12:26:12 amIt is possible that differences in size might be largely down to chunks of zero bytes present in the larger executable. Now, that, I would consider an indicator of poor quality along with the presence of code that shouldn't be there.  That stuff should be optimized away. ---------------------------------------------------------------------- JiaXing · 2020-05-06 03:35 Quote from: munair on May 05, 2020, 08:50:22 pmQuote from: JiaXing on May 05, 2020, 06:45:52 pmYou don't know how bad average Windows user is. How do you know what I know? If there is one thing in a discussion that is meaningless, it is these ridiculous assumptions.That's where the problem starts. No one should assume anything about someone without knowing that someone. I will leave it at that. 440bx was right. I was win. You can do nothing other do an personal attack to me. That poor fallacy is cheap. The only ridiculous assumption is yours, Windows hater and Linux fanboy. Keep your religion. You will find more luck on channels like Reddit and Phoronix, where full of Linux is da best fanboys like you. You lose. Now go away ---------------------------------------------------------------------- JiaXing · 2020-05-06 03:40 Quote from: marcov on May 05, 2020, 10:21:04 pmQuote from: JiaXing on May 05, 2020, 06:50:06 pmQuote from: marcov on May 05, 2020, 06:32:39 pmAnd even IF I would assume it were through, that indication doesn't mean that thus attention should go to getting  the minimal size down. (since those might not be major factors where binary size in normal applications could be fixed). It will only lead developers into a quagmire of reducing functionality of system for no significant benefit for nobody. In short, it's just about ease of development. It is about lack of people actually doing something about it (and even if they can't fix it, try to really nail the issues). Anything other than gratuitous ranting on the fora. I don't understand your words. Are you using Latin? Anyway, I think I didn't rant about anything. So I assume you didn't talk about me. BTW, is my short summary anything wrong? After all it's just ease of development. OOP definitely wins for most of the people ---------------------------------------------------------------------- JiaXing · 2020-05-06 03:49 To our dear 440bx, you didn't give us a showcase about your method, so people is ignorant about it, ignorant gives hate, and hater gonna hate. What about some example code so people could really consider it? Talk is cheap, wall of text is meaningless and just a waste of time, you can't convince the other guys with only words. Continue the discussion is only to repeat old statements again and again. Don't you feel tired? You currently have no advantage over your opponent. Hope it help. ---------------------------------------------------------------------- JiaXing · 2020-05-06 03:52 Quote from: JiaXing on May 05, 2020, 06:51:31 pmQuote from: 440bx on May 05, 2020, 02:07:27 pmQuote from: JiaXing on May 05, 2020, 10:37:24 am@440bx: You didn't answer my question about if you prefered the OOP style of Oberon. I think it's very similar to what you are currently using  My apologies, I wasn't ignoring you.   The problem is, while I have had a _casual_ look at Oberon, I really do not have a reasonable enough amount of knowledge about it to even state a preference.  That means, I would be unable to justify a preference, therefore I cannot have one. Keep in mind the different between Oberon-2 and Oberon-07. It's there: https://en.wikipedia.org/wiki/Oberon_(programming_language)#Object_ori entation there: http://ssw.jku.at/Research/Books/Oberon2.pdf and there: https://miasap.se/obnc/data-abstraction.html#class BTW, I failed to do the same kind of OOP on Free Pascal. And you are so keen about countering this guy and forgot my post again ---------------------------------------------------------------------- 440bx · 2020-05-06 04:15 Quote from: JiaXing on May 06, 2020, 05:35:53 am440bx was right. wait a second, while I do agree with_some_ of the things you've said, that's the extent of my being "right".  As far as how you reply to people, I think you should tone it down a little. Quote from: JiaXing on May 06, 2020, 05:35:53 amWindows hater and Linux fanboy. Keep your religion. You will find more luck on channels like Reddit and Phoronix, where full of Linux is da best fanboys like you. You lose. Now go away  Calm down... take it easy... Quote from: JiaXing on May 06, 2020, 05:52:01 amAnd you are so keen about countering this guy and forgot my post again  I didn't forget your post... I refrain from emitting opinions on things that I'm only, at best, familiar with.  That simply isn't enough knowledge to base an opinion on.  That's the reason I didn't reply... I didn't forget and I didn't ignore it either. I simply cannot comment. Quote from: JiaXing on May 06, 2020, 05:49:16 amTo our dear 440bx, you didn't give us a showcase about your method, What about some example code so people could really consider it?You have a point and I am considering that. Quote from: JiaXing on May 06, 2020, 05:49:16 amTalk is cheap, wall of text is meaningless and just a waste of time, You're mostly right about that.  I say "mostly" because sometimes all that's needed is to point something out for someone to think about it and understand the point.  Unfortunately, that isn't always enough. Quote from: JiaXing on May 06, 2020, 05:49:16 am you can't convince the other guys with only words. I can't convince anyone about OOP not being a good methodology with words or examples.  OOP is like religion, it's a leap of faith and once someone has chosen to make it, it is extremely rare for the person to go back.  It doesn't take words and/or examples, it takes miracles and, I am really, really bad at making those happen. Quote from: JiaXing on May 06, 2020, 05:49:16 amDon't you feel tired? A little but, one of my many faults is being overly optimistic.  The posts simply reflect that. Quote from: JiaXing on May 06, 2020, 05:49:16 amYou currently have no advantage over your opponent. No.  I have a very significant advantage, which is, a clearly better programming methodology. Quote from: JiaXing on May 06, 2020, 05:49:16 am Hope it help. I appreciate the good intentions. ---------------------------------------------------------------------- munair · 2020-05-06 06:36 Quote from: 440bx on May 06, 2020, 06:15:12 amI can't convince anyone about OOP not being a good methodology with words or examples.  OOP is like religion, it's a leap of faith and once someone has chosen to make it, it is extremely rare for the person to go back.  It doesn't take words and/or examples, it takes miracles and, I am really, really bad at making those happen. Where exactly do you draw the line? Do you consider UDTs that allow procedures also a form of OOP? ---------------------------------------------------------------------- PascalDragon · 2020-05-06 07:23 Quote from: serbod on May 05, 2020, 04:53:01 pmQuote from: PascalDragon on May 05, 2020, 04:31:05 pm object and class are not compatible, they have different internal structuresthe compiler does not call constructors/destructors for objects on the stackmany of the classes in the RTL have parameters in their constructors and using the default TObject constructor would leave them in an invalid stateobjects are assigned using copy, for a class this would lead to memory leaksfor smart pointers you need to keep track of the number of references, thus a class instance converted to an object is  not suitable for this It's already working for "interface" and 'variant' type variables. And can be constructed automatically for invocable objects. Those are different. An interface variable is essentially the class instance pointer shifted by an offset and a VMT that provides the interface's methods that shift the Self pointer back again. Otherwise it's the same class instance on the heap. And a Variant is in fact a variant record with operator overloads that can take an interface variable. You can't assign a class instance to a Variant. Quote from: howardpc on May 06, 2020, 12:26:12 amFPC has been cross- platform from the outset. AFAIK it has never had a goal of producing the smallest Windows binaries possible, since that would constrain its cross-platform vision too much. For many years FPC relied on a cross- platform linker, and only got a dedicated Windows linker a few years ago. This reflects the fact that it is developed by volunteers in their spare time, scratching their particular itch (as well as doing the grunt work that no one really wants to do, but is needed nevertheless). Dedicated single-platform tools are almost bound to outperform equivalent cross-platform tools in most  areas, since they can take shortcuts and perform custom optimizations that are not possible for cross-platform tools to do without incurring unacceptable speed costs. Just for clarification: FPC wasn't cross platform from the outset. In the beginning it only targeted the GO32v1 DOS extender. Steps towards a cross platform capable RTL only came later. Quote from: 440bx on May 06, 2020, 12:59:42 am@howardpc, I think you make a number of valid points and you take into consideration a number of things that must be considered but, I also think that there are a few important considerations missing. Quote from: howardpc on May 06, 2020, 12:26:12 amThe Delphi 2 compiler is a single-platform compiler honed from the TurboPascal era onwards by a team of professionals to target Windows only. I don't know how many people were involved over the years in producing that compiler, but some were paid to work on it full time, most likely more than one person, at perhaps 35 hours a week for years; and others like Anders, Chuck and Danny worked on it from time to time as part of their Delphi development work. FPC has been cross-platform from the outset. All that is true but, it should also be considered that FPC has been under development since 1993.  That's a long time.  That seems to be a very reasonable amount of time to address the areas that need improvement. As far as the cross platform point, that is definitely something that enters into the equation but, the algorithms to determine if some piece of code is or is not used aren't (or at least, shouldn't be) platform dependent.  My point is that 24 years seems to be enough time to polish them. The problem isn't the mechanisms to strip away dead code (those work very well). The problem is the structure of the RTL which due to its cross platform nature has some parts that these mechanisms simply can't strip away, because they are at least touched in the RTLs initialization independent of whether the program uses them or not (thus they can not be considered "dead"). For example on Windows the thread manager is always initialized which means that all the functions the thread manager provides are linked in even if the user doesn't start a single separate thread. Same also for other concepts like the WideString and UnicodeString managers and such. Delphi has it easier there cause it doesn't know the concept of a thread manager (or UnicodeString manager, etc.), thus it can simply strip away all the functions that aren't used by the user. ---------------------------------------------------------------------- JiaXing · 2020-05-06 07:37 Quote from: munair on May 06, 2020, 08:36:42 amDo you consider UDTs that allow procedures also a form of OOP? Yes, it is. OOP is more than just class based. This kind of OOP is called prototype based OOP. Check the wiki: https://en.wikipedia.org/wiki/Prototype-based_programming and also check my post about OOP in Oberon. So yes, we could even do OOP with advanced records on Free Pascal ---------------------------------------------------------------------- munair · 2020-05-06 07:50 Quote from: JiaXing on May 06, 2020, 09:37:58 amQuote from: munair on May 06, 2020, 08:36:42 amDo you consider UDTs that allow procedures also a form of OOP? Yes, it is. OOP is more than just class based. This kind of OOP is called prototype based OOP. Check the wiki: https://en.wikipedia.org/wiki/Prototype-based_programming and also check my post about OOP in Oberon. So yes, we could even do OOP with advanced records on Free Pascal  I wasn't asking about the definition of OOP. I asked 440bx where he draws the line. ---------------------------------------------------------------------- JiaXing · 2020-05-06 07:59 Quote from: munair on May 06, 2020, 09:50:01 amQuote from: JiaXing on May 06, 2020, 09:37:58 amQuote from: munair on May 06, 2020, 08:36:42 amDo you consider UDTs that allow procedures also a form of OOP? Yes, it is. OOP is more than just class based. This kind of OOP is called prototype based OOP. Check the wiki: https://en.wikipedia.org/wiki/Prototype-based_programming and also check my post about OOP in Oberon. So yes, we could even do OOP with advanced records on Free Pascal  I wasn't asking about the definition of OOP. I asked 440bx where he draws the line. I can't answer for 440bx. But from his previous answer to me I guess he doesn't consider this as OOP. The fact is I think our 440bx is using a kind of quasi-OOP. But this kind of OOP is definitely different to our OOP. So of course he could challenge us. ---------------------------------------------------------------------- JiaXing · 2020-05-06 08:13 There are many kinds of quasi-OOP. We could implement an Object System on plain C, too. Check this: http://libagar.org/mdoc.cgi?man=AG_Object.3 BTW, I think the quasi-OOP our 440bx using is not as complex as this one. ---------------------------------------------------------------------- serbod · 2020-05-06 09:24 Quote from: PascalDragon on May 06, 2020, 09:23:36 amThose are different. An interface variable is essentially the class instance pointer shifted by an offset and a VMT that provides the interface's methods that shift the Self pointer back again. Otherwise it's the same class instance on the heap. And a Variant is in fact a variant record with operator overloads that can take an interface variable. You can't assign a class instance to a Variant. OLE variants behave like class instances, they invoke methods with some name and parameters. And what prevents making in compiler "object(class)" variables behave like "interface" variable, but with automatic constructor / destructor? And allow usung operators (:=, +, in, etc..) if  "operator constructor" defined: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i constructor Create(AOther: TSameClass; AOperator: TOperator) That make possible easy and safe copy/assign/iterate objects of same type. Maybe, with some restriction - object(class) allowed only for classes with "sealed" keyword. That already implemented in C++14, and working fine. ---------------------------------------------------------------------- marcov · 2020-05-06 09:34 Quote from: serbod on May 06, 2020, 11:24:14 amAnd what prevents making in compiler "object(class)" variables behave like "interface" variable, but with automatic constructor / destructor? Reference count cycles. See Python. ---------------------------------------------------------------------- PascalDragon · 2020-05-06 10:29 Quote from: serbod on May 06, 2020, 11:24:14 amQuote from: PascalDragon on May 06, 2020, 09:23:36 amThose are different. An interface variable is essentially the class instance pointer shifted by an offset and a VMT that provides the interface's methods that shift the Self pointer back again. Otherwise it's the same class instance on the heap. And a Variant is in fact a variant record with operator overloads that can take an interface variable. You can't assign a class instance to a Variant. OLE variants behave like class instances, they invoke methods with some name and parameters. They don't behave like class instances. They have far more compiler magic. Any call you do on a OLE variant is converted to a call to IDispatch.Invoke. You can't even remotely compare them. Quote from: serbod on May 06, 2020, 11:24:14 amAnd what prevents making in compiler "object(class)" variables behave like "interface" variable, but with automatic constructor / destructor? Because objects are not interfaces. Object variables on the stack are more like records than classes or interfaces. And as marcov said you'd have the problem of reference cycles. Also it wouldn't make sense for the user that a object(TSomeClass) behaves differently from a object(TSomeObject). TP style objects are a legacy type. They will not be extended for something like this. Quote from: serbod on May 06, 2020, 11:24:14 amAnd allow usung operators (:=, +, in, etc..) if  "operator constructor" defined: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i constructor Create(AOther: TSameClass; AOperator: TOperator) That make possible easy and safe copy/assign/iterate objects of same type. Magic constructors isn't something that we're going to implement. Pascal is not C++ where Bla(const Bla& bla) happens to be a copy constructor. ---------------------------------------------------------------------- 440bx · 2020-05-06 11:19 Quote from: munair on May 06, 2020, 08:36:42 amWhere exactly do you draw the line? Do you consider UDTs that allow procedures also a form of OOP? It's hard to even say where I draw the line. I definitely draw a line at how polymorphism is used.  Inheritance is simply stated, Pandora's box, a way to accumulate problems and create more along the way (such as the need for, and overuse of, virtual methods, polymorphism all over again.) I don't think I've ever found something in inheritance that I considered positive. I am not against polymorphism.  It is an extremely powerful and convenient mechanism but, it must be used with _great care_ otherwise the program very quickly becomes a mess that makes spaghetti code look well organized.  OOP has many problems but the unfettered and, scattered all over the place, use of polymorphism may be the biggest one (not sure though, inheritance may be worse.) A program that uses any form of polymorphism should have it centralized, i.e, all in _one_ place, not scattered all over the program and, how it is used, should be made crystal clear.  OOP violates that as a matter of course. Combine polymorphism with the common use of cross-stack exception handlers used for error handling and that makes spaghetti code look like a crystalline structure.  Add a few layers of that as a result of inheritance and Pandora's box starts looking like a bottle of isopropyl alcohol. The other thing I consider a problem in OOP is encapsulation and, that one is a really tough one to realize the problems it creates.  Conceptually, it really seems like a great idea, bind the code to the data... what could possibly be wrong with that ?... in theory, it sounds great but, in practice, it creates problems because even though the data _values_ should be determined by a well defined set of procedures (methods in OOP), the _use_ of the data isn't necessarily confined to those procedures/methods.   Obviously, there are ways to handle the problems it creates but, the code becomes complicated and messy. Encapsulation is probably the thing about OOP that bothers me the most and, the reason is, I do believe it's a good idea and, because of that, I can't help thinking there's got to be way to make it work well but, I have not been able to find it.   All variations I've tried eventually cause unwanted problems.   In spite of that, sometimes I just can't help myself and will use an advanced record where I put procedures to initialize it.   I get my little syntactic sugar fix out of it but, I don't go beyond that because I've learned time and again that going past that will create nothing but headaches. The concepts OOP rests on are good but, the current implementations yield very poor results. Some worse than others but, ultimately, all undesirable. Quote from: PascalDragon on May 06, 2020, 09:23:36 amThe problem is the structure of the RTL which due to its cross platform nature has some parts that these mechanisms simply can't strip away, because they are at least touched in the RTLs initialization independent of whether the program uses them or not (thus they can not be considered "dead"). For example on Windows the thread manager is always initialized which means that all the functions the thread manager provides are linked in even if the user doesn't start a single separate thread. Same also for other concepts like the WideString and UnicodeString managers and such. Just curiosity, I understand that restructuring the RTL would, quite likely take a significant effort but, taking that out of consideration, would it be possible to restructure the RTL so that the various managers are not linked in the final executable unless they are used ? Quote from: JiaXing on May 06, 2020, 10:13:22 amBTW, I think the quasi-OOP our 440bx using is not as complex as this one. The day I code something that remotely resembles that stuff, I stop programming. I will consider that as a clear indication that I'm probably (and hopefully) better at doing something else. ---------------------------------------------------------------------- jamie · 2020-05-06 11:22 No magic constructors ! That's it. The world is ending! ---------------------------------------------------------------------- PascalDragon · 2020-05-06 11:50 Quote from: 440bx on May 06, 2020, 01:19:02 pmQuote from: PascalDragon on May 06, 2020, 09:23:36 amThe problem is the structure of the RTL which due to its cross platform nature has some parts that these mechanisms simply can't strip away, because they are at least touched in the RTLs initialization independent of whether the program uses them or not (thus they can not be considered "dead"). For example on Windows the thread manager is always initialized which means that all the functions the thread manager provides are linked in even if the user doesn't start a single separate thread. Same also for other concepts like the WideString and UnicodeString managers and such. Just curiosity, I understand that restructuring the RTL would, quite likely take a significant effort but, taking that out of consideration, would it be possible to restructure the RTL so that the various managers are not linked in the final executable unless they are used ? Ehm... "restructure the RTL so that the various managers are not linked" is the part of "restructuring the RTL" that would take a significant effort. ---------------------------------------------------------------------- Warfley · 2020-05-06 13:38 Quote from: 440bx on May 05, 2020, 09:23:16 pmThere is nothing unfair about it. There is an operating system that provides services.  I use the services, that's why they are there for, to be used.   Because _you_ choose bloat and someone else doesn't, doesn't make it unfair.Ok, you still don't get it, let me explain this a little bit slower. The windows api is a library provided by the windows OS. The libc is a library provided by (most) Unix systems. If you would build a unix program directly for windows, you need to provide the libc. If you would build a windows program for unix you would need to provide the winapi. So comparing a gcc program under windows which contains the libc to a program developed for windows is about as fair as a comparison as to compare a windows program + wine under linux to a program compiled using the GCC. This way I can also say: Look at your PE viewer, requireing multiple megabytes under linux. Both of these comparisons are not fair. You might now ask why I used g++ then, this is simply because I was under windows (which I only use for skype and some programs), and don't have many tools installed there, so cygwin g++ and fpc are the only compilers I have installed under windows. QuoteYou can pass the record as "constref", that will prevent most attempts to modify the record.Oh yes, the highly granular access regulation, either locking everything or nothing... QuoteThere is no difference there with OOP, _every_ field that is in the scope of the method can be trashed by the callee.  There is _nothing_ in OOP or any paradigm that prevents code that has write access to a field from messing it up. There is a big difference, in OOP you define access control on the object site, using constref you define access controll on the callers site. If I now as a function writer decide I want to change values, I simply change the function signature. In OOP you as the object owner can decide what should be editable and what not. Also there are a few more issues with that: 1. records are fix ordered, classes not. Even if I wanted to hack my way into the class data, the next compiler update could skrew the whole program. 2. You can only either lock everything or nothing, there is no way to enforce granular control QuoteAs far as all those guards you're talking about, if the callee only needs access to _some_ of the fields in the record then, only those fields should be passed by reference, not the entire record.Ok but how do you enforce that for example the values written to a record will have a certain range? I can use a property that throws an exception for that, or a function returning a boolean in OOP. In procedual programming you can provide the same mechanism, but you can't enforce the usage of them. QuoteI can do better and much simpler in procedural programming than all the scope _junk_ compilers have added to mitigate all the problems of object/classes fields which are nothing more than object/class global variables and, it is for that reason that all that scoping junk is necessary.    In well designed procedural code none of that stuff is needed, the structure of the program determines scope and visibility not a bunch of junky keywords added as a hack to alleviate a problem that shouldn't exist if the paradigm was worth anything. No you can't. If I have access to the record I can change it. Sure I can call a given function that does things but I can also directly change it. If I don't have access to the record I can not change it but also can't call a function that can. The way this is avoided in e.g. windows is to use handles, which are internal pointers the outside program can not use. But this way you are simply loosing all of the compilers typechecking mechanism, which means you won't get any warnings if you use wrong types. QuoteA highly deficient method that would be completely unnecessary in a well designed procedural program.You claim that, but feel free to prove it. Show me an example where you grant an outsider the possibility to access a record but only to 1 field and with a range check inplace, which can not be avoided without some hacks. QuoteI have no doubt pre and post conditions can be used in OOP but,  they are almost as common as seeing a unicorn in New York.Showing that you have no clue what you are talking about. In big OOP projects it's common to 1. model the system using e.g. UML (or a DSL in more specific areas), 2. extend your specification e.g. with OCL. 2.b. validating that the UML and OCL is contradiction free 3. create test cases from UML and OCL for the following implementation to be tested if the pre and postconditions (and invariants) will hold. Sure they are not directly implemented, but will be enforced by the OOP design. QuoteI understand doing it right is just too much work.  It's not about the work, it's about that with every procedure that can fail it massively increases the boilerplate code and makes the whole unreadable. QuoteWhen a programmer needs exceptions, it is often an indication of exceptionally bad code.  Of course, there are exceptions (pun intended) to that. No it's often a sign of *clean* code. Every bit of code that is more than is necessary to understand what is happening is cluttering the code. QuoteThat said, I routinely use the Windows API functions to validate readability and/or writeability of memory areas (most commonly parameters) and those APIs implement the exception handlers.  That keeps my code clean and working as it should _without_ exceptions.So before every memory access you need to write a check? That said if your program has the possibility of getting invalid memory addresses something else in your program is pretty broken QuoteWhat a terrible thing!  have to check results and pass them back to the proper handler in a predictable manner.  That's really terrible.And exceptions aren't predictable? Sure they need to be documented, which is actually quite a problem amongst Pascal, but e.g. in Java you need to explicitly say in every function which exceptions are allowed to be thrown. In pascal, if you document it correctly this is also really predictable. And this also needs to be done with procedual programming or would you say that the strtol example I posted is predicatble without documentation? QuoteFine!... do you keep 500 pounds of useless, unreachable junk in the trunk of your car ?... probably not.Are you playing fallacy bingo? because after the "Obvious" and the "It's bad because it's bad" argument now here is the wrong equivalency. Having more weight in your car increases the gas usage and therefore gives you continous costs. A larger program has a slower load time (which could be equivacted with the slower acceleration) and you have a maximum amount of memory available (the max load of a car). But once it is running there is no linear cost to larger executables. QuoteAnd you are still making the totally unproven assumption that all that junk is unreachable.  You have no proof of that, just wishful thinking.  OTH, if it's not there then, it is a _fact_ it is unreachable. No this is an argumentative strategy called counter example. You say: "bloated executables are bad because are a sign of bad code", to which my example is is: "if i take any executable and inject unreachable junk it will get bloated (in the most literal sense possible). The underlying code, nor the quality of that code has not changed". It's a cuonter to your unproven assumption that bloat is bad by providing an example where bloating an executable has no runtime implications at all. QuoteAnd I stand by that claim.  The more code there is in a program, the more likely the program is to have a bug, simply because there is more code.  Can a compiler produce and _infinite_ amount of bug free code ?... rather unlikely (to put it very kindly.)This is ignoring a very simple thing, transformations. Sure if it would be new code it would increase the probability of having bugs. But if these are transformations that are proven to not introduce new bugs (e.g. inlining, using jumping tables) or adding a lot of code that is known to be bug free (e.g. the stack canaries), you know all the stuff I was talking about up until now, it will add code without introducing any new errors. QuoteOptimization is necessary and, I am under the impression that optimization includes removing code that is not used.  Am I mistaken about that ?Sorry I simply missread what you where writing. QuoteNot true.  A smaller executable has less code, therefore there are fewer instructions that may be logically incorrect.Again the assumption that 1. the code is taken from some form of spread distribution and 2. that the bloat will be code. RTTI for example adds data not code. QuoteOk.  It's really easy, if something _can_ happen then it is only a matter of time before it happens.No, what you are talking about is a very simplified version of the law of large numbers which states that when sampling random variables from the same distribution, with the number of samples going to infinity the sampled distribution will take the shape of the real distribution. (Paraphrased). I've highlighted the key words, it needs to come from some distribution. Again you have my prior point about transormations that do not introduce new bugs, or the example of the stack canary which is basically so simple code that you can assume it to be error free, but is inserted into ever function call, massively increasing the executables size. Or RTTI, which only adds data and no code. These are all samples from a distribution which doesn't have any errors. Sampling from it will not result in more errors. And about unused code removal, let's take an example, printf. It can print Strings, Integers (in base 10 and 16) and Floats. A lot of code. Let's say your program only uses printf to print strings, then most of it's functionality is not needed, but deciding what paths a program might take is in general not decidable. I.e. you end up with a lot of "junk code" you never need, the optimizer can't remove. Thats one of the reason why C++ makes so heavy use of templates, because then only the used functionality will be created at compiletime and the unused functionality won't. Especially if you have very general functionality you will inevitably have unused code, e.g. you write a library that checks the current windows version because it needs a special treatment for windows 95. That library is then used in a program that will only run on windows 10, i.e. this code is unused, but can't be removed because this is something the optimizer simply can't know. QuoteWell... should I also prove that 0 + 0 = 0 ? That was one of the first maths lectures at university... So yes, if you want to make claims about maths you should at least be able to prove this (which is easy because this is true by definition of 0 as the neutral element of the addition). QuoteThe only one presenting a circular argument here is _you_ and you have offered nothing to validate your claim that executable size does not matter because you _choose_ to _believe_ the code is unreachable.  Your argument so far is based on unproven claims solidly resting on a completely unfounded assumption.  Other than that, it's a good argument.And again a point in the fallacy bingo, shifting the burden of poof. You are making the positive claim I make the negative claim (null hypothesis). The burden of prove is on you not me. You know there is a unicorn running around on the Kilimanjaro  every first sunday of october night. Is it now my job to prove it or your job to disprove it? And again the thing about unreachable code was a counterexample, as a matter of how to bloat executables without any negative effects. Because if you make a general claim (i.e. bloated executables are bad), only one counterexample is needed to disprove it. QuoteNo problem.  Most important and the crux of the fallacy you want to slide by: I am not assuming that code will _not_ be executed as you are doing.  My claim is: since the code is there, it can/may be executed and, since it is there, it can be the source of bugs.Still disregarding the fact that some of the "bloat" is simply data such as RTTI. QuoteAdditionally, if that code really isn't executed, don't you think it reflects on the quality of the tools that included it in there ?  If your answer is "no" then, you should have no problem with your neighbor putting 2000 pounds of junk he/she doesn't want anymore in the trunk of you car.Again a false equivalence? Aside the obvious same points from before, a compiler that I chose because of the benefits it has, as a tradeoff for the extra stuff is more comparable with a mechanic that adds a new feature to my car but in exchange it gets heavier. Maybe it does get heavier than would strictly needed, but better than having none of these features at all. QuoteI believe (maybe wrongly) you'd consider that a problem but, if the compiler puts a bunch of useless junk code in your executable, that's not a problem... since "obvious" is a word you don't like, I'll say, I "suspect" there may be a contradiction in the proper evaluation of the events on your part.It's a tradeoff. For example I'm not using movuscator for obvious reasons. It bloats the executables completely without any advantage to me. But for example RTTI allows for runtime level (de)serialisation, which can massively reduce the amount of boilerplate code that does not add anything to the understanding of what the program is doing, and is therefore a few bytes worth QuoteAll that said, if you think it's perfectly ok for your neighbor to load your car's trunk with a bunch of junk he/she doesn't need anymore then, in that case, that would weaken my argument.You really like false equivalences... QuoteWhether it's decidable or not depends on how the program is written.  What seems a bit strange is that "unreachability" seems to have grown significantly in the past few years.  It must be a coincidence that its growth seems to be greater (temporarily presuming your unreachability assumption is valid) in OOP code than in procedural code.  Pure coincidence, of course.Again you are making the assumption that this has something to do with OOP vs procedual programming. Then tell my why the size of GCC executables also increased over the years, even for non OOP languages like C or Fortran? Unreachability is only computable in very simple programs, so the more complicated the code becomes the harder reachability analysis will become. The GCC supports ~100 platforms. Around 10 years or so ago this was around 20. The code got much more complex. That said, why are you so fixated on unreachable code, I've mentioned a lot of things that increase executable size: 1. optimization 2. data (RTTI) 3. unreachable code Over the past years 1. optimization has gotten way better (and doesn't focus on size but on runtime), 2. more data is added such as RTTI, 3. code has gotten more complex. For C you could use the Tiny-C-Compiler, which produces much smaller executables than the gcc. That said it is widely known in the C world that the tcc produces much worse (performancewise) assembly than the gcc and supports way less plattforms. It's not that the gcc is bad because it creates larger executables, its that it creates large executables because it is so good. QuoteWhat a wonderful solution.  Now there are three (3) programs to recompile, manage, install, distribute, support, etc instead of just one (1).  I can see that's a significantly better solution if the goal is to minimize unemployment.1. Compiling and and distribution is fully automated using CI/CD, if you don't use the tools available not my problem. 2. Installing is done via an installation script i.e. there is no difference if it installs 1 file or 20. 3. management and support are exactly the same, because the functionality and code is still the same, only the way it is built differs. If you split up a pie into two halves, it still is only one pie. As you said your executable containst two programs, so you have to manage and support two programs. That they are inside one exec doesn't change the fact it's two programs QuoteFor that reason, it makes no sense to compile applications into the operating system.But the resulting executable will be much smaller *and* faster than having to dynamically link. QuoteI won't say it's obvious, I know you don't like that word but, I'll say that it _might_ be common sense. I'm a theoretical computer science nerd. If you can't prove it, it doesn't matter if you say obvious or common sense, at least some form of evidence is for me required. That said I can exactly tell you why it's a bad idea. 1. you need to update your whole system for updating one application. 2. changes in one application can break the whole system. 3. managing that buildsystem and project would be absolutely hideos... You know the same arugments I've said about your software QuoteI never claimed otherwise. I claimed and still claim, that _anything_ OOP can do can be done better with pure procedural programming.    Very important: note that I am _not_ claiming it can be done faster, it often cannot.   That last part, just to make things clear.Depends on what you say is "better". Because for many people faster is better. If you have a deadline this might be your way of being better. Tooling support for OOP is better, and extendibility is better for OOP (say about inheritance what you want, to make a program extendible it is absolutely great). Even if OOP bloats your program (which it doesn't, case in point C++ vs C using the same compiler), it still might not be any reason for it being worse. On the other hand, if you are programming for AVRs then executable size does defenetly matter (but even then I use C++ because it doesn't bloat the executable and I have all the OOP features) Quoteand you talk about useless programs... that "hello" program is so useful, someone should send it to Washington, it might solve the national debt problem (or if it can do that, to Greece.)Again, counter example. Your claim: "OOP bloats the executable". A general claim, to dispove only one (*any*) counter example is needed. I've provided one. QuoteLet's be clear, AFAIC, you can use whatever you want.Yes, but if we want to have a comparison, we should at least use the same toolset right? Using a library like the LCL and then compare filesize is like comparing a mercedes S-class to an Opel corsa on weight and then saying that therefore the Opel corsa is better. If you have more features (like the LCL has) you will have larger executables. Simple as that. QuoteA PE viewer is little more than "hello world" about a 100 times.  Format field, output field.  The PE specification is reasonably well documented and the program I have offers a crystal clear specification of what the program should do. You'd end up with something useful instead of a very limited calculator. (instead of other item to send to Greece to help ease the national debt problem.)The S Expression parser might not be usefull by it's own, but if the code is good it can be reused, and having a great S-Expression parser is always usefull. That said, I use windows in a pretty limited fashion, meaning a PE viewer will be of no use to me. ---------------------------------------------------------------------- munair · 2020-05-06 13:53 Quote from: Warfley on May 06, 2020, 03:38:22 pmYou might now ask why I used g++ then, this is simply because I was under windows (which I only use for skype and some programs), and don't have many tools installed there, so cygwin g++ and fpc are the only compilers I have installed under windows. If you provided that information with your example, it would've saved quite a bit of discussion, because the sizes you reported were way out of proportion. ---------------------------------------------------------------------- marcov · 2020-05-06 15:09 Quote from: 440bx on May 06, 2020, 01:19:02 pmJust curiosity, I understand that restructuring the RTL would, quite likely take a significant effort but, taking that out of consideration, would it be possible to restructure the RTL so that the various managers are not linked in the final executable unless they are used ? (Pascaldragon, correct me if I'm wrong) It is not just library rearrangements. Some things need to be in system for e.g. Delphi compatibility. Some of it will be linker related, and there you get into murky per platform problems, specially on *nix, where the linker is not controlled by us. On Windows it is better (and way better than e.g. GCC that doesn't even support dead code elimination on Windows afaik? ) E.g. making the relevant parts and initializers in some way weak linked, if some other unit doesn't use functionality that uses it, so that it will be smartlinked out. Putting roots of RTTI in certain sections that can be easily discarded on linker level etc. But all this requires a person that keeps up on this on a regular basis, follows GNU LD lists, prepares support (or at least a clear description of what needs to be done), and first and for all, somebody with a long term view. Just randomly starting to cut functionality is a nono, features must be maintained, source must remain compatible. ---------------------------------------------------------------------- 440bx · 2020-05-06 19:36 Quote from: Warfley on May 06, 2020, 03:38:22 pmOk, you still don't get it, let me explain this a little bit slower. The windows api is a library provided by the windows OS. The libc is a library provided by (most) Unix systems. If you would build a unix program directly for windows, you need to provide the libc. If you would build a windows program for unix you would need to provide the winapi. So comparing a gcc program under windows which contains the libc to a program developed for windows is about as fair as a comparison as to compare a windows program + wine under linux to a program compiled using the GCC. This way I can also say: Look at your PE viewer, requireing multiple megabytes under linux. Both of these comparisons are not fair.I'm going to explain slower too... approximating the speed of continental drift... the choices _you_ make and their consequences are _not_ my problem.  Obviously, you can use g++ on Windows, if you don't like the results it produces then it is up to _you_ to make some changes in the choices of development tools you've made.  It is _not_ up to me to lower the quality of my code to compensate for the choices you've made. Most of the Windows API functions I use are O/S services that any halfway decent O/S provides.  That said, if I need to get the text representation of an integer, NTDLL provides _itoa (among a gazillion functions.)  OTH, I don't like writeln, I don't like printf and I don't like any of their derivatives either, because of that, I have my own functions to do basic output.  They are way faster than the library stuff, C or other and, the main reason I implemented them is because it allows the compiler to do type checking on what I'm passing to them.  My own implementation also provides some capabilities that would either, not be available using printf/writeln or be clumsy and cumbersome to implement using them.  The price I pay for that convenience: I had to write the code (my time) and the code takes space in the executable, additionally, my functions aren't as syntactically sweet as writeln (printf, being very close to decomposed organic matter, is not sweet) they require more work on my part but, IMO, the advantages are worth the additional work. The point of the above is this: you don't like how much space libc occupies then, write your own functions otherwise live with the bloat.  Your choice to make, not mine.  As far as the rest of your post... _you_ claimed, not me, _you_ did, that OOP adds no overhead to an executable.  Your claim: your burden of proof, not mine.   If Linux, g++ or whatever else your using ends up adding a pile of junk into your executables: that's you're problem, not mine.  Consider using Windows to make your point, that way, your can eliminate the problem. I've claimed this time and again: I can do with procedural programming _anything_ OOP can do, _better_ than OOP.  That includes size _and_ speed, _both_.   The reason for that is simple, in procedural programming, the programmer, in this case me, retains complete control, which means more work, something that an ever increasing number of programmers seem to have become allergic to. That control is used to determine what code, among other things, is generated (unfortunately, there are compiler deficiencies that either cannot be controlled or would require undesirable coding to work around them but, I deal with those too.) Once a programmer goes OOP, a lot of the control a programmer could have goes out the window because, it is now up to the compiler to make choices that are simply _not_ its place to make and, as expected, they usually leave something - if not a lot - to be desired. I find your claims about how much access control there is on class fields to be dubious but, I'll let that slide because, I have no desire to examine how C++ implements classes internally. As far as properties throwing an exception, I don't need exceptions.  I can write a program that is correct without them. As far as enforcing some range, that's what pre-conditions are for. As far as run-time type checking, it is a very rare occurrence that I need it.  If I need it, I can tag the subset of data that requires it with type information. Quote from: Warfley on May 06, 2020, 03:38:22 pmIn big OOP projects ... etc ... I get the impression that any OOP project ends up being big.  (at least as far as the executables are concerned.) As far as OOP enforcing anything by a design... procedural code is designed too and... the interfaces to every function that is used by multiple programs should be defined beforehand... therefore the compiler can do just as much enforcement as when using OOP. Quote from: Warfley on May 06, 2020, 03:38:22 pmNo it's often a sign of *clean* code. Clean code is code that doesn't need to rely on exceptions to work correctly. Quote from: Warfley on May 06, 2020, 03:38:22 pmThat said if your program has the possibility of getting invalid memory addresses something else in your program is pretty brokenI'm pleased you mention that because a common occurrence associated with OOP around here is accessing a class which hasn't been "created" yet or accessing it after it's been freed.  On that one, I agree with you, "something" is broken there.  Related to that point, there is another thing I do agree with you, classes should be on the stack by default and reside on the heap _only_ if the programmer uses an explicit mechanism for it to be allocated on the heap. Quote from: Warfley on May 06, 2020, 03:38:22 pmAnd exceptions aren't predictable? No, they aren't because exception handlers get to choose what they will and will not handle, that's one problem, that combined with the fact that nothing prevents an OOP programmer to add another exception handler somewhere that ends up trapping an exception it doesn't have a clue how to handle or will handle incorrectly is a problem inherent in the OOP exception handling mechanism.  Exceptions should _never_ be allowed to be cross stack frame, the fact that they can be is a design atrocity.   Exception handlers are the most efficient mechanism ever conceived to create spaghetti code at run time. Bloated executables are bad simply because they contain more code that may be buggy.  I know you don't like the word obvious but, that is obvious and, you're desperately trying to claim the implication does not exist.  You're trying to claim that rain (on earth) doesn't imply water.  Your inlining claim doesn't pass muster.  If the function/procedure/method has a bug, the bug will be replicated as many times as the function is inlined.  Not only you get more code but you also get more bugs.  You can't excuse bloat with function inlining. Quote from: Warfley on May 06, 2020, 03:38:22 pmRTTI for example adds data not code. Still disregarding the fact that some of the "bloat" is simply data such as RTTI. Wonderful... not only does OOP fill the executable with deficient code, it also adds data.  A bloat sandwich.  Would you like mustard and mayo on your RTTI sandwich ? Quote from: Warfley on May 06, 2020, 03:38:22 pmAnd about unused code removal, let's take an example, printf. It can print Strings, Integers (in base 10 and 16) and Floats. A lot of code. Let's say your program only uses printf to print strings, then most of it's functionality is not needed, but deciding what paths a program might take is in general not decidable.Sounds like the people who designed OOP took out a page of the printf book. Quote from: Warfley on May 06, 2020, 03:38:22 pma compiler that I chose because of the benefits it has, as a tradeoff for the extra stuff is more comparable with a mechanic that adds a new feature to my car but in exchange it gets heavier. Maybe it does get heavier than would strictly needed, but better than having none of these features at all. Sounds like a car with an Olympic swimming pool.  I can see the advantages... good choice!  Yes, definitely a little heavier than strictly needed. Quote from: Warfley on May 06, 2020, 03:38:22 pmAgain you are making the assumption that this has something to do with OOP vs procedual programming. It has plenty to do with OOP because polymorphism and inheritance are wonderful mechanisms to shatter decidability.  Granted, polymorphism can also be used in procedural programming but, unlike in OOP, it is somewhat rare. Quote from: Warfley on May 06, 2020, 03:38:22 pm why are you so fixated on unreachable code, because you made the _invalid_ claim that bloat was unreachable code.  That's why. Quote from: Warfley on May 06, 2020, 03:38:22 pmsay about inheritance what you want, to make a program extendible it is absolutely great.It's a wonderful bloat mechanism.  You're right... very extensible... apparently, no limit. Quote from: Warfley on May 06, 2020, 03:38:22 pmYour claim: "OOP bloats the executable". A general claim, to dispove only one (*any*) counter example is needed. Just about any program is a counter example.  I can post a program that has a listbox and the OOP version will be several times larger and, that will probably always be true.  You're trying to deny reality. Quote from: Warfley on May 06, 2020, 03:38:22 pm That said, I use windows in a pretty limited fashion, meaning a PE viewer will be of no use to me. Fair enough.  I'll try to think of something that is useful to both of us. Bottom line is this: create the program however you like, I do the same.  We compare results.  No complaining about compiler libraries, what the O/S does or does not provide. You make choices, I make mine, we compare results. Simple. ---------------------------------------------------------------------- Warfley · 2020-05-06 21:17 Quote from: 440bx on May 06, 2020, 09:36:04 pmThe point of the above is this: you don't like how much space libc occupies then, write your own functions otherwise live with the bloat.  Your choice to make, not mine.Yes but I wasn't making the claim that the output of g++ was small, everyone else (including you) claimed it was way to big. My claim was that OOP does not add any bloat, which the example showed. QuoteAs far as the rest of your post... _you_ claimed, not me, _you_ did, that OOP adds no overhead to an executable.  Your claim: your burden of proof, not mine.   If Linux, g++ or whatever else your using ends up adding a pile of junk into your executables: that's you're problem, not mine.  Consider using Windows to make your point, that way, your can eliminate the problem.Yes and I proved this. I've proven that in general OOP does not add overhead. To disprove a generall assumption (forall quantifier) you only need to have one counterexample (not forall holds ... <=> exists such that not ...). Also since when is that something is happening the null hypothesis? Do we test medicine like that: This will cure cancer and it's your job to prove that it doesn't. Of course not. You are making the general claim that it will add bloat so it's your burdon of prove. I've made the specific claim that in general it will not add overhead which can simply be proven by an example. QuoteI've claimed this time and again: I can do with procedural programming _anything_ OOP can do, _better_ than OOP.  That includes size _and_ speed, _both_.Again a general claim disproven by my example from before... Thank you QuoteThe reason for that is simple, in procedural programming, the programmer, in this case me, retains complete control, which means more work, something that an ever increasing number of programmers seem to have become allergic to. That control is used to determine what code, among other things, is generated (unfortunately, there are compiler deficiencies that either cannot be controlled or would require undesirable coding to work around them but, I deal with those too.) Once a programmer goes OOP, a lot of the control a programmer could have goes out the window because, it is now up to the compiler to make choices that are simply _not_ its place to make and, as expected, they usually leave something - if not a lot - to be desired.At it's core OOP is nothing more than syntactic sugar. Take the following code: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i struct User {  string name;  int age;}; void printUser(User const &user) {  ...}And this OOP code: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i struct User {  string name;  int age;  void print() const {    ...  }}; Feel free to argue how you are loosing control by this and how the first code will be less efficient in any way. You are right that in OOP many people don't try to build the optimal executable, but there are also performance programming guidelines for OOP to build maximum performance OOP programs. But you are not arguing against the average OOP user, but against OOP in general, and as already stated, there are guidelines and techniques available to write highly efficient OOP code. QuoteI find your claims about how much access control there is on class fields to be dubious but, I'll let that slide because, I have no desire to examine how C++ implements classes internally.Thats simple, in C++ is the internal structure of classes undefined. In fact every major C++ compiler has a different implementation making these classes incompatible. If you don't have access to a class, you can not reliably (e.g. that it will work with the next compiler version) access any of the data. QuoteAs far as properties throwing an exception, I don't need exceptions.  I can write a program that is correct without them. As far as enforcing some range, that's what pre-conditions are for.Yes I can also, doesn't matter that the code is better. Let's say you are implementing a webprotocol (which I say because I did so recently), then during the handshake you have to do several pretty specific reads (i.e. read first 4 bytes, then depending on what they are read the next few and so on). So during one procedure you have like 5-10 write procedures. As soon as any of them fails you have to completely abort the process. Procedually this will have this 5-10 times: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if ReadBuff(buff, size) <> size and checkError then begin  // Error handling  Exit(False);end;With exceptions you have this once: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i try  ReadBuff(buff, size);  ... (5-10 x)  ReadBuff(buff, size);except  On E: ESocketException do begin    // error handling    Exit(false);  end;end; Saving 5-10 times the error handling code (at least 15 lines of code), which btw is completely pointless for understanding how the protocol works. QuoteAs far as run-time type checking, it is a very rare occurrence that I need it.  If I need it, I can tag the subset of data that requires it with type information.Yes, and in for example sone C++ compilers does also only add RTTI for classes where RTTI is checked against. The difference is, they do it automatically, not cluttering the code. QuoteAs far as OOP enforcing anything by a design... procedural code is designed too and... the interfaces to every function that is used by multiple programs should be defined beforehand... therefore the compiler can do just as much enforcement as when using OOP.I'm not claiming that you can't design procedual programming, this was just an example of how pre and postconditions are enforced in large OOP projects nowadays. QuoteClean code is code that doesn't need to rely on exceptions to work correctly.No clean code is code that is easiely readable. As stated above, if you have 3 times the code size only to catch the same error at 10 different points in your code, this means that ony 1/3 of the code is actually required to understand what it is doing. Therefore by definition not clean. QuoteNo, they aren't because exception handlers get to choose what they will and will not handle, that's one problem, that combined with the fact that nothing prevents an OOP programmer to add another exception handler somewhere that ends up trapping an exception it doesn't have a clue how to handle or will handle incorrectly is a problem inherent in the OOP exception handling mechanism.  Exceptions should _never_ be allowed to be cross stack frame, the fact that they can be is a design atrocity.   Exception handlers are the most efficient mechanism ever conceived to create spaghetti code at run time. Then the programmer is doing it wrong. If there is a type of exception that can occur that your function doesn't handle, its your job to put it into the documentation. If you now add this to your function to be handled, it's your job to update the documentation. In Java for example this is easy. If a function can throw an exception that is not added to the function header, the program will simply not compile. You need to anotate any exception the function can possibly throw. Whats more predictable than having a list with things that can happen and a compiler enforcing you to handle ever one of them? QuoteBloated executables are bad simply because they contain more code that may be buggy.  I know you don't like the word obvious but, that is obvious and, you're desperately trying to claim the implication does not exist.  You're trying to claim that rain (on earth) doesn't imply water.Would you stop making general statements you can't prove? It starts to annoy me. There are two assumptions here: 1. they contain more code 2. that code introduces bugs that wouldn't be there otherwise. As I stated numerous times there can exist bloat without any of these assumptions to be true. QuoteIf the function/procedure/method has a bug, the bug will be replicated as many times as the function is inlined.  Not only you get more code but you also get more bugs.  You can't excuse bloat with function inlining.Grasping at straws I see. Even if we agree that a bug is a fault and not a failure (i.e. the existance of an error not the arising of an error), your ultimate argument is that it is therefore bad. If the amount of faults rise while the amount of failures stays the same (because the faulty code would be executed no matter what), why is this bad? I agree with you that failures are bad. But the simple fact that the amount of faults is technically higher with constant amount of failures, does not get you any step further to showing your point. You are just doing a semantical detour. QuoteSounds like a car with an Olympic swimming pool.  I can see the advantages... good choice!  Yes, definitely a little heavier than strictly needed.You really love your logical fallacies do you? But let's roll with it. Let's say there are no downsides to having a swimming pool in your car, other than some speed loss (so basically saying it would be physically possible). And let's say I'm an olympic swimmer who needs to train as much as possible, and I need to do a long roadtrip. Then I would have this. QuoteIt has plenty to do with OOP because polymorphism and inheritance are wonderful mechanisms to shatter decidability.  Granted, polymorphism can also be used in procedural programming but, unlike in OOP, it is somewhat rare.Haven't you read a singe one of my previous posts? In a lot of C++ programs for example polymorphism is quite rare. Quotebecause you made the _invalid_ claim that bloat was unreachable code.  That's why.Still not understanding what a counterexample is. QuoteJust about any program is a counter example.  I can post a program that has a listbox and the OOP version will be several times larger and, that will probably always be true.  You're trying to deny reality.Another point on the fallacy bingo: Black swan fallacy. The thing is the following: you can't prove a general claim by example, but you can disprove a general claim by example. You say all swans are white, so you go and point to a swan and say: "Look hes white". You do so with 20 more swans. You haven't proven anything. On the other hand, if I only find a single swan that is black, I've disproven you. It's even worse, because I can give you a formula how to convert any C program into a C++ program without adding *any* overhead. Simple as that: take any record on which functions act. Turn that record into a class and put all the functions into the class as methods (basically the thing I did above). If you compile using the same compiler, (rtti disabled, because you don't need it for this), it will be compiled to the same assembly as before, but now you are using OOP. So I've not only given you one counterexample but an infinite class of counterexamples. QuoteBottom line is this: create the program however you like, I do the same.  We compare results.  No complaining about compiler libraries, what the O/S does or does not provide. You make choices, I make mine, we compare results. Simple.Benchmarking anything does not make sense if different tools are used. Lets say you write your procedual program using the FPC for windows and I write an OOP program using G++ for linux this tells absolutely nothing about OOP vs procedual, in fact the result will be influenced by a shit tone of things like target platform, executable format, compiler, and of course code style. If you want to have anything comparable, it must run on the same pc, using the same compiler with the exact same options, and using the same libraries. Anything else is pointless and will only be a waste of time. ---------------------------------------------------------------------- Warfley · 2020-05-06 21:37 Quote from: Warfley on May 06, 2020, 11:17:10 pm[...]Also that all said, OOP is incredibly diverse. From the performance oriented implementation in C++ or Rust, the all is virtual implementation of Java or C#, to the Runtime Dictionary approach of Javascript and Python. In C++ you have multiple inheritance in Java heavy usage of interfaces. In Go you don't even have classes and it is still considered OOP through it's interfaces. In Ocaml combines functional programming with OOP, in swift there is not even a concept of pointers only references. And that are just the languages I personally have come in contact with. I don't know what else is out there. Every claim about OOP will inevitably be proven wrong for some implementations out there. @440bx This will be my last post about this whole matter because this starts grinding my nerves. In the end I will just say that. If you feel like making any claim about OOP, first think about every single language I've listed above and if you don't know enough to also provide evidence for that in that language, don't make that claim. From your post I already know that you are not familiar with C++. If you don't even know how one of the most widely used OOP languages handles it's version of OOP, it's obvious that you don't even know the scope of how differently OOP can be implemented *and* used. ---------------------------------------------------------------------- 440bx · 2020-05-06 23:00 @Warfley, The only thing you've proved is that you can make a lot of excuses. It's libc, it's Linux, it's g++, it mingw, it's cygwin, I don't do Windows API, etc, etc Here is version of your "hello" program:Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  5/06/2020  17:58           7,168  hello.exeIt's 32bit, no API and it includes the compiler library and, I can produce another 32bit version using FPC that cuts it down to 3584 bytes.  OOP that!. When you can beat that using OOP then maybe you'll have a point worth considering. ---------------------------------------------------------------------- Martin_fr · 2020-05-06 23:55 Using FPC + OOP, I got  2312 bytes . . . . . . Or at least I make that claim... Prove me wrong. This is not about 440bx's OOP claims this time. It's about 440bx's general discussion techniques. Besides you (the 2 of you) are not comparing programming paradigms (oop <> procedural). You are comparing compilers, as they are available today. No single compiler/compilation result is meaningful. Comparing a statistical significant sample of compilers, with a statistical significant amount of different test code (not biased), would give somewhat of an indication. Good look, by even defining the boundaries for such a test.... ---------------------------------------------------------------------- 440bx · 2020-05-07 00:38 Quote from: Martin_fr on May 07, 2020, 01:55:50 amUsing FPC + OOP, I got  2312 bytes Or at least I make that claim... Prove me wrong. That is funny.  Thank you for the laugh.  Prove your claim, post the code and how you got it to be that size. Here is the support for my claim, which is fact. I claimed 3584 bytes.  The source code is found in this thread: https://forum.lazarus .freepascal.org/index.php/topic,41722.msg290587.html#msg290587 along with how to get it to that size using FPC v3.0.4 Quote from: Martin_fr on May 07, 2020, 01:55:50 amBesides you (the 2 of you) are not comparing programming paradigms (oop <> procedural). That's true.  There isn't much to compare.  There is a 300K+ "hello" program and a long list of why bloat isn't bloat and bloated executables are good. Quote from: Martin_fr on May 07, 2020, 01:55:50 amYou are comparing compilers, as they are available today. No single compiler/compilation result is meaningful. Comparing a statistical significant sample of compilers, with a statistical significant amount of different test code (not biased), would give somewhat of an indication.That is true but, anyone discussing this topic in good faith _knows_ that OOP code has a tendency to generate larger executables and there are many reasons for that, including but not limited to, RTTI, VMTs, inheritance and polymorphism among others. That "including but not limited to" is just too much fun to not use. ---------------------------------------------------------------------- Martin_fr · 2020-05-07 02:11 Quote from: 440bx on May 07, 2020, 02:38:53 amQuote from: Martin_fr on May 07, 2020, 01:55:50 amThat's true. Quote from: Martin_fr on May 07, 2020, 01:55:50 amThat is true Agreement, and on 2 points.... I am speechless... Quote from: 440bx on May 07, 2020, 02:38:53 amThat is funny.  Thank you for the laugh.  Prove your claim, post the code and how you got it to be that size. For this, I never indented to prove the numbers. Just "proving" the need for prove, which you so eloquently put in words. (Well yes, and have a bit of fun) Quoteanyone discussing this topic in good faith _knows_ that OOP code has a tendency to generate larger executables and there are many reasons for that, including but not limited to, RTTI, VMTs, inheritance and polymorphism among others. Well.... 1) RTTI is not OOP.  You have managed types, and they produce RTTI. But of course since RTTI is information and in the exe, any RTTI applied to OOP adds to the exe. But again not OOP.  Try to be a bit more precise. There is enough to be discussed, without stretching the borders. (Even if you see some connection, and could explain it, that does not mean that other will see it, or agree to your explanation) 2) VMT and the class info itself, yes that is extra bytes. More below 3) Bloat not equal to extra size. IMHO Bloat is only such extra size, that does not have value of any kind. "size" not the only factor for judgement.   That is why we use compilers, and do not write highly optimize asm our self. "man hours" are an important factor too. And that gets back to "no one shoe fits all". Some tasks may be faster written in procedural. Others in OOP (oh, yes indeed). About the size of a VMT: If you restrict virtual methods to what is needed. (And a good compiler can get rid of some unused virtual methods => wpo in fpc) Then they are a jumptable. Assuming you use them, because the problem at hand requires this, then in procedural you would have a big "case somevar of ..." jumptable. Only you do save the asm code for the "case of".  So there the OOP could even save a bit. But I do agree, virtual methods may be used for convenience. But if that is so, then it should get some man hours saved. Which has value too. Every gain comes with a trade off. While I know it is not a serious challenge, I would still like to know how much one could save going procedural on something like "fpdebug" - size/speed (if any) with disregard to other factors - complete, include man hours and all. ---------------------------------------------------------------------- 440bx · 2020-05-07 03:09 Quote from: Martin_fr on May 07, 2020, 04:11:42 amAgreement, and on 2 points.... I am speechless... It's a historical moment... those tend to leave people speechless Quote from: Martin_fr on May 07, 2020, 04:11:42 amFor this, I never indented to prove the numbers. I knew it was in jest, that's why I got a chuckle out of it. Quote from: Martin_fr on May 07, 2020, 04:11:42 am1) RTTI is not OOP.  You have managed types, and they produce RTTI. But of course since RTTI is information and in the exe, any RTTI applied to OOP adds to the exe. But again not OOP.  Try to be a bit more precise.You have a technically accurate point but, not very accurate in reality.  RTTI may not be OOP but, while it is very rarely needed in procedural programming, it is commonly needed to support features common in OOP.   Because of that, I still put RTTI as one of the reasons for OOP causing executables to be larger than those obtained from procedural programming. Quote from: Martin_fr on May 07, 2020, 04:11:42 amThat is why we use compilers, and do not write highly optimize asm our self. "man hours" are an important factor too. And that gets back to "no one shoe fits all". Some tasks may be faster written in procedural. Others in OOP (oh, yes indeed). I believe I have an unusual viewpoint about compilers.  IMO, a true, industrial-strength and quality compiler should generate code that is both smaller and faster than hand coded assembler by an expert assembly language programmer.   I am fully aware that is placing the bar quite high but, a compiler can and, in time, should be a container of the knowledge of multiple programming experts in multiple areas.  IOW, a compiler _should be_ in a way an expert system that can surpass the knowledge and abilities of the great majority of experts taken individually.  OTH, for a compiler to achieve that, its grammar descriptive abilities must be very precise, otherwise, the compiler has to "play it safe" which means producing code that isn't optimized for the case at hand. Quote from: Martin_fr on May 07, 2020, 04:11:42 amEvery gain comes with a trade off. That is true and, one claim I would never make is that procedural programming will lead to less work for the programmer.  OOP makes it very easy for the programmer to be more productive _initially_.  OTH, in the long run, I believe procedural slowly but surely ends up being the more productive way.  Quote from: Martin_fr on May 07, 2020, 04:11:42 amI would still like to know how much one could save going procedural on something like "fpdebug" I concur, it would be interesting to find out.  Quote from: Martin_fr on May 07, 2020, 04:11:42 am- complete, include man hours and all. It would probably take about a fourth of the time with OOP than with procedural programming but, I honestly believe that the procedural approach would result in a better product.  Better in the sense of being easier to debug, easier to maintain, be more compact (use less code) and, be more responsive. I doubt we'll find out because I have no desire to re-implement fpdebug but, in good conscience and honestly, there is no doubt in my mind that the result using procedural programming would be better. ---------------------------------------------------------------------- Thaddy · 2020-05-07 05:20 Well, why do many people not make use of WPO? In fact, that goes a long way in translating OOP into actual procedural code, since it tries to de-virtualize. https://wiki.freepascal.org/Whole_Program_Optimization. Sometimes - but not always - this leads to spectacular improvements in the generated binaries, both in code size as in speed. The compiler itself is a prime example. So you can actually write OOP code without a penalty and this has been available for years. Try it. Caveat: limit your use of published. Public is OK. ---------------------------------------------------------------------- munair · 2020-05-07 07:03 Quote from: 440bx on May 07, 2020, 02:38:53 amHere is the support for my claim, which is fact. I claimed 3584 bytes.  The source code is found in this thread: https://forum.lazarus.freepascal.org/index.php/t opic,41722.msg290587.html#msg290587 along with how to get it to that size using FPC v3.0.4 Producing standalone executables is not efficient from a OS point of view when run-time stuff is included that could otherwise remain separated. It is the best way to avoid code duplication on a massive scale. ---------------------------------------------------------------------- munair · 2020-05-07 07:15 Quote from: 440bx on May 07, 2020, 01:00:19 amWhen you can beat that using OOP then maybe you'll have a point worth considering. That very much depends on a compiler's capabilities. If, as Warfley indicated, a compiler like C++ cuts away all references through optimization leaving exactly the same result as a program that was coded without OOP, then these "hello world" examples are pointless. What makes sense is to compare code against more advanced OOP implementations such as virtual stuff that does have an impact on code size. ---------------------------------------------------------------------- PascalDragon · 2020-05-07 07:33 Quote from: marcov on May 06, 2020, 05:09:28 pmQuote from: 440bx on May 06, 2020, 01:19:02 pmJust curiosity, I understand that restructuring the RTL would, quite likely take a significant effort but, taking that out of consideration, would it be possible to restructure the RTL so that the various managers are not linked in the final executable unless they are used ? (Pascaldragon, correct me if I'm wrong) It is not just library rearrangements. Some things need to be in system for e.g. Delphi compatibility. Some of it will be linker related, and there you get into murky per platform problems, specially on *nix, where the linker is not controlled by us. On Windows it is better (and way better than e.g. GCC that doesn't even support dead code elimination on Windows afaik? ) E.g. making the relevant parts and initializers in some way weak linked, if some other unit doesn't use functionality that uses it, so that it will be smartlinked out. Putting roots of RTTI in certain sections that can be easily discarded on linker level etc. But all this requires a person that keeps up on this on a regular basis, follows GNU LD lists, prepares support (or at least a clear description of what needs to be done), and first and for all, somebody with a long term view. Just randomly starting to cut functionality is a nono, features must be maintained, source must remain compatible. You got it essentially right ---------------------------------------------------------------------- 440bx · 2020-05-07 08:21 Quote from: munair on May 07, 2020, 09:03:26 amProducing standalone executables is not efficient from a OS point of view A standalone application you can carry with you on a flash drive and use it anywhere, AFAIC, that's very efficient not to mention very convenient too.   I don't program for the O/S, I program for human beings, including me. Quote from: munair on May 07, 2020, 09:03:26 am when run-time stuff is included that could otherwise remain separated. It is the best way to avoid code duplication on a massive scale. I'm not advocating code duplication, on the contrary but, I also don't want my applications to have undesirable dependencies such as msvcrtxxx.dll.  That makes the program non-portable and in addition to that, a run-time installation program needs to be run on any machine that doesn't have it already installed and, installing software on a machine which isn't your own isn't something that is always allowed. Quote from: munair on May 07, 2020, 09:15:52 amThat very much depends on a compiler's capabilities. To some extent, yes but, also to a large extent, no.  The reason is simple, when using OOP, because of inheritance and polymorphism there is a lot of coupling and dependencies among objects/classes' methods, much much more so than in a well written procedural program.  That is characteristic and endemic of OOP.  There is no compiler that can do anything about that.  Quote from: munair on May 07, 2020, 09:15:52 ama compiler like C++ cuts away all references through optimization leaving exactly the same result as a program that was coded without OOP, Even if the compiler could do such optimizations, the result would still be larger than the same procedural program, as long as it is well-written.  IOW, no matter how well written an OOP program is, a well written procedural rendition will be better in every way, that includes speed and size. The above statement does presume equally capable compilers.  The _one_ good thing that I can say about OOP is it will _initially_ take substantially less human effort, in the long run, it's even doubtful that paradigm will be able to maintain that initial advantage. Quote from: munair on May 07, 2020, 09:15:52 amWhat makes sense is to compare code against more advanced OOP implementations such as virtual stuff that does have an impact on code size. I'm not picky about it, I'll compare any OOP program against any procedural program on, and, for the same platform, in my case, Windows because that's what I know and, the result will always be the same: the procedural program will be smaller, faster and use less resources, IOW, it will always be a better program.  The downside - or the price I pay for that -, it will take me longer to write. I have a quite a few little test programs I've written over the years.  I seriously doubt an OOP version of any of them would be even the same size, most of them would likely be about twice the size if not more, they would very likely be slower and very likely use quite a few more resources but, it's also quite likely that many of them could be written using OOP in substantially less time than it took me.   To me, the additional program quality is well worth the additional time. ---------------------------------------------------------------------- Martin_fr · 2020-05-07 11:49 Quote from: 440bx on May 07, 2020, 05:09:23 amQuote from: Martin_fr on May 07, 2020, 04:11:42 am1) RTTI is not OOP.  RTTI may not be OOP but, while it is very rarely needed in procedural programming, it is commonly needed to support features common in OOP. True as observation, but possible twisted. 1) Managed types (string/array) are not bound to OOP. So are enums and sets. 2) Indeed, streaming of data (lfm files) in Pascal only happens with OOP. So it is a feature "common in OOP". From here on forward we can both speculate, and I guess we will do so different. "Streaming to lfm" was desired for creating a GUI editor (form designer). Because Borland had OOP avail they choose to add it on top of OOP.  If there had been no OOP, they may very well have added it on top of procedural. - So it is a historical coincidence that RTTI effectively is now bound to OOP. - It is not something inherent  in OOP itself, that caused RTTI to be added to it. If one goes far enough, one might say, that OOP may have made it easier to create a GUI editor framework, and claim this as the ultimate reason why rtti was added here. Still there are GUI frameworks without RTTI. So its still can have been an arbitrary decision by Borland. All we know is Borland created the connection between the two (maybe others did for other languages, I do not know). Why they did is hard to say. But it is well possible that OOP was simply a "victim". QuoteQuote from: Martin_fr on May 07, 2020, 04:11:42 amThat is why we use compilers, and do not write highly optimize asm our self. "man hours" are an important factor too. And that gets back to "no one shoe fits all". Some tasks may be faster written in procedural. Others in OOP (oh, yes indeed). I believe I have an unusual viewpoint about compilers.  IMO, a true, industrial-strength and quality compiler should generate code that is both smaller and faster than hand coded assembler by an expert assembly language programmer. Missing the point. Yes a compiler should. But if a human being would invest insane amounts of times, gather knowledge and experience, that human being could always beat the compiler. (Except in a few mostly simple cases, where the compiler got the perfect result, so there will be a draw / In many cases even the best compiler will not get the perfect result. Pretty darn good, but not perfect) My point was to hint at the "insane amount of time". One of the reasons compilers exist is to save human time. Hence the importance of man hours. Hence, if some added bytes can save adequate amount of man hours, then they are not bloat, but a price paid for a gain. You already said that OOP is faster at early stages in the development. You believe that changes later on. I believe that it will persist. Of course assuming:  well written code, but you would have made that assumption for the procedural comparison code too. QuoteOOP makes it very easy for the programmer to be more productive _initially_.  OTH, in the long run, I believe procedural slowly but surely ends up being the more productive way. ---------------------------------------------------------------------- Warfley · 2020-05-07 13:58 Quote from: Martin_fr on May 07, 2020, 01:55:50 amBesides you (the 2 of you) are not comparing programming paradigms (oop <> procedural). You are comparing compilers, as they are available today.I didn't want to argue about this anymore, but I think one might misinterpret my motivation. The claim "OOP is less efficient" is a claim that if it would be true would hold for every compiler in every language. I.e. G++ Procedual code will be more efficient than G++ OOP code. Same for Javascript or python in every possible interpreter of theirs, etc. (Also I haven't mentioned that any of the arguments of 440bx completely falls apart when considering interpreted languages) The thing about this whole topic from my point of view is, that if one argues about a language paradigm it needs to be argued on a conceptual not implementation level. E.g. I can prove that LOOP programs are less computationally expressive than WHILE programs, i.e.  there is no way that someone will ever implement a loop program implementing the ackerman function, no matter how hard one tries or which tools are used. I can also prove that for ever procedual C program that uses datatypes and functions acting on those types, you can create a C++ program using OOP structs, without being less efficient. I can do so by defining a transformation (which I did above), which is reversible (i.e. you can transform any C++ OOP struct back to a C struct). So I can transform any C program to an OOP C++ program and implement a compiler that basically just reverts this transformation and then uses a C compiler again. This is a mathematical proof by reduction that procedual code is not more efficient than OOP code. I did not argue that every OOP code is as efficient as ever procedual code. I think it should be quite clear that using virtual functions opposed to code that does not will lead to overhead in many cases. But I'm not here making the general claim, I'm disputing a general claim. And if I dispute a conceptual argument only one implementation example is needed to do so. For example if one would be able to find a LOOP program being able to solve the ackerman function the whole argument that LOOP programs are not expressive enought to solve the ackerman function would be disputed (well we have prove that such a program is not possible, but if that wouldn't be the case, only one example would suffice). So in this case, finding two pieces of code doing the same thing, using basically the same logic, just one uses OOP syntax and one uses procedual syntax, is already enough to dispute the claim. Sure one could argue that the average OOP code with most of the currently available tools is worse than the average procedual code, which is where such an empirical study comes in, but this is a totally different claim. I would even think that this might be true, because from personal experience most OOP code is not built to be most efficient but well maintainable, reusable (not in the same application but across different projects like a library) and extendible, but I can't prove any of that so I won't even try to. But this does not at all imply that OOP is in general less efficent, but only that projects using OOP are on average less efficient. Computer science is a branch of mathematics. A general claim about a theoretical construct such as language paradigms require a general and theoretical prove. Simple as that. ---------------------------------------------------------------------- Martin_fr · 2020-05-07 14:21 Quote from: Warfley on May 07, 2020, 03:58:41 pmThe thing about this whole topic from my point of view is, that if one argues about a language paradigm it needs to be argued on a conceptual not implementation level. QuoteComputer science is a branch of mathematics. A general claim about a theoretical construct such as language paradigms require a general and theoretical prove. Simple as that. +1 Very much what I tried to say. But proof is neither needed, nor possible for claims such as Quote from: 440bx on May 05, 2020, 12:36:06 am the OOP paradigm creates a mindset in the programmer that promotes very poorly thought out and structured code IMHO its statements like that that create a mindset in the reader that .... To be correct, and keep the context: The above was in relation to the ability of throwing exception as an alternative means to return "results". It had previously been pointed out that exception actually were not related to OOP. And in reply to that distinction the above quote was meant to prove that yet the existence of Exceptions is related to the "bad-ness of OOP". ---------------------------------------------------------------------- JiaXing · 2020-05-07 14:39 The source of binary size bloat in C++ is not from OOP alone, though. It's mostly from template. C++ abused template too much. You will not find that bloat with Objective C. I'm very dislike template. Not because any technical reason, though. But the fact it caused the code compilation is awfully slow. When coupled with full debug info generation (-g3 on GCC) the binary size is ridiculously big. About libc, sorry but I have to disagree. Libc is the same as the MSVCRT.DLL on Windows. Notice: the default MSVCRT.DLL shipped with Windows itself, not the one installed by redistribute packages. You can't do anything without it, other than using asembly to directly talk with the system or to link with other libc (but it's troublesome to use other libc apart from the system ones). So, libc itself doesn't contribute anything to the bloatness of the binary. Our dear 440bx could be a very good programmer on Windows, but he doesn't anything about Linux. So take his claims about things on Linux with a grain of salt. ---------------------------------------------------------------------- JiaXing · 2020-05-07 14:58 Quote from: Warfley on May 07, 2020, 03:58:41 pmComputer science is a branch of mathematics. A general claim about a theoretical construct such as language paradigms require a general and theoretical prove. Simple as that. Being a guy learning from practical, I see the arguments of 440bx appealing. But if it's about theoretical I can't said anything. I just an amateur without any CS background. ---------------------------------------------------------------------- marcov · 2020-05-07 15:26 Quote from: JiaXing on May 07, 2020, 04:39:26 pmAbout libc, sorry but I have to disagree. Libc is the same as the MSVCRT.DLL on Windows. Notice: the default MSVCRT.DLL shipped with Windows itself, not the one installed by redistribute packages. You can't do anything without it, other than using asembly to directly talk with the system or to link with other libc (but it's troublesome to use other libc apart from the system ones). So, libc itself doesn't contribute anything to the bloatness of the binary. So how does FPC then do this? Pascal must be very mighty and anti- bloat to be able to NOT use msvcrt, and not even having to use assembler to do it. ---------------------------------------------------------------------- Thaddy · 2020-05-07 15:38 Indeed, fpc does not use msvcrt at all. The programmer can choose to do so if required. ---------------------------------------------------------------------- 440bx · 2020-05-07 16:41 Quote from: Martin_fr on May 07, 2020, 01:49:59 pm1) Managed types (string/array) are not bound to OOP. So are enums and sets. True, managed types are not bound to OOP but, they are a gimmick to cater to the poor programming methodology OOP promotes in programmers.  Quote from: Martin_fr on May 07, 2020, 01:49:59 pm2) Indeed, streaming of data (lfm files) in Pascal only happens with OOP. So it is a feature "common in OOP". From here on forward we can both speculate, and I guess we will do so different. "Streaming to lfm" was desired for creating a GUI editor (form designer). Because Borland had OOP avail they choose to add it on top of OOP. streaming to .lfm is another one of those TV dinners OOP regales its users with.  That's the thing typical of an OOP programmer, wanting a component or compiler "feature" that does work _they_ should be the ones implementing.  Ultimately, quality suffers in both size and speed among other areas.  OOP leads to things like .net and components "a go-go".  Everytime I was tempted by the initial increase in productivity (I acknowledge it's quite tempting) what I found is that I ended up needing to have not only knowledge about the O/S API but, in addition to that, I needed to have solid knowledge about the framework and its internals in order to use it reasonably well.  In the long run, it takes a whole less time to develop without those frameworks because of the time saved _not_ having to know how they work, their internals, their quirks and all the workarounds they usually require to get something done.  Frameworks like .net, the LCL, VCL, etc are a result of the OOP way of thinking.  The result is a microwaved dinner. It's normally usable, like a TV dinner is edible but, there is a big difference in quality in the end product. And when it's all said and done, that is the point, using OOP leads to acceptable results but, of noticeably lower quality.  For that loss of quality, the programmer gets to be more productive for a short period of time. Quote from: Martin_fr on May 07, 2020, 01:49:59 pm  If there had been no OOP, they may very well have added it on top of procedural. I cannot say it wouldn't have happened but, I see that as a rather unlikely event. Quote from: Martin_fr on May 07, 2020, 01:49:59 pm- So it is a historical coincidence that RTTI effectively is now bound to OOP. It must also be a "coincidence" that it's heavily used in OOP.   Just "coincidence". Quote from: Martin_fr on May 07, 2020, 01:49:59 pm- It is not something inherent  in OOP itself, that caused RTTI to be added to it. That's debatable.  OOP needed it or, at least, benefited from it, which I "speculate" that's why it's there. Quote from: Martin_fr on May 07, 2020, 01:49:59 pmIf one goes far enough, one might say, that OOP may have made it easier to create a GUI editor framework, and claim this as the ultimate reason why rtti was added here. Still there are GUI frameworks without RTTI. So its still can have been an arbitrary decision by Borland. I don't know that there a single reason why RTTI was added to OOP but, I know it's not available in procedural programming, I'll speculate again, it might be because there is rarely any use for it. Quote from: Martin_fr on May 07, 2020, 01:49:59 pmAll we know is Borland created the connection between the two (maybe others did for other languages, I do not know). Why they did is hard to say. But it is well possible that OOP was simply a "victim". that's a good one.  Call the police, Mr. RTTI molested OOP. Quote from: Martin_fr on May 07, 2020, 04:11:42 amMissing the point. Yes a compiler should. But if a human being would invest insane amounts of times, gather knowledge and experience, that human being could always beat the compiler. It's not "a human being".  It's a team of human of beings accomplishing that over a period of time.  Just like FPC is the result of what could genuinely be considered an "insane amount of time" if all the effort by a group of people over a period of 24+ years had come from just _one_ human being.  Quote from: Martin_fr on May 07, 2020, 04:11:42 am (Except in a few mostly simple cases, where the compiler got the perfect result, so there will be a draw / In many cases even the best compiler will not get the perfect result. Pretty darn good, but not perfect) On the contrary, the more complex the case is, the greater the advantage a good compiler would have.  In the time it takes the programmer to just write the code, the compiler could evaluate thousands of different ways to optimize and implement the algorithms.  It's like Big Deep Blue, in the presence of enough expertise and enough computing power, it is possible to exceed the best any human can do.  A compiler is a "hello world" class program compared to all the analysis required to beat the world's champion chess player, yet, it has been done.  It took years of effort from a large number of people and a lot of technology but, it made the point, the computer has the potential to exceed the most qualified human being in the analysis of a problem. Quote from: Martin_fr on May 07, 2020, 04:11:42 amMy point was to hint at the "insane amount of time". One of the reasons compilers exist is to save human time. Hence the importance of man hours. Hence, if some added bytes can save adequate amount of man hours, then they are not bloat, but a price paid for a gain. Yes but, the presumption in that statement is that the man-hours savings don't diminish as the project gets larger.  That presumption is far from being always true, it is more often not true than otherwise. My "framework" is the O/S core services.  That's my framework. Quote from: Martin_fr on May 07, 2020, 04:11:42 amYou already said that OOP is faster at early stages in the development. You believe that changes later on. I believe that it will persist. For something simple, that's probably true. Quote from: Martin_fr on May 07, 2020, 04:11:42 amOf course assuming:  well written code, but you would have made that assumption for the procedural comparison code too. Absolutely. Quote from: JiaXing on May 07, 2020, 04:39:26 pmOur dear 440bx could be a very good programmer on Windows, but he doesn't anything about Linux. There is one very important thing in life to always be aware of, that is, with a lot of dedication, an individual can hopefully become reasonably good in one  area.  Those who try to be good at everything - or even just a few things - end up being not particularly good in any of them.  Some people are exceptions to that, among them, Leonhard Euler and Carl Friedrich Gauss but, those are truly exceptional individuals,  IOW, the common mortal can consider himself/herself lucky if they manage to be good at _one_ thing.  I can say that I have a reasonable amount of knowledge when it comes to Windows and, all that makes me aware of, is all the knowledge I could have about it that I don't have. Quote from: JiaXing on May 07, 2020, 04:39:26 pm So take his claims about things on Linux with a grain of salt. Take it with a ton of salt because my applied knowledge of Linux approximates the absolute zero quite well but, in spite of that, I can compare results obtained in Windows and Linux.  Things I have seen so far in this thread about Linux and g++ are excuses and, excuses don't make a compiler or operating system better.  If Linux doesn't offer commonly used services then that's a problem in Linux and, using that as excuses for executable bloat won't get any sympathy from me. ---------------------------------------------------------------------- Martin_fr · 2020-05-07 18:00 This thread return to your "mindset" theories again.... For all you have said and shown so far those theorise exist in your "mindset" only (and possible that of some other people, some due to your influence, others maybe by coincidence (one of my coincidental theories)). Unless you plan on giving mathematical proof (Not examples, but proof) to those mindset claims, they are of no relevance whatsoever. They simple do not exist in the real world. NOTE: I am not generally denying that when using OOP, a programmer applies different techniques. And so yes by knowing those techniques, and usually knowing them (at least to some extend) in addition to procedural techniques, people who know OOP have a broader mindset than those who do not know OOP. I do question the wide reaching implication that you you infer from this additional knowledge. That is for what I ask to see prof. There are of course a few (and yes that is a very narrow few) fanatics. But there arefanatics for procedural exists too (I am always certain to have seen proof of that). Quote from: 440bx on May 07, 2020, 06:41:25 pmOOP leads to things like .net and components "a go-go".  Everytime I was tempted by the initial increase in productivity (I acknowledge it's quite tempting) what I found is that I ended up needing to have not only knowledge about the O/S API but, in addition to that, I needed to have solid knowledge about the framework and its internals in order to use it reasonably well. You just keep diverging from the point. (mindset theory) The quality of a framework does not depend on its underlying paradigm. Frameworks can be well written, or not. That is the same for OOP and procedural.... Having to have knowledge of a framework, is also entirely unrelated to OOP. A procedural framework requires knowledge too. Quotethe OOP way of thinking.  More on frameworks. And again "mindset theary". QuoteQuote from: Martin_fr on May 07, 2020, 01:49:59 pm  If there had been no OOP, they may very well have added it on top of procedural. I cannot say it wouldn't have happened but, I see that as a rather unlikely event. Yes, procedural would probably have been to much work (despite you claim, it is less work...). So they might not have done a GUI editor at all.  But that would just prove that your claim "procedural is less work" is wrong. So what should it be? QuoteQuote from: Martin_fr on May 07, 2020, 01:49:59 pm- It is not something inherent  in OOP itself, that caused RTTI to be added to it. That's debatable.  OOP needed it or, at least, benefited from it, which I "speculate" that's why it's there. Where or how did OOP need it? There is plenty of oop code that works 100% without any use of RTTI. Certain frameworks needed it. But as already pointed out: Framework is not OOP. You have similar things in Perl (and maybe (?) javascript). A lot of Perl is written in procedural style, yet access to the perl equivalent of RTTI is made. I.e. finding global (yes global, bad design, but heck its procedural....) entities by name (variables, procedures, even build in) and replace them. Quote I'll speculate again, it might be because there is rarely any use for it. Well speculation is of course allowed. I speculate (based on your speculation), that there is no use for it in procedural programming, because looking at anything for which RTTI could be used, it is so much more effort to implement it in procedural (even assuming a really great procedural RTTI implementation), than it is to implement the same in OOP. So in conclusion your speculation actually shows that OOP is superior. QuoteQuote from: Martin_fr on May 07, 2020, 04:11:42 amMissing the point. It's not "a human being".  It's a team of human of beings accomplishing that over a period of time.  Just like FPC is the result of what could genuinely be considered an "insane amount of time" if all the effort by a group of people over a period of 24+ years had come from just _one_ human being.  Still missing the point.... Quote Quote from: Martin_fr on May 07, 2020, 04:11:42 amMy point was to hint at the "insane amount of time". One of the reasons compilers exist is to save human time. Hence the importance of man hours. Hence, if some added bytes can save adequate amount of man hours, then they are not bloat, but a price paid for a gain. Yes but, the presumption in that statement is that the man-hours savings don't diminish as the project gets larger.  That presumption is far from being always true, it is more often not true than otherwise. Never said that it is always true. Using OOP it is more often true than using procedural. In fact using OOP it is also extendable to projects of way bigger proportion than it is with procedural. Maybe an idea for the next (cheap) television hit series: "The mindset theory" ---------------------------------------------------------------------- 440bx · 2020-05-07 19:43 This thread is a great example of some people afflicted with denying the obvious because accepting reality would be "inconvenient".  Methodology: reinforce denial with demands of mathematical proof.  I think I've also observed that behavior in religious environments. Quote from: Martin_fr on May 07, 2020, 08:00:16 pmThis thread return to your "mindset" theories again.... Yes, I return to it because it is reality.  It's commonly seen in C programmers that, much too often, produce unintelligible code.  You need proof of that ?... read a good bunch of C code... go to the site where some programmers take pride in producing undecipherable code, then claim the C language has nothing to do with it. Quote from: Martin_fr on May 07, 2020, 08:00:16 pm For all you have said and shown so far those theorise exist in your "mindset" only (and possible that of some other people, some due to your influence, others maybe by coincidence (one of my coincidental theories)). No doubt the tendency C programmers have of producing unreadable code is pure "coincidence". Quote from: Martin_fr on May 07, 2020, 08:00:16 pmUnless you plan on giving mathematical proof (Not examples, but proof) to those mindset claims, they are of no relevance whatsoever.Not everything is mathematically provable but, it doesn't mean it isn't true. Quote from: Martin_fr on May 07, 2020, 08:00:16 pm They simple do not exist in the real world. Denial... very mathematical. Quote from: Martin_fr on May 07, 2020, 08:00:16 pmNOTE: I am not generally denying that when using OOP, a programmer applies different techniques. Just like writing spaghetti code is also a "technique".  I'm sure getting a lot of good examples of producing nice euphemisms in this thread. Quote from: Martin_fr on May 07, 2020, 08:00:16 pm people who know OOP have a broader mindset than those who do not know OOP. I believe they do have a broader mindset.  Just a bit too broad.  e.g, bloat is good (someone claimed that somewhere in this thread... maybe obesity is good too but, for some reason, I doubt it.) Quote from: Martin_fr on May 07, 2020, 08:00:16 pmI do question the wide reaching implication that you you infer from this additional knowledge. That is for what I ask to see prof.I posted a little program that shouldn't take much effort to implement using OOP.  Comparing the results is not proof but, at least, it would give an idea of the results obtained with each paradigm. Quote from: Martin_fr on May 07, 2020, 08:00:16 pmThere are of course a few (and yes that is a very narrow few) fanatics. But there arefanatics for procedural exists too (I am always certain to have seen proof of that).I find a bit difficult to believe that .net is just the result of a "few fanatics" that cater to another "few fanatics".  There is a bit of a stretch there.  I believe that's not the only example but, I thought, it was the more politically correct one to mention here. Quote from: Martin_fr on May 07, 2020, 08:00:16 pmThe quality of a framework does not depend on its underlying paradigm. Frameworks can be well written, or not. That is the same for OOP and procedural.... If that is true then, it should be possible to implement the framework, without any loss of quality, in a language that doesn't include functions, local variables, loops, polymorphism, inheritance, RTTI and _no_ way to implement them in the language either.  By the way, the challenge isn't that it cannot be done, the challenge is: that the result would be a code mess (strangely, it would be similar too OOP but, instead of being a result of feature abuse, it would be the result of feature deprivation.) Quote from: Martin_fr on May 07, 2020, 08:00:16 pmHaving to have knowledge of a framework, is also entirely unrelated to OOP. No, it is not.  It is much more difficult to acquire knowledge of a framework programmed using the spaghetti code paradigm than the structured programming paradigm.  That also applies to OOP. Quote from: Martin_fr on May 07, 2020, 08:00:16 pmMore on frameworks. And again "mindset theary".I see you like that "mindset theory" thing you came up with.  I admit, it's got a nice ring to it.  Too bad it's just a cop out. Quote from: Martin_fr on May 07, 2020, 08:00:16 pm  But that would just prove that your claim "procedural is less work" is wrong. You conveniently forgot to mention "in the long run".   You have to learn about all the idiosyncrasies of the components you use (which you didn't write, which makes it more laborious) and that takes time.  There is some of that when not using a framework but, at least it's limited to the facilities provided by the O/S. Quote from: Martin_fr on May 07, 2020, 08:00:16 pm  Where or how did OOP need it? There is plenty of oop code that works 100% without any use of RTTI. Are you suggesting someone added RTTI in OOP in spite of the fact that, according to the implication in your statement, OOP doesn't need it to implement some of the features it offers ?... who would do something like that ? Strangely, you also forgot to mention that there is plenty of OOP code that needs RTTI to work.  That might be a side effect of the mindset.  Quote from: Martin_fr on May 07, 2020, 08:00:16 pm  You have similar things in Perl (and maybe (?) javascript). A lot of Perl is written in procedural style, yet access to the perl equivalent of RTTI is made. I.e. finding global (yes global, bad design, but heck its procedural....) entities by name (variables, procedures, even build in) and replace them.I've heard there are people who consider Perl a programming language.  If anyone needed proof that reality is often stranger than fiction, that's a good exhibit for it. Quote from: Martin_fr on May 07, 2020, 08:00:16 pm  Well speculation is of course allowed. Glad to hear it. Quote from: Martin_fr on May 07, 2020, 08:00:16 pm   it is so much more effort to implement it in procedural (even assuming a really great procedural RTTI implementation), than it is to implement the same in OOP.On the contrary, it is usually much simpler and fully localized. Quote from: Martin_fr on May 07, 2020, 08:00:16 pm  So in conclusion your speculation actually shows that OOP is superior. You can speculate good but, the conclusions are not as good.  Quote from: Martin_fr on May 07, 2020, 08:00:16 pm  Still missing the point.... QuoteIn that case, we have something in common.  Quote from: Martin_fr on May 07, 2020, 04:11:42 amMy point was to hint at the "insane amount of time". One of the reasons compilers exist is to save human time. Hence the importance of man hours. Hence, if some added bytes can save adequate amount of man hours, then they are not bloat, but a price paid for a gain. Yes but, the presumption in that statement is that the man-hours savings don't diminish as the project gets larger.  That presumption is far from being always true, it is more often not true than otherwise. Never said that it is always true. No, you just implied it. I agree it's different than stating it's always true. Quote from: Martin_fr on May 07, 2020, 04:11:42 amIn fact using OOP it is also extendable to projects of way bigger proportion than it is with procedural. That's a nice claim but, so far, I believe the development of the operating system for IBM's System/360 vastly exceeds anything that has been attempted with OOP by several orders of magnitude and, that was all procedural.  Your extensibility claim hasn't been put to the test in projects of "bigger proportion"(s). Quote from: Martin_fr on May 07, 2020, 04:11:42 amMaybe an idea for the next (cheap) television hit series: "The mindset theory" It's got a nice ring to it. ---------------------------------------------------------------------- Martin_fr · 2020-05-07 20:11 Quote from: 440bx on May 07, 2020, 09:43:11 pmThis thread is a great example of some people afflicted with denying the obvious because accepting reality would be "inconvenient". Yes indeed. I fully agree. ---------------------------------------------------------------------- 440bx · 2020-05-07 20:45 Quote from: Martin_fr on May 07, 2020, 10:11:01 pmYes indeed. I fully agree. Another unforgettable historic moment... we found something to agree on two days in a row ---------------------------------------------------------------------- Warfley · 2020-05-07 22:56 I've gone through google scholar and searched some evidence. First let's take a look at the thing OOP is developed for, productivity: https://vtechworks.lib.vt.edu/bitstream/handle/10919/19750/TR-92- 15.pdf?sequence=3 It measured: Quote1) Does the object-oriented paradigm promote higher productivity than the procedural paradigm? 2) Does the object-oriented paradigm promote higher productivity than the procedural paradigm when programmers do not reuse? 3) Does the object-oriented paradigm promote higher productivity than the procedural paradigm when programmers reuse? 4) Does the object-oriented paradigm promote higher productivity than the procedural paradigm when programmers are moderately encouraged to reuse? 5) Does the object-oriented paradigm promote higher productivity than the procedural paradigm when programmers are strongly encouraged to reuse? 6) Does reuse promote higher productivity than no reuse regardless of the language paradigm used? 7) Is the extent of improvement due to reuse higher for the object- oriented paradigm than for the procedural paradigm? Here the subjects where given a specification for a target system as well as a set of pre developed components (developed by a different group), one set OOP components written in C++, one set procedual components written in Pascal. The reusability level varied (i.e. some components needed more changes for the new situation than others) The subjects had to then implement the program in 3 groups: 1. no reuse, 2. reuse at will, 3. the most reuse possible. The measures taken where: QuoteMain productivity measures • Runs - The number of runs made during system development and testing, • RTE - The number of run time errors discovered during system development and testing • Time - The time (in minutes) to fix all run time errors, Secondary productivity measures • Edits - The number of edits performed during system development and testing, and • Syn. - The number of syntax errors made during system development and testing. Results: When comparing OOP vs procedual over all groups, all three main metrices are statistical significantly lower for OOP than in procedual programming. The secondary metrices are not statistically significant in ayn direction. In the No-Reuse group all metrices are not statistically significant. When reusing all three main metrices are statistically significant lower for OOP There are some other measures in here, but here I only want to cover the last point, the productivity increase due to reusing of components was statistical significantly higher for OOP over procedual for Runs and Runtime errors. So to summarize, reusing code improves the productivity and it is "easier" (my word not by the authors) in OOP than in procedual. 6 or 8 people per group, so 20-22 each doing OOP or procedual programming Peer reviewed studie, published not in a rather prestigeous journal, 58 citations on google scholar. Relating to this there is also https://dl.acm.org/doi/pdf/10.1145/117954.117969 by the same authors released a year prior, doing the same experiment but not considering 3 groups but only two (no reuse and reuse at will). This was peer revied in a rather highly respected journal (compared to the later one) and cited by 121 people. So the total citation count is 179. Next one: https://dl.acm.org/doi/pdf/10.5555/781915.781967?download=true Measures productivity of IBM projects as ProjectSize(Kloc)/Duration(months) for teams  the person-productivity as size/mahours. Results: QuoteThis  indicatesthat,  in  this  case,  there  is  no  statistically significant difference between the  productivity of object-oriented   software   development   andprocedural software developmentSo no difference in any direction could be found. Take this with a grain of salt because 1. the software may not be comparable, as stated here: Quote in our case, allprocedural projects were follow-on releases, whilefour of the seven regular object-oriented projectswere  first  releases.  Generally,  first  generationprojects have a somewhat lower productivity thanlater generation projectsAlso, which I want to add (and is not mentioned in the paper) that the productivity is measured by size in lines of code. This does not account for 1. differing code length due to different technology (e.g. different languages produce more lines of code) 2. differing code length due to the different paradigms. So if one project has more lines of code due to the language or paradigme, the productivity metric will be artificaly inflated. That said, compared to the other two studies above it measures on real world software and not academically created tests. The study also had a few OOP projects in there that where ports to a different platform, which where highly productive, but there is no comparison to procedual. Still this is an indicator that OOP can make code reusing very efficient. 30 citations, peer reviewed, trustworthy but not so prestigeous jurnal (that said I honestly don't know how prestigous CS journals where in general in '95). https://strathprints.strath.ac.uk/2676/1/strathprints002676.pdf QuoteThe collected data showed that subjects maintaining object- oriented software with three levels of inheritance depth performed the maintenance tasks significantly quicker than those maintaining equivalent object based software with no inheritance. In contrast, subjects maintaining the object-oriented software with five levels of inheritance depth took longer, on average, than the subjects maintaining the equivalent object-based software (although statistical significance was not obtained)If you don't know about scientific working, having no statistical significance means the same as: We absolutely have no idea. I.e. small inheritance hierachies improves maintainability. For larger inheritance we don't know. Peer reviewed, respected journal, cited by 32 papers (according to google scholar) 15 people per group, all have learned turbopascal procedual programming and C++ object oriented programming. Take this with a grain of salt because it compared an OOP program vs a "flatened OOP" program, i.e. an OOP program without hierachy. So one can argue that procedual programs will be fundamentally different Lastly there is https://dl.acm.org/doi/pdf/10.1145/243350.243356 This is not an empirecal study, but simply a discussion about the pros and cons of OOP. Might be nothing more than an opinion, but it's peer reviewed and cited by 40 people so it's at least worth more than some people here writing in this thread. These where the relevant results in the first two pages of google scholar when searching for "object oriented programming productivity procedural" (but only those I got access to, of cours I can't discuss what I can't read). I did not skip a paper because it was inconvinient or something like that. So to summarize OOP vs procedual, regarding productivity, all of the reasearch I've found at least stated that OOP is not less productive than procedual programming even on large scale projects. That said, OOP makes reusing code very efficent, leading to a higher productivity when reusing code, as well as having a higher increase in productivity than in procedual languages. Also was shown that in OOP inheritance can help to increase maintainance productivity. It should be noted that in all of these papers the sample size is rather small (at most 20 per group), which is of course also due to the nature of this (you need people to work on and projects to compare). All the claims of statistical significance where with a 5% p-value. Also all the paper are rather old, back when OOP was new. This of course might only be comparable in a very limited fashion to modern OOP implementations That said, here is now my personal opinion about the research. I've now read 6 paper (of which the 4 that where relevant to this discussion where discussed above), all talking to some extend to OOP vs procedual (one paper not mentioned compared the usage of frameworks, which, while also being interesting, does not fit to what I'm currently looking for). Productivity wise I wasn't able to find any claim that OOP is less productive, makes maintainance harder or anything comparable. I also need to note, that compared to the time the papers have been written, a lot has changed in the world of OOP. There are now massively different OOP approaches out there like Javascript, Python or Go, to some extend even modern C++ (since C++11), which are not really comparable to what was considered OOP back then, when these paper where written. Also, the programmers during that time period where pretty familiar with procedual programming but would have been rather new to OOP, not having the experience or the best practices (especially for the IBM study). That said, I still believe they give a great (empirical) insight into this topic and show that even for projects with up to a million lines of code (IBM study) OOP is not less productive. It also shows the heavy emphasis on code reusage, which I already suspected, which clearly gives an edge to OOP over procedual regarding productivity (as the IBM programs written in OOP where new developments, code reusage didn't really factor in there). From my personal experience I can also sign this off, as I had to use a lot of frameworks and libraries for both C++, C and Java, and from my experience libraries and frameworks built for OOP are massively easier and more straight forward to use than those that are of procedual nature. Extendibility was also a part of the discussion (I think I brought that up), I haven't found any papers comparing OOP to procedual on an empirical basis, but it was slightly covered in the maintainability paper, which showed that inheritance can increase maintainability (and therefore also to some degree extendibility), and also while not being epirically quantified, the consensus in the literature seems to be that OOP increases extendibility. But this is also nothing more then educated opinions. So after reading through this I think it is fair to say that productivity wise, as long as one makes use of reusability, OOP is better for productivenes. For me, in most of my projects, productivity outweighs performance. I'm rather having my program be 20% larger or even slower, rather than having to invest 20% more time into its development. I've never came to the point where memory consumption was the bottleneck and only a very few times that execution speed was. But if I'm motivated I might take a look tomorrow into the efficency, and maybe correctness of OOP vs procedual programs and what the literature says about that. But this should at least take a stop to the productivity discussion, because here is a bunch of empirical evidence proving that OOP is not only not less productive, but when considering reusability is even more productive. All these paper are peer reviewed and also have a bunch of citations (179 for the reusability paper is pretty good). Even more though I haven't found a single paper that showed (or even claimed) otherwise. It's not only scientific consensus, theres also empirical evidence for it. If that is not enough to convince someone, nothing will be. It can't get more objective than that ---------------------------------------------------------------------- 440bx · 2020-05-08 01:22 Quote from: Warfley on May 08, 2020, 12:56:29 amThis  indicates that,  in  this  case,  there  is  no  statistically significant difference between the  productivity of object-oriented   software   development   and procedural software developmentThat's interesting.   One study concluded there is and  another concluded there isn't... but I really like this part: Quote from: Warfley on May 08, 2020, 12:56:29 amTake this with a grain of salt because 1. the software may not be comparable, Quote from: Warfley on May 08, 2020, 12:56:29 am as stated here: Quote in our case, allprocedural projects were follow-on releases, whilefour of the seven regular object-oriented projectswere  first  releases.  Generally,  first  generationprojects have a somewhat lower productivity thanlater generation projectsThat sounds really strange.  If OOP code is so re-usable, was the same code written four times the cause of not seeing a greater productivity ?.  Hard to believe, four first release projects had no code in common.  Quote from: Warfley on May 08, 2020, 12:56:29 amAlso, which I want to add (and is not mentioned in the paper) that the productivity is measured by size in lines of code. Productivity measured in lines of code ?  that's like measuring weight by the volume it occupies.  Helium filled Balloons are really heavy. Quote from: Warfley on May 08, 2020, 12:56:29 amSo if one project has more lines of code due to the language or paradigme, the productivity metric will be artificaly inflated.And quite doubtful that is the only artificial element in such a way of measuring productivity.  Quote from: Warfley on May 08, 2020, 12:56:29 am this is an indicator that OOP can make code reusing very efficient.if there one thing OOP is particularly good at is code reuse.  The size of the executables attest to that.  Quote from: Warfley on May 08, 2020, 12:56:29 am I honestly don't know how prestigous CS journals where in general in '95). 1995 ?? very fresh information.  No doubt corroborated by many other studies since but, they are probably classified as military secrets and that's why Google didn't find them. Quote from: Warfley on May 08, 2020, 12:56:29 am That said, OOP makes reusing code very efficent, leading to a higher productivity when reusing code, Not to mention very visible. Quote from: Warfley on May 08, 2020, 12:56:29 am as well as having a higher increase in productivity than in procedual languages. Measured in SLOCS ?... that goes counter to the claim of code re-use. Quote from: Warfley on May 08, 2020, 12:56:29 amAlso was shown that in OOP inheritance can help to increase maintainance productivity. It would probably be difficult to find a more efficient way of re- using code whether it's needed or not and, it goes a long way to increase productivity measured in SLOCS. Quote from: Warfley on May 08, 2020, 12:56:29 amI also need to note, that compared to the time the papers have been written, a lot has changed in the world of OOP. Definitely... such as measuring productivity in SLOCS. Quote from: Warfley on May 08, 2020, 12:56:29 amas the IBM programs written in OOP where new developments, code reusage didn't really factor in there). That is really interesting.  Projects that are so different than one another that code couldn't be reused among them.  It would sure be interesting to know what those projects were. Quote from: Warfley on May 08, 2020, 12:56:29 amSo after reading through this I think it is fair to say that productivity wise, as long as one makes use of reusability, OOP is better for productivenes. if productivity is measured in executable size then there is no doubt in my mind that OOP is the champ.  I find it a bit surprising that, in spite of its supposed abilities to promote code reuse, it was also the champ when productivity was measured in SLOCS. Quote from: Warfley on May 08, 2020, 12:56:29 amFor me, in most of my projects, productivity outweighs performance. I'm rather having my program be 20% larger or even slower, rather than having to invest 20% more time into its development.The users of the program may have a different opinion depending on what the net effect of those losses are. Quote from: Warfley on May 08, 2020, 12:56:29 am I've never came to the point where memory consumption was the bottleneck Considering that a browser routinely uses half a gigabyte to display 3 pages of mostly text, it's a really good thing that the days of limited amounts of memory are behind us. Quote from: Warfley on May 08, 2020, 12:56:29 am and only a very few times that execution speed was. if there were "very few times" that execution speed was a problem it's doubtful SSDs would have been created. Quote from: Warfley on May 08, 2020, 12:56:29 am but when considering reusability is even more productive. I knew OOP reused a lot of code without reading any study.  It's quite evident it does. ---------------------------------------------------------------------- Martin_fr · 2020-05-08 02:00 Quote from: 440bx on May 08, 2020, 03:22:10 amQuote from: Warfley on May 08, 2020, 12:56:29 am this is an indicator that OOP can make code reusing very efficient.if there one thing OOP is particularly good at is code reuse.  The size of the executables attest to that.  QuoteQuote from: Warfley on May 08, 2020, 12:56:29 am That said, OOP makes reusing code very efficent, leading to a higher productivity when reusing code, Not to mention very visible. QuoteQuote from: Warfley on May 08, 2020, 12:56:29 am but when considering reusability is even more productive. I knew OOP reused a lot of code without reading any study.  It's quite evident it does. If I interpret those answers correct, putting them in light of previous statements, then you (440bx) may be mixing two things up. - The ability of the programmer to re-use code. Which is to what the Warfley quotes refer. - Your  earlier references to exe size, because OOP allegedly forces every compiler to pull in unused code   (which is not re-use, as "re-use" implies usage, while "unused" states the opposite) ---------------------------------------------------------------------- 440bx · 2020-05-08 02:59 Quote from: Martin_fr on May 08, 2020, 04:00:18 amIf I interpret those answers correct, putting them in light of previous statements, then you (440bx) may be mixing two things up. I apologize if, in a number, probably most, of my replies it wasn't evident that I was being a bit facetious. Quote from: Martin_fr on May 08, 2020, 04:00:18 am- The ability of the programmer to re-use code. Which is to what the Warfley quotes refer. - Your  earlier references to exe size, because OOP allegedly forces every compiler to pull in unused code   (which is not re-use, as "re-use" implies usage, while "unused" states the opposite) I'll address your points seriously. I get the distinct feeling from Warfley's post that code reuse includes code unused too and, quite likely the same code being counted multiple times.  I get that feeling because, if OOP is truly better at reusing code then it cannot look good in any test where productivity is measured in SLOCS.   The greater the amount of code reuse the lower the number of SLOCS.  Using that metric and, if OOP truly reused a lot of code then, it should look really bad, which would be a good thing since, no one that knows anything about programming would measure productivity in SLOCS. I facetiously pointed out that OOP's code "reuse" was evident in the size of the executables it produces because it has a very clear tendency of including a lot of code that is _unused_.  Re-using code to produce unused code isn't exactly what most people would consider a desirable feature but, its doing that is clearly noticeable in the size of the executables it produces (and that is presuming the code generated is as tight as the code generated for a procedural implementation, an unproven and likely generous presumption.) It is difficult not to wonder how those studies counted SLOCS.  If OOP ends up requiring as many lines of code as procedural programming then, obviously, it does not provide any productivity advantage.  If it produces more, indicated by its having greater productivity (greater number of SLOCS) then, it is obviously an undesirable software development paradigm. ---------------------------------------------------------------------- PascalDragon · 2020-05-08 07:47 Quote from: 440bx on May 07, 2020, 09:43:11 pmQuote from: Martin_fr on May 07, 2020, 08:00:16 pm  Where or how did OOP need it? There is plenty of oop code that works 100% without any use of RTTI. Are you suggesting someone added RTTI in OOP in spite of the fact that, according to the implication in your statement, OOP doesn't need it to implement some of the features it offers ?... who would do something like that ? Strangely, you also forgot to mention that there is plenty of OOP code that needs RTTI to work.  That might be a side effect of the mindset. No, RTTI is only required in specific instances. For example at work our operating system and its user space is implemented in C++ and is highly OOP. Yet for around 15 years the RTTI generation of the MSVC compiler was not enabled at all, because the necessary low level functionality of the language runtime that MSVC expects to be there was not implemented. And even now it's only used for dynamic_cast which allows to cast a parent type to a sub type. And in FPC the RTTI is only required if you want to dynamically access published properties at runtime. Things like retrieving the class type does not require RTTI, that is instead part of the class' type. Also the RTTI is available procedurally as well. In fact the TypInfo unit that provides access to it is completely procedural. Take this example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses  TypInfo; type  TMyEnum = (    meOne,    meTwo  ); var  e: TMyEnum;begin  e := meOne;  Writeln(GetEnumName(TypeInfo(TMyEnum), Ord(e)));end. What is also part of the RTTI, but is not related to OOP is the so called Init RTTI. This exists due to the managed types which includes AnsiString, UnicodeString, WideString, dynamic arrays, interfaces and (with 3.2) records with management operators. This allows for a record containing such types to be copied while keeping the reference counts correct. While class instances use this as well (they need to initialize their fields upon construction), it's used everywhere these types are used. ---------------------------------------------------------------------- Warfley · 2020-05-08 12:25 Quote from: 440bx on May 08, 2020, 03:22:10 amThat sounds really strange.  If OOP code is so re-usable, was the same code written four times the cause of not seeing a greater productivity ?.  Hard to believe, four first release projects had no code in common. No these where 4 completely different projects. You would expect that reusability is higher when writing a followup release than when you are writing a completely new piece of software. Sure there is a "baseline" reusability, e.g. an SHA-hashing function will be reusable no matter what. But if you write a followup software you often can reuse whole components with rather little effort. A luxury you don't have for new releases.  QuoteProductivity measured in lines of code ?  that's like measuring weight by the volume it occupies.  Helium filled Balloons are really heavy. Yes, I know, I actually wrote about that I don't think this is the best comparison. BUT: whats the alternative? No study is perfect and is often limited by real world constraints. Getting an objective metric about code complexity is hard, and while LOC are not perfect, they at least give an indication. QuoteAnd quite doubtful that is the only artificial element in such a way of measuring productivity.  If you have a better study at hand feel free to post it. Quoteif there one thing OOP is particularly good at is code reuse.  The size of the executables attest to that.  Code reuse and executable size are as related to one another as gravity and the time it takes for ice to melt under the sun. Quote1995 ?? very fresh information.  No doubt corroborated by many other studies since but, they are probably classified as military secrets and that's why Google didn't find them.Thats simply how science works. Once we found something out there is little drive to redo that experiment again and again. If you develop a heat pump, you don't need to reinvent the laws of thermodynamics. Also it's not google (the websearch engine) but google scholar a search engine that searches most scientific publications. I've invested 3-4 hours and didn't cherry pick, I've looked at every study from the first two pages of google scholar. Sure I could have searched further, but after 3-4 hours I was simply tired. If you think there are newer studies out there I haven't found, feel free to post them here. I'm also quite interested because modern OOP such as it is used in .Not make the claim to be more productive, something I would love to see empirical evidence for or against. Also, don't get me wrong, I think that it's a real flaw of the current scientific complex that papers aren't reproduced. I've read some papers where I thought that you can't trust them on face value (e.g. if their statistic analysis is more than questionable). Especially if you think about it, simply due to chance, when using a p-value of 5%, it means that 5% of all papers will simply be wrong. But fact is, if you are a company doing research you don't want to waste money on reinventing the wheel every time, and if you are a university, the funds you are getting are directly linked with your prestige. And discovering new stuff is much more prestigeful than finding out that some other guys discovery was true. That said, it's still better than no evidence at all. QuoteMeasured in SLOCS ?... that goes counter to the claim of code re- use.1. This study never measured code reuse, it's something they have not accounted for. 2. Of course, if you reuse code, you get LOC for free. If I reuse code from an old project in my new project, this code will still be part of my new project and be counted as such. Otherwise this performance metric would be completely useless, because reusing gives you functionality in a fraction of the time it would take to reprogramm it. I.e. measuring it as LOC/time is actually a good solution here. The only point where LOC isn't the best metric is when comparing completely different project using different languages. But even then, feel free to bring forth a better study using better metrices. QuoteDefinitely... such as measuring productivity in SLOCS.Feel free to bring forth a better study using better metrices. QuoteThat is really interesting.  Projects that are so different than one another that code couldn't be reused among them.  It would sure be interesting to know what those projects were.These software was developed by completely different teams, meaning 1. they might not even know about the existance of the other software, 2. they might not even have access to the other software. In a large company like IBM most people don't have access to most of the projects. That said, of course some reusability is always given, like I said before, something like an SHA hasher only needs to be written once. But it is a completely different level of reusability if you are writing a totoally new project somewhat isolated, compared to having the source of the previous version (most likely even being the developer of the previous version) and then being instructed to build a new version. As the study said: QuoteGenerally,  first  generation projects have a somewhat lower productivity than later generation projects Quoteif productivity is measured in executable size then there is no doubt in my mind that OOP is the champ.  I find it a bit surprising that, in spite of its supposed abilities to promote code reuse, it was also the champ when productivity was measured in SLOCS.Feel free to provide another study that measures it better. Also you are getting it wrong they don't measure productivity in LOC but complexity. Productivity is then Complexity/Time. The thing is, there are arguments for measuring complexity in lines of code, because there is a causality between those two. And if you have two projects using the same language, it will be a very good measure of complexity. Here the point of discussion is simply a matter of degree when comparing different languages and paradigmes. Executable size on the other hand is, thanks to the fact that resources can be packed into executables, only very weakly related to complexity (if at all). A program making heavy usage of graphics will inevetibly produce larger executables than one that doesn't, no matter how complex. A hello world printing a 4k image can be much larger than a 300 KLOC fully function program like SQLite. QuoteThe users of the program may have a different opinion depending on what the net effect of those losses are.Sure thing. I mean it is obious that you fetishize exec size. IBM, who conducted one of the studies, makes heavy use of OOP because they prioratize productivity. QuoteConsidering that a browser routinely uses half a gigabyte to display 3 pages of mostly text, it's a really good thing that the days of limited amounts of memory are behind us.A browser is about as complex of a piece of software than an operating system. (It provides API's, a file system, a process scheduler, a debugger, a virtual CPU, an virtual MMU, a network stack, an interpreter and a JIT optimizer for javascript, etc.). If you start your browser you are basically starting a VM. Software is getting increasingly complex, and this is reflected best amongst browser. Quoteif there were "very few times" that execution speed was a problem it's doubtful SSDs would have been created.Execution speed -> creation of SSDs. This makes as much sense as saying: I'm hungry, thats why I am buying a new T-Shirt. SSD's only have an impact on loading speed. Once an executable is loaded the SSD has nothing to do with execution speed. This is only limited by BUS speed, CPU speed, and RAM speed. And if you are writing a network application or a GUI application, or in fact anything that relies heavily on OS interaction (i.e. has frequent context switches) the speed of your program will not become the bottleneck. The only time you need to be concerned about speed is when you are doing raw processing work. This is why many websites run using PHP, which is an interpreted languages thats really slow. Because speed simply is not the bottleneck. QuoteI knew OOP reused a lot of code without reading any study.  It's quite evident it does.Yes and the first study I showed also shows a statistically significant link between code reusage and productivity (and no, this is not measured in lines of code). It also showed a statistically significant link between productivity and the usage of OOP for code reusing. QuoteI get the distinct feeling from Warfley's post that code reuse includes code unused too and, quite likely the same code being counted multiple times.  I get that feeling because, if OOP is truly better at reusing code then it cannot look good in any test where productivity is measured in SLOCS.   The greater the amount of code reuse the lower the number of SLOCS.  Using that metric and, if OOP truly reused a lot of code then, it should look really bad, which would be a good thing since, no one that knows anything about programming would measure productivity in SLOCS.Code reuse specifically was only measured in the first study, which had nothing to do with LOC. The IBM study that measured LOC had a few projects that where ports to new platforms of existing OOP projects and measured that these took a lot less time than comparable new projects (or followup releases for that matter), and thereby indicate that code reusage might be very efficient in OOP. It does not in any way shape or form compare code reusage between OOP and procedual, this is only done in the first study, which explicitly measured that. Also the claim that the greater the amount of code reuse the smaller the LOC is simply wrong. This was measured on the completed project. If I reuse code, I need to put it into my new project, that means that from an outsider perspective (like the one of those who conducted the study), there is no way of knowing which code was reused and which wasn't. Thats why they didn't assess it. QuoteIt is difficult not to wonder how those studies counted SLOCS.  If OOP ends up requiring as many lines of code as procedural programming then, obviously, it does not provide any productivity advantage.  If it produces more, indicated by its having greater productivity (greater number of SLOCS) then, it is obviously an undesirable software development paradigm.If you are wondering this then maybe read the study? It did not compare the "same" programs. This study compared many different programs that where finished by IBM at the time of writing. This is not a controlled experiment but a field experiment. It makes the assumption that the complexity of a program can be measured in LOC (which of course is only true to a certain degree) and then estimated the productivity by the manhours it took to finish. This of course is only a rather limited view on the matter, but if you are not doing a controlled experiment, this is about the best you can do. The first study I presented on the other hand conducted a controlled experiment. There all groups had to implement the same software, which made the "normalization" of the complixity by LOC not needed. Besides this, such a field experiment is of course not bad simply because it is limited in this way. It still gives an insight on industrial scale project. The size of the programs was up to 1 million lines of code, something you simply can't get in a controlled environment. You can't simply look at one study for a result. But here you have two that seem to both measure the same thing. OOP is not more (or less) productive than procedual programming on it's own, but code reusage is much more productive in OOP. ---------------------------------------------------------------------- marcov · 2020-05-08 15:14 Note that a lot of the arguments for code-reuse are for codereuse as a fairly black box (e.g. team development, or even with bought libraries). If you need to descent onto the level that you can decide "this bit of code is unused" or that "piece of code use a feature I don't currently use" for every bit of code in the exe, that defeats the whole purpose of modularization and team work. That is not about OOP, but about some desperate attempt at total control vs  normal engineering on an always too small time budget. These things are not absolute. On my embedded development I also want  way more control, and even in my main apps I keep an eye on things that connect to the central core (that processes hundreds of mbytes worth of image data per second) The sound engineering is however to control your need to control. Relax where needed and just get the job done in minimal amount of time, but at the same time keep an eye on the core controls that pay the bills (because the competition simply can't throw it together in python in the same way) ---------------------------------------------------------------------- 440bx · 2020-05-08 15:34 Quote from: marcov on May 08, 2020, 05:14:57 pmThat is not about OOP, but about some desperate attempt at total control vs  normal engineering on an always too small time budget. It is about OOP and, it is _not_ a "desperate attempt at total control" as you put it.  It is about controlling what goes into your programs and I believe that is _one_ of the many things a programmer, not only should but, is responsible for exerting along with choices of algorithms, program structure, etc, etc. You're simply advocating "TV dinner" programming.  No doubt if you went to a restaurant and ordered lobster you'd be thrilled they brought you Haggis instead because "total control" is a bad thing.  If you said something about it, the waitress would inform you have a "total control" obsession... eat your Haggis, it might cure the "total control" problem you have.  By the way, the Chef reused the Haggis from the previous client's meal that simply got up and went someplace else.  That's your consolation prize.  It's OOP culinary science, you inherit from the previous customer. ---------------------------------------------------------------------- marcov · 2020-05-08 15:48 Quote from: 440bx on May 08, 2020, 05:34:23 pmYou're simply advocating "TV dinner" programming.  I'm saying TV dinner when you are late during the week is not the end of the world. You can still all go all-gourmet and fun cook all saturday. But that doesn't pay the bills. ---------------------------------------------------------------------- Warfley · 2020-05-08 20:26 In my search for newer studies I've found one from 2014: https://arxiv.org/pdf/1409.0252.pdf This study compares different languages on Rosetta Code examples. The languages in question are C, Go, C#, Java, F#, Python, Haskell and Ruby. Because this compares Bytecode based OOP languages with native procedual languages (Go is somewhat OOP, but also not classical OOP so I leave it out of the comparison for this matter), the comparison of RAM usage or runtime is not really comparing OOP to procedual but more VM vs native. But one thing that might be interesting is about the lines of code (concisenes). Amongst OOP and procedual programs the code size does not differ much. Java is statisticaly significant (5% p value) smaller than C, Java, C# and Go, but between the rest of the three, no statistically significant differences could be found. So there is no inherent  difference in code length with OOP vs procedual. But there is a difference between languages in general (see java vs c#, even though they share a lot of conceptual paradigms). Also what might be interesting for 440bx, if you are so concerned about executable size, you should use bytecode languages like Python, C#, F# or Java, because they are statistically significant smaller (with even p < 1% not 5%) than compiled (procedual) languages. Another study I've found is: https://www.cs.tufts.edu/~nr/cs257/archive/lutz- prechelt/comparison.pdf from 2000 (not so new after all) and it is absolutely terrible. The statistical evaluation is limited to boxplots, in which the median is not even computed correctly, and a p-test using p values of 10% and 20%. They are completely wrong at computing the median and then have the guts to say something like "C++’s median differs significantly from any other language’s." Despite this, if one looks only on the corrected medians, C and C++ are pretty head to head, so there is not really a difference between OOP and procedual. That said, because the statistical evaluation is so bad, nothing could be said clearly. You might ask why I shared this study then, because I suffered reading this and so I had to share it. Then there is https://www.cs.ucr.edu/~neamtiu/pubs/icse11bhattacharya.pdf This study from 2011 directly compares C to C++ in terms of maintainability and error proness, so might even be the most relevant paper. This does so by taking software like Blender which is written in both C and C++ and compares the C and the C++ code against one another. They do so to eliminate variance due to different teams or different project expectations and a different development process. It also tries to compare code of the same developers in both C and C++ parts of the software. They are testing the following hypothesis: QuoteH1:  C++ is replacing C as a main development language. H2: C++  code  is  of  higher  internal  quality  than  C code. H3: C++ code is less prone to bugs than C code. H4 : C++ code requires less effort to maintain than C code.They did this evaluation on the following Projects: Mysql, Blender, Firefox and VLC media player, and they evaluated over their whole existence, i.e. over multiple decades of history. They assessed defect density by searching the bugtracker databases as well as the change logs. Maintainance effort was measured in edited Lines of Code (eLOC) and number of commits. All these assessments where mapped against the release versions, so the increment between releases could be measured. They conduct a Welchs t-test with p-value of 1% (i.e. 99% confidence), for each metric in both the C++ and C code base. Now to their results: H1 C++ replaces C: In all projects except blender the C++ code is increasing. The increase is statistically significant with the 99% confidence t-test H2: C++ is less complex than C. For this they measure  cyclomatic complexity and interface complexity, which is: QuoteCyclomatic complexity is the number of logical pathways through a function Interface complexity is the sum of number of input parameters to a function and the number of return states from that functionBoth seem to be academically established methods for evaluating complexity of a program. Here they found that C++ code is statistical significantly less complex than C code for all 4 projects and both metrices. But it should be noted that for VLC the complexity was initially the same, but diverged later on, while in the other projects it was different from the beginning. H3: C++ is less error prone to C Here they mesure the defect density, i.e. the number of bugs in a version divided by the changes done to that version (i.e. #bugs/eLOC). They also assess the number of bugs in relation to the change in edited lines of code (i.e. #bugs/∆eLOC), because only a fraction of code changes are in the new version (as the rest is still on the development branch) and so this is to account for this. Again for both metrices the result is that C++ is statistical significantly less error prone than C code overall. For MySQL neither of the metrices was statistically significant, which might be due to the unavailability of the bugtracker database (i.e. they only had the changelog to track bugs and therefore only a very limited sample size) and to quote the paper: Quotethe mean defect density values for the C sets can be up to an order of magnitude higher than the mean values for the C++ sets And lastly H4: C++ code requires less effort to maintain than  C code. About the metrices they are choosing are #commits/eLOC and #commits/∆eLOC Resoning: QuoteA widely used metric for effort is the number of commitsdivided by total eLOC.  To avoid considering those parts of code which remain unchanged in a new release [...] we also measure number of commits divided by ∆eLOCResult: For #commits/eLOC no statistical significance over all projects (there is for firefox but not in general) for #commits/∆eLOC C++ has a statistically significant lower maintenance effort. Respeced Journal, peer reviewed, 52 citations. So to summarize this with the older studies, we now have considered 4 studies regarding productivity. The first tested reusability and productivity by time consumption, number of runs and runtime errors, and showed that reusability in OOP let's it excell at productivity opposed to procedual programming. The second study at IBM which measured productivity as LOC/manhours could not find a productivity difference between OOP and procedual projects even on a large scale. The maintainability study showed that (3 level) inheritance can improve maintainability in the same language, and this study showed that OOP C++ code is less error prone and less complex (also to a certain extend better maintainable, even though the results are not as clear cut here) So from a productivity standpoint this is a pretty solid case for OOP. I wanted to look into papers about performance, but now after another 4 hours of literature search I am simply to tired. But at least I can now say that evidently OOP gives you a higher productivity and better reusability than procedual programming. It can help to reduce bugs and can make maintenance easier. ---------------------------------------------------------------------- 440bx · 2020-05-08 21:20 Quote from: Warfley on May 08, 2020, 10:26:39 pmAlso what might be interesting for 440bx, if you are so concerned about executable size, Executable size reflects on the compiler's ability to optimize code which includes being able to remove unused code.  That's why I pay close attention to executable size, because it tells me a fair amount about the compiler's ability to optimize code.  It's not the disk space it occupies I care about, there is plenty of that.  I do somewhat care about the waste of memory the unwarranted size causes. Quote from: Warfley on May 08, 2020, 10:26:39 pmyou should use bytecode languages like Python, C#, F# or Java, because they are statistically significant smaller (with even p < 1% not 5%) than compiled (procedual) languages. I use interpreters for throw away programs.  The one I use the most is AWK.  It's quite often that I write an AWK script I've already written in the past because it takes longer to find it than to rewrite it.  I don't even keep track of those. Everyone can mention all the studies they want but, the reality is this: a program written procedurally is _consistently_ smaller than its OOP counterpart.  I am yet to see _one_ exception to that (using the same compiler.)  _Very_ often, the procedural program is faster than the OOP one.  In that area, there are times when the OOP rendition is a little faster than the procedural rendition because very few, if any, Pascal compilers flatten the stack of nested procedures which is a feature I use _extensively_.  I am willing to pay the performance cost for code that is well structured. OOP is great for programmers addicted to exception handlers, global variables (classes allocated on the stack heap share many characteristics with global variables), run time type information because instead of designing upfront they find it more convenient to "if a is someclass then...",  breaking down code into tiny little methods that have no logical purpose, they are there only to give the possibility of overriding them, the consequence of that, is a program that is a lot closer to a jigsaw puzzle than a piece of software and, the list of deficiencies in OOP goes on and on and on... An example of the mess OOP makes is found in this thread  https://forum.lazarus.freepascal.org/index.php/topic,46097.30.html  a trivial little function gets broken down in 4 pieces, handles are left open that should be closed and a number of other deficiencies.  The procedural code is atomic and crystal clear.  BTW, I've reused variations of that function plenty of times. 3 classes involved in mapping a file.  That's not code reuse.  It's shredding code into pieces and, one of the many undesirable consequences of that is, a larger executable size. I can post a really simple (one baby step above "hello world") program here that is less than 100K (32bit FPC, 33K Delphi 2) and, I seriously doubt the OOP rendition wouldn't be at least twice as large and, when it comes to consuming resources, it would likely use as much as 10 times what the procedural rendition uses.  That's on Windows, on Linux, given what you've said, it would probably approach a megabyte.  And the little program I'm thinking about doesn't use the Windows API to format and do output, plain Pascal stuff.   Of course, it's a graphical app, Linux and g++ need not apply, they'll be left in the dust. That's the reality. The results stare everyone in the face.  The real problem: writing procedural code takes more time and effort, that's the problem.  TV dinners are faster to microwave than preparing a real meal.  That's a fact, no studies needed to point that out. ---------------------------------------------------------------------- marcov · 2020-05-08 21:22 To be honest, I throw all benchmarks that test one straight piece of code (no multimodule) directly into the rubbish bin without looking. It is usually not worth the time as benchmark for real world general development, unless you have some use for that exact problem in some ultra tight loop somewhere. ---------------------------------------------------------------------- Warfley · 2020-05-09 00:59 Quote from: 440bx on May 08, 2020, 11:20:25 pmI can post a really simple (one baby step above "hello world") program here that is less than 100K (32bit FPC, 33K Delphi 2) and, I seriously doubt the OOP rendition wouldn't be at least twice as large and, when it comes to consuming resources, it would likely use as much as 10 times what the procedural rendition uses. Hello name procedual: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Test;var  name: String;begin  ReadLn(name);  WriteLn('Hello ', name);end.Hello Name OOP: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Test; type  TGreeter = object  private    FName: String;  public    procedure ReadName;    procedure Greet;  end; procedure TGreeter.ReadName;begin  ReadLn(FName);end; procedure TGreeter.Greet;begin  WriteLn('Hello ', FName);end; var  g: TGreeter;begin  g.ReadName;  g.Greet;end. Compiled with fpc -O3 ... Size: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 181800 test181800 ooptestLiterally not a single byte overhead due to using oop. Also when running both the Time taken as well as the memory consumption during runtime is exactly equal. So no matter what procedual program you are writing, I will be able to take that very same source and OOPify it with no overhead (or at most 10%). QuoteThat's on Windows, on Linux, given what you've said, it would probably approach a megabyte.I am under linux, let me check: Procedual: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include  int main() {  printf("Hello World\n");  return 0;} OOP: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include  struct Greeter {  void greet() {    printf("Hello World\n");  }}; int main() {  Greeter g;  g.greet();  return 0;} Size: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 16544 cpptest16544 ctestYou are just off by a factor of 100. Again, give me any C source and I will be able to OOPify it without any overhead. OOP does not have any inherent overhead. Face it or lie to yourself. Here are hard numbers that prove it. All you do is claim. You claim OOP adds bloat, it doesn't. Procedual projects will more productive than OOP project in the long run, they aren't. All you do is claim, claim and claim again. One wrong thing after another. I've proven it for the claims that are verifable (with a simple experiment). For those claims about productiveness (which is nothing one can prove mathematically or by example) I've searched multiple studies. What have you provided as evidence? Put your money where your mouth is and give me a source code I can't OOPify with less than a factor 10 of overhead. No not simply an executable, a source code where I will replace the procedual code with OOP code (by adding classes/objects), because everything else would not test anything inherit to OOP but only who of us the the better programmer at reducing size, which I will admit I am not, because it's something I don't care about. ---------------------------------------------------------------------- 440bx · 2020-05-09 02:20 Quote from: Warfley on May 09, 2020, 02:59:20 amLiterally not a single byte overhead due to using oop. Also when running both the Time taken as well as the memory consumption during runtime is exactly equal.That's quite an achievement, you used static objects.  Try the same thing with a class instead (and no class/static fields.)  IOW, the waaaay most common case, not the exception which is rarely done.  It would be one sorry compiler that couldn't make static objects the same as procedure calls because they are the same thing. Quote from: Warfley on May 09, 2020, 02:59:20 amSo no matter what procedual program you are writing, I will be able to take that very same source and OOPify it with no overhead (or at most 10%). I like the last part "at most 10%"... that's good.   What you're asking for is, for me to give you a program that is properly designed, which means, it can easily be implemented with static objects and then, you are going to claim that's the common case.  Nice try but... try again. Attached is a program - simple one - but, no source, it should take less than 20 minutes to implement using OOP then we compare (I don't think it even took me 20 minutes to write it.)  I'm not going to solve the OOP problem for you so you can use static objects.  You want to use static objects ?, you'll have to design the program to enable their use, just like I do (but in procedural code, of course.) The program is graphical but, that shouldn't matter, you can use Lazarus to implement it.  You don't need to know anything about the Windows API, Lazarus and FPC will do everything for you.  The program makes very little use of the Windows API, mostly calls to TextOut (I believe there is a method in one of the classes that does it for you... no need for you to even code a call to that API) and, it's way larger than anything I would normally code because it uses the sysutils unit which I never use except in test programs.  IOW, that program is bigger than if I had written it as a "real" program (I suspect I could easily cut 20K out of it in a few minutes.)  It's attached to this post.  NOTE: the program is a test for the GetFileInformationByHandle, therefore it calls that API but, you don't have to, you can use whatever gets the _same_ job done with Lazarus.  As long as it's functionally the same... use whatever you want (except assembly code... mine doesn't use any.) One requirement: the OOP version has to be functionally identical. Which, specifically, means this: a. start one instance of the program, b. without closing the currently running instance, change the executable's read only attribute, c. run a second copy. You should notice that the first copy and the second copy list a different set of attributes for the executable (they should because the read only attribute was changed in between.)  You should also notice that the fields moved downwards to make room for the additional attribute.  I expect the OOP version to do as much.  Also, fields should align properly and there should be no ":" on lines where there is no label. That's it... it's hard to offer something simpler than that, other than "hello world".  Let's compare that.  32bit, not even 64bit.  BTW, the version attached to this post is compiled with FPC -O3 and "smaller rather than faster".  The Delphi 2 version is not even half the size but, start by matching what FPC produced. Quote from: Warfley on May 09, 2020, 02:59:20 amthe the better programmer at reducing size, which I will admit I am not, because it's something I don't care about. I'm no expert on reducing size either... I expect the _compiler_ to do that, that's its job, not mine!. ---------------------------------------------------------------------- Martin_fr · 2020-05-09 03:46 Quote from: 440bx on May 09, 2020, 04:20:22 amAttached is a program - simple one - but, no source, Again 2312 bytes.... QuoteThat's quite an achievement, you used static objects.  Try the same thing with a class instead (and no class/static fields.)  IOW, the waaaay most common case, not the exception which is rarely done.  You ask for a chainsaw to be used to remove a splinter. If someone demanded unnecessary additions to the procedural code, it would grow too. Now yes, of course: the mindset. (the really - by now - famous mindset). According to this lore, all or nearly all OOP programmers will use inappropriately costly means. Strange only, that none of the many OOP programmers that I know, fall into that category. Let me guess: We are the rule that confirms the exception. Further note: "inappropriately costly" Yes, I have used code that compiled into more bytes than absolutely needed, and may also have used some extra CPU cycles. Lets see, I started that a long time back. (I am old enough). When I started this, OOP was not yet the tool of the masses. Compilers available to me, did not even include it. So at a time, when I had no knowledge of OOP at all, when I could not have been influenced by it, and could by no means have had that famous mindset, at that time I already wrote code that may have produced a few extra bytes. Code that was more generic, than it absolutely had to be. Code that could be re-used, not only for the exact same, but also for similar issues. Much of that sort of code is commonly called "framework", and frameworks do actually often add more to your executable than absolutely needed. That was already the case when compilers did not even have OOP. (In this context: "compilers" => compilers I used / that would have been somewhere in the 80ties, IIRC) Generic re-usable code is something OOP inherited (pun intended) from procedural programming. So that is in no way part of the famous mindset. You demand classes. But classes are like an investment. You first pay, and reap the money later. If you have neither need for either inheritance/polymorphisms or for multiple instances or maybe a few other reasons, then you do not need them. In procedural you would not call "pInt := getmem(sizeof(integer)" if all you ever need is ONE single integer. Why do you demand such things to be done in OOP? The mindset? But, if that mindset existed, then you would not need to demand such usage, it should be caused by that mindset without your demand. There are cases where OOP will be smaller (not necessarily with every compiler though). And of course, not if you implement your own OOP in procedural code. (I.e. simulate VMT) If you have a class many different inherited class, each having/needing a big amount of overridden methods. In procedural, you do not have a class. So you would have something like an "enum datatype". Then when it comes to calling the correct subroutine for the datatype, you end up with a huge "case of" statement. That generates quite some code. Oh yes, you can have it smaller, a jump table. Actually a jump-table for each of the many sets of procedures that may depund on "enum datatype" values. Well that is just a matrix transformed VMT. So if you want to avoid that, then your procedural approach needs more size. ---------------------------------------------------------------------- 440bx · 2020-05-09 04:53 Quote from: Martin_fr on May 09, 2020, 05:46:58 amAgain 2312 bytes.... Wonderful ... now where is the executable ?... did you forget to attach it ? Quote from: Martin_fr on May 09, 2020, 05:46:58 amYou ask for a chainsaw to be used to remove a splinter. If someone demanded unnecessary additions to the procedural code, it would grow too. No.  Simply no.  You know just as well as I do that it's almost a reflex in OOP programmers to create classes.   Answer this: what percentage of static objects are there in Lazarus and what percentage are classes that use polymorphim ?  Quote from: Martin_fr on May 09, 2020, 05:46:58 amNow yes, of course: the mindset. (the really - by now - famous mindset). Yes the mindset, which among many other things, causes OOP programmers to choose classes over static objects.  And, just in case you'd try to contest that, from the wiki page https://wiki.freepascal.org/Object_Or iented_Programming_with_Free_Pascal_and_Lazarus Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Objects are not used very often by themselves in Free Pascal and Lazarus; instead, Classes are used very widely. Don't miss the three letter word "not" in that sentence.  It seems I am not the only one who "demands" classes because those are used very widely. Quote from: Martin_fr on May 09, 2020, 05:46:58 amAccording to this lore, all or nearly all OOP programmers will use inappropriately costly means. According to what I've seen and, what is stated in the wiki, that seems to be the case. Quote from: Martin_fr on May 09, 2020, 05:46:58 amStrange only, that none of the many OOP programmers that I know, fall into that category. Are you suggesting that a rogue programmer surreptitiously inserts classes in the code written by OOP programmers in the cover of the night ?.   That would be terrible but, at least it would explain how the classes that got there. Quote from: Martin_fr on May 09, 2020, 05:46:58 amLet me guess: We are the rule that confirms the exception. The rule seems to be to prefer classes over objects.  I know you're going to claim that classes have class methods which are basically the same thing as methods in a static object but, to that, I'll just ask for a comparison of the number of class methods vs non-class methods. Quote from: Martin_fr on May 09, 2020, 05:46:58 amGeneric re-usable code is something OOP inherited (pun intended) from procedural programming. Quite likely true but, OOP doesn't seem to have made very good use of it.  Instead, code re-use consists of putting most of the inheritance in the executable.  I have to admit, it's a very generous paradigm. Quote from: Martin_fr on May 09, 2020, 05:46:58 am So that is in no way part of the famous mindset. What's part of the mindset and, the cause of it's not working well, is how reuse is accomplished. Quote from: Martin_fr on May 09, 2020, 05:46:58 amYou demand classes. But classes are like an investment. You first pay, and reap the money later. If you have neither need for either inheritance/polymorphisms or for multiple instances or maybe a few other reasons, then you do not need them. I "demand" classes because that's the way most OOP programming is done (see wiki article I mentioned above.)  Lazarus is quite likely to be a good example of that.   What I also "demand" is that the program be designed without _me_ providing a good, OOP free, solution beforehand for it to be OOP-ified in a completely different way had I not provided the solution. That reminds me... where is that 2312 byte executable ?  In some assembly language forum maybe ? Quote from: Martin_fr on May 09, 2020, 05:46:58 amThere are cases where OOP will be smaller (not necessarily with every compiler though). Must be something that will come with next appearance of Jesus Christ because I am yet to see an OOP program be smaller than the equivalent procedural program.  I suppose it's possible... miracles happen.  The day I see one of those, I'll send it to Ripley's Believe or not. Quote from: Martin_fr on May 09, 2020, 05:46:58 am Actually a jump- table for each of the many sets of procedures that may depund on "enum datatype" values. Well that is just a matrix transformed VMT. So if you want to avoid that, then your procedural approach needs more size. First, it is relatively rare the case of having to have a table of function pointers and, in the great majority of those already rare cases, a single table is all that's needed.  Even in the rare cases that a jump table is needed, it doesn't have all the overhead present in VMTs to support "features" like class names and other useless things I don't remember at this time. Are you attaching your OOP implementation of the little procedural program I offered in your next post ?... that would be nice.   We could compare results for a change. ---------------------------------------------------------------------- munair · 2020-05-09 06:54 I think we could agree on that moderate forms of OOP are legit if it increases program structure, readability and ease of maintenance, even if programs get somewhat (but not much) larger as a result. However, when OOP becomes more complex, it increases the risk that programmers lose sight of what is happening, which will have a growing impact on readability, maintainability and also portability. In general, the more (hidden) encapsulation, the harder it will be to port code to another language, not to mention the risk of code duplication. So it is not just how much faster code can be written using OOP, but also how maintainable and perhaps portable the code is in the long run. One of the biggest problems with more complex OOP is inheritance. While seemingly a great feature, code easily breaks when changes are made up the hierarchy. This is one of the reasons why some language developers decided not to implement classes; there is a big difference between simple objects retaining transparency and classes that support all the fancy stuff whereby much is being kept out of a programmer's sight. ---------------------------------------------------------------------- Thaddy · 2020-05-09 10:03 Quote from: munair on May 09, 2020, 08:54:37 amOnee of the biggest problems with more complex OOP is inheritance. While seemingly a great feature, code easily breaks when changes are made up the hierarchy. This is one of the reasons why some language developers decided not to implement classes; there is a big difference between simple objects retaining transparency and classes that support all the fancy stuff whereby much is being kept out of a programmer's sight. Not if you have a proper editor like Lazarus or Delphi. E.g: Code completion wil show everything available from the inheritance tree. I am used to sometimes very complex inheritance and working in larger teams 30+ developers. ( Delphi, C++ and C#). In such environments a proper OOP framework is often essential. It avoids programmers start duplicate coding. But if I write something small, like a utility, I often use procedural style too. But the core development in all three languages is done in OOP. 35+ years of development and 28+ OOP years working in teams have learned me that OOP is a life saver and in teams much cheaper. ---------------------------------------------------------------------- Warfley · 2020-05-09 11:00 Quote from: 440bx on May 09, 2020, 04:20:22 am[..] Don't you realize how stupid this is? You claim this is about OOP, but when I ask to OOPify a procedual project you say the project needs to be designed from ground up, so it's not about OOP but about design practices. Then your whole argument with Classes vs objects is only true for Pascal. So your point is not even about design in OOP in general, it's about design in OOP in Pascal. If you don't see the difference between "OOP is bad" (what you claim you are arguing for) and "Common usage and design of OOP programs in the Pascal community is bad" (what you actually arguing for), I'm sorry I can't help you. Even if you are true about this, tell me why the latter implies the former, and how therefore performance optimized OOP in C++ or Rust, following one of the many performance guidelines (like described in this https://books.google.de/books?hl=de&lr=&id=IR- MQiktobMC&oi=fnd&pg=PR13#v=onepage&q&f=false), will be worse than a procedual implementation. If not all you've proven is that code that is not designed to be as efficent as possible, will not be as efficent as possible. Even I don't need a paper or mathematical prove for this. Your whole mindset theory is based on your personal experiences, which you already shown are quite limited. I agree that Pascal or Java or C# programmers (which is not surprising because both Java and .Net are heavily inspired from the RTL and VCL of delphi) usually use less efficient classes over procedual code. That said C++ or Rust programmers don't. If that mindset theory is true, it shouldn't be so hard to find a paper about that... You know something that is empirical and not: "It's true because I say so". Because you have already shown that your experience in the world of OOP is not very deep if you don't even know about C++, one of the most prominent OOP languages available Quote from: munair on May 09, 2020, 08:54:37 amHowever, when OOP becomes more complex, it increases the risk that programmers lose sight of what is happening, which will have a growing impact on readability, maintainability and also portability.Every program getting more complex becomes less maintainable. But that this is more the case for OOP than for procedual is simply not true I've postet 4 studies about OOP that show: 1. OOP code is less complex, 2. OOP code is less error prone and 3. moderate levels of inheritance (3 levels) actually improve maintainability (but this effect vanishes at 5 levels). So you can have really complex OOP projects that, as long as they don't overuse inheritance (5 levels of inheritance is already pretty deep), it will most likely be better maintainable than a procedual equivalent. I am working on a pretty large C++ project with somewhat around 100 KLOC and using OOP everywhere, and I think there is not a single inheritance chain exceeding 4 levels of inheritance. That said, all three of those traits, readability, maintainability and portability, are much more dependent on design than on the paradigm used. This is for example a big part of model driven development, where models are used (e.g. UML/OCL) to design the program structure beforehand, which will then be used to generate sources, which then only need to be ammendet with specific functionality. This way, to understand what the program is doing (i.e. readability) you don't need to read the source at all but only the Models, and only look into the sources for implementation details. It targets maintainability because changes in the models correspond to changing hundreds of lines of code at once through the code generation. Portability is ensured because only the implementation specifics need to be changed, the models are by their nature completely independent. There are other development techniques that try to handle complexity, this is just one example, and while MDD is often associated with OOP, there is nothing stopping one from creating a procedual model and using this (even though there are no tools I know of for procedual MDD). ---------------------------------------------------------------------- Martin_fr · 2020-05-09 13:43 Quote from: 440bx on May 09, 2020, 06:53:32 amQuote from: Martin_fr on May 09, 2020, 05:46:58 amAgain 2312 bytes.... Wonderful ... now where is the executable ? You know that I know that you know what I meant. QuoteQuote from: Martin_fr on May 09, 2020, 05:46:58 amYou ask for a chainsaw to be used to remove a splinter. If someone demanded unnecessary additions to the procedural code, it would grow too. No.  Simply no.  You know just as well as I do that it's almost a reflex in OOP programmers to create classes.   Answer this: what percentage of static objects are there in Lazarus and what percentage are classes that use polymorphim ?  Are you talking about OOP, or OOP in a specific dialect of a specific language? Tell me, why so many people made such a fuzz about "advanced records"?  (Which is basically the new "object", but with even less features...) But more to what actually matters. I have several times stated: "no one shoe fits all" (I take it, you know what it means). So yes, there are programs where procedural is more suited, but your claim that "any and all program can be made in a more efficient way using procedural", to that I say: bollocks. Hello world is typically written in procedural, because there is no benefit in doing it OOP. So what? I never claimed the opposite. Yet it can be done OOP, without any loss to the binary result. Never mind if that is "your terms of OOP". Actually you said, anything but assembler. So that was 100% fulfilled. You say the average OOP coder does not use "object".... - So potentially, you dictate an OOP as used in some specific dialect of some specific language? - So why then are people so happy to see advanced records? (sorry I repeat myself. Probably this text is OOP, so it is bloated by unnecessary re-use ) Here is another think about OOP coders. (Except maybe for java). They usually use a mix of OOP and procedural. Look through the LCL/RTL => there are plenty of normal procedures. Why, because they have both available, and can use both, depending an what is better suited. Now anticipating what may be brought forward next. There are indeed pieces of code (in frameworks, and in small stand- alone apps) that use OOP where maybe procedural would have done (or that use certain OOP techniques where a simpler one had done). There are often good reasons for that. In the very same way, as the "more generic / re-usable code, even in procedural" that I wrote about earlier, the choice of tools for implementing a program, is not just done by what is needed right at the time. There is something called foresight. And that may very well and reasonable mandate such usages. (And as pointed out with "more generic" the concept of foresight applies to procedural too) To be honest, for many small and simple tasks, it is a lot easier to write something in procedural style. But be aware, if that code lives on, and grows. I have been there, cursing myself. Because then all the sudden I was faced with some huge procedural project. Despite being well written, it cost a fortune in extra maintenance. (compared to the probable cost an OOP equivalent would have had) So yes, I should have had the foresight, and done it OOP from the start. Maybe "foresight" is what you refer to by the "oop mindset"? And there may be another the problem.... Though I have not looked at the details, and I can not say if it really applies. So far you propose what to implement for the comparison. I do trust you do not intentionally choose programs where procedural is the better fitting shoe. But that could still accidentally be the case. That is why I proposed fpdebug. I know that it is unrealistic, because it is to much work. (And it would be too much work for me too, as for a real comparison, I would have to do quite a bit of OOP refactoring). I chose fpdebug because the data (as defined by the dwarf standard) that fpdebug works on, makes it a good fit for OOP. There will be smaller examples, but I could not be bothered to come up with one. Also fpdebug is bigger, and that would be a good way to see that your claim holds up, that procedural is fine and maintainable for bigger projects. QuoteQuote from: Martin_fr on May 09, 2020, 05:46:58 amStrange only, that none of the many OOP programmers that I know, fall into that category. Are you suggesting that a rogue programmer surreptitiously inserts classes in the code written by OOP programmers in the cover of the night ?.   That would be terrible but, at least it would explain how the classes that got there. I did not even think of that. But its worth being investigated. It would guess its a procedural coder, who does so as counter attack. Maybe you could have a look into that? You have better ties to procedural coders.   ---EDIT Quote from: 440bx on May 09, 2020, 06:53:32 amclasses that use polymorphim ?  That is exactly part of what I wrote above. Take "hello world" => Even the most fanatic OOP coder (let alone the average) would be hard pressed to use polymorphism for it. Not impossible, but really not normal. (I do not know, do procedural coders think that is normal oop practice?) Polymorphism is not the only reason for using classes. But some reason can usually be found. And yes, that includes foresight. It also includes beginners, who still have to learn the ropes. But beginners (and associated coding issues) exist in procedural code too. ---------------------------------------------------------------------- 440bx · 2020-05-09 16:23 Quote from: Warfley on May 09, 2020, 01:00:28 pmDon't you realize how stupid this is? You claim this is about OOP, but when I ask to OOPify a procedual project you say the project needs to be designed from ground up, so it's not about OOP but about design practices. I clearly see how "stupid" it is.  I've offered multiple projects for you or anyone else to OOP-ify and so far, the result has been a masterpiece "hello world".  Very impressive!.  Yes, I expect OOP programmers to design their programs because most programmers do, I understand that for an OOP programmer, designing might be an unusual activity but, it isn't supposed to be. I've offered a number of small programs that are trivial in procedural programming, they should be equally trivial to implement in OOP. Quote from: Warfley on May 09, 2020, 01:00:28 pmThen your whole argument with Classes vs objects is only true for Pascal. So your point is not even about design in OOP in general, it's about design in OOP in Pascal.You might have somewhat of a point there but, it isn't limited to Pascal.  MS has provided the option to its C++ programmers to mix native/compiled C++ code with .net managed code.  Quote from: Warfley on May 09, 2020, 01:00:28 pmIf you don't see the difference between "OOP is bad" (what you claim you are arguing for) and "Common usage and design of OOP programs in the Pascal community is bad" (what you actually arguing for), Great, put the OOP deficiencies on the backs of Pascal programmers, so nice of you. Quote from: Warfley on May 09, 2020, 01:00:28 pmI'm sorry I can't help you. Please don't be.  I'm very pleased you won't. Quote from: Warfley on May 09, 2020, 01:00:28 pmYour whole mindset theory is based on your personal experiences, which you already shown are quite limited. I agree that Pascal or Java or C# programmers (which is not surprising because both Java and .Net are heavily inspired from the RTL and VCL of delphi) usually use less efficient classes over procedual code. That said C++ or Rust programmers don't. My mindset is based on the results I've seen in a number of languages and, it is consistent, using OOP leads to less than desirable results compared to the same program written using procedural and structured programming techniques. "hello world" class program are a bit of an exception because, while they don't produce a larger executable, they do require a lot more code (which is good when productivity is measured in SLOCS.) Quote from: Warfley on May 09, 2020, 01:00:28 pmIf that mindset theory is true, it shouldn't be so hard to find a paper about that... Hold the papers... show me _results_ then we can compare the _results_.  I've offered a number of options and can offer a few more if need be but, the implementation will be up to _you_.  IOW, I am not providing the solution, only the _result_ which, you should have no problem matching if there is any truth to what all those papers say. Quote from: Warfley on May 09, 2020, 01:00:28 pm You know something that is empirical and not: "It's true because I say so". You are correct, something isn't true because I say so and that also applies to what OOP programmers say too.  Let's see what is true or isn't true by comparing _results_ instead of words.  I've provided a few _results_ and so far, no OOP programmer has provided anything to compare them with (except for the historically useful "hello world" program in OOP which took about 5 times more lines of code than the procedural version takes.) Quote from: Warfley on May 09, 2020, 01:00:28 pmBecause you have already shown that your experience in the world of OOP is not very deep if you don't even know about C++, one of the most prominent OOP languages availableThat's a good argument.  I have to make the mistakes, it doesn't suffice to look at the ones made by those who use the paradigm.   No one can claim that hitting a tree at 100MPH, without seat belts on and in a VW bug, is bad until they've done it.  What a solid argument that is.  Quote from: Warfley on May 09, 2020, 01:00:28 pm 1. OOP code is less complex, Your "hello world" certainly didn't show that.  It took 5 or more times the number of lines of code than in procedural programming.  The procedural rendition is obvious "writeln('Hello World');", the OOP one requires reading the object definitions, how they are implemented and used.  It seems a lot more complex to me than the one-liner in procedural programming. Quote from: Warfley on May 09, 2020, 01:00:28 pm 2. OOP code is less error prone Again, based on your "hello world" example that claim is false.  The more lines of code, the greater the probability for a bug to exist. Quote from: Warfley on May 09, 2020, 01:00:28 pm and 3. moderate levels of inheritance (3 levels) actually improve maintainability (but this effect vanishes at 5 levels). The cops must get suspicious after inheriting that many times.  That could have some very disadvantageous "side effects".  Seriously, inheritance leads to "onion programming", umpteen layers of code, few if any fulfill a logical purpose but are simply there to provide the option of overriding the method that implements them. Quote from: Warfley on May 09, 2020, 01:00:28 pmSo you can have really complex OOP projects that, as long as they don't overuse inheritance (5 levels of inheritance is already pretty deep), it will most likely be better maintainable than a procedual equivalent.Your OOP "hello world" program showed that OOP can achieve complexity quickly and without the use of inheritance.   That "hello world" program you wrote isn't totally useless after all. Quote from: Warfley on May 09, 2020, 01:00:28 pmThat said, all three of those traits, readability, maintainability and portability, are much more dependent on design than on the paradigm used. It is quite true that they greatly depend on design but, it is also true that the possible designs are _greatly_ influenced by the paradigm used and, as your "hello world" program shows, the resulting design does _not_ emphasize simplicity and ease of understanding but, it very nicely emphasizes productivity when measured in SLOCS.  It's got that going for it. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmYou know that I know that you know what I meant. Yes, I know.   I also know you have more than enough knowledge and experience to implement that simple little program using OOP in very little time.  If you did that then we could compare actual executable sizes, use of resources and, maybe even possibly implementation by comparing the source of both programs. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmAre you talking about OOP, or OOP in a specific dialect of a specific language? Are you trying to say that OOP in Pascal is "not so good" but there are "good" implementations of the paradigm in other languages ? The main characteristics of OOP are inheritance and polymorphism.  It's quite likely that any variant of OOP that implements those characteristics are flawed by design.  Those are not features that should be used casually as OOP does because they, very rapidly, generate complexity. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmTell me, why so many people made such a fuzz about "advanced records"?  (Which is basically the new "object", but with even less features...)I am not aware of any fuzz made by anyone about advanced records, therefore, no comment. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmbut your claim that "any and all program can be made in a more efficient way using procedural", to that I say: bollocks. I have provided multiple ways for you or anyone else to prove that is "bollocks" but, instead of being shown a _result_ that proves it, what's offered are studies and more text.  That is simply not convincing. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmYet it can be done OOP, without any loss to the binary result. You conveniently forgot to mention that what is a simple one-liner in procedural programming ended up being about 10 or 15 lines in OOP.  That's really good for maintenance and ease of understanding. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmSo that was 100% fulfilled. You're right.   It was 100% fulfilled with a significantly greater number of lines of code.  A good thing when productivity is measured in SLOCS. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmYou say the average OOP coder does not use "object".... - So potentially, you dictate an OOP as used in some specific dialect of some specific language? - So why then are people so happy to see advanced records? (sorry I repeat myself. Probably this text is OOP, so it is bloated by unnecessary re-use ) I stand by that claim.  OOP programmers don't make use of objects nearly as often as they use classes.  I don't dictate anything.  In the thread I previously referenced https://forum.lazarus.freepascal.org/index.php/topic,46097.30.html I didn't ask for anything other than an OOP implementation of that simple function.  No advanced records were used, no objects were used but, classes and exceptions were used (and it wasn't anything I "dictated".) Quote from: Martin_fr on May 09, 2020, 03:43:19 pmTo be honest, for many small and simple tasks, it is a lot easier to write something in procedural style. Thank you for acknowledging that. Not to mention faster since it takes less code and the result is easier to understand and maintain.  I suppose that's your way of saying that the small programs I offered so far are better done in procedural programming than OOP.   If that's what you're saying, I agree but, I also believe it is just as true for larger programs. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmit cost a fortune in extra maintenance. (compared to the probable cost an OOP equivalent would have had) Comparing fact to something that is just "probable" is not convincing.  You buy a lottery ticket and it is probable you win but, it doesn't happen to many of those who went the "probable" way. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmI do trust you do not intentionally choose programs where procedural is the better fitting shoe. On the contrary, I am offering programs which are _proven_ to be doable using static objects which is the one case where OOP may match procedural programming as far as the size of the executable but, even in that case, it cannot match the simplicity and conciseness of the procedural implementation. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmBut that could still accidentally be the case. An accident that is in favor of OOP and the (invalid) points OOP programmers are attempting to make in this thread. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmThat is why I proposed fpdebug. If OOP makes things easier as OOP programmers are claiming in this thread then it should make things easier every time.  Procedural/structured programming does, at least when compared to OOP. Quote from: Martin_fr on May 09, 2020, 03:43:19 pmTake "hello world" => Even the most fanatic OOP coder (let alone the average) would be hard pressed to use polymorphism for it. Fortunately, there was no need for that.  The OOP "hello world" clearly showed it takes more work in OOP than in procedural programming even in the absence of polymorphism. Quote from: Martin_fr on May 09, 2020, 03:43:19 pm(I do not know, do procedural coders think that is normal oop practice?) I can't be abnormal, it is commonly present in OOP code. Granted, except "hello world" class programs. ---------------------------------------------------------------------- Warfley · 2020-05-09 21:05 Quote from: 440bx on May 09, 2020, 06:23:06 pmI clearly see how "stupid" it is.  I've offered multiple projects for you or anyone else to OOP-ify and so far, the result has been a masterpiece "hello world".  Very impressive!.  Yes, I expect OOP programmers to design their programs because most programmers do, I understand that for an OOP programmer, designing might be an unusual activity but, it isn't supposed to be. So there are two options, either you are talking about design, or you are talking about a language feature. If you want to test anything you need control. E.g if you want to test if a language feature like OOP is bad, you need to control for all other factors, amongst others is design. Thats simply how science works. You only provided a few executables. How the hell does this control for any variables? If you would have read the papers I've posted you might have seen that every experiment in there was controlled. The Firefox and blender one, e.g. was controlled by looking into code of the same projects, written by the same programmers. The paper about reusability controlled by providing the exact same functionality in different paradigmes as reusable components. So when you claim QuoteI've offered a number of small programs that are trivial in procedural programming, they should be equally trivial to implement in OOP.shows that you have absolutely no clue about scientific workings at all. Even if we would do such a thing, it would tell you absolutely nothing, because it controlls for nothing. It is as good as an indicator on what performs better as flipping a coin to decide... No forget about it, when flipping a coin at least we can estimate the error probability. QuoteYou might have somewhat of a point there but, it isn't limited to Pascal.  MS has provided the option to its C++ programmers to mix native/compiled C++ code with .net managed code.  Yes, you can use .Net in C++. But what does that have to do with the point? It shows even more how much you are grasping at straws, because .Net C++ is a small fraction of the C++ code out there. It's a decision one can make if he wants to. Most C++ developers don't use it (from my personal experience) QuoteGreat, put the OOP deficiencies on the backs of Pascal programmers, so nice of you.I'm not doing anything. You haven't brought up any argument against OOP at all. All you complained about is how programmes from your personal experience use OOP. If you want to prove me wrong it's really simple, just give me an argument why OOP on it's own is bad. I mean inherently. An argument that holds true at least for the most prevalent Languages supporting OOP (Java, C++, Javascript, C#, Python would be enough). It does not even need to hold for some niche implementation of OOP like D or OCaml. QuoteMy mindset is based on the results I've seen in a number of languages and, it is consistent, using OOP leads to less than desirable results compared to the same program written using procedural and structured programming techniques.Yes but you are still missing control. What is desirable and was what you describe as desirable the goal of these OOP projects. Because if you don't control for anything, all your experience is useless. What distinguishes measurements from anecdotes is control. If you don't have control it's completely useless. Quote"hello world" class program are a bit of an exception because, while they don't produce a larger executable, they do require a lot more code (which is good when productivity is measured in SLOCS.)When was productivity ever measured in SLOCS? From all I can recall everything I presented productivity was measured in SLOC/Time, you know because writing more code requires more time. Also you haven't given me any alternative to this measurement for that paper. I mean sure you can complain as much as you want, but some data even if the metric might not be fully accurate is still better than no data. Especially if that data was peer reviewed and cited. QuoteHold the papers... show me _results_ then we can compare the _results_.  I've offered a number of options and can offer a few more if need be but, the implementation will be up to _you_.  IOW, I am not providing the solution, only the _result_ which, you should have no problem matching if there is any truth to what all those papers say.Until you understand the concept of scientific measurements and control we can't compare anything. Simple as that. I've started researching papers, because these are scientifically acquired data. It is independent and created with statistically sound methodology, and I had the stupid idea that, while it's understandable that you might not believe anything some random on the internet claims, that you might consider empirical evidence. But you have now shown multiple times that your scientific understanding is pretty low, so I can't expect anything... QuoteLet's see what is true or isn't true by comparing _results_ instead of words.  I've provided a few _results_ and so far, no OOP programmer has provided anything to compare them with (except for the historically useful "hello world" program in OOP which took about 5 times more lines of code than the procedural version takes.)I'm more than happy to if we do a controlled experiment. I mean I don't even know what libraries your executables use. I don't know how you compiled them or anything. I can't even reproduce your results. And if you know say something along the lines that I can decide on myself which libraries to use and how to compile my code, than you have your problem right there. Because then we wouldn't measure anything, because our result would be influenced by everything at the same time. QuoteNo one can claim that hitting a tree at 100MPH, without seat belts on and in a VW bug, is bad until they've done it.  What a solid argument that is.  Ever heard of crash tests? They are conducted exactly to finding out how bad which form of impact in each car would be. So yeah, you gave a pretty solid argument here, thanks. QuoteYour "hello world" certainly didn't show that.  It took 5 or more times the number of lines of code than in procedural programming.  The procedural rendition is obvious "writeln('Hello World');", the OOP one requires reading the object definitions, how they are implemented and used.  It seems a lot more complex to me than the one-liner in procedural programming.Have you read the paper or at least my post about the paper? Because the complexity metrics they used was not SLOC, but cyclomatic complexity and interface complexity, which both where identical in the OOP and procedual code. Maybe, just maybe, you should understand what you are trying to dispute. You just embarrassed yourself really hard. QuoteThe more lines of code, the greater the probability for a bug to exist. [CITATION NEEDED] QuoteThe cops must get suspicious after inheriting that many times.  That could have some very disadvantageous "side effects".  Seriously, inheritance leads to "onion programming", umpteen layers of code, few if any fulfill a logical purpose but are simply there to provide the option of overriding the method that implements them. You know the beauty of the scientific method, if you think these papers are bad, simply write your own dispute-paper and get it published in a peer reviewed journal. I mean if they are obviously false, why don't you do that? Other question, why doesn't the 10 or so peer reviewer, which all are researchers in a comparable field, noticed that these findings are so obviously wrong? It only takes one to reject the paper so it won't get published. I have provided empirical evidence, you don't. Make of that what you want. QuoteIt is quite true that they greatly depend on design but, it is also true that the possible designs are _greatly_ influenced by the paradigm used and, as your "hello world" program shows, the resulting design does _not_ emphasize simplicity and ease of understanding butMy design choice in the hello world example was not to write a good program, my design was to show that OOP does not add overhead. Sure this design choice is depenend on the fact that I'm using OOP, but that doesn't mean that everyone using OOP makes this same design choice. That said, procedual is a subset of OOP, meaning every procedural desing decision can also be done when designing on OOP project. Simple as that. You can use OOP simply as syntactic sugar like advanced records in Pascal. I know some C++ developers who do so, they basically write C programms with classes instead of structs Quote, it very nicely emphasizes productivity when measured in SLOCS.  It's got that going for it.Yeah thats why literally no one measures productivity in SLOC except in your head. Name a single example where I claimed that. It is always measured in SLOCS/Time, and I can tell you that it took me much longer to write the Hello World in OOP than in procedual. So, while I haven't measured the time exactly, I think that the SLOC/Time of the procedual was higher than of the OOP example (especially in C++, where I've made a syntax error first time trying to compile). So to summarize, you expect an experiment without control.You either haven't read what I was writing or you didn't understand it, thats why you completely misinterpreted the studies and claim things that neither I, nor the study I was reciting claimed. And lastly you reject empirical evidence because they don't align with what you think, but don't want to provide any of your own... Sorry but I'm having some standards. I'm not a great scientist, I'm only working in CS research for 2 years now, and haven't even published a single paper. But if I don't have evidence for something myself, I start looking for scientific papers and empirical data. You seem to do the complete opposite. You assume something and even when confronted with empirical evidence, you stick your fingers up your ears and sing *la la la I cant hear you*. If your next post isn't any different (i.e. you still want an experiment without control, misquote or misinterpret the empirical data, or make claims without any shred of evidence), this will be my last answer to you. ---------------------------------------------------------------------- Martin_fr · 2020-05-09 21:26 If you insist on compare of compiled exe (which is really just a subset (if even that) of comparing paradigm) then let others set the task (I wont do it, don't have the time) and you match it. Also give others access to all the ways you may save space/time. Because it is not about, if the other knows those tricks, but if they can be used in OOP or not. (You hide your code, its 2312) Let the other one use all of your techniques, in a task set by the other person, with a compiler chosen by the other person. So the only diff is the paradigm. (Again, I am not going to be that other person, I rather write code that's on my todo list already, without this here) If you insist on classes, a compiler must be found that can optimize them reasonable. From the fpc system unit: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i        TObject = class       public          { please don't change the order of virtual methods, because            their vmt offsets are used by some assembler code which uses            hard coded addresses      (FK)                                 } This is not about OOP, this is about how fpc handles it. And that fpc does not optimize certain parts of it. I dare say, an application the size of fpdebug, those things may not be very relevant. They make a tiny percentage, and are well worth their price. (nice to optimize, but not relevant, not if you judge everything that goes into a typical development process) But for benchmarking apps in your sample size, they do make a difference. Anyway I digress => this is about a compiler. Not about a paradigm. ---------------------------------------------------------------------- 440bx · 2020-05-09 23:08 Quote from: Warfley on May 09, 2020, 11:05:41 pmshows that you have absolutely no clue about scientific workings at all. I do have a clue and, that clue says that a _correct_ scientific theory can predict results/events.  You made a number of claims  and I've offered a number of opportunities for you to demonstrate those claims.  So far, the result is a "hello world" program that requires a significantly greater number of lines of code to do what is done in one (1) line of code in procedural programming.  I'll grant this much: it didn't produce a larger executable but that's only because it didn't use any of the features that are characteristic of OOP: polymorphism and inheritance.   IOW, your OOP rendition of "hello world" is just a convoluted way to express something that is expressed in only one (1) line of code in procedural programming.  Show _results_.  Einstein's General Theory of Relativity predicted gravitational lensing.  It was observed to be a fact.  That put his theory on really solid footing.  Use scientific theory and show _results_. Quote from: Warfley on May 09, 2020, 11:05:41 pmMS has provided the option to its C++  Most C++ developers don't use it (from my personal experience)I don't know but, it seems a bit suspicious to do all the work necessary to enable it if close to no one uses it.  Stranger things have happened, therefore, you might be right on that one.  Quote from: Warfley on May 09, 2020, 11:05:41 pmWhen was productivity ever measured in SLOCS? From all I can recall everything I presented productivity was measured in SLOC/Time, you know because writing more code requires more time.Accept my apologies then.  I just wrote a little AWK script to generate 100,000 lines of no-ops which I pasted in my editor, I had no idea I could be this "productive" and, not a single syntax error either.  You're right this OOP stuff is great. That's what programming is all about, for sure. Quote from: Warfley on May 09, 2020, 11:05:41 pmAlso you haven't given me any alternative to this measurement for that paper. I don't have one and I've never seen one done soon after the software was produced that I considered remotely accurate except, years after the programs have been written, after the number of bugs found is counted, the number of hours spent fixing them, the number of hours spent adding features to the program, are all in.   Then, and only then, can a measurement that is realistic be made.  Measurements done before that are pretty darn close to meaningless. Quote from: Warfley on May 09, 2020, 11:05:41 pm I mean sure you can complain as much as you want, but some data even if the metric might not be fully accurate is still better than no data.No.  No data is better than bad data because that way, at least, there is a chance of getting reasonably good data. Quote from: Warfley on May 09, 2020, 11:05:41 pm Especially if that data was peer reviewed and cited. That sure makes a difference.  For 19 centuries, peers "reviewed" Aristotle's principles of Physics.  That sure proved how good they were. Quote from: Warfley on May 09, 2020, 11:05:41 pmBut you have now shown multiple times that your scientific understanding is pretty low, so I can't expect anything... I would hope that people who, supposedly, have a greater understanding than mine be capable of showing me they can obtain better _results_ with their method than the one I'm using.  I've shown you the results I obtain.  Show me yours then, we compare.    So far the "result" you've provided only shows that OOP can do with a lot more lines of code what procedural programming can do in one.  And, if productivity is measured in SLOCS/time, there is no doubt that typing 20 times more characters takes longer.  (that presumes, all thing being equal, that is, a human being with 10 fingers, reasonably adept at typing and, a working keyboard.) Quote from: Warfley on May 09, 2020, 11:05:41 pmI don't know how you compiled them or anything.Yes, you do.  The last example I provided made that very clear, compiled with FPC v3.0.4 in 32 bit, using -O3 optimization.  Only restriction: no assembly code because mine doesn't use any, other than that, implement however you like as long as it's using OOP (not really a requirement I'm imposing since it would make little sense for you to present a result that doesn't use OOP to support your beliefs about OOP.) Quote from: Warfley on May 09, 2020, 11:05:41 pm I can't even reproduce your results. What problem did you run into ?... maybe I can help. Quote from: Warfley on May 09, 2020, 11:05:41 pmEver heard of crash tests? They are conducted exactly to finding out how bad which form of impact in each car would be. So yeah, you gave a pretty solid argument here, thanks.But, according to what you stated, you don't really acquire knowledge unless you've done it yourself.  I strongly discourage you of running into a tree at 100MPH, I assure you the results won't be good and, you can take my word for it. Quote from: Warfley on May 09, 2020, 11:05:41 pmHave you read the paper or at least my post about the paper? Because the complexity metrics they used was not SLOC, but cyclomatic complexity and interface complexity, which both where identical in the OOP and procedual code. Maybe, just maybe, you should understand what you are trying to dispute. You just embarrassed yourself really hard. You can go on about those papers all you want but, so far, the only actual example I've seen from you is a "hello world" program that takes way too many lines of code.  If I were in your situation I would refrain from using the word "embarrassing". Quote from: Warfley on May 09, 2020, 11:05:41 pmQuoteThe more lines of code, the greater the probability for a bug to exist. [CITATION NEEDED] That's well established in probability theory.  If that is new to you, use Google. Quote from: Warfley on May 09, 2020, 11:05:41 pmYou know the beauty of the scientific method, Yes, I do.  It has been used quite a few times to prove that time is relative with _facts_/_results_.  It would be really nice to see some _results_ from you (other than it takes more code... and apparently that you may believe that more code means less bugs.) Quote from: Warfley on May 09, 2020, 11:05:41 pmwhy don't you do that?because I'd much rather be writing a program than a paper which will only produce an endless and fruitless argument.  The real question is: why would I want to do that ?  (something I ask myself about my participation in this thread.) Quote from: Warfley on May 09, 2020, 11:05:41 pm Other question, why doesn't the 10 or so peer reviewer, which all are researchers in a comparable field, noticed that these findings are so obviously wrong? It only takes one to reject the paper so it won't get published.I don't know but, that doesn't mean they are right, it only means none of them can clearly refute what is in the paper. Quote from: Warfley on May 09, 2020, 11:05:41 pmI have provided empirical evidence, you don't. Make of that what you want. I'd rather see evidence in code and, so far, it's been limited to a "hello world" program.  For some reason, it reminds me of the Rolling Stones, I don't get no satisfaction. Quote from: Warfley on May 09, 2020, 11:05:41 pmMy design choice in the hello world example was not to write a good program, my design was to show that OOP does not add overhead.I concede that in that particular case, where static objects can be used, OOP doesn't add any executable overhead.  However, it definitely added a lot of overhead when it came to unnecessary lines of code to get the job done.  (something which you admitted.) IOW, even in the somewhat rare case that OOP can match, not even exceed, just match, what procedural programming can do, it requires significantly more code.  That's not productive at all. Quote from: Warfley on May 09, 2020, 11:05:41 pm It is always measured in SLOCS/Time, SLOCS or SLOCS/time, both are completely inadequate ways of measuring productivity. Quote from: Warfley on May 09, 2020, 11:05:41 pmI can tell you that it took me much longer to write the Hello World in OOP than in procedual. So, while I haven't measured the time exactly, I think that the SLOC/Time of the procedual was higher than of the OOP example (especially in C++, where I've made a syntax error first time trying to compile). I can see that.  What I cannot see is why anyone would want to go down that route.  I'll take that back, I can see why but, the reason isn't good, therefore, I won't mention it. Quote from: Warfley on May 09, 2020, 11:05:41 pm You assume something and even when confronted with empirical evidence, you stick your fingers up your ears and sing *la la la I cant hear you*.I'm pleased you acknowledged not being a great scientist above because, just a good scientist would have already provided conclusive proof that his method leads to results that are observably better.  You have not. Quote from: Warfley on May 09, 2020, 11:05:41 pm this will be my last answer to you. Honestly, I'm pleased to hear that.  You are not providing any real support for your argument and, all the typing is getting is tiresome. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmIf you insist on compare of compiled exe Yes, exe size and I broadened that in a recent post to resource usage. Quote from: Martin_fr on May 09, 2020, 11:26:41 pm (which is really just a subset (if even that) It's an important subset.  Code size generally reflects the quality of the code. Granted, dirty tricks and assembly can be used to create smaller executables but, I have explicitly stated that I do not use them.  Quote from: Martin_fr on May 09, 2020, 11:26:41 pm of comparing paradigm) then let others set the task (I wont do it, don't have the time) and you match it. I believe what I've offered is simple and reasonable.  Things that an experienced programmer will do in probably less time than it took me to type this reply. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmAlso give others access to all the ways you may save space/time. ... Let the other one use all of your techniques... That I will not do and, the reason is simple, those ways come from the time spent towards the goal of writing a reasonably decent program.  I _expect_ programmers who use OOP to have their _own_ ways of producing better code that are particularly well suited to the OOP paradigm.  That's their responsibility, not mine. Furthermore, on that point, I am under the, possibly mistaken, impression that OOP, at least as implemented in Pascal discourages programmers from finding better and, more flexible and, powerful ways of implementing an algorithm.  One of the things that gives me that impression is the pointer hiding the compiler does for the programmer combined with the apparent aversion of many OOP programmers to use pointers.  Restricting one's set of algorithms to those which do not require pointers is quite detrimental. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmIf you insist on classes, a compiler must be found that can optimize them reasonable. I don't "insist" on classes.  What I "insist" on, if you want to use that word, is for the programmer to program normally, as he/she always does, which in the great majority of cases includes using classes.  IOW, I don't want the implementation to result in code that is not what the OOP programmer would have normally coded. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmThis is not about OOP, this is about how fpc handles it. And that fpc does not optimize certain parts of it. It is still about OOP.  What the compiler can do with OOP code is a reflection on the OOP paradigm. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmI dare say, an application the size of fpdebug, those things may not be very relevant. They make a tiny percentage, and are well worth their price. (nice to optimize, but not relevant, not if you judge everything that goes into a typical development process) But for benchmarking apps in your sample size, they do make a difference. The differences in size in particular are usually much more noticeable in small programs than in large ones.  You're asking for a large one because hopefully less of the OOP junk that makes it in the executable is unused thus, making it appear better than it actually is. ---------------------------------------------------------------------- Martin_fr · 2020-05-10 00:27 Quote from: 440bx on May 10, 2020, 01:08:09 amAccept my apologies then.  I just wrote a little AWK script to generate 100,000 lines of no-ops which I pasted in my editor, I had no idea I could be this "productive" and, not a single syntax error either.  You're right this OOP stuff is great. A nop slide is not OOP. A nop slide may be viral though. Quoteso far, the only actual example I've seen from you is a "hello world" program that takes way too many lines of code.You changed the measure (introduced lines of code) after the results where in.  Lines of code weren't the challenge. IIRC, you also already stated, that hello word was not a realistic example. You stated (on papers) Quote that I considered remotely accurate except, years after the programs have been written, after the number of bugs found is counted, the number of hours spent fixing them, the number of hours spent adding features to the program, are all in.and yet you propose to compare executables, without knowing anything about the bugs and maintenance issues that might be encountered with their respective sources. According to the above quote, comparing those executables is also totally meaningless. Maybe one is smaller, or faster..., but what if that ones happens to have hidden bugs, and maintenance turns out to be total hell. What good is a byte saved, when you may have paid for it with a bug put into the app? You judge by different standards, choosing them as it suits you best. QuoteQuote from: Warfley on May 09, 2020, 11:05:41 pmQuoteThe more lines of code, the greater the probability for a bug to exist. [CITATION NEEDED] That's well established in probability theory. You probably disproved it yourself. Your said you wrote plenty of nop lines => What is the likelihood those nops contain any bug? QuoteCode size generally reflects the quality of the code. That statement is ambiguous.  Do you mean the quality of the (1) generated machine code? or (2) the quality of the original sources? (From not quoted context: "Code size" refereed to the exe, as that was the size that was to be compared) 1) Maybe. Also execution speed would also be part of that "quality assessment". And faster code may sometimes need more space. (e.g. inlining, loop unroll, etc) 2) Not really (at least not generally)... If it did, I could compile the same sources, with 2 different compilers (heck even the same with different settings), and the quality of the same source code would change. Obviously the quality of the sources do not depend on the compiler. At the utmost, exe size could be used as an indicator that the sources should be checked for quality issues, such as "copy and paste". ("copy and paste" is an issue, that happens completely independent of OOP vs procedural). But even further, a too small source could indicate bad source quality too. Maybe the programmer has written code that was more aimed at being shorter, than at being read/maintainable. (And that will be fun, if a bug needs to be fixed in a years time or so) QuoteQuote from: Martin_fr on May 09, 2020, 11:26:41 pmAlso give others access to all the ways you may save space/time. ... Let the other one use all of your techniques...That I will not do and, the reason is simple, those ways come from the time spent towards the goal of writing a reasonably decent program.  I _expect_ programmers who use OOP to have their _own_ ways of producing better code that are particularly well suited to the OOP paradigm.  That's their responsibility, not mine.So what Warfley said is true: You want (at least to a reasonable part) to compare the skills of the programmer, instead of the result of the paradigm used. Hence what's the point... (More details further below) Quote many OOP programmers to use pointers. I don't have data on that, but - I do use pointers, no problem at all (typed and untyped, as needed) - I dislike exceptions - I am not fond of RTTI - My OOP code contains procedural code, where it makes sense. ... And I am an OOP programmer. Really. (And there are plenty others that fit above list) Quote Restricting one's set of algorithms to those which do not require pointers is quite detrimental.True. I give you one more "Restricting one's set of algorithms is quite detrimental" Does not have to be caused by pointers. QuoteI don't "insist" on classes.  What I "insist" on, if you want to use that word, is for the programmer to program normally, as he/she always does, which in the great majority of cases includes using classes.  IOW, I don't want the implementation to result in code that is not what the OOP programmer would have normally coded.Ok, but .... From reading your contributions, it would appear more than strongly suggestive that your way of procedural programming is quite far away from what the average procedural programmer does. (Remember I grew up procedural, as everyone around me. And also today I still get in contact with procedural code from time to time). The average procedural programmer from the sample I know, wants to get the job done, like any other person in the world. They wants to be able to still read and understand their code in a few years time. They wants to use a framework if available. They accepts if that is paid for by some extra bytes. So for the comparison we need to find an OOP programmer, that is more like you. That is not average... Or we need to replace you by a more average person. But even if we did that, the result would still depend on the person, and the data would be awfully tainted by that. To counter that, we need a large set of programmers on both sides, in the hope that the average is not tainted to heavily. Where do we get, lets say at least (?) 100 people for each side? QuoteIt is still about OOP.  What the compiler can do with OOP code is a reflection on the OOP paradigm.- What a compiler could be made to do... (i.e., what could be implemented in a compiler) => yes. - What a specific compiler can do => Not at all. Just because it wasn't implemented, it does not make a statement on the input (be that the source, the paradigm or the language) Imagine, you take the results of FPC 3.0.4 and make them a statement about the quality of the Pascal language, because that is what the result of optimization is. And then you discover 3.2 will have more optimizations. Does that mean that the same input, the same Pascal language is now suddenly better than it was before? How could it, if the language itself has not changed. QuoteThe differences in size in particular are usually much more noticeable in small programs than in large ones.  You're asking for a large one because hopefully less of the OOP junk that makes it in the executable is unused thus, making it appear better than it actually is.But if it is being used, then it is not junk. (And for smaller samples it depends on the compilers abilities) Yes, if you use instances, you need to call MemAlloc (or similar). There are of course apps, that can work with using only memory from the stack, and in OOP, you could do them with static objects). But as apps grow, many will need some memory outside the stack (even if you alloc mem yourself from the OS....) So the apps do have some codes to get that memory, and decide which data goes where. At that point the AllocMem for an instance, is no different from the alloc mem for other data. (there are other diffs between an instance and other data, just doing ONE example here). Also, you kind of just admitted, that you choose your "example apps" for comparison with full intend to be less suited for OOP. Despite you said, you could match any OOP program with a better procedural one. And just a reminder, I have been saying all along: No one shoe fits all. You said, that the procedural shoe always fits better. Quote from: 440bx on May 04, 2020, 03:20:53 amThe real problem is that, so far, I can always think - with little effort - of a clearly better solution that doesn't use OOP.  And now you admit that you want to lure as into a "prof" by example, which for some reason you tried to pre-bias. ---------------------------------------------------------------------- 440bx · 2020-05-10 03:23 Quote from: Martin_fr on May 10, 2020, 02:27:46 amYou changed the measure (introduced lines of code) after the results where in.  Lines of code weren't the challenge. I am _not_ the one who brought up SLOC.  Don't tell me I can't use the stuff you people pretend gives the upper hand to OOP.    Measure productivity in SLOC because OOP requires more lines of code to express what can be expressed in one line in procedural and, after that's pointed out, you complain about my using SLOC which _you_ guys brought into the discussion, not me.  Next time don't bring up additional ways OOP leaves something to be desired. I'm willing to forget the SLOC thing and go back to executable size.  Quote from: Martin_fr on May 10, 2020, 02:27:46 amIIRC, you also already stated, that hello word was not a realistic example. Functionally, I don't think it's realistic but, it certainly is a nice example of the greater amount of code OOP requires at least in some cases.  I don't really know if that applies consistently (though I strongly suspect it does), therefore, to be very clear, I am not making any claims about that one way or the other, it's just fun to notice. Quote from: Martin_fr on May 10, 2020, 02:27:46 amAccording to the above quote, comparing those executables is also totally meaningless. Nice try but, no.  Executable size is something known immediately after the compile.  No need to run the program thousands of times to find out what its real size is, and executable size does reflect on the paradigm. Quote from: Martin_fr on May 10, 2020, 02:27:46 amMaybe one is smaller, or faster..., but what if that ones happens to have hidden bugs, and maintenance turns out to be total hell. What good is a byte saved, when you may have paid for it with a bug put into the app? That's a completely generic argument.  You are trying to imply that the additional junk in OOP executables don't make a difference.  It's simple and mathematical, the probability of a bug being present increases with the number of lines of code and instructions in the executable. Therefore, OOP programs are more likely to contain bugs. Quote from: Martin_fr on May 10, 2020, 02:27:46 amYou judge by different standards, choosing them as it suits you best. Very nice, accusing me of what you do.  Quote from: Martin_fr on May 10, 2020, 02:27:46 amYou probably disproved it yourself. Your said you wrote plenty of nop lines => What is the likelihood those nops contain any bug? I have to admit that, with no-ops, the probability of any of those lines containing a bug is extremely small but, is that what causes OOP executables to be larger ?... a generous amount of free no-op instructions in the executable.  I know sometimes compiler have a hard time removing no-ops but, if that's what's making OOP executables larger then, the compiler's optimizer needs some serious and urgent attention. Quote from: Martin_fr on May 10, 2020, 02:27:46 amDo you mean the quality of the (1) generated machine code? or (2) the quality of the original sources? Both and, additionally the quality of the paradigm. In the case of OOP, both commonly leave something to be desired which negatively reflects on the quality of the paradigm. Quote from: Martin_fr on May 10, 2020, 02:27:46 amAnd faster code may sometimes need more space. (e.g. inlining, loop unroll, etc) I do not believe those characteristics are specific to OOP. Also, I do not believe that is the reason OOP executables are consistently larger. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmSo what Warfley said is true: You want (at least to a reasonable part) to compare the skills of the programmer, instead of the result of the paradigm used.Nice try.  It's not about the programmer skills, it's about the different way an OOP programmer goes about designing a program, just like, the fact that C programmers tend to produce hard to maintain code is also promoted by the semantic and syntactic structure of the language. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmI don't have data on that, but - I do use pointers, no problem at all (typed and untyped, as needed) This forum has plenty of examples of OOP programmers who don't use pointers and openly admit their dislike for them.  That's something the Free Pascal and Delphi OOP implementation promotes by its hiding pointers from the programmer.  classes are pointers... and it's quite obvious from some of the questions posted in the forum that there are good number of programmers who don't realize that and end up writing code that doesn't work properly as a result. Quote from: Martin_fr on May 09, 2020, 11:26:41 pm- I dislike exceptions I'll take your word for it but, I see exceptions being commonly used in many situations where they are not warranted.  One of the reasons, is that in Pascal's OOP implementation, they seem to be a class just like any other class.  The same applies to classes and also to inheritance. Quote from: Martin_fr on May 09, 2020, 11:26:41 pm- I am not fond of RTTI - My OOP code contains procedural code, where it makes sense. I believe you. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmAnd I am an OOP programmer. Really. (And there are plenty others that fit above list) And obviously, a large number who don't and, that is promoted by OOP and the way it is implemented in Free Pascal and Delphi. Quote from: Martin_fr on May 09, 2020, 11:26:41 pm"Restricting one's set of algorithms is quite detrimental" True but, you're trying to overlook the fact that OOP promotes not using pointers by openly hiding them.  In all fairness, that characteristic may not be specific to OOP itself but, the specific implementation in Free Pascal/Delphi. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmFrom reading your contributions, it would appear more than strongly suggestive that your way of procedural programming is quite far away from what the average procedural programmer does. (Remember I grew up procedural, as everyone around me. And also today I still get in contact with procedural code from time to time). There is likely some truth to that.  I can be very finicky about most everything in a program, even the formatting.  The average programmer doesn't seem to care much about the code as long as it works (or seems to work.) Quote from: Martin_fr on May 09, 2020, 11:26:41 pmThe average procedural programmer from the sample I know, wants to get the job done, like any other person in the world. They wants to be able to still read and understand their code in a few years time.I have the same wants.  In addition to those, I want to be able to read the program and derive a feeling that it's good stuff.   Whether the program works or not, until I get that feeling, the program isn't done.  Of course, I cannot get that feeling if the program doesn't work exactly as I want the thing to work. Quote from: Martin_fr on May 09, 2020, 11:26:41 pm They wants to use a framework if available. They accepts if that is paid for by some extra bytes. If it were just "some extra bytes", I'd use a framework too.  I use a compiler and, for using it, I pay "some extra bytes" since I could code the thing in assembly. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmSo for the comparison we need to find an OOP programmer, that is more like you. That is not average... Or we need to replace you by a more average person. No.  Simply a programmer who knows how to use the paradigm to get the best out of it.  Quote from: Martin_fr on May 09, 2020, 11:26:41 pm Where do we get, lets say at least (?) 100 people for each side? I don't think that is necessary.  There are some very capable OOP programmers that frequent this forum.  There is no doubt in my mind they can produce code that is as good as what I write.  The differences in executable size will be determined by the paradigm and, maybe a little bit by the compiler but, the compiler shouldn't be an issue because we'd be using the same compiler.  That means, same version and same optimization level. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmBut if it is being used, then it is not junk. (And for smaller samples it depends on the compilers abilities) Yes, if you use instances, you need to call MemAlloc (or similar). There are of course apps, that can work with using only memory from the stack, and in OOP, you could do them with static objects). But as apps grow, many will need some memory outside the stack (even if you alloc mem yourself from the OS....) So the apps do have some codes to get that memory, and decide which data goes where. At that point the AllocMem for an instance, is no different from the alloc mem for other data. (there are other diffs between an instance and other data, just doing ONE example here). It's still junk because part of it is caused by OOP programmers breaking code into tiny little pieces which causes long chains of calls to execute code that should have been just one function/procedure and, that is, squarely a very bad poor programming practice that the OOP paradigm openly encourages. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmAlso, you kind of just admitted, that you choose your "example apps" for comparison with full intend to be less suited for OOP. On the contrary, the example apps I offered are particularly well suited to prove OOP can produce as tight and fast executables as procedural programming because _every_ one of them can be implemented using static objects which is the best case for OOP.  I have been very accommodating and only offered examples where OOP can be at its best, which is far from the most common case. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmDespite you said, you could match any OOP program with a better procedural one. And I stand by that. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmAnd now you admit that you want to lure as into a "prof" by example, which for some reason you tried to pre-bias. The only bias I am guilty of is offering the best case for OOP. ---------------------------------------------------------------------- munair · 2020-05-10 07:07 I already emphasized that inheritance can cause problems in traditional OOP. The vulnerability however seems to be largely ignored in this thread. So let me copy-paste the issue of the "fragile base class" problem: QuoteThe fragile base class problem is a fundamental architectural problem of object-oriented programming systems where base classes (superclasses) are considered “fragile” because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class. Golang is sane in that it decided a different approach that eliminates the inheritance vulnerability. In case anyone is interested, this is a good read on the matter. It also explains very well why classes being the tightest form of coupling is a bad thing. ---------------------------------------------------------------------- marcov · 2020-05-10 09:00 As explanations go, that is not a great one. It just parrots wikipedia, and then provides some simplistic and very abstract example of composition over inheritance, without ever explaining why this is so very important. The problems are always that properties are rarely so isolated as the simplistic examples demonstrate. IMHO the problem is not creating some pure pattern to separate properties, but actually dealing with the exceptions ---------------------------------------------------------------------- munair · 2020-05-10 09:38 Quote from: marcov on May 10, 2020, 11:00:46 amAs explanations go, that is not a great one. It just parrots wikipedia, and then provides some simplistic and very abstract example of composition over inheritance, without ever explaining why this is so very important. It's not about parroting Wikipedia. Inheritance has vulnerabilities which are well known among programmers. The fact that it is also stated on Wikipedia doesn't make it any less valid. While the base class problem is important, the article emphasizes the power of composition (rather than its importance) and its advantages over traditional classes. ---------------------------------------------------------------------- marcov · 2020-05-10 10:49 Quote from: munair on May 10, 2020, 11:38:49 amQuote from: marcov on May 10, 2020, 11:00:46 amAs explanations go, that is not a great one. It just parrots wikipedia, and then provides some simplistic and very abstract example of composition over inheritance, without ever explaining why this is so very important. It's not about parroting Wikipedia. Inheritance has vulnerabilities which are well known among programmers. So you say, and euh,  "Vulnerabilities" ? But the reference that you give doesn't say much about it. The references of the wikipedia is one whole article.  But at least that explains it better. Overrides might depend on the implementation of baseclass, resulting in e.g. recursion. Yes, that is a problem. How big, can be argued (and neither source does a very good job explaining WHY it must be addressed so urgently) But I'm still not convinced that the composition really "solves it".  The problem remains how to reuse the code of the baseclass in multiple similar cases. Making one object each and copy-and-pasting the code might solve that, but so would making the method abstract and implement it fully in each descendent, so is composition then really a solution? (note that the composition is from the GO lang, not from the article that defines fragile base. Actually the article warns that composition using derived classes might have the same problem. Quote The fact that it is also stated on Wikipedia doesn't make it any less valid. IMHO the wikipedia article pretends it is some giant consensus. But it references exactly one article on two different sites, and a rough link to the "override" modifier of C# which I don't understand why it is there in the first place. No GoF or other standard work reference. Just the sole article. QuoteWhile the base class problem is important, the article emphasizes the power of composition (rather than its importance) and its advantages over traditional classes. IMHO it only details composition support in golang, with some reference to fragile baseclass (fbc) problem, without saying how composition solves the same problem.  Its examples are also different from fbc as in the article. The article seems to be talking more about fbc as implicit dependencies of the implementation of the descendent, while the go article is more talking about guarding that interfaces are implemented in full. Which could lead to problems if the baseclass is extended. Both problems are somewhat similar in that it poses problems for the implementors of root classes (e.g. in STL etc) and their inability to change them without risking code breaking somewhere. However changing to composition seems to put the onus on the user, which solves the problem for the library implementor, but saddles the user with complexity. But maybe I totally misunderstood, and you can explain it to me. ---------------------------------------------------------------------- munair · 2020-05-10 11:46 In the end everyone has his own opinion. Inheritance has some serious well-known draw-backs (but not everyone agrees on that either). Composition allows for more design flexibility, but may force derived types to re-implement rather than inherit, although some languages support constructs to solve/mitigate this problem. Everyone who is interested can find a ton of information about composition versus inheritance. IMO composition provides code that is better/easier to maintain in the long term. ---------------------------------------------------------------------- jiaxing2 · 2020-05-10 12:57 I don't know how you guys could keep this discussion that long. BTW, I lost my forum account ---------------------------------------------------------------------- Martin_fr · 2020-05-10 12:59 Let me clarify (and correct) my position on the "mindset" 1) There are many different mindsets in the OOP community (as there are in the procedural world) 2) Those mindset may share some common parts / similarities. (which is what you may have refered too) 3) Those common parts, may (or may not) have pre-existed.     People may have chosen OOP to fit there existing mindset, rather than having been influenced by OOP So when it comes to "mindset" there may be something to be referred to. I may have dismissed it to broadly.  You may be over advertising it. And most of all, it may not be a consequence of OOP. It may be the cause of the existing of OOP. Or a mix. Also, quite some parts of this "shared mindset" may in similar form exist in the mind of procedural programmers. They just use different tools to put it into code. There may remain some small part of a "shared mindset" that is exclusive to OOP. However this is a pool of additional ideas, to be used when the problem demands it. Also to make it very clear, from what I read: We do strongly disagree on the content of that shared by of mindset. ---------------------- As for your "look at the mass of OOP programmers out there" As we determined, there are a lot of "wanna be programmers". Because big companies make a lot of noise for OOP, the wannabe over-frequently choose OOP (they have no idea why, so it cant be something that is inherent of OOP). That of course affects the sample quality, if you look at sources available in the wild. But the reason for that in not OOP. There may be other similar points. There may also such points for procedural. So it may go both ways. But it does mean to separate between what you see done in one Paradigm, and what is caused by that Paradigm, that is a fairly complicated task. Not sure if we even scratched the surface yet. Quote from: 440bx on May 10, 2020, 05:23:25 amQuote from: Martin_fr on May 10, 2020, 02:27:46 amIIRC, you also already stated, that hello word was not a realistic example. Functionally, I don't think it's realistic but, it certainly is a nice example of the greater amount of code OOP requires at least in some cases.  I don't really know if that applies consistently (though I strongly suspect it does), therefore, to be very clear, I am not making any claims about that one way or the other, it's just fun to notice. Now, you see "in some cases": That is a statement I have on problem with. Everything has its up and downsides (and again I said from the start "no one shoe fits all"). Yes, there are cases were OOP does not fit. And there are cases were it leads to a bigger exe size, without any benefit in return. (like "hello world"). QuoteQuote from: Martin_fr on May 10, 2020, 02:27:46 amAccording to the above quote, comparing those executables is also totally meaningless. Nice try but, no.  Executable size is something known immediately after the compile.  No need to run the program thousands of times to find out what its real size is, and executable size does reflect on the paradigm.But fixing a bug, can increase the exe size considerable. So a buggy exe can be considerable smaller. Because maybe some (rarely used) feature was forgotten, and will just always display an error. So, I stand by my statement. QuoteYou are trying to imply that the additional junk in OOP executables don't make a difference.  It's simple and mathematical, the probability of a bug being present increases with the number of lines of code and instructions in the executable. Therefore, OOP programs are more likely to contain bugs. One of your claims is that OOP pulls in a lot of unused Code. (I say that is framework, but for the moment is does not matter / for arguments sake). Now you add that this code pulls in bugs that manifest in the final exe. Now the unused code may contain bugs. But if it is unused (i.e. never executed) they do not manifest. They are not bugs in the exe. There is also (with in the "no one shoe fits all" / some cases) code such as memory alloc for the classes, that in those few cases could have been saved in procedural code. I do not say, it makes "no difference". I do say, the difference it makes, in most cases brings in other advantages that are worth a hell lot more. (So it makes a positive difference, if you see the whole picture.) You are pulling out one factor for determining the likelihood of bugs, and ignore all others. Your way of determining said likelihood is massively buggy. QuoteQuote from: Martin_fr on May 10, 2020, 02:27:46 amYou judge by different standards, choosing them as it suits you best. Very nice, accusing me of what you do.  I actually quoted you doing the different judgement. You just put down a claim without backing it up. QuoteQuote from: Martin_fr on May 09, 2020, 11:26:41 pmSo what Warfley said is true: You want (at least to a reasonable part) to compare the skills of the programmer, instead of the result of the paradigm used.Nice try.  It's not about the programmer skills, it's about the different way an OOP programmer goes about designing a program, just like, the fact that C programmers tend to produce hard to maintain code is also promoted by the semantic and syntactic structure of the language. Well the question is, how to we remove the influence of the single individual. If (for arguments sake) the programmer needs to be part of the comparison, then comparing 2 individuals just adds a huge margin of error. So then comparison can only be done by taking two groups (each large enough to even out the influence of single individuals). I guess at least a 100, but you may propose a figure. And they cannot be handpicked. I also state, that I have doubts, that you represent the average procedural programmer. And therefore your code is to be considered tainted, and can not be used for comparison. That may or may not be the case, but to make the comparison fair, both sides have to agree on the input selection. So your code has to be excluded. Comparing with an exe for which you wrote the source, is pointless because we can not agree if or if not it is representative. (maybe it is, but that is no good, if we cant agree) Also the matter remains on agreeing what the task to be implemented should be. QuoteQuote from: Martin_fr on May 09, 2020, 11:26:41 pm Where do we get, lets say at least (?) 100 people for each side? I don't think that is necessary.  There are some very capable OOP programmers that frequent this forum.  There is no doubt in my mind they can produce code that is as good as what I write.  The differences in executable size will be determined by the paradigm and, maybe a little bit by the compiler but, the compiler shouldn't be an issue because we'd be using the same compiler.  That means, same version and same optimization level. Well, the problem is that I think this comparison will be flawed. 1) you are not representative of a typical/average procedural programmer 2) When Warfley, did to produce code as good as, you said it was untypical The end is, you expressed concerns about Warfley's code. We express concern about your code. Unless we find a comparison where neither side has concerns, it will be pointless. Otherwise I claim that Warfley's hello world was valid and proved the point in favour of OOP. I believe you do not agree. So thats pointless. If we do not agree, it is equally pointless. Same rules for both sides. QuoteQuote from: Martin_fr on May 09, 2020, 11:26:41 pmFrom reading your contributions, it would appear more than strongly suggestive that your way of procedural programming is quite far away from what the average procedural programmer does. (Remember I grew up procedural, as everyone around me. And also today I still get in contact with procedural code from time to time). There is likely some truth to that.  I can be very finicky about most everything in a program, even the formatting.  The average programmer doesn't seem to care much about the code as long as it works (or seems to work.) What I said all along. Some of the points, you claim OOP programmers do badly (due to mindset), are done by procedural programmers too. So those "some" points are not related to OOP. QuoteIt's still junk because part of it is caused by OOP programmers breaking code into tiny little pieces which causes long chains of calls to execute code that should have been just one function/procedure and, that is, squarely a very bad poor programming practice that the OOP paradigm openly encourages. In procedural coding, people use procedures/functions. They break up code too (and across units, or namespaces, or source files). Doing so is not at all OOP related. I came across the rule of writing small procedures way before I even heart of OOP. And there are many procedural programmers following that rule. Dividing code into small sections, is one of the golden rules. Heck, even assembler has subroutine calls. And just to be clear:  I do not defend "over cutting" (splitting code that belongs together). But mistakes on where to cut, are made by both sides ... ---------------------------------------------------------------------- winni · 2020-05-10 13:12 Quote from: jiaxing2 on May 10, 2020, 02:57:06 pmI don't know how you guys could keep this discussion that long. It is the "Next Millenium Edition" of "War and Peace" by Leo Tolstoy. Like the original with more than 1200 pages. ---------------------------------------------------------------------- jiaxing2 · 2020-05-10 13:20 @Martin_fr: there are people write procedural code with OOP mindset, too. The final result is a program full of pointers  https://www.state-machine.com/doc/AN_OOP_in_C.pdf p/s: I tried to implement this in plain procedural Pascal but after that I asked myself why I have to go through all of this stuffs so I decided just stick with the old object of mode FPC. No need to create my own object system. ---------------------------------------------------------------------- Warfley · 2020-05-10 13:50 I didn't want to answer anymore, but you surprised me, this answer is even worse than all of the above. So this is not a real answer, but I will only mock your illiteracy in that topic. QuoteI do have a clue and, that clue says that a _correct_ scientific theory can predict results/events.If we would be talking about scientific theories this comment might be in place here, but we aren't we are talking about hypothesis. I.e. the step towards a scientific theory QuoteYou made a number of claims  and I've offered a number of opportunities for you to demonstrate those claims.Yes because 4 peer reviewed papers are no evidence, but a single executable I can't even reproduce (because I don't have the source), without any protocol or anything remotely scientific is? QuoteI'll grant this much: it didn't produce a larger executable but that's only because it didn't use any of the features that are characteristic of OOP: polymorphism and inheritance.Oh yeah the gods of OOP will punish me for deciding to not use a feature when it's not appropriate. It is common knowledge that every OOP programmer uses Inheritance and polymorphism everywhere becuase otherwise the gods of OOP will strike your git server and wipe all your backups. Quotethat is expressed in only one (1) line of code in procedural programming.Moving the goal post I see. First the claim was that OOP will add bloat, now when I've shown you an example where this isn't the case, you suddenly shift that "OOP is bad because of unnecessary lines of code". You really want to win at your fallacy bingo right? QuoteShow _results_.  Einstein's General Theory of Relativity predicted gravitational lensing.  It was observed to be a fact.  That put his theory on really solid footing.  Use scientific theory and show _results_.Yes and to measure the results of gravitational waves multiple stations all over the planet have to be synced up and follow a strict protocol to control for interfering forces. You know, like the studies I've shown controlled for different designs, development phases, etc. Or like your experiment doesn't control for anything. If you think that one of your comparisons is any scientific evidence, then feel free to measure gravitational waves in your garage. This is about as scientific. QuoteI don't know but, it seems a bit suspicious to do all the work necessary to enable it if close to no one uses it.You know that less than 1% of all computers are running windows? C++ is a language famous for being used to write server software in, that has to run on POSIX servers. So simply by that fact you should already know that VC++ can not be that prevalent in the world. That said, when I talk about C++ I, in nearly all cases talk about standard ISO-C++. VC++ is not part of the ISO standard. QuoteAccept my apologies then.  I just wrote a little AWK script to generate 100,000 lines of no-ops which I pasted in my editor, I had no idea I could be this "productive" and, not a single syntax error either.  You're right this OOP stuff is great. I'm sure production ready software like used at IBM will contain unnecessary noop-sledges. There is this famous quote "if a metric becomes a goal it seizes to be a good metric". That means you can hack any metric to artificially blow up your results. So the idea is to use a metric that was no goal in the beginning. I'm pretty sure IBM doesn't pay by SLOC, so why should they add unnecessary code? QuoteI don't have one and I've never seen one done soon after the software was produced that I considered remotely accurate except, years after the programs have been written, after the number of bugs found is counted, the number of hours spent fixing them, the number of hours spent adding features to the program, are all in.   Then, and only then, can a measurement that is realistic be made.  Measurements done before that are pretty darn close to meaningless.So like the last study I cited? You know, the one that showed the strongest link between C++ and productivity of all the studies I cited? The one with the highest sample size? That controlled for even being the same developers writing the C and C++ code in the same project? QuoteNo.  No data is better than bad data because that way, at least, there is a chance of getting reasonably good data.Black and white fallacy, another point in the fallacy bingo. Only because something is not great, it doesn't mean it's bad. In a production environment like IBM, while of course there will be differences in code length between different coding styles, the SLOC will still be a measurement of effort, even if there is some variation to that. That said the rosetta-code study I've provided showed that there is no statistically significant difference in code size between C, C# or Go, meaning that at least for these languages this measurement would be well suited. Also I criticised this metric in the same paragraph I've introduced the study, this is exactly the reason this was not the only study I've provided, I've provided 4 studies regarding that topic, because in most cases one study alone can't tell you anything. Let me see what you provided as evidence... Right some anecdotes QuoteThat sure makes a difference.  For 19 centuries, peers "reviewed" Aristotle's principles of Physics.  That sure proved how good they were.You really know nothing about the scientific apparatus do you? https://www.wikiwand.com/en/Scientific_method#/History QuoteThe term "scientific method" emerged in the 19th century, when a significant institutional development of science was taking place and terminologies establishing clear boundaries between science and non- science, such as "scientist" and "pseudoscience", appeared.https://www .wikiwand.com/en/Peer_review#/Peer_review_and_trust QuoteResearchers have peer reviewed manuscripts prior to publishing them in a variety of ways since the 18th century.The scientific apparatus has massively changed around the 18-19th century. Especially peer-review in the form we know it today simply didn't exist before that. So by saing that it took 19 centuries you are giving an argument for modern day peer review. So thanks for your example on how great modern day peer review is. QuoteI would hope that people who, supposedly, have a greater understanding than mine be capable of showing me they can obtain better _results_ with their method than the one I'm using.  I've shown you the results I obtain.  Show me yours then, we compare.If you still think any comparison can be done without control, feel free to measure gravitational waves in your garage. QuoteSo far the "result" you've provided only shows that OOP can do with a lot more lines of code what procedural programming can do in one.And you've shown that as soon as one proves you wrong you shift the goal post. The goal never was to have as little lines of code possible   And, if productivity is measured in SLOCS/time, there is no doubt that typing 20 times more characters takes longer.  (that presumes, all thing being equal, that is, a human being with 10 fingers, reasonably adept at typing and, a working keyboard.)[/quote] I love how you focus on 1 out of 4 studies because it uses, as I already agree with you on, not a really precise metric. This fallacy is called cherry-picking. QuoteYes, you do.  The last example I provided made that very clear, compiled with FPC v3.0.4 in 32 bit, using -O3 optimization.  Only restriction: no assembly code because mine doesn't use any, other than that, implement however you like as long as it's using OOP (not really a requirement I'm imposing since it would make little sense for you to present a result that doesn't use OOP to support your beliefs about OOP.)What libraries where used? Because if create an empty program using the FPCs system unit, it will be more than 100kb by default. So I think you don't use the RTLs system unit, but your own. In that case any comparison is meaningless, because this would not compare OOP vs procedual, but RTL vs own system unit. So if you would want comparison thats worth something, you need control with a strict protocol. For example I suggested a simple program that uses nothing but the RTLs system unit. Because the system unit will be the same, all differences in the program will soly be due to our programming decisions. QuoteWhat problem did you run into ?... maybe I can help. I don't know the source. How should I reproduce your result without the source? I mean I could create a program in C that is smaller and tell you I did it with the fpc, and simply upload it as executable and you couldn't trust me. Why should I trust you? QuoteBut, according to what you stated, you don't really acquire knowledge unless you've done it yourself.  I strongly discourage you of running into a tree at 100MPH, I assure you the results won't be good and, you can take my word for it.That's why I searched papers, because I only trust things I've did myself and not what others tested... Right.. Honest question where did you get that sentiment from? Yes I think you shouldn't believe anything on face value, but that doesn't mean that you have to show everything yourself. Citation and peer review are the pillars of science for a reason. The only reason one can see further than his predecessors is because he is standing on the shoulders of giants. I don't need to drive with 100MPH at a tree to find out it will most probably kill me, crash test results are made for this. And guess what, these results also control for multiple variances. QuoteYou can go on about those papers all you want but, so far, the only actual example I've seen from you is a "hello world" program that takes way too many lines of code.  If I were in your situation I would refrain from using the word "embarrassing". I know that you don't have an understanding of science and empirical evidence. But the papers have a combined number of more than 200 samples. QuoteThat's well established in probability theory.  If that is new to you, use Google.What law, lemma or theorem is that? If you think its the law of large numbers, I need to remind you that you've already proven prior to this with that statement: QuoteIt's really easy, if something _can_ happen then it is only a matter of time before it happens. that you don't understand it. Because thats not the law of large number, not even close. This is what statistically illiterate people think the law of large numbers is. But it doesn't apply in this case because of reasons I've mentioned before QuoteYes, I do.  It has been used quite a few times to prove that time is relative with _facts_/_results_.  It would be really nice to see some _results_ from you (other than it takes more code... and apparently that you may believe that more code means less bugs.)You have shown multiple times here that you don't know about control, you don't know about the history and the peer review process, which you successfully demonstrated with your aristotle example, and you don't accept empirical evidence without bringing forth your own. QuoteI don't know but, that doesn't mean they are right, it only means none of them can clearly refute what is in the paper.Peer review does not mean it will be correct, none of the peer reviewers try to refute the work, they are only trying to eliminate bias by ensuring a sound methodology was used. QuoteI'd rather see evidence in code and, so far, it's been limited to a "hello world" program.  For some reason, it reminds me of the Rolling Stones, I don't get no satisfaction."Multiple large scale experiments with together more than 200 samples, statistically evaluated, are no form of evidence, let's compare some single example this will defenetly prove anything"... Please answer me this question, what is the 95% confidence interval of a t-distribution with only a single datapoint? You clearly showed you don't understand the scientific method, statistics, the peer review process, controlled experiments or the simple meaning of empirical evidence. This gave me a good laugh ---------------------------------------------------------------------- munair · 2020-05-10 14:17 Quote from: Warfley on May 10, 2020, 03:50:47 pmCitation and peer review are the pillars of science for a reason. I wouldn't put much faith in peer-reviews these days if I were you. There is a lot to read about peer-reviews leaving much to be desired (and I'm not just referring to these reads). Unfortunately "peer- reviews" give people a misplaced sense of science retaining a high standard, being guarded and safe from becoming pseudo-science or even false science, whereas in fact it is being heavily used to auto-filter away everything that is not established and generally unpreferred. This is especially true if it comes to mainstream science. While this may not apply to maths and programming where evidence is plain and easy to obtain for everyone through statistics c.q. benchmarks, I do wish to clarify this in light of your general claim that "[..]peer review are the pillars of science". Yes, they are supposed to, and it would make sense, but in truth they are not. It would be closer to the truth to claim that "peer-reviews are the pillars of preferred science." ---------------------------------------------------------------------- Martin_fr · 2020-05-10 14:45 Quote from: jiaxing2 on May 10, 2020, 03:20:13 pm@Martin_fr: there are people write procedural code with OOP mindset, too. The final result is a program full of pointers  Quite possible (thought depending on what you mean by "oop mindset", see my other post). Yet, not possible according to 440bx. He states clearly that people under the OOP mindset despise pointers. (except if the pointers are well hidden). ---------------------------------------------------------------------- 440bx · 2020-05-10 16:29 Quote from: Martin_fr on May 10, 2020, 02:59:21 pmNow, you see "in some cases": That is a statement I have on problem with. Everything has its up and downsides (and again I said from the start "no one shoe fits all").Honestly, I wrote "in some cases" because there might be an exception here and there.  There usually is an exception but, at the end of the day, in the great majority of cases (note: I didn't say all) the results obtained with OOP leave something to be desired in one way or another.  It could be in exe size, it could be in resource waste, it could be in performance, it could be in unnecessary code complexity, it could be due to too many lines of code (Warfley's hello world is an example of that) and, plenty of additional reasons.  The common case is a program that has multiple flaws and, that's inherent to the paradigm.  The two most common causes of the many deficiencies are the gross abuse and misuse of polymorphism and inheritance. OOP isn't a deficient paradigm for just one reason, it's deficient for many reasons. Yes, small executables can have bugs too but, in spite of what some "scientists" believe, the greater the number of instructions that make up a program, the greater the probability of a bug in it.   I've stated OOP puts a lot of unused code in the executable and, that is part of the executable size problem but, not all of it.  Another reason, OOP executables are larger is because of breaking things down into tiny pieces.  All those calls take space.  The point is: I'm being kind when stating the code is unused, that's the most favorable case for OOP.  Unfortunately, in many cases the code isn't unused and, it may contain bugs just like any piece of code may contain bugs.  Bloat isn't bug-free. Quote from: Martin_fr on May 10, 2020, 02:59:21 pmThere is also (with in the "no one shoe fits all" / some cases) OOP is the right shoe for programmers who can't be bothered to program.  Just use the libraries, components or whatever else someone has made.  Paste all that stuff together and call it a program.  OOP inherited from "paint by numbers". Fortunately, I have seen a good number of OOP programs that are not just that, such as Lazarus.  IOW, OOP in spite of being a very flawed paradigm can be used to create software worth using.  Just like C is an atrocity but, it can be used to produce usable software. Quote from: Martin_fr on May 10, 2020, 02:59:21 pmWell the question is, how to we remove the influence of the single individual. No, that's not the question because, it is sufficient to find two programmers reasonably competent in each paradigm and simply compare results.  It's not rocket science.   The real question is, how to eliminate the poor design influence a paradigm has on a programmer ?... and, when it comes to OOP and the C language (included to show it's not only OOP that causes problems), I don't know the answer and, I'm not sure there is one. Quote from: Martin_fr on May 10, 2020, 02:59:21 pm If (for arguments sake) the programmer needs to be part of the comparison, then comparing 2 individuals just adds a huge margin of error. No. What it adds isn't a margin of error.  What it _may_ add is a margin of quality.   The conclusion and point is this: pick two reasonably competent programmers in each paradigm and compare the results.  It really doesn't need to be more complicated than that.  IOW, what can a reasonably competent OOP programmer do with that paradigm compared to what can a reasonably competent procedural paradigm programmer do.   I'll grant you that using just one pair of programmers can't be used to create an average but, as long as the programmers are reasonably well selected, the deviation from the average should be within the standard deviation. Quote from: Martin_fr on May 10, 2020, 02:59:21 pmSo then comparison can only be done by taking two groups (each large enough to even out the influence of single individuals). I guess at least a 100, but you may propose a figure. And they cannot be handpicked.History is full of "many individuals believing one thing and confirming it" and being totally _wrong_.  Galileo, among others, proved that. No need for 100 individuals, what's needed are people who know what they're doing. IOW, and that applies to what Mr. Warfley suggests, statistical events are not indicators of scientific fact.  Succinctly, one billion Aristotles won't get Physics right.   One Galileo, One Newton, One Einstein... those will. Quote from: Martin_fr on May 10, 2020, 02:59:21 pmI also state, that I have doubts, that you represent the average procedural programmer. You're probably right about that.  I'm way too picky and demanding.  That a program works is what I consider the bottom of the basement.  Once I get it to work, I rewrite the thing because the first time is simply to learn about how to solve the problem.  The second time is about solving it the right way (or at least a decent way.) Quote from: Martin_fr on May 10, 2020, 02:59:21 pm And therefore your code is to be considered tainted, and can not be used for comparison. The implication in that sentence is that the only valid comparisons are between lousy implementations.  Decent code is "tainted".  That's a new one.  I hadn't heard/read that one before. Quote from: Martin_fr on May 10, 2020, 02:59:21 pm So your code has to be excluded. I don't see why.  The samples I provided are well within the grasp of an average programmer. Quote from: Martin_fr on May 09, 2020, 11:26:41 pm Where do we get, lets say at least (?) 100 people for each side? This isn't a poll to predict who's going to get elected to a public office.  Quote from: Martin_fr on May 09, 2020, 11:26:41 pm1) you are not representative of a typical/average procedural programmer You're probably right about that.  I use pointers, that alone seems to be untypical. Quote from: Martin_fr on May 09, 2020, 11:26:41 pm2) When Warfley, did to produce code as good as, you said it was untypical ... The end is, you expressed concerns about Warfley's code. It wasn't and, it isn't.  And, for the record, code that takes 10 (or thereabouts) lines to do what can be done in one line isn't "as good as" something.  In the best case it might be "as bad as" something but, not good.  Quote from: Martin_fr on May 09, 2020, 11:26:41 pmWe express concern about your code. And what is the concern specifically ?... it's not even what I consider good code.  It's just code thrown at the computer to test one API or another.  Simple, trivial stuff meant to be used as a test bed for a Windows API.  It's far from what I consider good code. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmOtherwise I claim that Warfley's hello world was valid and proved the point in favour of OOP. I believe you do not agree. It proved that, in some mostly exceptional cases, OOP can produce an executable that does not include more bloat than one produced using procedural programming but, to get there, takes 10 times more code than the procedural version.  It's really hard to see some value in that. Quote from: Martin_fr on May 09, 2020, 11:26:41 pm So thats pointless. If we do not agree, it is equally pointless. Same rules for both sides. You don't want the same rules.  What you are indirectly asking for is for all the deficiencies in OOP to be ignored.  In that case, after ignoring all the deficiencies, OOP is as good or, even better, as anything it is compared with.  Quote from: Martin_fr on May 09, 2020, 11:26:41 pmWhat I said all along. Some of the points, you claim OOP programmers do badly (due to mindset), are done by procedural programmers too. So those "some" points are not related to OOP.Yes, they are, because while procedural programmers may misuse some feature, OOP programmer misuse inheritance (among many other things) and, that cannot be misused in procedural programming since it is not a feature available in that paradigm.  The "features" that OOP provides have a very significant influence on the programmer's mindset with consequent results, mostly poor in the case of OOP. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmIn procedural coding, people use procedures/functions. They break up code too (and across units, or namespaces, or source files). Doing so is not at all OOP related. Yes, in procedural programming code is broken according to its _logical_ function.  In OOP a lot code has no logical purpose, it is there only to provide a way to override it.  The net effect is, in OOP, getting a logical function often requires assembling a jigsaw puzzle of bits of code scattered everywhere.  A good example of that is in the thread I've already mentioned https://forum.lazarus.freepascal.org/index.php/topic,46097.30.html  a simple function gets broken into 3 pieces, after that, the programmer has to assemble those pieces in his/her mind to figure out it's no more than just a trivial file mapping and, let's not forget that the function doesn't leave unnecessary handles open, create memory blocks (that class is in the heap and must be managed, etc, etc.)  OOP is a paradigm that causes (and encourages) programmers to "over-break" code to the point that the code sequence no longer has a logical purpose and, one of the many consequences of that, is a significant increase in the number of things the programmer has to keep track of, e.g, unclosed handles, freeing classes, logically meaningless little chunks of code everywhere, what little chunk of code has been overriden by another little chunk of code somewhere, etc, etc. Quote from: Martin_fr on May 09, 2020, 11:26:41 pmI came across the rule of writing small procedures way before I even heart of OOP. And there are many procedural programmers following that rule. Dividing code into small sections, is one of the golden rules. Heck, even assembler has subroutine calls. Yes but, along _logical_ use of the code.  Not breaking it down into pieces so the piece can be overriden by another chunk of code somewhere (and who knows where.)  That over breaking of code into logically meaningless pieces is a characteristic of OOP driven by inheritance and polymorphism.  Not good at all.  It results in hard to maintain code and executable bloat (all the parameter passing and calls take space... usually not much but, in OOP it ends up being considerable.) Quote from: Martin_fr on May 09, 2020, 11:26:41 pmAnd just to be clear:  I do not defend "over cutting" (splitting code that belongs together). But mistakes on where to cut, are made by both sides ... Yes, I can agree that over cutting does happen in procedural code too but, it's not nearly as often because there isn't inheritance and polymorphism promoting it. Quote from: Martin_fr on May 10, 2020, 04:45:59 pm(except if the pointers are well hidden). Yes, thank you for not omitting that.  As long as the compiler can do the work automatically for them then, pointers are "ok".  Once the Pascal OOP programmer has to explicitly make use of the pointer, the number of Pascal OOP programmers that use pointers drops significantly. That pointer hiding gimmick is very unfortunate, another Borland-ism.  @Warfley Given that our definition of what science is diverges so significantly, I don't see any point in continuing the discussion with you. ---------------------------------------------------------------------- jiaxing2 · 2020-05-10 16:57 Quote from: Martin_fr on May 10, 2020, 04:45:59 pmQuote from: jiaxing2 on May 10, 2020, 03:20:13 pm@Martin_fr: there are people write procedural code with OOP mindset, too. The final result is a program full of pointers  Quite possible (thought depending on what you mean by "oop mindset", see my other post). Yet, not possible according to 440bx. He states clearly that people under the OOP mindset despise pointers. (except if the pointers are well hidden). Now I'm not even sure if I agreed with 440bx at all. ---------------------------------------------------------------------- avra · 2020-05-10 17:00 To go back to the topic... for those still interested maybe some sort of pseudo managed objects could be achieved with this solution: https://github.com/pda0/AutoScope Not the same as support in the language it self, but at first look it seams good enough to cover many use cases (haven't tested my self). ---------------------------------------------------------------------- jiaxing2 · 2020-05-10 17:05 Quote from: 440bx on May 10, 2020, 06:29:52 pm@Warfley Given that our definition of what science is diverges so significantly, I don't see any point in continuing the discussion with you. @winni: ---------------------------------------------------------------------- jiaxing2 · 2020-05-10 17:09 Quote from: avra on May 10, 2020, 07:00:50 pmTo go back to the topic... for those still interested maybe some sort of pseudo managed objects could be achieved with this solution: https://github.com/pda0/AutoScope Not the same as support in the language it self, but at first look it seams good enough to cover many use cases (haven't tested my self). This thing is cool! ---------------------------------------------------------------------- Martin_fr · 2020-05-10 17:38 Well, thanks for the added detail in some parts. Gives a bit of insight where from you derive your view. Overall, nothing that would change my statements. Still at an impasse. ---------------------------------------------------------------------- 440bx · 2020-05-10 17:47 Quote from: Martin_fr on May 10, 2020, 07:38:27 pmWell, thanks for the added detail in some parts. Gives a bit of insight where from you derive your view. You're welcome. Quote from: Martin_fr on May 10, 2020, 07:38:27 pmOverall, nothing that would change my statements. Still at an impasse. I understand.  I didn't expect to change anyone's mind about OOP. ---------------------------------------------------------------------- Thaddy · 2020-05-10 18:01 Quote from: avra on May 10, 2020, 07:00:50 pmTo go back to the topic... https://github.com/pda0/AutoScope That is similar to my smartpointer approach, also on this forum. ---------------------------------------------------------------------- Warfley · 2020-05-10 18:15 Quote from: munair on May 10, 2020, 04:17:42 pmI wouldn't put much faith in peer-reviews these days if I were you. There is a lot to read about peer-reviews leaving much to be desired (and I'm not just referring to these reads). Unfortunately "peer-reviews" give people a misplaced sense of science retaining a high standard, being guarded and safe from becoming pseudo-science or even false science, whereas in fact it is being heavily used to auto-filter away everything that is not established and generally unpreferred. This is especially true if it comes to mainstream science. While this may not apply to maths and programming where evidence is plain and easy to obtain for everyone through statistics c.q. benchmarks, I do wish to clarify this in light of your general claim that "[..]peer review are the pillars of science". Yes, they are supposed to, and it would make sense, but in truth they are not. It would be closer to the truth to claim that "peer-reviews are the pillars of preferred science." They are not flawless, that is true, but they are still the pillar of science. No one said that that pillar is flawless. But the reason we excelled so much at scientific research in the past 200 years, is mainly because of the new scientific apparatus. We did more advancements in the previous 200 years, than in all of the 2000 years prior to that. I know especially since the internet there are a lot of "preditory journals" out there (on of my favorite papers ever making it through peer reviewed is still http://www.scs.stanford.edu/~dm/home/papers/remove.pdf), but even this can be handled by checking a journals impact factor, h-index or similar statistics. Very often a lot of things change rapidly, e.g. last time I was reading psychology papers about some mental illness and you can see how the medical view of those things rapidly changed over the past 50 years, which of course is due to the inherently complex nature of that topic (it's much harder to control for the brain activities than some PC environment). That said, it is still the gold standard in science, and an empirical study if something was released in a respected journal, you can be rather sure it at least has some sound methodology. Quote from: 440bx on May 10, 2020, 06:29:52 pmGiven that our definition of what science is diverges so significantly, I don't see any point in continuing the discussion with you.The definition of science is not a matter of oppinion, science is a methodology (https://www.wikiwand.com/en/Scientific_method) that follows a rule set. Most simply the following cycle: 1. make hypothesis, 2. test hypothesis (e.g. in a controlled experiment) 3. refine hypothesis based on the results. Each hyptothesis needs to be falsifiable by experiment. If a hypothesis has gone through so many iterations of this cycle that it can describe the natural really well, it will become a *scientific theory*, like newtons theory of gravity. A theory is the closest thing to a fact you can have in science. It doesn't mean it's perfect (see Einsteins theory of general relativity, which is more precise than newtons), but that it is applicable to explain most naturally occurring phenomena. So your hypothesis could for example be: OOP adds bloat. So we first create a test that could falsify that assumption. For this you first need to define your null-hypothesis, which is OOP does not add bloat. You will now design a test for this, where you control for all other variables, e.g. you could take a lot of procedual programs and replace records or other datatypes by static objects. Because everything else about the code stays the same you controlled for all variables except for the paradigm used. Then you can make a statistical evaluation, e.g. by computing confidence intervals over the t-distribuiton, and if they don't overlap we call that statistically significant. Your goal is now to reject the null hypothesis with statistical significance. This means you need to assume that the opposite of your hypothesis is true and your goal is to show that this is a wrong assumption. Here is the first crux of your approach. You first assume your hypothesis is true, and design tests to verify it, not to falsify it. My hello world example on the other hand is created to falsify your assumption. You need to create tests for the null-hypothesis not for your hypothesis. So let's say you can't reject your null hypothesis, e.g. because your experiments show the result like my hello world program. Then you need to refine your hypothesis, e.g. you could say something like: "Using design patterns common in OOP create bloated executables". This of course needs you to argue what are design patterns common to OOP, and here you usually don't reside to personal experience, but search the literature. But let's simply assume you have a list of design patterns common to OOP and comparable design patterns (in effect/usage) for procedual programs, then you can start to create a test for this. Again you start of by creating your null-hypothesis, in this case: Common OOP design patterns will not lead to bloated executables. Prepare your test to reject that hypothesis, i.e. a test to test the null hypothesis. In this case you could get a bunch of programmers, give them all the same task, but tell them to use the specific set of design patterns. Note, in this case you need to control for everything else, including used libraries, and in the best case even the language or the paradigm. So if you can reject the null hypothesis, then you need to design more tests to verfy other aspects (e.g. chose different patterns, etc). But you only supported the refined hypothesis and not the original. Therefore while you can say that "common OOP design patterns can lead to bloated executables" you have in no way shape or form gathered any evidence that "OOP leads to bloated executables". This is the second problem with your argumentation, you assume that when you are able to prove a certain subset, the original hypothesis must be true. This is not the case. The third thing is that of course you need to make assumptions, and control for other factors. E.g. two different persons write different code. So if you would just have two people writing the same program you will expect differences. For example if you just say: Write me a GUI calculator one in OOP and one in Procedural, one person might meticulously write a calculator using the system API, while the other one will simply use GTK for doing so. Now you have the problem that here you don't compare the two paradigmes but you are actually comparing GTK vs system api as well as the paradigmes. You then have no way to know which effects are attributed to which of the differences. This is the third problem with your argumentation, you don't control for any other influences. For example, let's assume classes will add overhead opposed to procedural programming. If you then write the OOP program not using the RTL and the procedural project does, the procedural program will be much larger. This would lead you to the wrong conclusion that classes can reduce the memory usage a lot, even though this is a wrong conlcusion. So without knowing how you created your executables, any comparison will be pointless because you can't factor out the other influences. As you can't controll for all factors you assume that the influence of these factors will add up to some form of distribution around the *ground truth*, usually a gaussian. Due to the finite nature of sample sizes, often a t-distribution is used, which is a gaussian adjusted for the error due to the limited sample size. You can then compute the probability that the two mean values will be different, this is called a p-value. You then set an (arbitrary) limit like 5% and say: If p < 5% then it is statistically significant (i.e. the probability of this being soly by chance is less than 5%). This is why one example means absolutely nothing. Note that the smaller the sample size, the higher the standard error, the more "randomness" you have, i.e. the higher your p-value will be. If you can't find statistical significance (i.e. your p value is to large), you can't reject your null hypothesis and therefore need to default to it. Now here come in such papers. Every paper is a snapshot of one iteration cycle. The last paper I presented contained 4 hypothesis 1. C++ is replacing C in big hybrid projects, 2. C++ is less complex than C, 3. C++ is less error prone than C, 4. C++ is better maintainable than C. They where able to reject the corresponding null hypothesis for the first 3 of those points, showing, under their assumptions of course, that the margin between C and C++ here is statistically significant, i.e. the chance that this different in measurement is due to randomness is less than 1%. All the tests where conducted by following a certain protocol, to control for variances. E.g. they only compare C and C++ code from the same project, i.e. following the same development scheme and design process. They also ensured that devlopers developing C++ code also develop C code. This way they control for both, personal preferences as well as the program design and project organization. Now the next step would be to extend the testing, e.g. test this for other languages than C and C++ (which might not be realistically possible, because there are not so many other language combinations that are as prevalent as this one), or the last hypothesis that could not be shown, could be refined, i.e. C++ is better extendible than C. But this would be the work for a different paper and another iteration of the cycle of the scientific method. This is why you can never look at one paper in isolation, and why citations are so important. And this is why you should always search for some papers covering a wider range. The peer review process is not here to tell if something is right or wrong, you need to look at multiple papers for this. The peer review process can only tell you if the methodology followed the scientific method or not. You should not assume peer review and citations mean this is true, it only shows that there is a certain quality to how the paper approached their measurements. So let's recap. A scientific approach would try to falsify the hypothesis, controlling for all factors not mentioned in the hypothesis and you can only prove your hypothesis with a certain probability. If that is to high, you must default to your null hypothesis. This is the reason why your approach is completely unscientific, because 1. you design the tests to confirm your hypothesis not to reject it, 2. you are switching your hypothesis all the time and assume that one being true means others also being true, and 3. your "tests" don't control for anything and use anecdotes for proof. An example for the first would be you demanding an OOP program to reach the metric of your posted procedual program, rather than trying to OOPify it and see if it adds overhead. An example for the second problem is you arguing that OOP adds bloat, and when confronted with an example that doesn't add bloat, you say that "classes add bloat" and think that therefore your hypothesis "OOP adds bloat" defaults to true, even though these are totally different hypothesis. An example for the last thing is that you simply post .exe files and expect others to reach the same size with OOP. What you forget about this is, I also wouldn't be able to reach that size with procedural programming because as soon as I use the RTL, no matter how my code will look like afterwards, it will be larger than 100k. This means you are not measuring OOP vs procedural but rather your implementation vs my implementation, which could have hundreds of variables influencing the result. OOP vs procedural could be the main contributor or the least noticable of these, there is simply no way to find out. And this is why your approach is completely unscientific ---------------------------------------------------------------------- munair · 2020-05-11 07:07 Quote from: Warfley on May 10, 2020, 08:15:27 pmThe definition of science is not a matter of oppinion, science is a methodology (https://www.wikiwand.com/en/Scientific_method) that follows a rule set. There is a difference between definition and practice. You seem to have a lot of faith in modern day science and you bring it to the table as a means to convince. Do you have any idea how much valid research results are being kept out of text books? There are layers firmly in place and each of them acts as a filter. Research results may be confirmed and even accepted at the first level, but they will NEVER reach the final level. This is especially true in the fields of archaeology and anthropology (astronomy may be a good third) where certain findings would have a mind-altering effect. I can assure you that certain finds, even 200 years ago, never reached the text books and never will in our current society. So again, while science by definition is supposed to be 100% impartial and void of private opinion, in practice this is not the case. If it were, we would have an entirely different society which would be much more advanced and with much less conflict. While this is going way off topic, it is essential to point this out. ---------------------------------------------------------------------- Warfley · 2020-05-11 13:32 Quote from: munair on May 11, 2020, 09:07:45 amWhile this is going way off topic, it is essential to point this out. But textbooks are outside of the scientific process. The scientific process is the accumulation of knowledge through the scientific method. It's findings are represented by papers and the discussion on them is done via peer-review and citations. Textbooks are written by science communicators whose goal it is to basically capture the current state of the scientific knowledge and make it accessible to the public. This is usually not peer reviewed, i.e. there is no bias control in there. This then leads to such things as history books that usually portray a very one sided view of history. This is not part of the scientific process but rather the "interface" of the sciences to the public, because most people have neither the time, nor the ability (most papers are behind a paywall), nor the knowledge (you need to know where to find and how to read those papers) to do so, this is where science communicators come in. While there are many great science communicators who have the standard of trying to be as impartial as possible, there are also many who simply aren't. The last step is then that some text books are used in schools or so. This decision is done by (local) governments or school boards and is a completely unscientific process that is governed by political and financial interests. There are still schools in the western world that don't teach certain scientific theories because of political reasons (e.g. evolution is highly conservative Cristian areas/schools). The last two points both have very little to do with the scientific process and are more guided by personal policy. And don't get me started on scientific reporting in the press. This is one reason I usually try to go directly to the papers and not through some form of middle man But don't get me wrong, there are some major problems with the scientific process itself, e.g. the fact that the institutions need funding there is a heavy incentive to research new topics rather than verifying other peoples work. This leads to a lot of not reproducible work being published. Especially in the field of machine learing you very often see paper where simply the parameters used are missing so you have absolutely no chance to reproduce the results. But there is no real incentive to write a verification paper.