jstimpfle
Joined 11 years ago
Joined 11 years ago
If the state needs money, it needs to take it from where it is, which is still with the masses. In Germany, at around maybe 90k EUR income is a particularly bad place to be. You are nominally considered to be a good earner. But at that point you already give around 70% on the next EUR you earn for various taxes and social security. If you are financially responsible not only for yourself but for other people (which is not reflected in lower taxes unless you're legally married), you can still get along fine, but it might not feel like you are a good earner. I was in a similar situation at one point in my life, it had taken me hard work to earn that money, and I have to say I was a little pissed about the tax situation.
I think I understand why progressive tax systems exist. Given our societies' structures, they probably _have_ to exist. But also I wonder if long-term they _contribute_ to income and wealth inequality. It reduces incentives for those who earn less to earn more (which of course for many people is not easily possible, but for some it would be, by working more, working harder, looking for a different job, etc.). It also allows employers to spend less on their workforce, meaning you could understand it as a kind of subsidiary for employers. Of course, lower salaries might be the only way for employers to even offer a product at prices the market wants to pay. But again it also reenforces inequalities in the income structure.
I've realized that naming is an art that is difficult to master but makes a huge difference when gotten right. It consists of not just combining names into compounds but also finding new shorter names that are ergonomic and distinguishable. For example, I've replaced the compound "NodeIntersectTest" in my current project with simply "Probe", which is much easier to read and write, easy to distinguish from other terms after learning its meaning once (it is a central concept to my app), and also perfect for log messages and stats where brevity matters a lot.
A two letter prefix for all identifiers in a project or company codebase is a good idea, but I try to avoid hierarchies and finer granularity, and generally to be overspecific, in order to keep things easier to change later.
The point of namespaces is exactly to allow less qualified names, to allow spending less energy when creating new names, by having the compiler always add a qualification implicitly. However, that doesn't solve the problem with name collisions when reading or grepping the source code -- it actually makes it much worse. And avoiding those name collisions, i.e. what's in the source literally, what the programmer reads, and what less-than-perfect tools see, is at least as important as avoiding "semantic" name collisions and being able to compile the code.
Namespaces not only encourage many more literal collisions -- now a single name can be available in various shortenings, and even under different aliases, which also makes it hard to tell that two symbols refer to the same thing!
I've found that the only way to get names right is to find a good scheme, to find meaningful good prefixes, suffixes, and abbreviations, and to come up with a system to create new names more mechanically but still keep them as short and readable as possible.
Much bigger problem is understanding the scope of dependencies. Dependencies can go bad and you need to update. A dependency might not be available on some new platform so you might have to replace with something else on that platform. To make the software portable, good modularity is required. This is to a large extent an aspect of software architecture. Even Rust can't magically make this happen, if you depend on 300 crates that's probably not a great place to be in either if you want to be portable and maintainable.
There is probably a point that C's flat namespace is a major contributor to badly designed software, because people aren't aware of the dependencies they're mixing all the time. Also C encourages transitive includes, leaking implementation details to the user instead of just to the compiler. (But btw. I find C++ and Rust namespace to be unergonomic syntax-wise, and what's needed is not actually namespaces but control over visibility).
It's also easy to write C that won't build on the system it was originally developed on, a few years down the line. But that is true for almost every other language ecosystem. I would say, C makes it _possible_ to write code in such a way that it works on many different platforms and compilers, and/or can continue to work in decades to come with relatively little maintenance.
The latter isn't true for most other ecosystems, because to get anything done in them, you need to rely more on that language and its ecosystem -- specific language features, specific libraries. C isn't a glue code language. It's very good at letting you create your own thing.
To do it well though, requires a lot of care and expertise.
Fully agree, for locks or other simple begin/end pairs it doesn't create the same kind of architectural damage. But I don't use it even there, because RAII fundamentally doesn't play well with manual cleanup code. It's kind of an all-in game, if you use some RAII there are strong forces (whenever you need to get the "nesting" right) to convert all remaining manual begin/end type code to types that define that functionality out-of-line in the destructor/destructor, leading to fragmentation.
I could re-type all the essential stuff from std::string that I've ever used myself within 10 minutes, no problem, without looking up external sources, including copy & move semantics and whatnot. But I'm deliberately not doing it. Because I don't like this "invention".
I don't know why you are now jumping to setjmp/longjmp, trying to make a point that somehow C is the worst programming languages ever, when all I am trying to argue is for sane programming practices, hinting that more complex features (line especially found in newer languages) are not solutions but part of the complexity problem.
No, just saying this stuff is implicit and thus hard to read. More so the allocation on indexing assignment. and keeping things which shouldn't be mutated const wasn't a problem at all.
> and keeping things which shouldn't be mutated const wasn't a problem at all.
As soon as datastructures become more complicated and more interconnected, it's not clear anymore what const should even mean (issues are similar as with deep vs shallow copies, how do you even draw the lines, where are the objects?).
And the major philosophical flaw in the const vs. non-const distinction is that to make a strict separation you have to move everything mutable into constructor calls (for the most part, not getting more into the weeds of C++). Which is very awkward, it's a real tradeoff you need to be aware of. I realized only after playing these games for a long time what a waste of time it is and how much complexity it creates.