(BTW, would be nice if I could read your API docs without signing up for an account.)
1,103 karma · joined August 22, 2011
[ my public key: https://keybase.io/cakoose; my proof: https://keybase.io/cakoose/sigs/gNz7dqjDBzs5anzP30jhCtr5bcogtlGjKLP2yghDN9I ]
(BTW, would be nice if I could read your API docs without signing up for an account.)
Would you create a single operation that reads one record, checks that it's enough, then adds the amount to another record?
Or maybe you'd first read both accounts, then issue a conditional write operation that makes sure the data hasn't changed before doing the write?
How often people actually do a hard refresh? I would guess most people don't know about that key combination.
Rust's type system, like any type system, is limited. It enforces a certain style of safe programming and will reject other styles of safe programming.
The compiler is also not great at explaining why something is wrong. I'm not knocking the compiler writers, because it's a hard problem and they're putting serious effort into it. But from ESR's perspective, he's writing code that is safe (according to a style he's developed over decades of programming) only to have it rejected with an explanation that doesn't make sense. It's frustrating.
There are ways to improve the learning experience. You can improve documentation, improve compiler error messages, and improve the type system itself (e.g. non-lexical lifetimes). The Rust team appears to be taking all of these seriously.
I think the people who make it past the initial frustration are those who believe that it will be worth it. I'm a huge fan of type safety guarantees. I've also followed the development of Rust enough to know that the people making decisions are good at designing languages. So when I'm frustrated, I remind myself that this is probably all worth it.
But reading ESR's write-up, he's clearly not coming from the same place. He believes that Go and Rust both have "strong type systems", which is clearly false. He complains about Rust exposing an unsafe construct like mutexes without realizing that Rust mutexes are much safer than in C. But to be fair, he's also thinking about a specific project that needs an efficient epoll-style mechanism and Rust is just not there quite yet.
Why do you categorically say that something is broken if it requires personal presence?
Since HTTP connections are typically kept alive between requests, it's very common for them to be idle. It could be the case that 99.9% of the time, X bytes of memory is enough to avoid transfer delays, but to cover the 100% case, you'd need 10X that.
I think it's reasonable to decide that avoiding delays in the 100% case is not worth 10X the cost in memory.
If we stick with the airplane analogy, maybe this is better: it's like incrementally converting an older model jet engine to a newer model jet engine in between flights. Every incremental version must work correctly, which isn't easy, but the upgrades are definitely performed on the ground.
That seems reasonable. But wouldn't the same thing apply to Javascript? Terrible Javascript code bases are very common.
In this case, it's an implicit conversion from "nil" to the "nil value" of a given type. This is convenient in many cases, but causes confusion in other cases.
If the laptop doesn't have an SSH private key, how do you SSH to the bastion host?
> In your .ssh/ directory, you'll see id_ecdsa and id_ecdsa.pub. Copy the latter to the CA server and get it signed. Because this is public information, the transport isn't important. You can copy and paste, or fax it; just don't copy id_ecdsa anywhere.
The transfer of id_ecdsa.pub doesn't need secrecy, but it does need integrity. You don't want to accidentally sign an attacker's public key.
Would an OTR-style protocol be immune any type of DOS proof-of-work? Are there disadvantages to having deniable authentication for the kinds of communication that TLS is used for today?
Edit: according to the paper, the attack only works on TLS 1.2+, and only works on the setup phase. Apparently, TLS allows you to forge the contents of the communication. Does OTR allow you to forge the setup phase as well?
Let's say I want to use the new type system, but some library I depend on hasn't been updated. If I enable the new type system, I'll get both false positives and negatives when type checking.
If a library writer updated to the new type system, they'd break compatibility with callers that haven't updated. The safest option would be to maintain two almost-identical copies of the library -- one for the old type system and one for the new one.
A better option would be to allow specifying the type system mode at the top of each file (like "use strict"). This allows me to use the new type system even if not all my libraries have updated yet. This also allows libraries writers to use the new type system features without breaking existing users.
This makes me wonder why Goa just doesn't rely on the Swagger code generators? Are they not very good?
The Goa page talks about generating Swagger so you can use the Swagger doc generator. Maybe that's the only part of Swagger that the Goa developers think is useful?
Also, Swagger has more traction right now. Maybe the ability to generate a Swagger spec lets people not feel so locked in to Goa, the newcomer?
> So what's the point ? Linux is a niche market. Mac & Windows will be the vast majority of your users and won't enjoy your killer kernel-based feature...
Even when Windows/Mac are the vast majority of clients, each client only needs to process its own traffic. The VPN gateway is more likely the bottleneck, since it needs to process everyone's traffic. There are many organizations that would have no problem running Linux on the VPN gateway and could reap the benefits.
Also, the Linux in-kernel implementation is just the first(?) thing being released. WireGuard is a VPN protocol and its killer feature is good security that's simple enough to implement in 4000 lines of code. This simplicity makes it easier for someone to write a Windows/Mac kernel driver.
What are the advantages of doing UDP instead of IP?
It seems like, all else being equal, doing IP has the advantage of working with UDP and TCP out of the box.
For example, what if you were taken apart, your molecules were sent to Mars, and then you were reassembled exactly as they were? Would that be continuous consciousness?
If so, how is that different from the cloning option if your clone were assembled on Mars and the original were completely destroyed at the very same instant? (Or maybe the original were destroyed just an instant earlier.)
Interpreters are typically slower (though simple to write and portable). The standard Python/Ruby/PHP implementations are interpreters. (The Python interpreter doesn't interpret from source every time, though; it usually uses the bytecode from previous runs.)
Implementations that generate machine code are more complicated and less portable, but have the potential to be faster. However, while compiling "down to machine code directly" can help startup time, it has little to do with what allows a language to be fast. What matters is whether it's possible to generate efficient machine code.
Static typing, for example, allows a compiler (ahead-of-time or JIT/VM) to generate more efficient machine code [1]. The ability to monkey-patch code -- which is common in many dynamic languages -- makes things harder for a compiler.
That said, there are compilation techniques to make dynamic languages pretty fast -- much faster than the standard Python/Ruby/PHP interpreters. For example, Javascript VMs have gotten 10x (or more?) faster over the last 5 years. (One of the big ideas: <https://en.wikipedia.org/wiki/Inline_caching>.)
A great example of all this is Facebook's PHP compiler. The first version would compile to machine code ahead-of-time, but it wasn't that much faster than the standard PHP interpreter (and definitely slower than the Firefox/Chrome Javascript VMs). They eventually switched to a JIT compiler, which is a better strategy for a dynamic language. Later, they transitioned to statically-typed sorta-PHP-compatible language called Hack, which allows for even more efficient machine code.
[1] There are different levels of static typing, too. For example, Go is statically typed but doesn't have generics. A C# generic data structure can be converted to more efficient code than a Go "interface{}"-based data structure.
"Light" is definitely relative but at least they list the exact size pretty early on.
"Modern", however, is something everybody seems to use to describe their programming framework/library and it's useless. Think about it this way: if you removed the word "modern", what information have you lost?
Let's say your API server followed the standard OAuth 2.0 protocol except required client-side certificates? Would that be as secure as TAuth?
If so, then the OAuth 2.0 option has the advantage of being well-supported by existing libraries and well-understood from a security perspective. It's less likely that a previously-unknown issue with OAuth 2.0 will crop up and force everyone to scramble for a fix.
And while client certificates prevent an attacker from forging client requests (i.e. tricking the API server) an attacker can still trick the client. An attacker capable of MITM'ing server-cert-only HTTPS can also trick TAuth clients into sending it's banking API requests the attacker's servers. It can respond to those requests with whatever it wants.
To summon the activation energy to adopt (or switch to) a new, less-popular protocol, I'd expect more security benefits.
But you're correct that eavesdropping is possible.
If a method needs to instantiate an object, the normal technique is to accept a factory function as a parameter. You can do the same thing with type-erased generics.
C# decided to create a shortcut for calling the constructor of a generic type parameter. But, for example, you can't call static methods of a generic type parameter (and a constructor is really just a slightly special static method).
That doesn't follow. You can have a well-designed system where the PHP code only contributes 10% latency and resource usage, in which case the PHP code is clearly not the most important factor.
"This might just indicate you better have 25 app servers vs 100 databases and spend the rest of money proportionally on both clusters."
Exactly. What matters is proportion of latency or resource usage contributed by the PHP code, and that can vary a lot between well-designed systems. The property of being "balanced" doesn't automatically make your PHP application cluster "the most important factor".
1. Can you configure it to make backups?
2. Can you configure it to replace data with low latency?
3. If you have multiple, can they work together to increase availability or data durability?
> Downloading a typical app with 20 MB APK can take more than 30 minutes on a 2G network
Then again overstating accomplishments is pretty standard for tech blog posts.
class Fruit {}
class Peach: Fruit {}
protocol FruitHolder {
var fruits: [Fruit] { get }
}
class PeachBasket: FruitHolder {
var fruits: [Peach] = []
}
This doesn't compile because it is not type-safe. Even though "Peach" is a subtype of "Fruit", "[Peach]" is not a subtype of "[Fruit]".If the above code were allowed, we could circumvent the type system:
var h: FruitHolder = PeachBasket();
var fruits = h.fruits;
fruits.append(Fruit());
I just added a non-Peach to a "PeachBasket". When someone iterates through it later, expecting it to be all "Peach" instances, they're going to be surprised.This reminds me of when Java 1.5 introduced generics. People were used to arrays being covariant even though that's not type-safe. The language designers decided not to carry that particular type system loophole over to generics, and people (including me) were surprised by the new behavior. (And then once we wrapped our heads around it, even more surprised we had never noticed the issue before!)
Objective-C had a bunch of holes in the type system and people got used to them. Swift is trying to be more type-safe. Interestingly, Dart made the conscious decision to retain this particular type system hole; their generics are always covariant.
BTW, Java's "wildcards" (existential types) get you roughly what you want in a type-safe way:
protocol FruitHolder {
var fruits: [? : Fruit] { get }
}
This roughly means that "fruits" is an array of some subtype "Fruit", but it might not necessarily be "Fruit". Then, doing "fruits.append(Fruit())" would fail to compile but you could still read from the array.It seems like an ill-fitting adjective even in a vacuum, but what's worse is that "serverless" is commonly used to describe something that runs entirely client-side (e.g. p2p).
Just because AWS Lambda is a "mental shift" doesn't mean that "serverless" is a good way to describe it.
Too often, products are in an extended state of limbo. Internally, the company has given up on it but has been dragging its feet on making the decision to shut it down (or just slow about making the decision public).
As a user, I like to know ASAP if a product I use is probably being killed.
From the company's perspective, keeping a product around half-assedly will probably lead to a slow death anyway; just kill it quickly.