개발자 99% 커뮤니티에서 수다 떨어요!
TIL (Today I Learned)
2022.02.22
오늘 읽은 범위
Functions (pp. 31-52)
책에서 기억하고 싶은 내용을 써보세요.
Nowadays only the function survives from those early days.
The first rule of unctions is that they should be small. The second rule of functions is that they should be smaller than that.
The indent level of a function should not be greater than one or two.
Functions should do one thing. They should do it well. They should do it only.
The reason we write functions is to decompose a larger concept (in other words, the name of the function) into a set of steps at the next level of abstraction.
Functions that do one thing cannot be reasonably divided into sections.
We need to make sure that the statements within our function are all at the same level of abstraction.
Mixing levels of abstraction within a function is always confusing.
We want the code to read like a top-down narrative. We want every function to be followed by those at the next level of abstraction so that we can read the program, descending one level of abstraction at a time as we read down the list of functions. I call this The Stepdown Rule.
We can't always avoid switch
statements, but we can make sure that each switch
statement is buried in a low-level class and is never repeated.
My general rule for switch statements is that they can be tolerated if they appear only once, are used top create polymorphic objects, and are hidden behind an inheritance relationship so that the rest of the system can't see them.
Names should describe what the functions do.
Remember Ward's principle: "You know you are working on clean code when each routine turns out to be pretty much what you expected." Half the battle of achieving that principle is choosing good names for small functions that do one thing. The smaller and more focused a functions is, the easier it is to choose a descriptive name.
Don't be afraid to make a name long.
Be consistent in your names.
The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible.
Arguments are even harder from a testing point of view.
One input argument is the next best things to no arguments.
There are two very common reasons to pass a single argument into a function.
A somewhat less common, but still very useful form of a single argument function is an event.
Using an output argument instead of a return value for a transformation is confusing.
Flag arguments are ugly. Passing a boolean into a function is a truly terrible practice.
Reducing the number of arguments by creating objects out of them may seem like cheating, but it's not.
So all the same rules apply. Functions that take variable arguments can be monads, dyads, or even triads. But it would be a mistake to give them more arguments than that.
The keyword form of a function name.
This side effect creates a temporal coupling.
If you must have a temporal coupling, you should make it clear in the name of the function.
Functions should either do something or answer something, but not both.
Returning error codes from command functions is a subtle violation of command query separation.
When you return an error code, you create the problem that the caller must deal with the error immediately.
It is better to extract the bodies of the try
and catch
blocks out into functions of their own.
Functions should do one thing. Error handling is one thing.
Error.java
Dependency Magnet (p.47)The duplication is a problem because it bloats the code and will require four-fold modification should the algorithm ever have to change. It is also four-fold opportunity for an error of omission.
Some programmers follow Edsger Dijkstra's rules of structured programming.
Dijkstra said that every function, and every block within a function, should have one entry and one exit.
Only be one return
statement in a function, no break
or continue
statements in a loop, and never, ever, any goto
statements.
goto
only makes sense in large functions, so it should be avoided.
I also have a suite of unit tests that cover every one of those clumsy lines of code.
I don't write them that way to start. I don't think anyone could.
When I write functions, they come out long and complicated. They have lots of indenting and nested loops. They have long argument lists. The names are arbitrary, and there is duplicated code.
In the end, I wind up with functions that follow the rules I've laid down in this chapter.
Every system is built from a domain-specific language designed by the programmers to describe that system. Functions are the verbs of that language, and classes are the nouns.
The art of programming is, and has always been, the art of language design.
Your functions will be short, well named, and nicely organized.
Your real goal is to tell the story of the system, and that the functions you write need to fit cleanly together into a clear and precise language to help you with the telling.
오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요
Before reading this chapter, I didn't realize that how much thoughts I should put when I make functions. There are a lot of things going on this chapter, but I cannot understand all of them. I would say I think I got the core idea but not most of the details. Hope I can read and understand the language that was shown as examples.
궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.
What is double-take? (p.45)
Level of abstraction?
Command Query Separation? (p.45)
Why four-fold modification? (p.48)