I agree with a lot of the criticisms in Dr. Armstrong's article, but I would say that they mainly affect languages such as Java that enforce OO; multi-paradigm languages that allow for OO but don't force it on you don't have these problems. I believe that OOP has valid uses.
> Objection 1. Data structure and functions should not be bound together
In languages like OCaml and C, one defines types separately from functions. Sometimes, however, I find that a function is best associated with a particular type. In OCaml, that's one purpose of modules. (The convention is to call the main type "t.") However, this organization shouldn't be forced on you.
> Objection 2. Everything has to be an object.
This objection only applies to languages like Java that force OO on you. In OCaml or C++, I don't have to use OO, but I still can if I want to.
> Objection 3. In an OOPL data type definitions are spread out all over the place.
Armstrong complains about having to decide what to inherit from when making a Time object. IMO this is a strawman; in Java, classes inherit from Object by default and I don't see any inconvenience. I do agree that it can be annoying that Time has to be object-oriented, and this is where the benefit of OO being voluntary comes in.
> Objection 4. Objects have private state.
I either disagree with or don't understand this objection. Dr. Armstrong lists three ways to deal with state.
His third option is to use pure functional programming. I see both the beauty and practical value in making functions be functions in the math sense, that is to say, mappings from elements of the domain to elements of the codomain. Then, you get equational reasoning. I am sympathetic to this idea. Nevertheless, languages like Haskell aren't for everybody.
His second option is to control access to mutable variables with scope. You can implement a pure function in an imperative way, and that can be a form of encapsulation. This is a good approach, too.
Dr. Armstrong's first option, which he says is the worst, is the idea that objects maintain hidden state which people control via methods. To me, this isn't about state, but rather encapsulation and abstraction. The idea is that when one, say, inserts into a hash table, the person doesn't think about the implementation ("hash the key and walk down the corresponding bucket"), the person thinks of the abstract problem domain ("map this key to this value"). The hash table interface hides its internal state behind the methods. Even in a programming language like C, one writes functions that operate on, and mutate, structs to abstract things away.
Although the second option is good, I see it as orthogonal to the first option, not a superior alternative. If you are going to confine state to within a function, ultimately, don't you have to do mutations on the local variables, and therefore call some kind of method or impure function on them? However, perhaps I am misunderstanding this fourth point.
A lot of arguments, including this submission, pit OOP against FP and argue that FP is superior to OOP. Even though I use FP, I also think that OOP can be useful. They are not opposites and don't have to conflict.
OCaml is infamous for its object layer, yet I ended up using it for a project. I wanted to describe UI "widgets" such that I could compose arbitrary different types of widgets. Before deciding on objects, I had considered first-class modules or a record of functions, but ultimately decided that objects were the most readable choice.
In my OCaml program, I mainly viewed OOP as a way to abstract different types into a common idea. Widgets are all different, and they have different behaviors, but they all have a position in space, a length, and a width. One can also reposition them (mutation!). To me, the purpose of OO is to express ideas such as these. I note that when I used OOP here, I cared less about state and more about the abstraction of what a "widget" was, via dynamic dispatch. It is bad when the language forces OO on you, but it has valid uses.