Also, unfamiliar with PHP, but a few years ago I somehow ended up maintaining/managing one or two reasonably trafficked Wordpress sites that some (untechnical) friends put together, so every now again I get to learn how weird some shit in PHP is. And it’s that time again, because the comment about name conflicts was confusing as I could’ve sworn that during couple times I’ve had to actually poke around PHP code I saw it had namespaces. After some quick googling though, I was able to confirm a) PHP has “namespaces” and b) they seem to work like most other “features” (i.e. not like you’d expect if you’ve programmed in anything but PHP) [1].
However, C has the a similar convention [2] (though the convention is — as far as I’m aware — for the sake of maintainability/readability as the compiler has no problem telling the difference between to things named the same, the person reading it probably will. While, as I understand it, PHP will just overwrite anything with the same name in the file/lib you include).
It seems like PHP is heading in the right direction, but I have no idea why anyone would pick it up or start anything new with it these days, I don’t care how well done and the nice and new stuff is, it’s the decade of utter mess it’s built on top of that has uninterested me. Don’t get me wrong, since “acquiring” the Wordpress sites I’ve gone from a blind PHP hater, to at least understanding/appreciating it (but still won’t actually touch it with a 10ft pole). PHP is brain dead easy to deploy and scale up, compared to ruby/python/node (which aren’t _that_ difficult to deploy), PHP is basically the web equivalent of a static binary, in that you can just drop in and it’s basically ready to go. PHP also actually really fast, it’s seriously impressive how fast it can render WP pages especially when you consider the absolute spaghetti/thrown together/clusterfuck code it’s running — Wordpress itself is pretty yikes from the code I’ve seen, but the plugins, Christ, the 50 million sloppy buggy poorly coded plugins — PHP can absolutely run laps around other a decently coded site in other languages (at the cost of having to use PHP I guess ).
I haven’t gotten around to actually trying it myself, but it advertises that it can compile Elixir projects into a single binary you can copy, paste & run (on Linux & MacOS). It’s not the greatest solution, and the mentioned ~0.5s startup time doesn’t make it great for cli tools when compared to Go/Rust/C.
I’m mostly just happy to see there are people out there trying to make Elixir/Erlang easier to use, as much as I love the language, some of the tooling and deployment methods (releases) make me groan.
My favorite “console wars” story that I came across a while back, and is relevant to pricing advantage, is when Sony more-or-less immediately killed the Sega Saturn before it’s US release.
Right after Sega’s E3 presentation announcing the Saturn, US release date, and it’s $399 price tag, it was Sony’s turn. The guy from Sony walked up to the mic, said “$299”, and walked off stage. [1]
I hate to sound elitist or whatever, but I’m just tired of seeing a blog title something about writing a scalable or “enterprise” web app and the content almost always being “write modular code, write comprehensive tests, and don’t write spaghetti code though usually through the veil of domain drive design jargon (whether or not they don’t use the term DDD or they are literally quoting Dr Bob blog posts and including vague graphics showing the “boundaries”). But, any decent developer will literally come to the same realizations after spending a significant amount on anything that’s not a toy/pet project. I also get that not everyone has had that realization and this blog may be insightful/helpful to them, it’s just not the content I was hoping to come across as it’s something I’m very interesting to hear what others are doing.
I’m not going to pretend I’m some hardass enterprise engineer, but my only time spent on frontend work these days are on two different applications that solely exist because the actual enterprise software sucked so much that these applications exist. So, I like to think I at least have an idea. As over the years the features have been added to the apps, and more of the “fun little quirks” in the data. Which is why I want to hear how real “enterprise” level frontends are being handled. Believe me, I know the value of keeping my code modular, and I really know the value of keeping logic out of presentation, but if working with enterprise software, and software that’s deployed to 30+ different departments to standardize and centralize processes they’ve been doing themselves for 50+ years (under the guise of “making their jobs easier” but really they central office where just tired of having to deal with the random of assortment and varying quality of data, lol) there’s always another edge case. I cringed when they mentioned that using one of the big frameworks, and forgoing global styles, because after a couple years of “the frameworks built in css isn’t totally the way we need it” (or more likely, “fucking updates broke the UI on a minor release for no reason”) or “oh using the current components we use to do that don’t take data that way or return it the way we need either, and it’d take too long to replace, just create a new set for this feature” it’s not going to be the nice paradise where everything is siloed off just like in Uncle Bob’s blog. I just this week got sick of UI framework’s because the built in component I needed wasn’t able to handle the task in the exact right way, so I had to make adjustments to it, and I’m just that’s never going to break in the future... not to mention that absolutely none of them are really doing any more than the bear minimum accessibility wise, which is one of the reasons to use a framework was to eliminate that boilerplate. So, I just started tinkering with the new Vue3 composition API to build a UI framework that literally has no styles attached just dom elements that know how to setup their aria-attributes, handle keyboard events so a mouse isn’t the only method, etc (as well as if they weren’t passed given enough information to make themselves complaint with the aria guidelines). To style them, I’m just going to make pass in a list of tailwind classes in a config files at build time, that they can (optionally) but will in no way the actual core framework itself is dependent on.
I just want to hear how some real enterprise team are managing their frontend (and more importantly their commentary — I can find code online but without the context it’s not the same) when they have 100x the amount of edgecase legacy bullshit I have to deal with and likely 1000x the burden of buroqracey
This reminded me of a question I’ve had, which is only tangentially related, but I’m hoping I’ll be able to get pointed in the right direction or told that the idea is stupid either is fine.
Login/Auth is one of the few areas that I have always just used whatever the standard library is for the platform because I don’t want to fuck it up, so I just have always gone with the tried and true sign in form -> server side sessions. I didn’t do anything more “advanced” until I started at the university I’ve worked out for a couple years now, and that’s still just been a SAML(?) request flow with our SSO (ugh) Shibboleth. If you’re lucky enough to be unfamiliar with Shib, it’s not that great, it does the job, but just barely while simultaneously holding our infrastructure hostage. I think SSO is great, but Shib (in our current architecture, and in my — potentially ignorant — opinion) is unnecessarily limiting while providing no real benefit. I’ve had an idea floating around in my head that could make it useful/less restrictive, since it’s not going to go away in lieu of something more modern, but I’m not sure if it makes sense/is secure/whatever. So, here’s my current issues with it.
Every web application that needs to use SSO at the university has to first send a request to the centralized authentication team — which consists solely of the creator of Shibboleth — this request is almost always sent back within 5 minutes with some condescending/snarky remark about how something wasn’t filled out correct, while also giving you the correction to be made, and told to submit it again (instead of just not being a dick and correcting it himself). Dealing with his shit attitude once a year or two l, I could handle, but my team is currently responsible for like 20-30 apps using SSO, and usually have to do this dance every at least once 2-3 months.
Once that’s over with and the app’s host name is now setup with the central idp. However, to utilize the idp, the app server requires the Shib service provider to execute the callback flow. Once again, wouldn’t be that awful if it weren’t for the fact that the Shib SP only officially supports 2 web servers Apache HTTPD and (I think) Tomcat or Jetty. An unofficial nginx plugin for Shib exists, but because we are “lucky” enough to have the Shib creator be the sole dictator of the SSO service, and nginx does not have his blessing (because fuck you, that’s why). Once again! I could deal with Apache, I prefer nginx, but ok I never have to actually manage Apache’s configs so it wouldn’t an issue, but it requires a version of Apache that doesn’t support shit like websockets.
However, what really makes it un enjoyable, is when it passes back the user auth info, it ACCORDING TO THE DOCS, should also include some additional data like the affiliations the user has, what departments they belong to, etc. What actually happens is outside of the users uid, it only reliably will give you their primary affiliation (staff/student/faculty) but not any others they may have. On the off chance you get the departments they belong to, they’re actually just numbers that correspond to a department — not the id commonly used by anything else which would be annoying but useful still — these numbers are seemingly only used by it, and nobody seems to have the full mapping(???). There’s a list of other useful attributes it supposed to return but nobody has ever seen it happen, lol. So now if an app wants to restrict itself to just certain departments/affiliations, it has to now check with another api or have that data piped into its DB from the central data store daily, to be able to do that. Among other things like not supporting sign out without jumping through hoops for every app that decides to let users sign out with a button, confusing documentation, and mountains of XML. It’s sucks.
My idea is to consolidate it into a single auth service for all my teams apps, as we’d just have to make on last request for the auth service host name, and it’d be the only one required to use Apache. Basically serve as a middle man, to pass requests to the idp, then lookup the data that’s supposed to be there from Shib, and provide that back to the app in one swoop. Is this reasonable? What’s the best approach to managing the Shib session? As it will set a cookie for the auth service host, not the app host, so I have thought about sticking the Shib session into the auth service session data to prevent the same user automatically getting authorized if they use another of our apps they may not have access to (i.e. I want don’t want the Shib session to work across app domains if a user has a session in one app and not the other). Almost every other week I feel there is an article about rolling auth wrong, so I just haven’t wanted to bother with it. So is my idea stupid? Is this an actual appropriate use for JWTs to store the Shib session id in while the auth service still will use cookies (with that JWT inside or an id to lookup that JWT)? Or should I use OAuth here? I can’t find any information that definitively describes my situation anyway, and every other article I read about setting up auth flows contradicts the one before it, or just says let the experts handle it or whatever, which unfortunately they apparently have been and the experience as dev sucks. Any information would be greatly appreciated, or just a definitive “it’s a stupid idea” would be appreciated as well so I can stop thinking about a world where I can use NGINX at work.
I think if you setup something like keycloak with identity brokering, you can have shib sso as your Idp upstream and then turn around and manage downstream oauth resources from within keycloak. Perhaps cloud foundry's UAA is another option.
Typically additional attributes would need to be configured aka "released" by the IdP on a per-SP basis. I've also never heard of any specific server requirements when interfacing with Shibboleth. SAML is a standard and any generic library that supports SAML (e.g SimpleSAMLphp, saml2-js) can, in theory, work with Shibboleth. It sounds like there are other organizational/operational restrictions or requirements in place.
I’m still runnin a 2012 (non retina) without any issues, and I plan on keeping it until it literally won’t boot. What’s funny is I was initially annoyed as I got it a few weeks before they announced they were releasing the first Retina display models (discontinuing the non retinas), however getting the last non-retina generation was a blessing because that’s was that was when they also began making upgrading MacBooks nearly impossible (non upgradable ram/and I believe some weird half SSD/half disc drive that didn’t come in >512GB or something like that). So getting the last (upgradable) MacBook Pro was the better deal because two or so years ago I upgraded the RAM to 32GB and because it was also the last MacBook to have a CD drive (that I never used) I was able to rip it out, put a $5 hardrive bracket in it’s place and threw the original (I think) 750GB or whatever HDD where the CD drive used to go, and popped in a nice 1TB SSD into the main disc drive, and nowadays it’s almost always plugged into a monitor so I wouldn’t really even be using the retina anyway.
Sadly though, I think I got the last generation of great MacBooks, and as much as I love it I fear for the day it finally dies, because I’m probably not getting another MacBook unless something changes, and there still isn’t a laptop out there that comes close to the good MacBooks (I know good one’s exist and I’ll manage, but they’re still not the same)
I'm exactly in the same boat as you, I love my 2012 non retina Macbook Pro.
Upgraded the RAM a few years ago, changed the HDD for an SSD, and it still works fine.
I didn't like the newer MBP keyboard or touchbar, maybe now they're getting better.
But the price is what will push me away.
I'll probably try to find a nice model on which I can make sure Linux run fine.
It really was a fantastic piece of hardware, and probably the only Mac I’ll ever live. The dual SSDs(I replaced the cd drive too) gave it a few more years for me.
I’m pretty happy with the replacement I got though. It’s and MSI gaming laptop, but without the “gamer” look. It’ll handle anything I throw at it, so now I can take VR in the go.
Definitely agree, though I respect the effort/desire to learn Erlang first given the fact the first time I saw Erlang code I was so confused/put off by it, the syntax was so foreign (not c-like, not lispy), variable names up capitalized, atoms are bare words, source files are just tons of functions, the tooling isn’t anything like modern languages (though since Elixir and hex/mix, that situation has gotten way better), then you’ve got all the OTP behaviors which are entirely unique to Erlang/BEAM, Erlang’s documentation though excellent and extensive isn’t by any means beginner friendly (IMO), and to top it all off, unless you’re coming from another pure functional language you have to deal with working in a new paradigm. Basically, Erlang is intimidating, which is unfortunate because how powerful BEAM and the OTP behaviors are.
However, Elixir wraps up the power of the BEAM and OTP in a much more approachable package. The syntax is much more familiar (thanks Ruby), provides tooling on par with (and better than some) popular modern languages, the language itself also provides more modern user friendly features (macros, pipe operator, protocols, etc). All with a community that is very beginner friendly and willing to help.
If you want to make use of OTP/BEAM, Elixir is by far the best way to enter. When you learn Elixir, you will also learn the major OTP behaviors and concepts (Supervisors, GenServers, Applications, Registry). Eventually you’ll find that there are even more goodies in the beam not directly exposed by Elixir (genstatem, ets/dts/menisia,timer,digraph — are a few of my favorites). Fortunately though, you can call Erlang modules/code directly from Elixir (and vice-versa), so you’ll then eventually dip your way into playing with Erlang modules as needed and when you approach the docs after having experience with OTP with Elixir, you’ll notice a lot of things are familiar and the Erlang docs become much less intimidating.
Basically Elixir is a much easier entry point to Erlang. Erlang is a great language, but very different with a lot of new concepts and which can kill your motivation to learn how awesome the BEAM is, so if you want to learn Erlang, by all means give it ago, but if you find yourself frustrated/confused with it, try Elixir for a while, then come back to Erlang and I bet it will be a lot easier.
When I initially saw Erlang, I was put off, the docs were confusing and I would avoid them at all costs, always try to look for an Elixir wrapper. Now after having worked with Elixir a lot? I frequently find myself going to the Erlang docs first to find a solution instead rather than hex or whatever. I can easily grok my way through an Erlang projects source, which previously was completely foreign to me. Will I ever likely write anything serious in pure Erlang? Probably not. Am I saying if you learn Elixir you will also just pick up Erlang? Absolutely not. What it will do though is make the process of learning Erlang (if that’s the goal), and it’s absolutely massive built in library of tools/abstractions/patterns that no language I’ve seen comes close to replicating an order of magnitude easier.
You may like this: the very odd gen_statem callback pattern exists to group different callbacks by state (which you can't do because you need to group like headers together). But in Elixir, we use modules and macros to organize our code more sanely and less ad-hoc-ey:
I've only had 2 complaints with gen_statem, the docs were initially some of the most confusing/unclear and the state_functions callback mode (which I think partially is to blame for my first complaint as I was expecting a more gen_server like api with handle_* functions -- which exists but the docs use the state_functions for most of the examples and the handle_event just kinda getting some "oh by the way this exists" examples). I actually initially decided to just keep using gen_server's with a "status" or whatever value in their state as I figured it was good enough. At some point over the next few weeks I actually ended up having this talk[1] pop up in the recommend videos, and I figured I give it a watch to see if it would help make sense of gen_statem or at least just confirm that I don't need it. And while watching it, once he started explaining actions (timeouts, state_timeouts, postponing, etc) I realized that gen_statem literally solves so many problems that I've had in the back of my mind on the project I was working on like "I should figure out a way to change the state of A and do something when it doesn't receive any messages from X,Y,Z processes" (gen_statem's timeouts!) or "how should I handle messages received while attempting to recover, I guess I could put them in a queue or something..." (oh, gen_statem will let me postpone them until it's healthy!). It took a couple more re-readthroughs of the docs to fully grasp, but now it gets included in almost everything I work on, it's so useful (though I guess I should've assumed those were already solved problems by the BEAM/OTP as usual).
However, now my biggest complaint about Elixir is that gen_statem didn't get any official wrapper. StateServer looks like almost exactly what I would want out of an official Elixir wrapper. I also like to see the addition of `handle_continue` as well, because the first thing I did before migrating any of the gen_server's to gen_statem's was create a small wrapper module to a) make the handle_* return values more in like with GenServer's (basically just making it {:(no)reply, (transition|keep), data, [actions]}) and b) add a quick and dirty handle_continue callback because I use it all the time with GenServer. And this literally just looks like a more polished version of that, so thanks!
Stream would technically better, however given the discussion is about Map/Reduce, the only thing Stream has in common with Map/Reduce is it's lazy. If you wanted something comparable (mapping is done in parallel, reducing as well just over partitions), then you'd want to use the Flow[1] library. As it does the same thing as Stream.map |> Enum.reduce just parallelized/partitioned, and what's great is the Flow module is more-or-less a drop in replacement for Enum/Stream (with a few caveats like calling Flow.partition before Flow.reduce). But, with just some quick a dirty benchmarks you can see Flow outperforms Stream on all but the smallest data set (range 1..100):
with_stream = fn range ->
range
|> Stream.filter(&(rem(&1, 3) == 0))
|> Stream.map(&(&1 * &1))
|> Enum.reduce(0, &Kernel.+/2)
end
with_flow = fn range ->
range
|> Flow.from_enumerable()
|> Flow.filter(&(rem(&1, 3) == 0))
|> Flow.map(&(&1 * &1))
|> Flow.partition()
|> Flow.reduce(fn -> [0] end, fn val, [acc | _] ->
[Kernel.+(val, acc)]
end)
|> Enum.sum()
end
iex(4)> Benchee.run(
iex(4)> %{"stream" => with_stream, "flow" => with_flow},
iex(4)> inputs: %{"small" => 1..100, "medium" => 1..10_000, "large" => 1..10_000_000}
iex(4)> )
Operating System: macOS
CPU Information: Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
Number of Available Cores: 4
Available memory: 8 GB
Elixir 1.9.4
Erlang 22.2.1
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
parallel: 1
inputs: large, medium, small
Estimated total run time: 42 s
Benchmarking flow with input large...
Benchmarking flow with input medium...
Benchmarking flow with input small...
Benchmarking stream with input large...
Benchmarking stream with input medium...
Benchmarking stream with input small...
##### With input large #####
Name ips average deviation median 99th %
flow 0.0994 10.06 s ±0.00% 10.06 s 10.06 s
stream 0.0782 12.78 s ±0.00% 12.78 s 12.78 s
Comparison:
flow 0.0994
stream 0.0782 - 1.27x slower +2.72 s
##### With input medium #####
Name ips average deviation median 99th %
flow 83.87 11.92 ms ±20.48% 11.30 ms 25.53 ms
stream 74.88 13.35 ms ±32.02% 12.32 ms 30.22 ms
Comparison:
flow 83.87
stream 74.88 - 1.12x slower +1.43 ms
##### With input small #####
Name ips average deviation median 99th %
stream 4.98 K 0.20 ms ±87.16% 0.169 ms 0.56 ms
flow 0.70 K 1.42 ms ±21.58% 1.35 ms 2.52 ms
Comparison:
stream 4.98 K
flow 0.70 K - 7.06x slower +1.22 ms
I’ve been using Boostnote[1] for several months and I really enjoy it, and it sounds exactly what you’re looking for. It has just two kinds of notes, markdown and snippets, supports syncing with Dropbox/google drive/etc. Though my absolute favorite feature, and the reason I haven’t looked for anything else since downloading it is it supports VI key bindings.
However, C has the a similar convention [2] (though the convention is — as far as I’m aware — for the sake of maintainability/readability as the compiler has no problem telling the difference between to things named the same, the person reading it probably will. While, as I understand it, PHP will just overwrite anything with the same name in the file/lib you include).
It seems like PHP is heading in the right direction, but I have no idea why anyone would pick it up or start anything new with it these days, I don’t care how well done and the nice and new stuff is, it’s the decade of utter mess it’s built on top of that has uninterested me. Don’t get me wrong, since “acquiring” the Wordpress sites I’ve gone from a blind PHP hater, to at least understanding/appreciating it (but still won’t actually touch it with a 10ft pole). PHP is brain dead easy to deploy and scale up, compared to ruby/python/node (which aren’t _that_ difficult to deploy), PHP is basically the web equivalent of a static binary, in that you can just drop in and it’s basically ready to go. PHP also actually really fast, it’s seriously impressive how fast it can render WP pages especially when you consider the absolute spaghetti/thrown together/clusterfuck code it’s running — Wordpress itself is pretty yikes from the code I’ve seen, but the plugins, Christ, the 50 million sloppy buggy poorly coded plugins — PHP can absolutely run laps around other a decently coded site in other languages (at the cost of having to use PHP I guess ).
[1] https://kornel.ski/en/phpns
[2] https://softwareengineering.stackexchange.com/q/404613