When I joined another development team this week to observe them working with our favorite design consultant, I arrived in a moment when they were discussing the name of a certain class. Later on they discussed issues like class responsibilities, where to put certain methods, what to mock in a test. I was amazed not just by the well-informed discussions, but also at the actual questions they were discussing.
In other teams and at other times, the questions would be "why does this not compile"? "how do I get this to work"? "how do I do X with (technology) Y?" (instead of: "is Y a good technology to do X?")
Of course, it's the developer's job to get things done, but if we struggle too much with the low-level questions then they won't be any time for really interesting questions of design and actually doing things well.
Next time, I have to choose a team to work with, I will pay attention to this point.
14 July 2012
Giving our architecture away
My team of software developers at work was discussing a book when the question of singletons came up. The format of our discussions was to discuss one chapter in each meeting which everybody had read before. During the meeting we'd try to apply the lessons from the book to examples from our own code and projects. We'd also tried to agree on some coding and design standards to apply to our own team work. So far that's great!
One time, the discussion came to the use of Singletons, but it was a very short discussion, because someone said "we don't use Singletons because we do that with Spring". I insisted that in this case, we should discuss some ground rules and best practices for the use of Spring, but out of the entire team nobody was interested in that thought. I insisted one more time, but the crowd then simply went on with the meeting agenda.
At the time of that meeting (several months ago, but still vivid in my mind), I didn't know much about Spring and all its magic and had hoped I would get a quick lesson out of the meeting. Now, I still haven't managed to read a full book chapter or even blog article about Spring (their dryness makes me fall asleep), but I have seen a lot of the Spring code in our project. And while I have never seen good Spring code, the one in our project just seems wrong to me. Too many levels of abstraction mixed and all intertwined. Too much duplication in Spring contexts for tests and production. And that makes simple refactorings (even renamings) much harder.
This week, the topic came up again, because I talked about it with our development coach Steve Freeman, who shares my suspicion about Spring being misused more than it's actually well used. In a discussion I had with one of coworkers right after, my otherwise so intelligent and reasonable coworker insisted that using Spring is always good, because we use code that has been written by experts and is well-tested in many big systems for a long time. My point was, that we don't actually use much of Spring's functionality, but rather we just use Spring XML as another language to express what could be just as conveniently expressed in Java – even with the advantage of allowing better code-surfing (following references), better refactoring, and a better architecture overall.
In short, my impression is that by doing things "with Spring" we just hand over responsibility over our architecture to "the experts" and give up to think about it ourselves. We all agree that "Singletons are bad", but then again, what's a Spring context if not a big uniform sea of intertwined Singletons? My coworker says: "Spring has important functionality like figuring out the order of bean dependencies for you." But then I totally agree with Steve who says: "Doing the bean creation yourself gives you crucial feedback about the design of your code."
Using Spring dependency injection blindly means giving up you architecture. I am not going to do that, because I am a responsible architect.
One time, the discussion came to the use of Singletons, but it was a very short discussion, because someone said "we don't use Singletons because we do that with Spring". I insisted that in this case, we should discuss some ground rules and best practices for the use of Spring, but out of the entire team nobody was interested in that thought. I insisted one more time, but the crowd then simply went on with the meeting agenda.
At the time of that meeting (several months ago, but still vivid in my mind), I didn't know much about Spring and all its magic and had hoped I would get a quick lesson out of the meeting. Now, I still haven't managed to read a full book chapter or even blog article about Spring (their dryness makes me fall asleep), but I have seen a lot of the Spring code in our project. And while I have never seen good Spring code, the one in our project just seems wrong to me. Too many levels of abstraction mixed and all intertwined. Too much duplication in Spring contexts for tests and production. And that makes simple refactorings (even renamings) much harder.
This week, the topic came up again, because I talked about it with our development coach Steve Freeman, who shares my suspicion about Spring being misused more than it's actually well used. In a discussion I had with one of coworkers right after, my otherwise so intelligent and reasonable coworker insisted that using Spring is always good, because we use code that has been written by experts and is well-tested in many big systems for a long time. My point was, that we don't actually use much of Spring's functionality, but rather we just use Spring XML as another language to express what could be just as conveniently expressed in Java – even with the advantage of allowing better code-surfing (following references), better refactoring, and a better architecture overall.
In short, my impression is that by doing things "with Spring" we just hand over responsibility over our architecture to "the experts" and give up to think about it ourselves. We all agree that "Singletons are bad", but then again, what's a Spring context if not a big uniform sea of intertwined Singletons? My coworker says: "Spring has important functionality like figuring out the order of bean dependencies for you." But then I totally agree with Steve who says: "Doing the bean creation yourself gives you crucial feedback about the design of your code."
Using Spring dependency injection blindly means giving up you architecture. I am not going to do that, because I am a responsible architect.
8 June 2012
Buy, don't build. But if you build, also sell.
Here's an additional thought to my last post. The model from which I inferred this rule is Google. Google famously used a variant of the "buy, don't build" rule when they build their data centers out of many standard computers instead of big customized ones. They also use standard Linux and its tools for many tasks. But Google also very often makes exceptions to this rule. There's the Google Collections (now Guava) libraries replacing of standard Java collections, there's GWT to write JavaScript in Java and Closure to compile JavaScript, and recently they went as far as creating Dart as a new programming language to replace JavaScript and SPDY as a new protocol to replace HTTP.
In each of those cases, Google must have decided that they could do better than the current state of the art, but that's not a point I want to discuss here.
In each of those cases, Google must have decided that they could do better than the current state of the art, but that's not a point I want to discuss here.
The noteworthy point that should be model for other companies is that in each of the cases mentioned, Google also polished their homebrew solutions and published them for everybody else to use. They're not selling it in the sense of asking money for it, but they're selling it in the sense of providing it with at least minimal marketing and minimal support (thru documentation and FAQs) and by opening a feedback channel for outsiders to report bugs or request features. At the same time, they allow outsiders to join the project in several ways.
An easy but important form of outside help is when outsiders blog about it (that's more marketing, but also basic how-to style tech support) or answer other outsider's questions on the support forums. Those forums are often mostly there for outsiders to help each other, so that the Google employees can save their time to answer just those questions which they themselves find interesting.
And then, of course, there's the more involved styles of outside-help when people beta-test software, package it into distributions or builds for different architectures, write better documentation (or even books) about it, report bugs and minimize bug test cases. And finally, there's the really involved ways of fixing bugs or contributing features.
An easy but important form of outside help is when outsiders blog about it (that's more marketing, but also basic how-to style tech support) or answer other outsider's questions on the support forums. Those forums are often mostly there for outsiders to help each other, so that the Google employees can save their time to answer just those questions which they themselves find interesting.
And then, of course, there's the more involved styles of outside-help when people beta-test software, package it into distributions or builds for different architectures, write better documentation (or even books) about it, report bugs and minimize bug test cases. And finally, there's the really involved ways of fixing bugs or contributing features.
With Guava, Chromium, and even Android, Google has started pretty foundational projects, which few companies could imitate. But I think that in almost every project that produces a lot of custom code (that is, builds stuff, instead of buying it), there is at least a fraction of that stuff which could be factored out and given to the world as a little product of its own. If you look at the plethora of Java Modules which are available in the global Maven repository, or all of Ruby's Gems, or Python's Eggs, you can imagine that many of them have been factored out of bigger company-specific projects. Many of those libraries initially started out very small, but with time, they grew to a certain completeness that now makes them The Standard Library™ for their domain. Examples that I have used in my current job include JodaTime, Awaitility, Mockito, and WebDriver.
Besides being a great way to give something small back to the community, I also think that treating your modules as products in their own right can be a great tool to drive separation of concerns. It means putting all the technical and general stuff into the public module and all the company- or project-specific stuff out of the module. This creates a decoupled architecture in which success of your module in the public market place means that you might get features and community-support for free. It even let's you profit in the opposite case: if a better product comes along to fulfill the purpose of your module, your decoupled architecture will allow you to adopt the improved solution. Win-win!
So that's my rule: Buy, don't build. But if you build, also sell.
Three silver bullets that have been forgotten
I recently thought about what my ideal programming language would be. Just for fun, I googled "ideal programming language" and read the first five hits. Man, was I disappointed! It seems that nobody who has any imagination has ever written about the topic in a way that brings them high up in the Google results. Basically all five authors described their ideal programming language simply by listing features from existing languages!
Here's a ruff list of requirements for the ideal programming language that I came up with:
Here's a ruff list of requirements for the ideal programming language that I came up with:
- has only a few built-in features so that it con be customized for different domains
- uses the same core syntax as a basis for all kinds of third-party supplied DSLs
- allows much better tool-supported factoring than any current tool for any current language provides
- allows IDEs to show the code in different views, rearranging methods, even graphical and tabular representations (see also light table and subtext)
- can scale from being a scripting language for a third-party module up to writing your own DSLs and modules to be used by others
- allows literate programming, support for verification, and also tests. IDEs should understand the verification annotations (such as preconditions, postconditions, invariants) to point out possible errors and better support refactoring.
- is explicit. I think that languages with implicit type conversion, implicit defaults, and other automagical things scale badly, because in a larger program, you'll have a mix of implicit and overwritten stuff and need to keep track of when the defaults are used or what else happens "behind the scences". integrating the language with the IDE means that the defaults can be put into new programs and modules by the IDE thus keeping the advantage of quickly starting a project but also gaining the advantage of staying agile by always seeing where everything comes from and being able to change it just right there.
Interestingly, tool support for different views and verification and flexibility to create DSLs all require that the core language has as few features as possible!
Even more interestingly, as I read Fred Brooks famous essay on "no silver bullet" again, I was easily convinced that new programming languages don't actually make that big of a difference in programmer productivity. Basically, there's been nothing really new since Smalltalk and ML! On the other hand, Brooks convincingly argues that the fastest way to write a software is to not write it at all, but to buy it! Or more generally, reuse existing modules!
While Brook's essay lists a lot of other technologies and methods from which he doesn't expect any significant improvements in productivity, he also mentions three things which actually do have potential in his mind. In short:
- Buy, don't build.
- Develop incrementally from prototypes.
- Find and develop great designers.
Interesting that he mentions incremental development back then in 1986. Agile ain't that new after all! And defining the minimal product hasn't become easier either. It's still one of the essential complexities of software engineering.
Edit: Added "explicitness" in response to Max' comment.
Edit: Added "explicitness" in response to Max' comment.
Don’t test your code – test theirs
Nowadays with many technical problems solved by third-party modules we include in our projects, the code we write ourselves is often so simple that unit tests don’t make any sense any more. Of course, we’ll still need automatic system tests (end-to-end tests) and those tests won’t always be green, but when we drill down to find the problem it is most likely that the problem is not in our code, but in our understanding of one of the modules we’re importing!
So how does that pair with “test first”? It simply means that before writing any code depending on third-party modules you explore the third-party APIs by writing unit tests for them which validate your understanding of just those features that you are going to need. And yes, you “test features, not methods”. (The web doesn’t yet know what that means, so you need to find a book such as GOOS to learn about that.)
So how does that pair with “test first”? It simply means that before writing any code depending on third-party modules you explore the third-party APIs by writing unit tests for them which validate your understanding of just those features that you are going to need. And yes, you “test features, not methods”. (The web doesn’t yet know what that means, so you need to find a book such as GOOS to learn about that.)
29 May 2012
two rules about testing and a meta-rule about software engineering
Here are two very important rules to write good automatic tests for software:
- Don't let the tests parrot the code.
- Focus tests on areas where you expect failures.
Before I go on with this post, I would like you, Dear Reader, to read those rules again, think about them deeply, and answer the following questions: have you ever seen a test that was useless because it violated rule 1? Have you ever worked on a piece of software that had lots of tests, but still let lots of failures happen? In hindsight, did some or many of those failure concentrate in particular areas?
More generally, due the rules seem true to you? Do they seem helpful? Or are they so obvious that they wouldn't even need to be stated so explicitly? Or might the opposite be true: the rules are too general for an ordinary developer to apply them well without further instruction? For example, what degree of redundancy between test code and production code constitutes parroting? How would an ordinary developer know in which areas to expect the most failures?
When I discovered the above two rules my attitude towards them swung wildly a couple of times. First I thought: “Wow, are those rules great. They're going to be the basis for my next book about software quality.” A bit later, I thought: “What silly rules to brag about. Any half-decent programmer is surely always following them unconsciously, just because they make so much sense.” Currently my thinking is: “Yes, yes, both is true: the good programmers follow the rules, even if they couldn't state them explicitly. But the bad programmers (or even the ordinary average wage-slave programmers of our day) will often create bad tests by ignoring just those two simple rules.”
And when I had that last thought, it occurred to me that the same is probably true about most “rules” or “guidelines” in software engineering or, for that matter, in any practical field. The best and most talented people always act in accordance with some unwritten rules and are often not aware of it. It takes other people to formulate those rules and even more people to reformulate them for specific audiences, discuss examples, do one-on-one coaching, ... until every ordinary practitioner of a particular profession has adopt the guideline into his daily routine.
That's the meta-rule:
Many good engineering (or life) rules sound simple and obvious, yet they require good judgement and/or lots of experience to be applied well.
And now, it's time for your comments!
28 May 2012
Variations on a Bowling Scorer
Instead of writing a lot about programming as I usually do, this post is made up mainly of code. The background story is that I was terribly offended by a piece of code I found on the web. So I rewrote it, documenting my process and design decisions on the side. I was very happy with the resulting code I got, but never had the time to rewrite the process and design description for publishing. My code, however, is always written to be readable for anybody, so I am publishing it here without any comments.
You'll probably notice that the code which offended me is very clean on the surface (after all, it's written by Mr. Clean Code himself!), but what bugged me was the design of the program and the tight coupling of methods by shared variables. In fact, the coding style reminded me a lot of programs written in C. (A higher-level machine language from the 70s, for those who don't know it.)
Here's Uncle Bob's solution; copied from his long post where he and a coworker derive it TDD style. (Code-highlighting on Blogger seems really hard to do, so for the moment, I need to feed you black and white code. Sorry for that!) Don't worry about the actual purpose of the code. If you want to learn the rules of bowling scoring, you can read them from the declarative program given below!
Here's the code:
If you don't have the time to study the code in detail, at least have a look at that one line in Frame(..) which says: this.score = previousScore + throwsScore() + bonusScore(); I think that this is as close as we get to formulating a really direct and concise specification of the score of a frame.
Finally, sorry for improvising some of the Matcher / Assertion stuff as I don't have all the proper tools installed right now.
You'll probably notice that the code which offended me is very clean on the surface (after all, it's written by Mr. Clean Code himself!), but what bugged me was the design of the program and the tight coupling of methods by shared variables. In fact, the coding style reminded me a lot of programs written in C. (A higher-level machine language from the 70s, for those who don't know it.)
Here's Uncle Bob's solution; copied from his long post where he and a coworker derive it TDD style. (Code-highlighting on Blogger seems really hard to do, so for the moment, I need to feed you black and white code. Sorry for that!) Don't worry about the actual purpose of the code. If you want to learn the rules of bowling scoring, you can read them from the declarative program given below!
Since I felt that mutable variables shouldn't be necessary in the solution at all, I first produced a solution in a purely functional programming language. Here's my solution in Haskell://Game.java---------------------------------- public class Game { public int score() { return scoreForFrame(itsCurrentFrame); } public void add(int pins) { itsScorer.addThrow(pins); adjustCurrentFrame(pins); } private void adjustCurrentFrame(int pins) { if (firstThrowInFrame == true) { if (adjustFrameForStrike(pins) == false) firstThrowInFrame = false; } else { firstThrowInFrame=true; advanceFrame(); } } private boolean adjustFrameForStrike(int pins) { if (pins == 10) { advanceFrame(); return true; } return false; } private void advanceFrame() { itsCurrentFrame = Math.min(10, itsCurrentFrame + 1); } public int scoreForFrame(int theFrame) { return itsScorer.scoreForFrame(theFrame); } private int itsCurrentFrame = 0; private boolean firstThrowInFrame = true; private Scorer itsScorer = new Scorer(); } //Scorer.java----------------------------------- public class Scorer { public void addThrow(int pins) { itsThrows[itsCurrentThrow++] = pins; } public int scoreForFrame(int theFrame) { ball = 0; int score=0; for (int currentFrame = 0; currentFrame < theFrame; currentFrame++) { if (strike()) score += 10 + nextTwoBalls(); else if (spare()) score += 10 + nextBall(); else score += twoBallsInFrame(); } return score; } private boolean strike() { if (itsThrows[ball] == 10) { ball++; return true; } return false; } private boolean spare() { if ((itsThrows[ball] + itsThrows[ball+1]) == 10) { ball += 2; return true; } return false; } private int nextTwoBalls() { return itsThrows[ball] + itsThrows[ball+1]; } private int nextBall() { return itsThrows[ball]; } private int twoBallsInFrame() { return itsThrows[ball++] + itsThrows[ball++]; } private int ball; private int[] itsThrows = new int[21]; private int itsCurrentThrow = 0; }
Given how easy that was, we now have a clear picture of the solution algorithm and design which we only need to port to Java. It's not exactly I one-to-one port, but you'll recognize the spirit of the algorithm.example_throws_incomplete = [1,2,3,4,10,10,1,2,3] to_frames :: [Int] -> [([Int], [Int])] to_frames (10:xs) = ([10], xs) : to_frames xs to_frames (x:y:xs) = ([x,y], xs) : to_frames xs to_frames _ = [] -- covers empty lists and trailing bonus throws test_to_frames = assert_equals (map fst $ to_frames example_throws_incomplete) [[1,2],[3,4],[10],[10],[1,2]] -- how many bonus throws are counted into a frame? num_bonus [10] = 2 num_bonus [a, b] | a+b == 10 = 1 num_bonus _ = 0 -- scoring a frame is really simple: score_frame (frame_throws, next_throws) = sum frame_throws + sum bonus_throws where bonus_throws = take (num_bonus frame) next_throws -- the straight-forward solution assumes that all the bonus throws are present score_complete_game throws = scanl1 (+) $ map score_frame $ take 10 $ to_frames throws assert_equals a b | a == b = "ok" | otherwise = "expected: " ++ show a ++ "\n" ++ "but got: " ++ show b
Here's the code:
Before start giving a lecture on why my program is better, I'll just let you read and find your own opinion. If you want some more food for thought, try to find the one concern that Uncle Bob's solution treats in two different places in two different ways without explicitly mentioning it as a concern. (Had they found the pattern and named it, they'd probably tried to solve it in one place only.)import java.util.List; public class BowlingScorer { static class Frame { static final public Frame firstFrame(Listthrowns) { return new Frame(throwns, 1, 0, 0); } public Frame nextFrame() { return new Frame(throwns, number+1, nextPosition(), score()); } public int number() { return number; } public int score() { return score; } public boolean isStrike() { return throwns.get(position) == 10; } public boolean isSpare() { return ! isStrike() && throwsScore() == 10; } public int numThrows() { return isStrike() ? 1 : 2; } public int numBonus() { return isStrike() ? 2 : isSpare() ? 1 : 0; } private int nextPosition() { return position + numThrows(); } private int throwsScore() { return sumThrowns(position, numThrows()); } private int bonusScore() { return sumThrowns(nextPosition(), numBonus()); } private int sumThrowns(int start, int count){ int result = 0; for (int i = start; i < start+count; i++) { result += throwns.get(i); } return result; } private final List throwns; private final int number; // number of frame in game, counting from 1 private final int position; // this frame's first throw in throwns private final int score; private Frame(List throwns, int number, int position, int previousScore) { this.throwns = throwns; this.number = number; this.position = position; this.score = previousScore + throwsScore() + bonusScore(); } } public int finalScore(List throwns) { return getFrame(throwns, 10).score(); } private Frame getFrame(List throwns, int number) { // requiresThat(number, atLeast(1)); // requiresThat(number, atMost(10)); Frame f = Frame.firstFrame(throwns); while (f.number() < number) { f = f.nextFrame(); } return f; } /* private static void requiresThat(T thing, Matcher matcher) { if (! matcher.matches(thing)) { throw new IllegalArgumentException(matcher.reason()); } } */ }
If you don't have the time to study the code in detail, at least have a look at that one line in Frame(..) which says: this.score = previousScore + throwsScore() + bonusScore(); I think that this is as close as we get to formulating a really direct and concise specification of the score of a frame.
Finally, sorry for improvising some of the Matcher / Assertion stuff as I don't have all the proper tools installed right now.
5 May 2012
Shimano Nexus/Alfine Inter-8 hub gear disassembled / reverse-engineered
On a beautiful day in 2011, when I visited my favorite Berlin bike builder and dealer on the Schöneberg Island, I noticed that he used the shell of a Shimano Inter-8 gear hub as an ash tray. When I asked him about the piece, he told me that one of his customers or friends had serviced the gear hub and not reassembled it correctly, making the ball bearings smash when he used it again.
I asked for the innards of the hub which Conrad still had below a shelf in a corner of the shop. He gave them to me and this week I finally got around to look at them more closely.
I already knew that this hub is logically composed of two stages of planetary gears. One has two gears, the other four. Both can be switched independently to give eight gears and the ratios of the cogs are tuned in such a way that the eight gears have roughly equal spacing and no gear overlap. (So logically they work like the 3×8 gears of a 24 gear derailer system, only that all the gears are shiftable in sequence.) After disassembling the hub, I counted the teeth of all the cogs and used the counts to calculate the gear ratios. I was happy to find that I just got the same results that are published on several places of the Interwebs. For those who can't wait to see them, here's my calculations. All others can first read on to find out how this stuff works. Actually, those who've never read anything about planetary gears, go start with my introductory blog post on planetary gears to learn some of terminology. Then come back to find that I am experimenting with different terminology here (after all, this is a work in progress and I need to figure out what works best). For now, let's say “cog” to the little toothed round devices that turn inside the gear hub to translate speeds. Then we can use the word “gear” for the resulting ratios of speed, just as you ordinarily do when you say “first gear, second gear” and so on.
Now, here's a summary of the hub's architecture: since both stages share the same planet carrier, the carrier serves as the one and only power transfer between the two stages. The carrier is therefore output of the first stage and input of the second stage, which conveniently serves the fact that the first stage reduces speed, while the second stage increases speed. In both stages the sun cogs are locked and the ring cog serves as the other moving part. (In the second stage, there are three sun cogs locked via switchable one-way ratchets.) One-way ratchets (aka freewheels) are used in many places in the hub. Thanks to the freewheels several gears can be switched “active” at the same time which has two key advantages. One, when shifting gears, the mechanism only needs to activate or inactivate the higher gear, while the lower will automatically be inactive (freewheel) without being actuated by the shifting mechanism. The second advantage is that during shifting (or when there's a problem with the shifting cable), there is never a no-gear stage, since the lower gear will always be active as fall-back in case that the higher gear doesn't engage properly.
A first surprise I found when looking at the hub innards was that the reduction stage has two planet sets to create just one reduction ratio. I had previously assumed that there was only one set, that is, one sun cog, a couple of planet cogs all engaging with the sun cog, and one ring engaging with all the planets. But in reality, the three planets are two cogs in one: a smaller cog that engages the sun and a little bigger one, that engages the ring. I should actually have thought of that because with a single planet set, it is quite hard to achieve an 89% gear ratio as this stage of the hub does. (The planet cogs would need to be to tiny, since their size approaches zero as the ratio nears 100%.)
Left is the reduction stage, right the 4-gear stage (including carrier shared by both stages). |
I already knew that this hub is logically composed of two stages of planetary gears. One has two gears, the other four. Both can be switched independently to give eight gears and the ratios of the cogs are tuned in such a way that the eight gears have roughly equal spacing and no gear overlap. (So logically they work like the 3×8 gears of a 24 gear derailer system, only that all the gears are shiftable in sequence.) After disassembling the hub, I counted the teeth of all the cogs and used the counts to calculate the gear ratios. I was happy to find that I just got the same results that are published on several places of the Interwebs. For those who can't wait to see them, here's my calculations. All others can first read on to find out how this stuff works. Actually, those who've never read anything about planetary gears, go start with my introductory blog post on planetary gears to learn some of terminology. Then come back to find that I am experimenting with different terminology here (after all, this is a work in progress and I need to figure out what works best). For now, let's say “cog” to the little toothed round devices that turn inside the gear hub to translate speeds. Then we can use the word “gear” for the resulting ratios of speed, just as you ordinarily do when you say “first gear, second gear” and so on.
Now, here's a summary of the hub's architecture: since both stages share the same planet carrier, the carrier serves as the one and only power transfer between the two stages. The carrier is therefore output of the first stage and input of the second stage, which conveniently serves the fact that the first stage reduces speed, while the second stage increases speed. In both stages the sun cogs are locked and the ring cog serves as the other moving part. (In the second stage, there are three sun cogs locked via switchable one-way ratchets.) One-way ratchets (aka freewheels) are used in many places in the hub. Thanks to the freewheels several gears can be switched “active” at the same time which has two key advantages. One, when shifting gears, the mechanism only needs to activate or inactivate the higher gear, while the lower will automatically be inactive (freewheel) without being actuated by the shifting mechanism. The second advantage is that during shifting (or when there's a problem with the shifting cable), there is never a no-gear stage, since the lower gear will always be active as fall-back in case that the higher gear doesn't engage properly.
Reduction stage with two planet sets. |
The power from the chain and cog is transferred to the ring cog of the first stage via a freewheel. To bypass the first stage (as in gears 5 to 8), a clutch connects the incoming motion directly to the planet carrier. Since the ring gear always turns faster than the carrier, it will be then freewheeling with respect to the input motion. (Inversely, when the clutch is disengaged and the ring is driven by the bike chain, then the carrier will turn with the translated speed, so it's important that the clutch is completely disengaged, since the gears would otherwise jam.) From experience during about 10'000 km riding a similar hub (and by what I've heard from others), switching this clutch is the most difficult and noticeable switch in the hub. It's the one between fourth and fifth gear. Also the one that first becomes edgy when the shifter cable is misadjusted. (Happens rarely and is easy to fix.)
Finally, let's look at the second stage which as I said is driven by the carrier and transfers its motion to the hub shell (and thus the wheel (and thus the road (and thus the earth, which makes is turn))) via the ring gear or (if in direct drive) via the carrier. Both ring and carrier connect to the hub shell via a freewheel so that the faster one will be driving while the other will be in fallback mode. Interestingly, direct gear (1 and 5) is achieved by locking none of the sun wheels which makes them turn freely, making the planets turn freely and the ring not being driven, so the carriers wins the race to drive the wheel. One last factoid: the ring cog sits on the smallest of the planet sets (with the biggest sun cog) which when locked makes the biggest gear (4 and 8). Locking the smallest sun cog, gives the smallest (non-direct) gear (2 and 6). The jump from direct drive to this gear is the biggest in the entire hub (22% compared to just 14% from gear 3 to 4). I think the reason for this is that the sun cog can't become much smaller than it already is because the ratched mechanism for locking it still needs to fit inside. (And the solid hub axle is still inside the ratched mechanism.)
I actually disassembled the hub one step further than the manual explains. I only figured this out by accident after removing one more stop ring (shown on the right in the very first picture) when suddenly the shafts holding the planets of the second stage fell out of the carrier. When I tried to make them all fall out, the shafts holding the first stage's planets also fell out from the same holes! :-D After taking out the first stage planets, the ring cog from the second stage could be removed since it was only held by the planets and then the planets from the second stage could be removed. The sun cogs are still inside the carrier. I can see and feel another stop ring inside them, but didn't try to take it out. I instead just counted the sun cogs teeth by marking one tooth and then turning the cog until the marked tooth came up again. It's really interesting how some parts are purposely held by stop rings while others (such as the second stage ring gear) are just floating on other parts (second stage planets) and held sideways by again other parts (first stage planets). I am a bit curious whether I could put that part back together again. Maybe some day... ;-)
Here's my calculations again for those who I made curious. I've already got a follow-up post in my head in which I'll explain the formula that the spreadsheet is using.
Sources:
Finally, let's look at the second stage which as I said is driven by the carrier and transfers its motion to the hub shell (and thus the wheel (and thus the road (and thus the earth, which makes is turn))) via the ring gear or (if in direct drive) via the carrier. Both ring and carrier connect to the hub shell via a freewheel so that the faster one will be driving while the other will be in fallback mode. Interestingly, direct gear (1 and 5) is achieved by locking none of the sun wheels which makes them turn freely, making the planets turn freely and the ring not being driven, so the carriers wins the race to drive the wheel. One last factoid: the ring cog sits on the smallest of the planet sets (with the biggest sun cog) which when locked makes the biggest gear (4 and 8). Locking the smallest sun cog, gives the smallest (non-direct) gear (2 and 6). The jump from direct drive to this gear is the biggest in the entire hub (22% compared to just 14% from gear 3 to 4). I think the reason for this is that the sun cog can't become much smaller than it already is because the ratched mechanism for locking it still needs to fit inside. (And the solid hub axle is still inside the ratched mechanism.)
I actually disassembled the hub one step further than the manual explains. I only figured this out by accident after removing one more stop ring (shown on the right in the very first picture) when suddenly the shafts holding the planets of the second stage fell out of the carrier. When I tried to make them all fall out, the shafts holding the first stage's planets also fell out from the same holes! :-D After taking out the first stage planets, the ring cog from the second stage could be removed since it was only held by the planets and then the planets from the second stage could be removed. The sun cogs are still inside the carrier. I can see and feel another stop ring inside them, but didn't try to take it out. I instead just counted the sun cogs teeth by marking one tooth and then turning the cog until the marked tooth came up again. It's really interesting how some parts are purposely held by stop rings while others (such as the second stage ring gear) are just floating on other parts (second stage planets) and held sideways by again other parts (first stage planets). I am a bit curious whether I could put that part back together again. Maybe some day... ;-)
Here's my calculations again for those who I made curious. I've already got a follow-up post in my head in which I'll explain the formula that the spreadsheet is using.
Sources:
- Shimano service manual (PDF)
- Same manual in German (pictures are better)
- Inter-8 how it works with tables and pictures. (German)
- List of gear ratios for popular hub gears
Misused Mock Objects
During the past year at work, I had trouble with mock objects several times. Often tests would break because the mocks were hard to program or to change. In one case, we missed a critical bug because our mock differed significantly from the real implementation.
Since I didn't have any experience with mocking, I didn't know how to improve any tests towards a best practice solution. I found a lot of code smells, but only for a few of them, did I know how to actually make it better. At one point I thought that mocks were more trouble than they're worth.
Fortunately, I also had some good experience with mocks during this year, which led me to the conclusion that in the bad cases, mocks were just badly used. Thinking about it now, some of the tests that I had to deal with seemed to be written under the motto: “Mock everything but the class you want to test.” Thinking about it, a much better motto would be: “Test every component in an environment that is as production-like as possible and mock only if there is a good reason to do so.” In fact, Wikipedia says the same and even lists valid reason for mocking. The valid reasons I personally experienced are the following: speed and simulating rare behavior. There are many instances where we mocked for speed: using an in-memory database instead of a remote one or stubbing calls to remote services. The rare behavior that we simulated was when testing handling of network errors. Instead of simulating real network errors (plugin out cables or intercepting packet traffic??) we just stubbed the interface that does the networking and let it throw a SocketException. That's a perfectly valid reason to use a mock!
While reading the Wikipedia article I noticed the words “indirect input” and “indirect output” of objects under test. This made me think that some uses of mocks might just be needed because of a bad software design. Before taking out the mocking framework, shouldn't we check if the code can be written with direct input and output? For small functionality, input is just method parameters and output is the method result. For bigger functionality, input is given via setters or constructor parameters and output again is the result of the method under test or getter methods called later. For even bigger functionality, some of the input (or context) will be supplied in the form of other objects that first have to be constructed. When there's lots of those objects, tests will obviously not just span the object under test, but also the classes of those other objects. Maybe you think that's too big for a unit test, but I think it's just fine for a big unit test. If those other classes have complex behaviors they will have their own unit tests that will have ran green every time before the bigger test runs. So we don't risk to test too much at once, since the lower layer of the application is already tested.
Since I didn't have any experience with mocking, I didn't know how to improve any tests towards a best practice solution. I found a lot of code smells, but only for a few of them, did I know how to actually make it better. At one point I thought that mocks were more trouble than they're worth.
Fortunately, I also had some good experience with mocks during this year, which led me to the conclusion that in the bad cases, mocks were just badly used. Thinking about it now, some of the tests that I had to deal with seemed to be written under the motto: “Mock everything but the class you want to test.” Thinking about it, a much better motto would be: “Test every component in an environment that is as production-like as possible and mock only if there is a good reason to do so.” In fact, Wikipedia says the same and even lists valid reason for mocking. The valid reasons I personally experienced are the following: speed and simulating rare behavior. There are many instances where we mocked for speed: using an in-memory database instead of a remote one or stubbing calls to remote services. The rare behavior that we simulated was when testing handling of network errors. Instead of simulating real network errors (plugin out cables or intercepting packet traffic??) we just stubbed the interface that does the networking and let it throw a SocketException. That's a perfectly valid reason to use a mock!
While reading the Wikipedia article I noticed the words “indirect input” and “indirect output” of objects under test. This made me think that some uses of mocks might just be needed because of a bad software design. Before taking out the mocking framework, shouldn't we check if the code can be written with direct input and output? For small functionality, input is just method parameters and output is the method result. For bigger functionality, input is given via setters or constructor parameters and output again is the result of the method under test or getter methods called later. For even bigger functionality, some of the input (or context) will be supplied in the form of other objects that first have to be constructed. When there's lots of those objects, tests will obviously not just span the object under test, but also the classes of those other objects. Maybe you think that's too big for a unit test, but I think it's just fine for a big unit test. If those other classes have complex behaviors they will have their own unit tests that will have ran green every time before the bigger test runs. So we don't risk to test too much at once, since the lower layer of the application is already tested.
22 April 2012
Modern Milk Making
When my dad grew up, my grand parents had their own cows at the farm. Every morning, grandma would milk the cows in the early morning and bring the milk to the village's cooling/collecting house. But she'd always keep one big can of milk for the family themselves and when my dad had his milk for breakfast it was still warm as it came from the cow.
I think that's why when I grew up, my family had the habit of heating our store-bought milk for breakfast so we could drink it warm. Most people are surprised by my habit of drinking warm milk since for them the natural state of milk is cold since it comes from the fridge.
Back then when my dad grew up, cow milk was a relatively natural product. Cows were fed mostly grass and hay while their dung – the natural byproduct of making cow's milk – was put back on the fields as a natural fertilizer. (Even better, when the cows grazed outside, their shit would just drop, stay where it landed and do good to the soil.)
In our days, things for the cows and the milk look quite different. The cows are fed less grass and more grains and soy, which is cheaper, but isn't good to their stomachs and causes sicknesses. Plant agriculture relies on cheap and more effective artificial fertilizer so the cow dung becomes waste. Since cows are now held in very small inside spaces the dung is very concentrated and becomes an environmentally damaging toxic, especially for small rivers and creeks into which some of the disposed dung might drizzle through the ground.
In our days the population of the earth is about 500 times higher than when agriculture was invented (now 7 billion, then 15 million). Planet earth, however, is still the same size as back then! In order to support this huge human population, agriculture and food need to become vastly more efficient. To make a liter of soy milk, I use about 100g of soy beans and about one-and-a-half liters of water. Besides the soy milk, I get about one cup of by-product (okara), which is a great food stuff to be used in a variety of dishes (or mixed with sugar or chocolate powder to be eaten like porridge). The dairy factory uses about 2kg of cow feed (often also soy beans) and 10 liters of water per liter of milk just to feed the lactating cows. That's already 20 times more plant material needed for the same amount of milk! Add to this all the food and water needed to raise the cow until milk-producing age plus all the chemicals and medicines needed for the cows. And with the cow milk, comes the toxic concentrated cow shit. While making better use of the plants and animals that we use for nutrition and industrial purposes, we don't want to poison the remaining ecosphere – plants and animals that we don't use (yet). So what are we to do?
To many people who are used to cow's milk, soy milk might seem like an artificial replacement for a natural product. But as we have seen, contemporary milk production in dairy factories is far from being anything like natural. The so called “factory farms” are certainly more factory than they are farm! Maybe you'll think that soy milk on the other hand, most certainly comes from a factory? While that's obviously true, we have to consider that soy milk production in a factory is not very different from how you would do it at home or, for that matter, how it is traditionally done for thousands of years in China. Additionally cow's milk has a lot of unhealthy saturated fats, while soy milk has more healthy unsaturated fats, including some of the essential fats that the human body cannot make itself and needs to get from food. Seen from that angle, isn't it just smart to be inspired by food production techniques from all the different human cultures when creating the diet of a future humanity of maybe 10 billion or more people?
Soy milk making is a simple process of soak, puree, boil, and filter. I do it at home several times per week and use a specialized pureeing-boiling machine for the two most messy steps.
When I drink my fresh-cooked soy milk in the morning, which is still hot from the machine, I feel a strong connection to the presumed natural life of my grand-parents who drank cow's milk still warm from the udder. So in a way, even though I don't live on a farm, and even though I am surrounded by a wagon-load of high-techy things, I still feel a connection to nature by making my own delicious, hot, and healthy milk in a way that respects the environment and is able to scale up to the other 7 billion (and counting) people on the planet.
Some interesting reads and sources:
I think that's why when I grew up, my family had the habit of heating our store-bought milk for breakfast so we could drink it warm. Most people are surprised by my habit of drinking warm milk since for them the natural state of milk is cold since it comes from the fridge.
Back then when my dad grew up, cow milk was a relatively natural product. Cows were fed mostly grass and hay while their dung – the natural byproduct of making cow's milk – was put back on the fields as a natural fertilizer. (Even better, when the cows grazed outside, their shit would just drop, stay where it landed and do good to the soil.)
In our days, things for the cows and the milk look quite different. The cows are fed less grass and more grains and soy, which is cheaper, but isn't good to their stomachs and causes sicknesses. Plant agriculture relies on cheap and more effective artificial fertilizer so the cow dung becomes waste. Since cows are now held in very small inside spaces the dung is very concentrated and becomes an environmentally damaging toxic, especially for small rivers and creeks into which some of the disposed dung might drizzle through the ground.
In our days the population of the earth is about 500 times higher than when agriculture was invented (now 7 billion, then 15 million). Planet earth, however, is still the same size as back then! In order to support this huge human population, agriculture and food need to become vastly more efficient. To make a liter of soy milk, I use about 100g of soy beans and about one-and-a-half liters of water. Besides the soy milk, I get about one cup of by-product (okara), which is a great food stuff to be used in a variety of dishes (or mixed with sugar or chocolate powder to be eaten like porridge). The dairy factory uses about 2kg of cow feed (often also soy beans) and 10 liters of water per liter of milk just to feed the lactating cows. That's already 20 times more plant material needed for the same amount of milk! Add to this all the food and water needed to raise the cow until milk-producing age plus all the chemicals and medicines needed for the cows. And with the cow milk, comes the toxic concentrated cow shit. While making better use of the plants and animals that we use for nutrition and industrial purposes, we don't want to poison the remaining ecosphere – plants and animals that we don't use (yet). So what are we to do?
To many people who are used to cow's milk, soy milk might seem like an artificial replacement for a natural product. But as we have seen, contemporary milk production in dairy factories is far from being anything like natural. The so called “factory farms” are certainly more factory than they are farm! Maybe you'll think that soy milk on the other hand, most certainly comes from a factory? While that's obviously true, we have to consider that soy milk production in a factory is not very different from how you would do it at home or, for that matter, how it is traditionally done for thousands of years in China. Additionally cow's milk has a lot of unhealthy saturated fats, while soy milk has more healthy unsaturated fats, including some of the essential fats that the human body cannot make itself and needs to get from food. Seen from that angle, isn't it just smart to be inspired by food production techniques from all the different human cultures when creating the diet of a future humanity of maybe 10 billion or more people?
Soy milk making is a simple process of soak, puree, boil, and filter. I do it at home several times per week and use a specialized pureeing-boiling machine for the two most messy steps.
When I drink my fresh-cooked soy milk in the morning, which is still hot from the machine, I feel a strong connection to the presumed natural life of my grand-parents who drank cow's milk still warm from the udder. So in a way, even though I don't live on a farm, and even though I am surrounded by a wagon-load of high-techy things, I still feel a connection to nature by making my own delicious, hot, and healthy milk in a way that respects the environment and is able to scale up to the other 7 billion (and counting) people on the planet.
Some interesting reads and sources:
- What are cows fed?
- How much does a cow eat?
- Information on factory farming is from the book Eating Animals (I like this quote: “Have a conversation with the people who produce your food. If you aren't allowed to see where your food comes from, you probably shouldn't be eating it.”)
- How to Make Soy Milk at Home (I use a simple metal strainer for filtering instead of a cheesecloth, because that's easier to clean. ;)
PS: I am going to add some really good photos here to relate past and present of my family heritage. It needs a while to find them!
21 April 2012
Metamorphosis of a milk junkie
Ever since I can remember up until not long ago, I used to drink two cups of cow milk every morning for breakfast. Besides that baseline of half a liter a day, I used about one to two additional liters a week for cooking (porridge, for instance) and baking. That was so much milk, that I'd instantly identify with a T-Shirt a friend once found for me and that read "milk junkie" in big letters. (“Milch” is German for milk).
Several years ago I discovered soy milk as an alternative option and I started to replace some of my cow milk consumption by soy milk, since I thought that it must generally be healthier to eat and drink a variety of stuffs instead of just the same every day. When I started to be interested in vegetarianism and veganism I increased the amount of soy milk (and rice milk and other plant milks) and had proportionally less cow milk. Until one day about a year ago, I realized that I didn't want to have any animal milk or dairy product any more and completely stopped drinking cow milk at all. (I didn't completely go vegan at that point, in fact, I am still not vegan now, since I occasionally eat products that contain dairy when I eat out. I find it's just not worth it to avoid all this stuff just to be 100% vegan.)
But that's not the end of my personal milk story. After getting rid of cow milk, I quickly got bored of the plant milks and wouldn't regularly drink my two cups each morning. Sometimes I instead just had tea or plain water or more recently I have a big home-made smoothie about every other day. To me, one big advantage of soy milk was that I could cook or bake any non-vegan recipe and make it vegan just by replacing animal milk with soy milk. (Also easy to replace the eggs, but even easier to simply google for vegan recipes so you don't bother about replacements.)
Now, two weeks ago, I purchased my personal soy milk making machine and that has brought a surprising insight and further change to my milky habits. When making four cups of soy milk, there's about one cup of okara left-over from the beans and I am trying to use all of it. I really like the idea of not wasting anything edible and nutritious and it also fits great with the nutritarian principle of eating whole foods instead of refined foods. Soy milk is clearly a refined food, because the okara is thrown away. Now, by eating the okara (even if it's in another dish), I do in fact consume the entire soy bean. That really seems like a good idea to me!
Still all that much soy consumption gives me the feeling that my diet gets a bit monotonous. To mitigate this I am occasionally making some almond milk with my machine. But a really surprising change occurred to me just today: a very simple way to use all the okara (and produce less okara at the same time!) is to use okara as a milk replacement in recipes! Since I am making soy milk at home I prefer to drink it directly when it's still hot, instead of cooling it, keeping it, and putting it in recipes. Smoothies and porridge also taste fine with water in place of soymilk. (Note that I always have my porridge with a big fruit salad that gives much of the taste!) And what's even better is that porridge cooked with water instead of milk is much less prone to boiling out of the pot or stick to the bottom of the pot! Now, my latest trick is to use okara in all those places! Add a bit to the smoothie. Add a bit to the porridge (after cooking, since okara is already cooked). Put it into cakes. Put it into casseroles (soufflés). I really like this a lot! Since I don't need to use soy milk any more for those purposes, I am eating less monotonous, and since I put in the okara that comes with the soy milk, I am eating much more whole. Killed two birds with one stone!
Welcome new whole foods, plant-based, highly diverse diet!
Several years ago I discovered soy milk as an alternative option and I started to replace some of my cow milk consumption by soy milk, since I thought that it must generally be healthier to eat and drink a variety of stuffs instead of just the same every day. When I started to be interested in vegetarianism and veganism I increased the amount of soy milk (and rice milk and other plant milks) and had proportionally less cow milk. Until one day about a year ago, I realized that I didn't want to have any animal milk or dairy product any more and completely stopped drinking cow milk at all. (I didn't completely go vegan at that point, in fact, I am still not vegan now, since I occasionally eat products that contain dairy when I eat out. I find it's just not worth it to avoid all this stuff just to be 100% vegan.)
But that's not the end of my personal milk story. After getting rid of cow milk, I quickly got bored of the plant milks and wouldn't regularly drink my two cups each morning. Sometimes I instead just had tea or plain water or more recently I have a big home-made smoothie about every other day. To me, one big advantage of soy milk was that I could cook or bake any non-vegan recipe and make it vegan just by replacing animal milk with soy milk. (Also easy to replace the eggs, but even easier to simply google for vegan recipes so you don't bother about replacements.)
I made one liter of soy milk and kept it warm in the thermos while putting about a third of the side-produced okara into my chocolate-whole-grain-porridge. |
Still all that much soy consumption gives me the feeling that my diet gets a bit monotonous. To mitigate this I am occasionally making some almond milk with my machine. But a really surprising change occurred to me just today: a very simple way to use all the okara (and produce less okara at the same time!) is to use okara as a milk replacement in recipes! Since I am making soy milk at home I prefer to drink it directly when it's still hot, instead of cooling it, keeping it, and putting it in recipes. Smoothies and porridge also taste fine with water in place of soymilk. (Note that I always have my porridge with a big fruit salad that gives much of the taste!) And what's even better is that porridge cooked with water instead of milk is much less prone to boiling out of the pot or stick to the bottom of the pot! Now, my latest trick is to use okara in all those places! Add a bit to the smoothie. Add a bit to the porridge (after cooking, since okara is already cooked). Put it into cakes. Put it into casseroles (soufflés). I really like this a lot! Since I don't need to use soy milk any more for those purposes, I am eating less monotonous, and since I put in the okara that comes with the soy milk, I am eating much more whole. Killed two birds with one stone!
“crazy monkey cake” named thus for the three mashed bananas it contains. |
“ok carrot cake” named thus for the okara and the simplicity of the made-up recipe. |
Welcome new whole foods, plant-based, highly diverse diet!
14 April 2012
Probefahrt Tern Eclipse
Nachdem ich die Tern Falträder schon auf der letzten Eurobike bestaunt hatte (ohne viel anfassen) und seit dem immer gern wieder im Internet ihre Fotos angeschaut, war es Heute endlich so weit und ich fuhr mit der S-Bahn zu Adams Bikeshop in Lichtenrade (Süd-Berlin), um mir die Räder genauer anzuschauen. Der Laden ist ein offizieller Tern Pro Shop und hatte wirklich fast alle Räder da. Am meisten beschäftigt habe ich mich mit dem Eclipse P7i, eine kürzere Probefahrte gemacht habe ich mit dem Link P9 und alle anderen Modelle habe ich mir in Ruhe angeschaut.
Auf das Eclipse bin ich gekommen, weil ich mich in diesem Winter an eine völlig aufrechte Sitzposition gewöhnt habe und mir für nächsten Winter ein Fahrrad wünsche, die mir diese bietet, ohne dass die Lenkstange zu lang wird. Bei meinem Speedy bin ich diesen Winter so gefahren, aber die Last, die sich am unteren Ende der Stange auf das Gabelrohr überträgt, scheint mir einfach zu groß, und so traue ich mich schon gar nicht mehr scharf zu bremsen. Beim Eclipse gibt es das Problem durch den höheren Rahmen nicht und man kann deutlich sehen, dass die Lenkstange kürzer ist, und trotzdem kann man den verstellbaren Vorbau auch auf eine völlig aufrechte Sitzposition einstellen.
Im Gegensatz zu meinen geliebten 20" Falträdern (406 mm Felge) erscheint mir das Eclipse (507 mm Felge) schon fast riesig. Mit den fetten Reifen (50 mm Big Apple) erreichen die Laufräder schon fast die Höhe von 26 Zoll (559 mm) Modellen mit sehr dünnen Reifen. Das gefaltet Paket soll laut Hersteller kaum größer sein als ein gefaltetes 20" Modell, aber mir erscheint das Paket wirklich riesig. Man kann es zwar problemlos tragen, aber beim Verstauen (gerade im Auto oder Öffi) braucht es eben doch wieder etwas mehr Platz.
Was mir am Eclipse gefiel:
Auf das Eclipse bin ich gekommen, weil ich mich in diesem Winter an eine völlig aufrechte Sitzposition gewöhnt habe und mir für nächsten Winter ein Fahrrad wünsche, die mir diese bietet, ohne dass die Lenkstange zu lang wird. Bei meinem Speedy bin ich diesen Winter so gefahren, aber die Last, die sich am unteren Ende der Stange auf das Gabelrohr überträgt, scheint mir einfach zu groß, und so traue ich mich schon gar nicht mehr scharf zu bremsen. Beim Eclipse gibt es das Problem durch den höheren Rahmen nicht und man kann deutlich sehen, dass die Lenkstange kürzer ist, und trotzdem kann man den verstellbaren Vorbau auch auf eine völlig aufrechte Sitzposition einstellen.
Lenker ganz hochgestellt und Sattel auf meine 1,86 m, sieht Eclipse fast aus wie ein "großes" Fahrrad und fährt sich auch schön aufrecht. |
Kann man so prima am Sattel schieben. (Lenker kann man noch kleiner falten.) |
Was mir am Eclipse gefiel:
- größter Vorteil gegenüber den meisten Dahon-Velos ist meiner Meinung nach der verstellbare Vorbau. Er ist leichter zu bedienen als die Teleskop-Lenkstange, sieht schöner aus, und das Verstellen per Drehung auch nach vorn/hinten ist besser als nur rauf und runter! Dieses Teil allein macht schon sehr viel Komfort aus! Schade nur, dass die meisten (preisgünstigen, aber auch Mittelklasse) Tern-Modelle nur einen ganz einfachen Lenker haben, den man überhaupt nicht verstellen kann.
- die Nexus Inter-7 Schaltung funktionierte im Test gut und schaltet auch, wenn man nicht komplett mit Treten aufhört. Da es in Lichtenrade keine Berge gibt, konnte ich die kleinen Gänge nicht realistisch testen, aber der größte Gang war hoch genug, um richtig schnell zu fahren.
- der Gepäckträger kann gleichzeitig normale Packtaschen an die Seiten hängen und einen Korb oder weitere Tasche (per Klickfix-System) obenauf. Außerdem gibt's natürlich noch einen Spanngummi dazu, damit auch mal eben so, was drauf festklemmen kann.
- Falten funktioniert prima. Die Achsmuttern von Vorder- und Hinterrad liegen gefaltet leicht versetzt, so dass das Velo nicht noch breiter faltet als es eh' schon tut. Der gefaltete Lenker wird durch ein unten am Rahmen verstecktes Gummi-Gürtelchen festgehalten.
- Den Sattel kann man viel höher stellen als bei den 20" Modellen, so dass ich auch meine Beine ausstrecken kann und trotzdem noch ca. 9 cm Reserve habe. Also sollte es führ Fahrer bis ca. 2 m Höhe reichen!
- Das ganze Velo ist leise. Ausnahme: der komische Kabelschlauch-Kettenschutz, aber der macht auch nicht mehr Krach als ein Hebie.
- Steuersatz war leichtgängig (im Gegensatz zu meinem Mµ Uno!) und hatte kein Spiel.
- und wie schon gesagt, der Rahmen erlaubt auch eine völlig aufrechte Sitzposition, ohne dass man Gabelschaftbruch fürchten muss.
Kabelkurv und -quetsch |
Was mir nicht gefiel:
- Die Beleuchtung konnte ich leider nicht testen, aber die Kabelführung fand ich echt beschissen und das Rücklicht hat nicht mal ein Kabel. Trotz Dynamo wird es irgendwann einfach aufhören zu leuchten und wird nicht wieder leuchten, bis man eine neue Batterie beschafft hat. Im gefalteten Zustand hat das vordere Lichtkabel sogar den Fauxpas begangen eine Schlaufe zu bilden, in der man beim Tragen oder herumstehen sehr leicht etwas verfangen kann und damit das Kabel abreißen...
- Gleich weiter zu den Brems- und Schalt-Kabeln: die werden beim Falten des Lenkers fast eingeklemmt und das Brems-Kabel fährt beim Falten auch eine sehr enge Kurve. Nicht gut!
- Typische Fabrikvelo-Montagefehler: Die vordere Bremse hat etwas geschleift (auch das Rad war nicht perfekt zentriert). Entweder der Lenker in der Gabel oder das Schutzblech war leicht schief, so dass ich immer den Eindruck hatte, irgendwas stimmt nicht. Beim Link P9 gingen die Bremsen besser, aber die Schaltung war nicht richtig eingestellt.
- Das Link P9 fuhr sich übrigens auch prima, aber die Falt-Pedale sind total lächerlich wackelig und scheinen billiger als die bekannten Suntours an den billigeren Modellen.
Noch ein schönes Detail: sehr ästhetisch und anfassbar geformter Hebel der Lenkerverstellung. |
Es war schon sehr interessant die beiden Velos auszprobieren und auch gut, im Laden mit den anderen Modellen zu vergleichen. Aber danach habe ich doch gemerkt, wie gut sich eigentlich mein Speedy nach sechs Jahren und 10'000 km noch fährt! Wenn ich nur weiter gut in Schuss halte, dann wird er sicher noch ein paar Tausend km mehr fahren. Direkt vor dem Laden habe ich auch Speedys Lenkvorbau wieder umgedreht und etwas tiefer gestellt, sozusagen auf Sommer zurück gestellt, so dass ich mich jetzt nicht mehr ganz so sehr um Gabelschaftrohrbruch fürchten muss, wie im Winter-Modus. Und bis zum nächsten Winter ist ja noch viel, sehr viel, Zeit!
Nachtrag: da ich ja einen Ersatz für meinen im Velowerk gebauten Speedy suche, hatte ich auch überlegt, mir den Ersatz auf Eclipse-Basis auch wieder im Velowerk bauen zu lassen. Über Nacht habe ich mal nachgedacht, ob ich es mir auch selbst bauen könnte. Also Fabrik-Eclipse reparieren/umbauen oder auf Basis eines Rahmensatzes bauen. Hier die Dinge, die ich selbst könnte:
Nachtrag: da ich ja einen Ersatz für meinen im Velowerk gebauten Speedy suche, hatte ich auch überlegt, mir den Ersatz auf Eclipse-Basis auch wieder im Velowerk bauen zu lassen. Über Nacht habe ich mal nachgedacht, ob ich es mir auch selbst bauen könnte. Also Fabrik-Eclipse reparieren/umbauen oder auf Basis eines Rahmensatzes bauen. Hier die Dinge, die ich selbst könnte:
- Laufräder nachzentrieren oder neu bauen (mein Hobby, haha)
- Elektrische Verkabelung und bessere Leuchten
- Schaltung, Bremsen nachstellen. Kleinteilmontage korrigieren.
- Bessere Faltpedale anbauen
- Ggf. Übersetzung anpassen
- Ggf. Gepäckträger, Sattel oder Lenker austauschen.
Zum Unterschied "Fabrikvelo umbauen" versus "ab Rahmenkit neu bauen" könnte ich jetzt auch einiges sagen. Mit James Bold (meinem immer noch unfertigen Mµ Uno) habe ich die Erfahrung ja gemacht und kann sagen: es war gut, dass das Velo auch vor dem Umbau schon fahrfertig war und ich Stück um Stück verbessern konnte. Schlecht war, dass sich für viele Komponenten der Umtausch nicht lohnte, weil mein die alten Teile übrig hat. (Beim Eclipse P7i würde ich z.B. die Inter 7 Nabe behalten, obwohl ich für ein neues Velo eine Inter 8 mit Nadellagerung verwenden würde.) Außerdem ist Mr. Bold gerade außer Betrieb weil dem Fabrik-Hinterrad Speichen brachen, was bei einem von Anfang an selbst gebauten Velo wohl nicht passieren würde.
Velowerk-Kabelbaum am speed werx. |
Und hier nur die Dinge, die ich nicht alleine tun kann, die aber Thomas vom Velowerk sehr gut kann:
- Bessere und nachschmierbare Tret- und Steuerlager; plangeschliffene Lagerflächen.
- Der geniale Velowerk Kabelbaum. (Mit jetzt noch verbesserter Kabelführung, von der es leider noch kein Foto gibt.)
- Hohlraumsiegel
- Spezielle Rahmen für Hinterbauständer und andere praktische Anbauteile.
- Überhaupt und allgemein vertrauenswürdige Komponenten, fachgerecht verbaut. Als Amateur kann ich ja gar nicht genug Velos bauen, um einen vergleichbaren Erfahrungsschatz aufzubauen, wie ein Profi.
31 March 2012
CRAP food
CRAP == calorie-rich and processed.
In fact, most food processing consists of taking away fiber and micro-nutrients and putting in more calories. I found this great diagram the other day which shows how much calories in the average US diet come from added fat and sugar:
However, for anybody who's regularly reading ingredient lists of food they buy, there is one other additive that makes it into virtually every item of processed food and also contains a big share of calories which very quickly get turned into sugar by your intestines. That third thing is starch, mostly in the form of refined wheat flour with ever more of that being replaced by corn starch recently. The nutritional value of starch is just as low as it is for sugar, and the sugar-high provided from starch is just as real as that from simple sugars, only that it's spread out a little more.
As you can see in the diagram, added fats make up the largest source of standard American Calories, but the close runner-up is "grains". Now –I thought– most of those grains are consumed as bread, pasta, pizza (dough), cake, pastries, (all made mostly of refined flour) and of course, lot's of starch added to almost any other food to make sauces more creamy or doughs stick together better. In other words: most of those "grains" are in fact just "added starch". Shouldn't that be reflected better in the diagram?
Fortunately the authors of that original post at Grist have provided a link to their source, the US Dep't of Agriculture, who in turn provide spreadsheets with all the detailed numbers. I guessed that about 60 to 90% of the "grain" bubble in the diagram could be labelled as "added starch". Thanks to the good scholarship of my sources, I could easily look it up! Here's a Google Docs Spreadsheet with the bubbles taken apart. While I was at it, I also broke up that weird protein bubble into animal foods and the poor nuts who don't deserve to live in that same group. Here's a diagram of the results:
You can look at the spreadsheet to see which food is grouped where. (Pedantics can check the formulas.) The actual ratio of "added starch" vs "healthy whole-grain" depends a bit on interpretation, but according to the data I think that about 80% added starch and refined flour made from all consumed grains is a fair guess. (Remember that most white breads, doughs, and pasta are 99% starch.) So this much belongs into the CRAP portion of the diagram, because starch and white flour are almost pure calories with little other nutrients. The remaining 20% of grains (and that includes pop corn, for example) goes to the healthy plant foods group.
Now, take one more look the diagram. See that large chunk of 60% calorie-rich and processed foods? Any doubts what the Americans mainly consume? Holy CRAP!
sources:
In fact, most food processing consists of taking away fiber and micro-nutrients and putting in more calories. I found this great diagram the other day which shows how much calories in the average US diet come from added fat and sugar:
However, for anybody who's regularly reading ingredient lists of food they buy, there is one other additive that makes it into virtually every item of processed food and also contains a big share of calories which very quickly get turned into sugar by your intestines. That third thing is starch, mostly in the form of refined wheat flour with ever more of that being replaced by corn starch recently. The nutritional value of starch is just as low as it is for sugar, and the sugar-high provided from starch is just as real as that from simple sugars, only that it's spread out a little more.
As you can see in the diagram, added fats make up the largest source of standard American Calories, but the close runner-up is "grains". Now –I thought– most of those grains are consumed as bread, pasta, pizza (dough), cake, pastries, (all made mostly of refined flour) and of course, lot's of starch added to almost any other food to make sauces more creamy or doughs stick together better. In other words: most of those "grains" are in fact just "added starch". Shouldn't that be reflected better in the diagram?
Fortunately the authors of that original post at Grist have provided a link to their source, the US Dep't of Agriculture, who in turn provide spreadsheets with all the detailed numbers. I guessed that about 60 to 90% of the "grain" bubble in the diagram could be labelled as "added starch". Thanks to the good scholarship of my sources, I could easily look it up! Here's a Google Docs Spreadsheet with the bubbles taken apart. While I was at it, I also broke up that weird protein bubble into animal foods and the poor nuts who don't deserve to live in that same group. Here's a diagram of the results:
You can look at the spreadsheet to see which food is grouped where. (Pedantics can check the formulas.) The actual ratio of "added starch" vs "healthy whole-grain" depends a bit on interpretation, but according to the data I think that about 80% added starch and refined flour made from all consumed grains is a fair guess. (Remember that most white breads, doughs, and pasta are 99% starch.) So this much belongs into the CRAP portion of the diagram, because starch and white flour are almost pure calories with little other nutrients. The remaining 20% of grains (and that includes pop corn, for example) goes to the healthy plant foods group.
Now, take one more look the diagram. See that large chunk of 60% calorie-rich and processed foods? Any doubts what the Americans mainly consume? Holy CRAP!
sources:
12 March 2012
Nutritarian diet in a nut shell
First of all, eat greens and beans.
On top of that, eat fruits and roots.
And last not least, eat nuts and seeds.
Divide your daily caloric intake about 60/35/5% in the first, second, and third group. Remember that the greens have very little calories per volume, so you'll need to eat a lot. Conversely, nuts and seeds are very dense in calories (especially fats), so you'll only need to sprinkle a few on your salad or blend them into a dressing.
Remember, unrefined plant foods (including mushrooms in the first group) are the only foods allowed, so there's no sugar, oil, or flour, or anything made of sugar, oil, or flour anywhere near allowed!
On top of that, eat fruits and roots.
And last not least, eat nuts and seeds.
Divide your daily caloric intake about 60/35/5% in the first, second, and third group. Remember that the greens have very little calories per volume, so you'll need to eat a lot. Conversely, nuts and seeds are very dense in calories (especially fats), so you'll only need to sprinkle a few on your salad or blend them into a dressing.
Remember, unrefined plant foods (including mushrooms in the first group) are the only foods allowed, so there's no sugar, oil, or flour, or anything made of sugar, oil, or flour anywhere near allowed!
10 March 2012
The food pyramid put on its proper base.
As a little kid I did quite well in school. I still remember many things I learned in class while I forgot about other school things which other people remember well. (For instance, I don't recognize old school mates even tho they remember me well.)
One thing I still remember from school is how healthy eating is supposed to be done. Here's the food pyramid as I was taught it in middle school:
One thing I still remember from school is how healthy eating is supposed to be done. Here's the food pyramid as I was taught it in middle school:
Just because I like pretty pictures, here's another one, without the labels:
Because I was so indoctrinated by school I always remembered this when planning my own groceries and meals. Additionally, the idea of having one starchy thing at the base (bread, pasta, or potatoes) was always reinforced by the meals that my family made or that I found in school dining halls, canteens, restaurants, and fast food places everywhere. Even when I went to the far east, the principle was just the same, only using rice at the base. (And of course also noodles, and steamed buns, and the famous bîng 饼.)
But as I grew more conscious about what I eat I found that the really interesting and most important stuff in a meal were really the vegetables. I felt the starches were always kind of the same and boring and what really gives you the most nutrients and also adds most of the flavor and character to a plate are all the other vegetables.
During the last months I grew more and more dissatisfied, upset, and in the later stages even angry with the fact that virtually all meals that one can buy outside have this huge starchy base and just not enough really nutritious (and delicious) veggies. Just think of a sandwich with just one leave of lettuce and slices from half a tomato. Or a pizza which is just a hot open sandwich that's still much more dough than veggies on top. Each time after having such a meal I would first feel full and tired (at work, this meant I needed coffee to not fall asleep!), then be fine for a short while, and then crash into a huge hunger (even greater than before I had eaten!) and sometimes accompanied with symptoms of low blood sugar. Maybe some readers know those shaky legs!?
For a while I avoided the problem by eating at the Asian fast food counter where the serving of veggies is big compared to the base of rice, but over time I also felt that there was still way too much white rice on the plate and also too few veggies. Sometimes I still needed coffee and wouldn't be satiated until the next meal time.
After my recent holidays in Taiwan where I enjoyed lots of great vegan kitchen, I had a big fallout with my Western diet – so bad that I called it my personal food crisis! Currently I am reading Joel Fuhrmans “Eat to Live” and find that my “dream food pyramid” is actually backed by science and medicine:
Something I just learned from the book and appreciated a lot to know is that leaf vegetables (like arugula, spinach, chard, broccoli, and kale) should actually be considered a separate group apart from other veggies because they are so rich in nutrients, especially micro-nutrients and natural fiber.
If you think that this pyramid seems weird and unnatural, then that's because the old one is just rooted so deeply in our culture. Dr. Fuhrman is not the only person that came up with this new food pyramid. Here are two other respectable sources: the University of Michigan and Dr. Dean Ornish (of TED fame) both promote a plant-based diet to promote health and avoid illness.
I'd like to write a lot more about what I learned from the book, and how it's just what I needed in my current crisis – but first I have to make another salad.
Minimal cooking for good health and meal variety -- a different veggie every day
Pumpkin soup, pumpkin pie, pumpkin bread, pumpkin spread, marinated pumpkin chunks -- there are over hundred different ways to prepare pumpkin, yet there's little prepared pumpkin available at restaurants and grocery stores. Of the top of my head I could name a few restaurants that have pumpkin soup and I've seem pumpkin puree on supermarket shelves, along with awfully sweet, unhealthy pumpkin pie.
So how do I get my healthy dose of pumpkin without spending too much time cooking?
Just make the simplest of pumpkin recipies (next to raw pumpkin): baked pumpkin parts.
So how do I get my healthy dose of pumpkin without spending too much time cooking?
Just make the simplest of pumpkin recipies (next to raw pumpkin): baked pumpkin parts.
I just took the seeds out and removed the fleshy parts, then they went into the oven on the same pan. The seeds will be crisps after five to ten minutes, much earlier than the pumpkin flesh, so they serve as a delicious appetizer while waiting for the main course. :-)
While eating, I found that the pumpkin flesh that was closer to the pan was much more moist and had more taste. While the upper part was good, too, I found it quite dry in comparison. So my plan for next time is to steam the pumpkin parts instead of frying them. I am already looking forward to trying that!
Subscribe to:
Posts (Atom)