6 ms·
Not to refute your experience, but "adding true -> ok to every if statement" sounds like an anti-pattern. A couple of notes to elaborate: 1. If-statementes sho
by e_proxus 7y ago
Not to refute your experience, but "adding true -> ok to every if statement" sounds like an anti-pattern. A couple of notes to elaborate:
1. If-statementes should rarely be used in Erlang because case is preferred
2. If you're returning ok everywhere, you could also just let it crash by doing something akin to true = function(). Always go for let it crash first, unless you really know you can handle the error sensibly (and then use a case-statement)
3. httpc is kind of known to not be the most formidable HTTP client. Hackney is a more modern and better choice. The good thing with httpc is that it is included with OTP, otherwise there are better choices (scalability- and feature-wise)
4. When someone says "multicore support" and "performance" support is not great it's usually one of two things: (a) they're developing a use case that is not fit for Erlang (e.g. compute heavy) or (b) they don't know how to use Erlang properly (e.g. too complex process setups)
Now, many of these things are not obvious to people new to Erlang and takes some experience to know about. This I would say is the bigger problem with the Erlang eco-system.
- ihuk 7y agoAgreed. Couple of clarifications/observations. (1) there are situations like this: if DeductCreditInRatingGroup -> log("deducting credit..."); end; unfortunately you cannot write it this way. You have to write it as: if DeductCreditInRatingGroup -> log("deducting credit..."); true -> ok end; Not a huge deal but it's annoying. (2) Let it crash attitude is something I never understood. It's just not something you can do most of the time. If subscriber consumed 2MB and you let it crash in the middle of rating function you just "lost" 2MB. With couple of million subscribers on LTE that turns into very expensive error handling very fast. (3) We actually ended up using hackney. (4) We were not doing anything compute heavy. I think our application was well architected and we had no problem fitting it into OTP "framework". Comparing CPU and memory usage to our Java implementation, Java is more performant. edit: fixed code formatting.
- e_proxus 7y ago1. Here I would do something like this: log("deducting credit...", DeductCreditInRatingGroup), ... log(Msg, true) -> do_the_logging(); log(Msg, false) -> ok. Nowadays though, you should really use the new logger introduced in Erlang 21. There you can do run-time filtering on many different parameters, or even write your own handlers. Using if-statements is usually considered an anti-pattern in Erlang, and I think very common coming from languages where only if-statements exist. Problems are almost always better solved by using case, or even better, pattern matching in function heads. 2. Sounds like one of the rare cases where you care about the error and can also handle it. In the use case you mentioned, I would buffer the data outside of the loop that produces it and wrap the loop in a try-catch statement. That way, you don't loose the data if one iteration crashes. 4. Erlang usually ends up being good at latency and concurrency (scalability over cores), together with a smaller and easier to read code base. I'm curious about your case, and what would have made Java a better fit. If you share a lot of global objects, Java might be faster for some things (at the cost of concurrency usually). Erlang has tools for that as well though (e.g. ETS and recently persistent_term).
- ihuk 7y ago(1) was not about logging. I was trying to illustrate a valid use case for `if` statement that requires `true` guard expression. We used lager[1] for logging. I understand that new logger was inspired or loosely based on lager. (2) I would argue that it's a rare case you don't care about errors. (4) Multicore support in Erlang was not always great and you would run into all kinds of problems after 2-4 cores. Than for a while it was 12-16 cores. Not sure what the limit is these days. Again, I am not arguing Java over Erlang. There is no lack of great examples of large successful project running on Erlang. For me and my team Erlang was just too much hassle for not much gain. Your milage may vary. [1]https://github.com/erlang-lager/lager https://github.com/erlang-lager/lager
- lostcolony 7y agoCan't comment on your other issues (I'll say I have noticed the complete opposite in practice, where the same team working with Java vs Erlang led to far more reliable, performant systems in Erlang, but I obviously can't speak to your experience), but for (2) - You always care about exceptions/errors. The thing is, most you won't predict/can't handle. Those you do predict, and know how to handle, you should, because they're not really errors/exceptions at that point; they're just edge cases. The point of Erlang is not to make it so you just throw instead of addressing an edge case; it's to make it so you reason about how, if something you don't predict and don't know how to handle happens, you can get back into a known good state. It's actually phenomenal at doing that. I've had complicated user facing production systems work without noticeable issue for years (even while under active development) in Erlang. I've never seen that in any other language. Not to say it can't happen, I just haven't seen it, and the operational lift to achieve that was no different for us than just "make it work"; we were spending the same amount of time thinking about failure cases with the Erlang system as other languages. The difference was a better approach to handling the things we didn't think of.
- e_proxus 7y ago1. My point still stands, using if-statements is not common in Erlang exactly for the reason you mention. 2. In Erlang it usually only make sense to care about errors which you can actually handle in a sensible way. Everything else you usually "let crash" and let the supervisor tree deal with recovering. Defensive programming is another anti-pattern in Erlang in my opinion. 4. Not sure what you mean with "not great". With Erlang, if you have a completely parallelizable problem you should see close to linear scalability. If it drops of after that it's either because the problem is not parallelizable enough or because of your architecture. Yeah, I'm not arguing Erlang over Java either. I'm just pointing out that blanket statements like this are usually because of architecture or design rather than shortcomings of the language itself.
- tutfbhuf 7y ago> Let it crash attitude is something I never understood. It's just not something you can do most of the time. If subscriber consumed 2MB and you let it crash in the middle of rating function you just "lost" 2MB. With couple of million subscribers on LTE that turns into very expensive error handling very fast. Let it crash is the only sensible thing to do. Depending on the type of error, the 2MB could be absolute garbage. I would rather stop sending any message instead of sending potential wrong data without knowing.
- h91wka 7y ago1) I would just write DeductCreditInRatingGroup andalso log("blah") 2) Let it crash attitude is often misinterpreted. It means your system should be fault-tolerant in general, so you can focus on the happy case instead of trying to predict all humanly possible failure modes. If you _expect_ invalid input, then handle it properly.