there’s been an explosion of people and companies looking to do interesting things with their data. I’ve been lucky to work on dozens of data-heavy interfaces throughout my career and I wanted to share some thoughts on how to arrive at a distinct and meaningful product.
I’ve been doing a lot of data-driven interface work over the last few years and the advice in this article is spot on.
It’s funny. I can’t count the number of times I’ve seen organizations with large monolithic software applications move toward SOA. It’s easy to think that we’ve learned a lesson in the industry and that services are just the new “best practice.” Surely we would’ve started with them if we were just starting development now. Actually, I think the truth is a bit more jarring. Different architectures work at different scales. Maybe we need to recognize that and understand when to leap from one to another.
The process space has similar issues. If we cargo-cult anything from the small team space into the large organization space, we’re falling prey to a blind spot. We’re missing an opportunity to re-think things and figure out what works best for small teams, interacting teams, and large-scale development. They may be quite different things.
I agree that the rules are different for different organisation sizes. I like Michael’s comparison of moving across organisation sizes to state transitions in physics.
At Grammarly, the foundation of our business, our core grammar engine, is written in Common Lisp. It currently processes more than a thousand sentences per second, is horizontally scalable, and has reliably served in production for almost 3 years.
Haskell isn’t a common choice for large production systems like Sigma, and in this post, we’ll explain some of the thinking that led to that decision. We also wanted to share the experiences and lessons we learned along the way. We made several improvements to GHC (the Haskell compiler) and fed them back upstream, and we were able to achieve better performance from Haskell compared with the previous implementation.
Terminology for iOS is based on WordNet, a great semantic lexical reference. We do not offer a full Mac app for Terminology, but have prepared a dictionary using this same great data for use in the built-in OS X Dictionary app.
So, interesting: an enormous amount of effort is spent on apps that convert map/vector-structured data into map/vector-structured data.
However, because of the mindshare dominance of object-oriented programming that came because of Java - “Smalltalk for the masses” - it’s hard for most people to think of an approach other than a pipeline of structured data -> objects -> structured data. The tools and frameworks and languages push you toward that. So: a programming model tailored to objects with serious lifetimes has been used for data that lasts only for one HTTP request.
We’ve given up on “fat models, skinny controllers” as a design style for our Rails apps—in fact we abandoned it before we started. Instead, we factor our code into special-purpose classes, commonly called service objects. We’ve thrashed on exactly how these classes should be written, so this post is going to outline what I think is the most successful way to create a service object.
Some good advice for building service objects in Rails.
As of today Front Row uses Haskell for anything that needs to run on a server machine that is more complex than a 20 line ruby script. This includes most web services, cron-driven mailers, command-line support tools, applications for processing and validating content created by our teachers and more. We’ve been using Haskell actively in production since 2014.
An experience report on using Haskell in production.
Ultimately all these statements are about creating responsive systems.
When we design processes that attempt to corral reality into a neat little box, we set ourselves up for failure. Such systems are brittle. We may feel in control, but it’s an illusion. The real world is not constrained by our imagined boundaries. There are surprises just around the corner.
I have told this story to different audiences. Programmers as a rule are delighted by it and managers, invariably, get more and more annoyed as the story progresses; true mathematicians, however, fail to see the point.
The Lisp model is that programming is a more general kind of interaction with a machine. The act of describing what you want the machine to do is interleaved with the machine actually doing what you have described, observing the results, and then changing the description of what you want the machine to do based on those observations. There is no bright line where a program is finished and becomes an artifact unto itself.
In iOS 8, this code doesn’t just fail, it fails silently. You will get no error or warning, you won’t ever get a location update and you won’t understand why. Your app will never even ask for permission to use location.
I just got bitten by this while updating an app. This post goes through what is needed to fix it.
When they create 4089 libraries for doing asynchronous programming, they’re trying to cope at the library level with a problem that the language foisted onto them.
Each of those function expressions closes over all of its surrounding context. That moves parameters like iceCream and caramel off the callstack and onto the heap. When the outer function returns and the callstack is trashed, it’s cool. That data is still floating around the heap.
The problem is you have to manually reify every damn one of these steps. There’s actually a name for this transformation: continuation-passing style. It was invented by language hackers in the 70s as an intermediate representation to use in the guts of their compilers. It’s a really bizarro way to represent code that happens to make some compiler optimizations easier to do.
No one ever for a second thought that a programmer would write actual code like that. And then Node came along and all of the sudden here we are pretending to be compiler back-ends. Where did we go wrong?
What’s even more difficult to understand is errors. Errors in multi-threaded callback code with shared memory is something that would give me an extremely large headache.
The in-language mixing of synchronous and asynchronous calls makes code hard to reason about. The language-side simplicity of Ruby or Java’s concurrency model is something I have taken for granted.
In my opinion, this is the greatest success “hack” there is. If you live in an environment that nudges you toward the right decision and if you surround yourself with people who make your new behavior seem normal, then you’ll find success is almost an afterthought.
Monads are in danger of becoming a bit of a joke: for every person who raves
about them, there’s another person asking what in the world they are, and
a third person writing a confusing tutorial about them. With their
technical-sounding name and forbidding reputation, monads can seem like
a complex, abstract idea that’s only relevant to mathematicians and Haskell
Forget all that! In this pragmatic article we’ll roll up our sleeves and get
stuck into refactoring some awkward Ruby code, using the good parts of monads to
tackle the problems we encounter along the way. We’ll see how the
straightforward design pattern underlying monads can help us to make our code
simpler, clearer and more reusable by uncovering its hidden structure, and we’ll
end up with a shared understanding of what monads actually are and why people
won’t shut up about them.
The accompanying video is short, snappy, and to the point.