Good software is approachable. It can be understood completely in independent, easy pieces. You don’t need to understand everything before you can understand anything.
Good software is consistent. It lets you take what you’ve learned about one part and extrapolate it to the rest. It doesn’t self-contradict. It is parsimonious, avoiding superfluous elements.
Good software explains itself. It has affordances for learning and discovery. It is role-expressive and minimizes hidden magic.
Good software teaches. It doesn’t just automate an existing task, but provides insight or imparts knowledge, such as a best practice or a new perspective on a problem.
Good software is for humans. It is cognizant of people and the reality in which they live. It does not expect elaborate and arbitrary rules to be memorized. It anticipates the need for learning and debugging.