I dislike them as PKs and I believe using a surrogate is a better choice. Why? If I do change something, I'm not changing it in many places, which is especially problematic as more companies try to ensure safe data in dev/test or compliance with regulations.
The world has changed. Surrogate keys provide better links and are easy to maintain even when the data changes. The problems you mention of duplicates or other issues can still be handled with constraints or other checks.
I actually don't want to belabor this point as there is a recent thread on just this topic. But the main point of the article was to design databases so that they have the least chance of going wrong and if they do to provide the best way to do a proper fix quickly. The advantages are plain to see. But so are the disadvantages. I've seen and lived those disadvantages, and fixing them was not easy. A lot of entities require a surrogate key. A table of names is a clear case in point. But a lot don't, and adding them handicaps the design. You can overcome some of the disadvantages by unique indexing the column(s). But you are now creating an additional object to the primary key when a primary key on the column(s) would have been sufficient. As has been pointed out, you may have to make a join that would have otherwise NOT been necessary. I would not have a surrogate key on a zip code table. Zip codes don't really change, although a location might have to change it's zip code. But the presence of a surrogate key complicates that update.
I have nothing against surrogate keys in principle. Per Kimball, I use them exclusively in my OLAP designs. But in my OLTP designs, if there's a good natural/business key, I will use that. Not doing so, in my view, makes the database that much more complicated.