Earlier quoted context omitted.
My point isn't so much that ditching the backwards compatibility is always right, even when it lets you shed lots of code, but that you can often massively reduce code size that way. Whether that's the right thing to do is often a fine balance, because it depends a great deal on how many people actually care about the old ways, and sometimes people will get it very wrong in either direction. Sometimes the 10x more co…
Rewriting the code isn't the hard part... The QA is the hard part. Developer: "Rewriting this line of code shouldn't change anything" Narrator: It did
How could the early Unix OS comprise so few lines of code?
141–150 of 170 posts
Re: How could the early Unix OS comprise so few lines of code?
#142Earlier quoted context omitted.
I think the most important thing to ask about an edge case is “how could I have designed this code to make it not an edge case”
"I should have beat the customer until they gave me full specifications of what they needed before writing code" Is unfortunately what happens a lot.
Re: How could the early Unix OS comprise so few lines of code?
#143Earlier quoted context omitted.
> you put it near the pointer that points to the beginning of the (sub)string. And now you have a "string pointer" which is distinct from a "data pointer". You can't allocate a heap block and "put a string in it" because the special thing at the start needs to go with the pointer and not the data in the block. And your 1970's compiler on your PDP-11 with 48kb of RAM needs to manage that. Good luck to you. Again, we'r…
> And now you have a "string pointer" which is distinct from a "data pointer". You can't allocate a heap block and "put a string in it" because the special thing at the start needs to go with the pointer and not the data in the block. The second sentence doesn't follow from the first one. struct string { char (*ptr)[static len]; size_t len; }; struct string new_copy = { .ptr = malloc(100), .len = 100; }; new_copy = s…
But what you seem to be asking for is support in the language for strings that work like this. And that causes problems because of that special handle you've invented. Now strings aren't arrays anymore, they can't have pointers taken to them, they can't have substrings in a natural way, they can't live in ordinary POD memory as a unified thing.
All of which is totally solvable in the runtime of a language written in 2003 or whenenver. But not on a PDP-11.
Re: How could the early Unix OS comprise so few lines of code?
#144Earlier quoted context omitted.
Pascal strings had the same size overhead as C strings. One using the "byte" for length, the other for size.
But C strings could at least be arbitrarily long, Pascal strings were extremely handicapped. It’s like they understood why length prefix is better, but then picked the worst possible implementation.
The editors I wrote back in the eighties were just linked lists of pascal strings so a line was limited to 256 characters but these were very fast in VMS and DOS
Also we only had a few character sets and you could live your whole life in ASCII
Re: How could the early Unix OS comprise so few lines of code?
#145Earlier quoted context omitted.
My experience is that while edge cases certainly adds bloat, there are plenty of cases where the bloat comes from entirely different things, and where simply rewriting with the hindsight of being able to see the overall structure better can do wonders. In other words: A lot of the time undoing mistakes made first time around as a result of not having the full picture. And often it's a result of trying to cater for ev…
In a converse reply, Microsoft has done very well financially by holding on to backwards compatibility. In the OSS world we tend to look at rewrites as "This is for me, who gives a shit about the customer", but most customer (paying) facing software there are the expectations of Do not break the application, and do not break the customers expectations. This said, X was and is a mess.
Re: How could the early Unix OS comprise so few lines of code?
#146Earlier quoted context omitted.
What features does it support? What if I pass in a complex regexp with data several GB in size? There is a large difference between toy examples and hardened enterprise ready code.
The features are less important than the linear complexity. It lowers to an NFA. An NFA can recognise any linear language, so adding more features affects the generation of the NFA, while increasing the performance involves faster matching against the NFA. In this case he's done a followup with benchmarks where he's converting the NFA to a DFA ajd comparing favourably against both Node and your browers regexp engine…
Re: How could the early Unix OS comprise so few lines of code?
#147Earlier quoted context omitted.
If you removed from a complex program any feature that was used by less than 2% of the users the program would be much smaller and simpler. However you also lose each 2%. In many cases every user uses a different subset of what your program does, and so the end result is no users at all because your program is useless.
Yes, but part of the argument was that you can often cut drastically without cutting features when you take the time to understand the problem properly. Sometimes everyone actually does use genuinely different features, but more often there are different ways of solving the problem that will still be more concise even if you keep everything. To take a somewhat concrete problem from a past job: We had an agency do a b…
It's very hard to understand what comprises the small and elegant set of abstractions to solve a particular problem without first trying many larger sets, and checking how well do they solve the problem in practice. Unix itself was born after an attempt to solve a similar set of problems by writing Multics, a much larger OS.
Re: How could the early Unix OS comprise so few lines of code?
#148Earlier quoted context omitted.
The features are less important than the linear complexity. It lowers to an NFA. An NFA can recognise any linear language, so adding more features affects the generation of the NFA, while increasing the performance involves faster matching against the NFA. In this case he's done a followup with benchmarks where he's converting the NFA to a DFA ajd comparing favourably against both Node and your browers regexp engine…
Being O(n) is important, but the size of the constant factor is important, too. E.g. the theoretically most efficient known matrix multiplication algorithm only outperforms the less efficient common algorithms at ludicrous matrix sizes, because of the huge constant factor.
Re: How could the early Unix OS comprise so few lines of code?
#149I feel that most 100K line programs could be rewritten with just 10K lines and end up being more reliable. Feature creep is responsible for some of the code bloat but I can guarantee from experience that, in the vast majority of projects, you could keep all the features and still cut the code to at least 1/10th of its size. I think the reason for this is because developers who focus on development speed do so at the…
First, I think we should use expression count instead of pure LOC because many styles add white space but keep the expression the same. I don’t consider one style “more terse” than another. e.g. a.map(…).reduce(…).join(…) a.map(…) .reduce(…) .join(…) If you can accept that expressions are a better metric for “terseness” then I will categorically say your statement is pretty easy to disprove. Essentially you’re saying…
It’s about preventing large (and poorly thought out) projects from being worked on in the first place, before they need to be scrapped or circumvented.
Re: How could the early Unix OS comprise so few lines of code?
#150I feel that most 100K line programs could be rewritten with just 10K lines and end up being more reliable. Feature creep is responsible for some of the code bloat but I can guarantee from experience that, in the vast majority of projects, you could keep all the features and still cut the code to at least 1/10th of its size. I think the reason for this is because developers who focus on development speed do so at the…
You may have the perfect code for your use case, with the right level of abstraction, until reality kicks in. For example, let's say you are writing a device driver, each device identifies itself with a unique identifiers, fine, until one day, you get different devices with the same id and you need to issue a special command to differentiate between them. And then, the next device receive commands in little endian order, even though all the other ones were big endian. And then another device sometimes silently fails to execute a command, you then need to a bit of time and check that it was actually taken into account and retry if it wasn't. Etc...
You can't plan for all that, if you try, it will only make things worse. All that will invariably result in ugly code, it is not bad design, it is just that reality itself is ugly.
If you try to start over, if you are really really good, you can reduce it to something nice until the next dose of reality. But more likely, you will make things even worse. Believe me, if you think you are good, try rewriting a legacy app that is used in production in a way that doesn't break production, I predict a humbling experience.