Experienced programmers in either approach will be more successful than inexperienced programmers in any approach. Here is one way to be "safer" in a dynamic language, using the same example as the original post.
The original post lists Ruby like so:
def send_message(message, recipient)
# send logic
raise ArgumentError, "Can’t send a plain text message"
But a "safer" solution would look more object-oriented (I'll use Smalltalk):
Tube>>send: aMessage to: aRecipient
"Send aMessage to aRecipient where aMessage can represent itself as an encrypted string."
| encryptedMessage |
encryptedMessage := aMessage encrypted.
"... send logic ..."
...where objects have the ability to encrypt themselves...
"By default an object answers its string representation, encrypted."
self asString encrypted
"Answer the string encrypted using some agreed-upon algorithm."
"Encrypted strings just answer themselves."
Oh the monkey patching! First of all, Smalltalk has so much better tools than Ruby. Smalltalkers don't have to denigrate the practice as "monkey patching". It's just "programming with objects". Not a utility class in sight and no confusion about where any of the code originates.
As an aside, you may not want to encrypt large objects as strings in memory. (Or self-referencing objects, without a seralization that can handle them.) This is making a point about programming in general, not serialization or encryption.
But mostly you don't want to sprinkle "if"'s and unnecessary error handling throughout your system. If you want an encrypted object, just ask the object to provide its own encrypted representation. Implement the default case, the special cases, and the case where the object is already encrypted.
You might decide certain objects are just not suitable to being encrypted. For example the tubes themselves, or windows, or processes, etc. Those objects might signal an exception. Standard Smalltalk defines a signalling mechanism similar to Common Lisp's condition system, where certain exceptions might be resumable, etc. This is another safety mechanism of good dynamic languages. Maybe the topic of a future blog post. Or you can read Practical Common Lisp's really good description now.