Hacker Newsnew | past | comments | ask | show | jobs | submit | onaraft's commentslogin

Ubiquiti isn't really consumer, though. They want to target enterprises and businesses.

Sure, their hardware ends up in residential deployments more often than perhaps any other kind of enterprise computer stuff, but if you're not willing to call them "enterprise", I'm going to insist they be practically alone in their own category of "pro-sumer but actually professional-consumer, and not the yuppie garbage that you usually call pro-sumer that's just the normal consumer crap but priced at 4x with a slick black plastic case."

I agree with GP in that the spectrum you are suggesting ("you get what you pay for" actually looks more like this:

<cheap garbage> ----------- <expensive garbage> ----[huge $$$ gap]----- <enterprise stuff for price-insensitive corporations who value brand and risk-aversion more than actual specs>

Which I would reify into the realm of, for example, computer hardware, as follows:

<a $100 best buy laptop with Windows> --------- <a $4000 alienware desktop with windows> --------------- <a $40000 Dell server with out-of-band management and ECC ram and HSM's and dual power supplies and actual RAID controllers and so on>

The best buy laptop and the alienware desktop are going to have the same issues with regards to control and privacy, and you need to make a huge jump to get to anything remotely respecting you.


Ubiquiti is targeting small business (not enterprise) but their prices are firmly within consumer range. (For actual enterprise look at Meraki prices.) Likewise Apple Airport (RIP), Google Wifi, Eero, etc. have long-term support for a modest premium. There's no huge gap.


I would argue that no matter what language you pick, adding abstraction always behaves like this:

Suppose I have a thing I need to do, called X. I write a program to do X. Then later I need to do Y, and I realize that if I think of X as (A + B) and Y as (A + C), then if I re-organize to have one segment of code to do A, then wrap it so that B or C happen afterwards based on context (whether that be polymorphism or different scripts or procedural flow control, whatever the branching mechanism), then I've achieved abstracting A out into its own standalone piece, hopefully because A describes some independent process that makes sense to stand alone. Therefore, I've made it so that B and C's concerns can be separated from A's concerns, and X and Y are now just compositions of these nice linkable, re-usable pieces.

No matter what language you pick, if you want program X to do the same thing, the X-iness needs to still live somewhere. In Java that might look like going from two classes (X and Y) to three classes (A, X and Y). In lisp it might be three functions. I feel like in your example just now, you're comparing A from lisp to X in Java.

Please correct me if I'm wrong. I just feel like when you consider a program holistically, more genericness, and therefore more nuanced program description, always results in more text.

I agree that Java is more verbose than say, lisp or python. But I think that syntactic verbosity is really limited to a per-statement or per-block scope. I disagree that the language itself is responsible for verbosity in the higher-order composition of these pieces, weighted for, of course, how dynamic each language is. I hope you won't fault Java for not having the terseness of Ruby when Ruby doesn't have the performance or rigidity of Java.

I think you only really make order-of-magnitude leaps in reducing verbosity/excess abstraction by sliding up or down the dynamicness vs performance/safety spectrum. Tit-for-tat, I think an equivalent Ruby and Python program will be about the same size, and an equivalent Java and C# program will be about the same size.

The huge asterisk to all this is, of course, the humans actually writing the programs. Obviously a sufficiently motivated developer will be able to make an abstract mess out of any language.


I'll give a concrete example where adding abstraction will make code shorter. This comes from my recent experience, with some details changed for the sake of discretion and simplicity.

Suppose you wanted to simplify the generation of contextual metadata for structured logging in an API service. The service handles requests that manipulate stored records, run logic, etc. Basic CRUD plus business logic.

The starting point is a bunch of raw calls to MDC.put() if a Java service, or an equivalent in another language[0].

An abstraction-free approach might give you a logUser method, a logUserAndAccount method, a logAccount method, a logTransaction method, a logTransactionAndAccount method, etc. This does at least simplify the actual request processing code from the starting point and make the logging consistent, but makes the program longer.

Alternatively, one could have a generic Loggable interface, with a function that returns metadata for the object to be logged, and a logWith method that takes a Loggable as a parameter. You can get fancy and provide a default implementation if all of your entities have common methods like id(). There are probably still ways to improve from here, but now instead of a dozen functions, you have one.

[0] Years ago I wrote a rubygem for this, but was not able to open source the bulk of it.


Another factual observation is to look at Virtu's recent earnings numbers. They're basically pivoting as hard as they can to get out of speed-based HFT and into execution services, because the profitability of the former is cratering.


Yeah Virtu's market cap is about the same as Groupon. I hardly doubt they're emptying the pockets of every American here.


I've been looking at Redis recently as a potential solution to some caching I might want to do, and one hurdle I encountered almost immediately is:

Suppose I have some function, get_members_of_group(dt, groupname). It returns a set of strings. There are arbitrarily many groups, so I can't just cache all of them in one key. Someone might make a new group at any time, and groups are never deleted or changed, they just age out.

So far, this seems great. I make get_members_of_group_from_redis() first check redis for a key group_members_{dt}_{name}. If it's there, return it. If it's not, get it, cache it, return it.

But groups can also be empty.

Redis doesn't let me store an empty set. If a group comes back empty, the fact that it's empty can't be cached because you can't tell the difference between "not cached yet" and "cached but empty".

I've googled it a bit and all of the workarounds (sentinel key/value pair, storing "empty" at that key so the SMEMBERS fails with an error, etc) are hacky and make me not want to use Redis.

Is this a me problem and everyone is OK with slamming their db with hits if a cached function returns empty, or is everyone just ignoring all non-str datatypes and storing everything as JSON? Or is it just that weird to have a function that might return an empty set that nobody else has this problem?


Yes, Redis requires more manual tracking of such things. What you have to understand is that it is incredibly fast: You can easily do hundred of thousands of sismember lookups within the time it takes to serve a usual request.

> or is everyone just ignoring all non-str datatypes and storing everything as JSON

I doubt it. I've been surprised by how many of the datatypes I have found uses for.


I'd guess that most people don't see a sentinel value to distinguish between empty and unknown as a serious problem.


Supposedly you can use a Lua script - although that’s a somewhat big hammer for such a simple problem...


Isolate the hack in a function with a snarky comment.

Sometimes speed is worth it.


Which requires a margin trading account, a non-trivial amount of trading experience, a non-trivial amount of capital, constant management, and is highly leveraged. The risk profile is totally different.


The gist of it is that if you have 1, 10, or even 100 thousand dollars in cash, sure you can sit that in your bank and probably earn ~0% interest, but at least it's not negative.

But if you have 100M in [edit: $your_native_currency], you aren't going to put it in a retail bank account, you're not going to put it in your mattress, and so you have only a few options:

1. Stocks/derivatives: If you were holding cash already, you're probably not comfortable with the risk profile of any of this stuff

2. Bonds - this exposes you to the slight negative interest rate

3. Corporate bank account - you might be able to avoid a negative interest rate here as well, but only because you're passing the buck (literally) to the bank, who then has to pick 1 or 2.

4. Actually use the money yourself, in your business.

The whole point of the NIRP (negative interest rate policy) is to push people to pick 3 or 4, and if 3, then for the banks to pick 1 or 4.

I just reread your question, and realized I didn't fully answer it. Investing in foreign bonds exposes you to exchange rate risk. I was sorta hand-waving it into 1 since it's basically like doing both bonds and forex. Not very appealing if your risk appetite is "preferably cash or govt bonds".

I feel obligated to include a disclaimer that this isn't investment advice and that monetary policy is immensely complicated and this is just the high-level thinking of the point of NIRPs.


I think 1. is not too bad with some kind of index fund. Even during the recessions the value will not vanish - and historically it recovers eventually.

My current worry is the holding company - e.g. what if Merrill Lynch goes bankrupt? There is a very small amount that is FDIC insured but the rest could go poof.

A mattress might work better for this use case, but I figure if it comes down to that we'll have bigger problems.


In general, you don't need to worry about Vanguard or Schwab or whoever provides your particular index fund going bankrupt. The actual assets in the fund don't go anywhere. Whoever buys the remnants of your now-presumably-dead brokerage would probably just carry on maintaining the fund, or it would cash you out if it didn't want to continue to run the fund.

On the brokerage side, SIPC insures securities in much the same way FDIC insures deposits, but the amount insured is significantly higher, though I don't know it off the top of my head. And beyond that, regulations require brokerages to hold client assets separately from the broker's assets, and this is audited. So for the most part, SIPC is mainly overseeing the transfer of securities from a dying brokerage to somewhere else.

So, for the most part, the risk you describe is more about inconvenience than actual material loss.


That seems like a risky strategy. The gamble would be that the government loses loan "revenue" in the short-term and makes up with business taxes. Is that a good gamble in weak or service-oriented economies? What are all the risk factors there?


To be clear, this is a central bank thing. The part of the government issuing debt doesn't technically have a say in it.

The Federal Reserve bank sets the Federal Funds rate. This is their "target rate" they will try to hit. They accomplish this by using their position as the central bank to "print" (not literally, it's a credit system, I'm hand-waving) money to bid on bonds. In the same way that lots of investors clamoring to lock-in rates on long bonds can bid their yield down, the federal reserve using their funny money to bid on treasuries also bids their yield down. And when the fed wants the rates below zero, they bid them to below zero. These are called "Open Market Operations".


> The part of the government issuing debt doesn't technically have a say in it.

To be fair, there is no economic law that says this has to be true. It is just true, today, in countries like the USA. It's very possible we reach a point where central banks work together with the government to directly purchase and monetize government debt. It seems absurd today, but so did negative interest rates 20 years ago.


I guess the negative is also tax deductible. so there might be an additional reason there?

on edit: punctuation


bitcoin! /s


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: