“Programs should be written for people to read, and only incidentally
for machines to execute.”
— from “Structure and Interpretation of Computer Programs” by Abelson and Sussman
Having said that, If I have to pick one thing, I would say code shouldn’t read like code, it should read like a natural language in the business domain on higher layers(test scripts/page object public methods in the automation framework). All the statements inside a function should be on the same level of abstraction. All the ‘code’ semantics(loops/if/switch) should be deeply buried in the lowest layers of the framework.
Also, well-abstracted code “responds back organically to changes” so if there is a change in the application, how easy to update corresponding automation code? Or best of all, does code jump back to you with specifics on what to change?
If NOT, these are one of most obvious code smells to me that code is not structured properly in different layers in the framework which makes code maintenance a hell due to multiple reasons on multiple levels in the long term.