Exercises in Programming Style
henrikwarne.com
henrikwarne.com
With the book having been published in 2014, and type hints [1] being introduced with Python 3.5 released in 2015 [2], without knowing how the book did it I guess this is one part of the book that could have been made better in 2018.
> My only criticism of the book is the naming of the styles...In many cases, there are already establish names for the styles, but instead of using them, the author came up with her own. For example: Trinity instead of MVC, Things instead of Objects, Hollywood instead of Callbacks, Bulletin Board instead of Pub/Sub and Kick Forward instead of Continuation-passing. Those names are OK, but it is much better to stick to the industry standard ones.
I'd definitely include this change in a 2018 edition, too.
Depending on what programming language background you come from, you may not use the "established" names either.
is that really important to avoid? and one is just gaining new criticisms in trade, no?
and of course, going bespoke and inventing everything yet again has it's perks. maybe you'll get to be the person who "invented" a term, should it catch on. great for the resume. :)
I'll create a new service that does all of the stuff the old services already did, aswell as this new thing, thus making the old n services obsolete. Everyone will be thankful for the unifying service and hail me for reducing the number of choices from n down to 1.
That's how we ended up with n+1 different services.
Objects vs Structs - a struct is just a collection of data, while an object is a collection of data AND behavior (methods).
Callback vs Continuation - I wouldn't expect a continuation to be called more than once, while I callback can.
Pub/Sub vs Observer - with the observer pattern you register for updates directly on the object that is responsible for them, while with pub/sub there is a central component involved and you don't even need to know who originally published it.
So no, for none of the examples you gave you can just replace one term with the other.
That said, maybe a list of tags for the styles would help? "Also called: [functional, imperative]" etc.?
I'd suggest this book even to experienced engineers to focus on different types or a style of programming that he/she may not be familiar. And when you recognize some of the styles it'll be a re-enforcement technique that you were doing something that is seen over and over again (much like a pattern language). I recall going over styles that are seen more in systems programming (like C). The book will contribute to an understanding of code architecture styles across different languages.
For the new engineer, I'd also highly suggest this book as you may begin to see a variety of ways to solve a problem. And I would not concern myself with idiomatic Pythonic styles as that will come with time.
When coding for myself, I prefer snake case to camel case and shorter variable names.
Likewise in code, For work, I abstract and decouple to keep the code open for future updates. For personal code, I write throwaway code. Given 2 classes that I have developed for work or play. You will not be able to tell it's from the same person.
Also it's not pseudo-science. There are real, live techniques for identifying programmers based on binaries:
"De-anonymizing programmers from executable binaries"
A young person (say 24), has experience coding of a few years, but very enthusiastic, loves reading programming blogs, a real stickler of doing it the "right" way, and sometimes forgets other people might have to read their code. They are not as pragmatic as they would be 10 years down the road. They would use vim or emacs in vim mode because that's more pro. Their code might have a good few "clever" one liners that do something complex in a very concise manner. Took a while to compress into a single line and will take a week to read back and understand. Clever, but only if it never breaks or never needs maintenance. They write factories, sometimes of factories. They have 110% test coverage, including trivial stuff that doesn't require it. They would refactor a piece of code many times until it feels it's the right shade of clever. I like these coders because I can learn something from them, but if you have tight deadlines they might actually get in the way. Great to have a couple of these in your car, but don't let them drive.
from itertools import chain
first_set = set(['one', 'two']).union(set(chain.from_iterable([next.key for next in some_yielding_iter()])))
other_value = make_value_factory_factory(first_set).make_value_factory()
10 years down the line these guys realise you write code once and it's read many times over, and the
above turns into a more vanilla multi line readable expression of the same idea.A less enthusiastic version of said 24 year old, codes because they knows how to, but has no aspirations to get better at their craft. Less organised individual. Pep8 is a new variation of Pepsi Cola? They are not bad coders, just sloppy. Their code works but can be better. They would benefit pairing with the above person.
def someFunction(value):
if (type(value) == ThisClass):
processObject(value)
elif (type(value) == str):
processString(value)
After pairing, maybe they were inspired a bit. Maybe they refactor to this: from functools import singledispatch
@singledispatch
def process_value(value):
process_object(value)
@process_value.register(str)
def _(value):
process_string(value)
def some_function(value):
return process_value(value)
I think a good exercise is to look at a person you know and try ot match their personality to the code
style. Then look at some code which might or might not be theirs and try to assert if it is.Maybe it's because I code in multiple languages daily, but I tend to not use a lot of the language features for each language. A part of it is definitely thinking about the ones that come after me, and wanting everyone -- from every background -- to be immediately able to reason about the code without having to look up what every syntax feature does.
I guess it's a fine line between depth of language features used vs. readability once one is gone from the project.
The third example is cool but I don't see the immediate value in writing code that way unless I am designing a framework of some kind.
I am of the opinion that code should be written in as simple manner as possible so that programmers from different background can get up-to-speed with the code with little trouble.
Checking for the types explicitly in your code creates a brittle system. For a one-off bit of code, fine. For anything that may be extended in the future, it's a bad idea and will have to be refactored to become maintainable.
It's fine when you have related types, but in the example `someFunction` accepts both ThisClass and str, which (I assume) have very different functionality.
You see this anti-pattern a lot in dynamically-typed languages. As an example, both these examples are valid and do the same thing in `knex`, an SQL query builder for node:
knex.select('name', 'email').from('users')
knex.select(['name', 'email']).from('users') try:
processObject(value)
except ValueError:
processString(value)
Where you've written processObject so that it only works on duck-like objects: def processObject(value):
try:
value.quack()
except AttributeError:
raise ValueError('I was expecting something like a duck!')Less sarcastically: I think you're being too dogmatic. I don't like the idea of 'code smells', because it encourages you to judge code not by performance, maintainability, or readability, but by the property that someone has decided it's a code smell. Often it's true that the pattern can be used to write utterly shit code. Code smells are, IMHO, being used as a substitute for common sense. My common sense tells me that the first example is most clean solution. If the code keeps you from obtaining the performance you need, or if you add more checks in other places which make the code unreadable, by all means, refactor it.
In my experience, it's not so much about age, hence I'm not sure if that is relevant in there. (For example, I'm not sure if using VIM is something younger programmers tend to learn, and I'd guess more of the 'older generation' will know it).