It comes with a bonus music video! [1]
1,061 karma · joined February 10, 2015
It comes with a bonus music video! [1]
Mark, for example, is now primarily a functional programmer and makes good use of F#’s type system:
https://blog.ploeh.dk/2015/08/10/type-driven-development/
So he might even agree with you these days (on the “baloney” part, but maybe not the “frog in a well”).
> use AWS Step Functions to orchestrate these workflows using a versionable, JSON-defined state machine.
I think a better approach would be to use a proper workflow engine [0]. Using a standard modelling language like BPMN and the ability to monitor, audit, and optimize make this a better option than an Amazon-specific approach.
[0] https://www.infoq.com/articles/events-workflow-automation/
I think if your business is largely transactional (think Stripe), there is a lot of value to be had by framing your development as “business process automation”.
The term (and BPMN) has a lot of enterprise baggage, but some of the tools out there [0][1] are well suited to orchestrating services (and people where necessary) as a single automated process. The the ability to build that flow visually using BPMN, and then execute it in a workflow engine where you can monitor it, audit it, and optimize over time is pretty compelling.
Here’s an interesting read on the topic: https://www.infoq.com/articles/events-workflow-automation/
The actual standard is quite light weight, which is its main selling point. The whole premise is that many teams find rigorous standards like UML and Archimate too heavy and thus resort to basic boxes-and-lines diagrams. C4 essentially says "take your boxes-and-lines and put full sentence descriptions on everything". Combine that will successive levels of detail, and you have the C4 standard.
You don't have to give up diagrams-as-code because you can create C4 diagrams with PlantUML [0] or using the C4 specific DSL [1].
If you’re willing to change browsers if necessary, Firefox has a Side View [0] extension that offers some functionality, though it’s just an “experiment” that hasn’t been updated in years.
Presentation - https://www.infoq.com/presentations/DDD-Clojure/
Code - https://github.com/zololabs/zolodeck
Its a Domain-Driven/Hexagonal Architecture codebase written in Clojure. Its not uncommon to see this sort of approach in Java/C# so it makes comparisons of the code relatively easy.
While the overall code layout is the same as what you'd see in Java/C#, a big distinction is that the "entities" that make up the core functionality of the domain in the Clojure version are simple data structures (rather than classes), and the logic that operates on them are pure functions (rather than methods on the classes themselves).
With this approach, a lot of the hoops you'd usually jump through with dependency injection to enable testability go away, since its easy to test pure functions that operate on simple data structures, no mocking required.
This sort of approach isn't limited to Clojure [0], but Clojure makes it idiomatic.
It walks through the process of building a Lisp in JSON and the associated parser in JavaScript. It could be a good starting point to build out a cross-platform approach to sending logic over the wire.
I see Clojure as almost sub-set of JavaScript bundled with a great standard library akin to Lodash or Ramda. You can write very Clojure-y functional code with JavaScript, and if that is what you are already used to doing, than you might not see a big difference in switching to Clojure.
But JavaScript is a bit of a kitchen sink. You want classes, you got em. You want prototypes, you got em. Functional programming, sure. This wide mix of language features means that everyone’s experience with the language will be different, and if somebody is coming from a very object-oriented background, being exposed to the data-oriented functional approach of Clojure can be an eye-opener.
Personally, using Clojure had a huge impact on how I approach development (having from from a traditional C#/Java background). I consider myself much more productive now and view problems in a completely different light. I don’t write Clojure for work, I’m pretty much full-time Node.js these days, but I credit Clojure with changing my development practices for the better.
I guess what I’m saying is that it’s not necessarily Clojure-the-language that make people feel more productive, but maybe it’s just the development style that Clojure almost forces upon people that makes them feel more productive.
(And personally, I just love the elegance of a language with such minimal syntax... and an abundance of parens)
It’s a fun side project for now, but hopefully I can use it to convince some of my JavaScript loving co-workers to give Clojure a try.
The hard part is that most Clojure devs default to using the JVM server side so there’s not much appetite there to do the work to embrace JS server side frameworks.
Behind the scenes ClojureScript is transpiled to pure JavaScript with Google’s Closure compiler, so there’s no external dependencies on libraries like the ones mentioned above. It’s all just built into the language.
This pretty much my view as well. There’s that classic joke comparing two books on JavaScript, the complete language vs. the good parts [0], and you could pretty much just replace the “good parts” book with ClojureScript.
It has everything you need and gets rid of most of the stuff that enables people to write bad code. (Assuming you like functional programming, of course)
This can lead to issues where you decide to refactor and rename a var (Clojure is all about concise and expressive names, so its not uncommon to do this.. At least not for me) but you might not catch every place the old var name is being used. Because both vars are still exist in the state of your REPL, everything seems to work, but once you compile your uberjar or whatever, things are broken.
A REPL isn't a replacement for good unit tests, and there are techniques for reloading your REPL state on save, but the issue of needing to keep the "REPL state in your head" is real, and not an artifact of doing things wrong. Just something that the developer needs to be aware of as a potential hiccup in the REPL experience.
I’m not sure how gRPC handles this, but adding an additional field to a SOAP interface meant regenerating code across all the clients else they would fail at runtime while deserializing payloads.
A plus for GraphQL is that because each client request is a custom query, new fields added to the server have no impact on existing client code. Facebook famously said in one of their earlier talks on GraphQL that they didn’t version their API, and have never had a breaking change.
Really, I don’t gRPC and GraphQL should even be compared since they support radically different use cases.
The best approach to dealing with that is to isolate that interop at the edges of your program.
I’m currently, coincidentally, working on a wrapper for Express to do just that. The wrapper library is responsible for mapping between the Express req/res objects to simple ClojureScript maps. Combine that with a similar wrapper around something like fetch or axios and all my code can be pure ClojureScript.
I mean, that is the general practice in Clojure/Java land. Write wrappers around the native libraries to isolate the pain that comes from interop.
I’m a sucker for Clojure though, and willing to do the work.
I’m not sure I can agree with the premise that “developer diligence” is a reliable approach immutability (or any other development ideals). Maybe in a small team of like-minded devs diligence is enough, but in the large, with a multi-paradigm language that allows pretty much anything, you can be sure to see pretty much anything!
I suppose it’s all a trade off. The pain of jumping through hoops with the libraries mentioned above vs dealing with an entirely different language and having to hire/train for it.
All the code is JavaScript and it tries to walk you through how you might solve common, everyday business problems with a more functional approach. All without getting bogged down with terms like “monad” or “functor”.
This book (along with Domain Driven Design made Functional, mentioned elsewhere) are both great resources for getting introduced to “useful” functional programming.
This is how I approached using XState in a proof of concept last year. I created a “service layer” made up of XState machines that handled different high-level aspects of the application behaviour; i.e. not tied specifically to a particular UI element. Things like managing the requests made during an OAuth flow and storing the authenticated user’s information.
This gave me a source of application state with well defined behaviours that I could use instead of “redux” and its usual accompaniment of boolean flags and thunks.
The best part of embracing the separation of state management from React is that I initially developed the application in Angular before lifting-and-shifting the “service layer” over to React and sticking in a “context”. All the application behaviours remained the same, it was just a matter wiring up some JSX in place of Angular’s HTML templates.
I’ve been getting more into functional programming this past year (via Clojure, though my day-job is mostly JavaScript/TypeScript) and this is the big takeaway for me.
Type theory and monads may have their place, but thinking about separating logic from side-effects is, I think, the most valuable aspect of functional programming.
That is a thought process that you can apply in pretty much any language that will give you the biggest bang for your buck.
Edit: Here’s some great examples of the benefits of functional thinking without going off the deep end.
1. Boundaries by Gary Bernhardt - https://www.destroyallsoftware.com/talks/boundaries
2. Pits of Success by Mark Seemann - https://youtu.be/US8QG9I1XW0
3. Grokking Simplicity by Eric Normand - https://grokkingsimplicity.com/
The container approach is lighter weight, and I found it easier to manage the configuration via Dockerfiles. Managing a full VM with the OS install is a bit of a pain.
That being said, I worked at an organization that did the VM approach using Vagrant. It wasn't as nice as the VS Code/Docker approach, but the results were similar.
Its not unusual for large organizations to have internally hosted registries (Artifactory), source control and network proxies. This usually requires setting up different config files (.npmrc for Node.js/NPM), installation of custom root certificates, ssh keys, etc. None of that includes project/team specific configurations and workflows.
Take all that and multiply it by thousands of developers and you have a recipe for an endless stream of Slack chats, email chains, and Teams messages repeating the same config questions and answers.
If you can reduce all that down to a single docker pull, while making sure everyone's development environment is consistent, it can be a big win.
I basically used the container like a VM. Configured it with all the tools I normally use (e.g. OhMyZsh, etc) and had it constantly running in the background. I would use VS Code as a front end and work directly inside the container (cloning repos and pushing commits).
It had its quirks but the main benefit was that my local machine was no longer a snowflake. I could easily move to any machine, pull my "development" image, spin up the container and everything was exactly as I liked it.