That's assuming the axiom that "engineer" must require licensing requirements. That may be true in some jurisdictions, but it's not axiomatically or definitionally true.
Some kinds of building software may be "engineering", some kinds may not be, but anyone seeking to argue that "licensing requirements" should come into play will have to actually argue that rather than treat it as an unstated axiom.
Depends on the country. In some countries, it is a legal axiom (or at least identity).
For the other countries, though, arguing "some countries do it that way" is as persuasive as "some countries drive on the other side of the road." It's true, but so what? Why should we change to do it their way?
> Depends on the country. In some countries, it is a legal axiom (or at least identity).
As I said, "That may be true in some jurisdictions, but it's not axiomatically or definitionally true.". The law is emphatically not an axiom, nor is it definitionally right or wrong, or correct or incorrect; it only defines what's legal or illegal.
When the article raised the question of whether "building software is an engineering discipline", it was very obviously not asking a question about whether the term 'engineering' is legally restricted in any particular jurisdiction.
To my mind, the term "engineering discipline" implies something roughly analogous to Electrical Engineering, Civil Engineering, Mechanical Engineering, Chemical Engineering.
There is no such rigorous definition for "software engineer" which normally is just a self-granted title meaning "I write code."
Because AI is attacking, plagiarizing, competing with, and destroying the most common industry of people here on HN, so suddenly it mattered more to people who were previously unaffected.
Some people have been concerned with this kind of politics all along. Some people are realizing they should be now, because of AI. And that's okay; both groups can still work together.
It's a social problem that's created by a technical problem.
In many languages, if you want to integrate package A with package B, you can make and share a package AB, which people can reuse. That scales, and facilitates reuse, and avoids either package having to support everything.
In Rust, if the integration involves traits, integration between package A and package B must happen either in A or in B. That creates a scaling problem, and a social problem.
Other than duck-typed languages (and I count Go as basically that), which languages actually provide this feature?
AFAIK, it’s not really very common to be able to extend foreign types with new interfaces, especially not if you own neither.
C++ can technically do it using partial specialization, but it’s not exactly nice, and results in UB via ODR violation when it goes wrong (say you have two implementations of a `std::hash` specialization, etc.). And it only works for interfaces that are specifically designed to be specialized this way - not for vanilla dynamic dispatch, say.
> Other than duck-typed languages (and I count Go as basically that), which languages actually provide this feature?
There are only like 3 significant languages with trait-based generics, and both the other ones have some way of providing orphan instances (Haskell by requiring a flag, Scala by not having a coherence requirement at all and relying on you getting it right, which turns out to work out pretty well in practice).
More generally it's an extremely common problem to have in a mature language; if you don't have a proper fix for it then you tend to end up with awful hacks instead. Consider e.g. https://www.joda.org/joda-time-hibernate/ and https://github.com/FasterXML/jackson-datatype-joda , and note how they have to be essentially first party modules, and they have to use reflection-based runtime registries with all the associated problems. And I think that these issues significantly increased the pressure to import joda-time into the JVM system library, which ultimately came with significant downsides and costs, and in a "systems" language that aims to have a lean runtime this would be even worse.
> Scala is interesting. How do they resolve conflicts?
If there are multiple possible instances you get a compilation error and have to specify one explicitly (which is always an option). So you do have the problem of upgrading a dependency and getting a compilation error for something that was previously fine, but it's not a big deal in practice - what I generally do is go back to the previous version and explicitly pass the instance that I was using, which is just an IDE key-combo, and then the upgrade will succeed. (After all, it's always possible to get a conflict because a library you use added a new method and the name conflicted with another library you were using - the way I see it this is essentially the same thing, just with the name being anonymous and the type being the part that matters)
You also theoretically have the much bigger problem of using two different hashing/sorting/etc. implementations with the same datastructure, which would be disastrous (although not an immediate memory corruption issue the way it could be in Rust). But in practice it's just not something I see happening, it would take a very contrived set of circumstances to encounter it.
> (although not an immediate memory corruption issue the way it could be in Rust)
Just to note, all of Rust's standard container types are designed such that they guarantee that buggy implementations of traits like `Hash` and `Ord` do not result in UB - just broken collections. :-)
C# does not support adding interfaces to foreign types. It does support extension classes to add methods and properties to a type, but nothing that adds fields or changes the list of interfaces implemented by a type. Rust supports this as well, because you can use traits this way.
Dependency injection is a popular solution for this problem, and you can do that as well in Rust. It requires (again) that the API is designed for dependency injection, and instead of interfaces and is-a relationships, you now have "factories" producing the implementation.
No, it has nothing to do with the time to crack encryption. It's to protect against two things: organizations that still have manual processes in place (making them increasingly infeasible in order to require automatic renewal) and excessively large revocation lists (because you don't need to serve data on the revocation of a now-expired certificate).
reply