Architecting The Cloud. Design decisions for cloud computing service models, by Michael J. Kavis describes cloud computing in general and the different service models that are prevalent today in particular. It explores the differences and trade-offs between Software as a service (SaaS), Platform as a service (PaaS) and Infrastructure as a service (IaaS). I consider the book a good introduction to considerations for cloud computing for those that are used to more traditional data-center deployments.
The author covers a section on worst practices: Things that do not translate well when moving to the cloud and recommendations on how to avoid them. I found the most useful chapter to be the one on disaster recovery: A good overview of different strategies to become fault-tolerant in the cloud and embracing resiliency.
Uncle Bob makes a useful analogy about code organization and physical organization of say, your desk or a library. Organization matter. Sometimes, all we need is a small amount of organization, sometimes we need the Dewy Decimal System
Most developers appreciate the benefits of plain text files since they play so well with other tools, like source control, grep, find, etc. W. Caleb McDaniel makes a great case for using plain text other than for programing code. In his case, he composes his academic writing in plain text and uses open source tools at the end to convert them to industry-standard proprietary formats. Awesome.
A big part of effective communication is sharing the same terminology. It helps with context and allows us to be more specific. Jessitron proposes expanding our vocabulary around what “Quality Software” means. Instead of saying a piece of code is “good” or “clean”, how about it’s “configurable” and “readable”.
The Metallica document is gone. Surprised? I definetly was.
The behavior may seem a bit contrived, but I actually encountered it while trying to optimize a produciton database. This example just boils it down to something trivial to reproduce. I should mention that if the index is created without the sparse option, the results are correct. The sparse option allows saving space on the index itself, by only creating an entry for documents that have the field. A non-sparse index, creates a record for all documents and sets the value to null.
In my opinion, the above-described behavior is awful. It is up to the database engine to decide which index to use. A sparse index may be useful in less queries than a non-sparse index. However, my expectations of indexes is that they are all about performance and trading off disk space and insert time for query time. The existance of an index should never change the result set for the same query and dataset.
In order to teach myself Elixir, I have been working my way through Exercism.io, which is a set of practice coding exercises with mentorship from the community. All exercises have the tests written for you and it’s up to the user to write a passing implementation.
Being new to Elixir and functional programming, the exercises are a great way for me to learn about syntax, idiomatic code and functional programming patterns. One of exercises consists of re-implementing common list operations, like count, map and reduce.
Implementing Count With Recursion
The test that the implementation must pass looks like this:
defmoduleListOpsTestdoaliasListOps,as:LuseExUnit.Case,async:truetest"count of empty list"doassertL.count()==0endtest"count of normal list"doassertL.count([1,3,5,7])==4endtest"count of huge list"doassertL.count(Enum.to_list(1..1_000_000))==1_000_000endend
First thing of note: count/21 is defined twice. This is part of the language provided functionality. In Java, method overloading required a different number of parameters which is how the dispatching picked the correct method at runtime. In Ruby, there can’t exist to method definitions in the same scope. In Elixir, the correct function is called at run-time depending on which pattern is matched.
On our first test, when L.count() is called, the count/1 function matches, because it only has one parameters. That function calls count(0, ). This will match the first count/2 definition, because it is being passed with an empty list. (Any acc will match). That in turn returns acc, which is 0, making the test pass.
For the second test, count/1 is matched, which ends up calling count(0, [1,3,5,7]). That call, matches the second count/2 definition, because it matches a list that is not empty2. That function call will call recursively, adding 1 to the accumulator each call, until the list is empty and the accumulator is returned.
The same trick as before is used here, where matching on an empty list returns the accumulator. When a list has at list one member, the function is called for that member and reduce/3 is called with the tail of the list recursively.
With reduce/3 in place, the count/1 implementation becomes much simpler:
The exercise has some other operations as well: map, reverse, filter, append and concat. I learned a lot working on the solutions and started to get a feel for functional programming. If you are learning a new language, I would recommend trying Exercism.io. It currently supports 23 languages!
In Elixir, when referring to functions, it is customary to add / and the arity to the name. foo/2 refers to the function foo defined with 2 parameters.↩
Elixir includes matching a list to it’s head and tail with the [head|tail] syntax. The _ signals that the parameter will not be used.↩
Based on a talk at Strange Loop 2014, this post was eye-opening. Although it’s supposed to be about Apache Samza, most of the talk is devoted to talking about databases in general and what they are good at: Keeping global state, replication, secondary indexing, caching, and materialized views. This high-level view provided me with a lot of new perspective of how to think of databases. The many illustrations in the article are beautiful. Please go and read.
The legendary Chad Fowler makes the case that empathy is a skill that everyone will benefit from developing further. Provides great list of why that is. Most importantly, he also details how to practice.
Git has often been criticized for having an inconsistent interface and leaking unneeded abstractions to the user. Some of that criticism is warranted. Nonetheless, git is one of my favorite programs. I use it hundreds of times throughout the day, always on the command-line, complemented by tig, the ncurses client for git. This article talks about the internals of git: How it stores data on disk for commits, trees, objects, tags, branches, etc. It is well written, well organized and a pleasure to read. If you read this guide, it will make it easier for you to interact with git because you will understand it’s intrenals. However, I think you should read it because it shows how great functionality can be achieved with software with minimal dependencies and using only the local filesystem as a data store.