“One of the differences between a great programmer and a bad programmer is that a great programmer adds logging and tools that make it easy to debug the program when things fail.” [reference below]
I’m sure you’ve experienced a good share of mystery/quiet/business-as-usual failures.
Wouldn’t it be nice to have code that is smart to detect error conditions and make it obvious?
There are many ways of doing the communication. Some are trivial and easy to do. Some require extra thinking. Some require that extra step — step which is not in acceptance criteria.
Logging is one. It falls under the “trivial and easy to do” category. I feel we’re not utilizing it to its full potential. I’ve seen many instances where error conditions are not visible in logs. When we debug issues everything works as expected. So it seems… Then what? We need to keep digging. We’ve got to turn into code and look for clues. It’s time consuming. It’s frustrating. Wouldn’t it be better if we got a clue from the log?
“When the program works as expected, there is often no difference in the quality of the logging. However, as soon as the program fails, or you get the wrong result, you can almost immediately tell the good programmers from the bad.” [same reference]
Exactly. Logging gets a bad rap. But it’s invaluable in situations like those. It’s a great lead in finding the underlying cause of the issue.
So think about those error conditions. Check that the object you’re working on is in a “correct” state and if not add a warning message. Those warning and debug statements serve as an excellent documentation tool! Think of them as live comments.
Most of our loggers are accessible via JMX. That means no restart is required to change a log level. Very convenient!
There is really no reason why all of us should not be utilizing logging.
Logging is just one way. There are other ways. Think of stats/counters/jmx/dashboards. These require that extra effort and thought but are critical in communicating the health of the system. And there are cases where logging might be excessive when we expect an error to happen frequently. It’d be better to 1) output a message about a fail rate once a minute or so and 2) have stats accessible via jmx/dashboard. That allows us to see if the feature we built is working as expected, but also monitor performance/usage/etc.
I’m sure there are other ways.
But the bottom line is that we shouldn’t just be asking “does it work?” but how am I going to debug it things don’t work? How is it going to respond to error conditions? How am I going to validate that it actually does work?
If you learn to write debuggable code there are a few things that will happen.
1) You will become a better programmer
You’ll start thinking of the end result. You’ll cover the edge cases and “share” those unexpected values/conditions. You’ll be delivering smarter and friendlier code.
2) You’ll reap the benefits when debugging issues
It’ll happen. It’ll happen sooner than you think. And you’ll be thankful that you or somebody else took the extra care and added those debug statements/stats/etc.
Writing debuggable code takes effort and skill. But those extra steps, that extra effort is what distinguishes the good from the best.
Great Programmers Write Debuggable Code
I am a TDD fan. I’ve been one for a long time.
But I’m not a TDD practitioner. I don’t follow the TDD methodology of writing the test first, implementation second.
Uncle Bob convinced me to try. Again.
Time to become a TDD developer! Time to step up my code quality.
I have said it many times, Robert Martin, Uncle Bob, is someone who has had a big influence on my career (you can find other references on this site). I usually buy all his books. His latest one, The Clean Coder, is not only a joy to read, it’s filled with great advice. It’s like reading The Pragmatic Programmers again. Who doesn’t want that?
Let’s get to the point, though. Why would I ever want to follow TDD? Isn’t that counterproductive, and… silly!
Do I want to write higher quality code? Faster? Less buggy? And get more fun out of it?
But I’ve tried before. And reverted to old ways of doing it.
This time, I want to infect myself with it.
How? By trying harder. By making this “my way” of doing things. And by actually writing the tests first.
It’s going to take more effort than that!
Today I got an opportunity to do just that. And I am surprised how I was able to kill a few bugs. Bugs that would have “bugged” me later.
But why write the tests first?
So I develop good coverage. So I design better. So I get instant feedback. Those are 3 very good reasons. Not only that, but by first thinking about the tests, I will cover more corner cases; I will make my code testable.
Do I really need more convincing?
Not really. Benefits are clear. It’s just a matter of “doing” it.
Lastly, to give some direction and insight on how to proceed, here are the three laws of TDD as per Bob.
The Three Laws of TDD
1) You are not allowed to write any production code until you have first written a failing unit test.
2) You are not allowed to write more of a unit test than is sufficient to fail—and not compiling is failing.
3) You are not allowed to write more production code that is sufficient to pass the currently failing unit test.
Martin, Robert C. (2011). The Clean Coder
Ready to join the TDD camp?
While looking at the top weekly links on dzone (good way to see what are the important things that happened), I came across a very intriguing entry: The Top 10 Attributes of a Great Programmer by Steve Riley.
These always “get me,” but a lot of times they end up being just a quick browse. This one is different. Though the attributes are similar to what I”ve seen before (see entries in Craftsmanship category), they’re good. And it’s always good to re-read them.
Here are the top 10 form the blog. Read the whole post as the author gives his own explanations. My thoughts are below.
- Being a great problem solver.
- Being driven and lazy at the same time.
- Ability to understand other people’s code
- Having a passion for programming
- Loving learning for the sake of learning
- Being good at math
- Having good communications skills
- Strong debating skills
- Extreme optimism
- Extreme pessimism
Being a good problem solver? Of course! Great programmers are great problem solvers. Agreed!
Being driven and lazy. I keep telling my wife that being lazy is a good think. She doesn’t get it! But I agree that being lazy is a good quality to have in programming.
Ability to understand other people’s code. Somewhat agree. Is it just me, though, but I see a ton of code that I’m having very hard time following! I would say it differently: great programmers write code that others can understand; great programmers write code for humans to read.
If you don’t have a passion for programming… can you excel in any other profession if you don’t have passion!?
Everybody needs to learn and work hard to get better. That’s why great programmers go the less traveled road.
Being good at math? Debatable. I think there is a connection, but wouldn’t pay that much attention to it. But yeah, I was good in math.
All in all, a good post by Steve.
Uncle Bob in Clean Code states, “the Boy Scout Rule tells us we should leave the code cleaner than we found it.” Another words, when we make changes to the code base, we should make sure we are leaving it (checking in to repository) cleaner.
The original rule of the Boy Scouts states: “Leave the campground cleaner than you found it.”
This is very relevant to the way we code!
Following this rule is not easy. In some cases it might not even be possible (most likely not a good sign).
Why isn’t it easy?
When I code, I try to follow similar, but fundamentally different rule: don’t make the code base worse than you found it. Worse, not necessarily better. Following this rule is not easy either. It means I have to get a good understanding of the code before I make a change. It means I don’t try to put in a quick fix or a hack, add special exceptions (wouldn’t it be easy to just add a simple “if” statement).
It all starts with one broken window, as the theory of a broken window tells us.
The Boy Scout rule takes it a step forward. It requires you to not only understand the code, but improve it before you check your code in. Just the other day, I saw something that smelled. It had a lot of duplication. My task was to add something similar. Since code was already written, somewhat complicated, I went with the easy route. I followed the same route: I added more duplication! I didn’t necessarily make the code base worse, as it’s already been like that. But I didn’t make it better either.
I did not follow the Boy Scout rule.
If I did, I would have taken the time to refactor the code, generalize it, and make it reusable. I would have removed the duplication and made it easier to modify later on. Read: I would leave it better than I found it.
I’m already feeling resistance. I’m thinking about situations where it might not be possible to follow the Boy Scout rule.
Resistance is good. It means that I have some growing to do. It means that following this rule is…
Yes, it’s going to be a challenge. But the reward is there. Making improvements to the system you’re working on is a reward on its own. Talking about this in an interview should also get me extra points. But most of all, following the Boy Scout rule will make me work harder. It will make me a better programmer.
No matter who. No matter what. No matter when. Short term.Long term. Any term. Writing good code is ALWAYS faster than writing bad code.
—Robert Martin (@UncleBob)
Is it because of pressure?
Is it because you want to be faster than others?
Or is it just because that’s the way you’ve been doing things and it has worked for you?
I hope it’s not the case. I hope you take the time to do it right. Because if not, as the saying goes, will you have the time to do it over? Or how will you look at it when you see the project codebase turning into spaghetti. Because it will.
I wish it was so clear cut. It’s usually not.
But I do believe in the theory of broken windows. One little “slack,” one not needed “if” statement starts this process. And then it goes downhill. It’s just a matter of time before somebody else puts another if. And another. Soon enough, you start searching where things have broken. It’s no longer easy to fix stuff. So you put another conditional.
That’s how things degenerate.
I’ve seen it many times in my career.
But I try to do it right. I think about consequences of my actions. Consequences of putting one line of code that will make things worse for others, worse for the codebase.
I take pride and always try to leave things in no worse condition when I found it. If I can, I try to make it better. I don’t always succeed. But I try to adjust. Learn. And always have “do it right” attitude. I think it matters.
If we had more people that cared about the quality, our dev world would be a better place.
Write Your Good Code First – blog post by James Sugrue and Uncle Bob’s quote that I found there that gave me motivation to write this post.
A few years ago, Cedric Beust, had a blog entry with the same title. I saved it. Here’s a summary of what he recommended for staying sharp:
- Reading (a lot of reading) is certainly a great way to accelerate your skills
- Studying other languages is also a fantastic and fascinating way of learning new concepts that change the way you think.
- Spend time with “curious” colleagues.
- Practice. Find the time!
It’s a very good entry. You should take the time now and read it.
How do you stay sharp?
I think it’s safe to say that you are not going to stay sharp by not doing anything. But that, I mean, just going to work and doing what’s required of you. Sure, it can happen, but imagine how much sharper you would be if you did something in addition to that.
To be honest, I don’t know a definite answer on what’s the key to staying sharp. There are different ways that can work for you. Rather than trying to tell you what you should do, I’m just going to explain what I do.
I’ve tried many things over the years. I would say that I’m an aggressive type. I spend a lot of time on learning and improvement. And I’m trying to adjust as I go along.
So, he’re what I do to stay sharp.
Reading. I think reading is critical. I try to read at least an hour every day. Book reading, that is. Sure, there is a lot of good and helpful material/articles on the web that you can read. I do that as well. I have my list of blogs that I read. I find reading them very helpful. It helps me to know the state of things. But reading books requires you to put the effort and spend some quality time with the book. It also means that the author had put some quality time to make the book. This combination means is more valuable than just reading an article.
Over the years, I have changed the way I read books. I have converted to reading most of the books in the PDF/electronic format. I find that much more useful. And easier. I can take notes. I can read the same book at work without actually carrying it to work. Sure, I still buy a hard copy from time to time, but only the select few.
Practicing. Reading will only take you so far. It’s easy to read. I know. I’ve done that for a few years. I was on a roll, reading 300+ pages per month. But I noticed that I am not learning that much. Certainly not as much as I’d like. Plus, the rate at which I started forgetting things concerned me. Why is that? Just reading is not enough. Reading something just once might not be enough as well. I am in the process of modifying this cycle. It looks more like this now: Read. Take notes. Practice. Re-Read. Notes. Practice. Do what works for you. One thing is clear: by reading alone you’re not going to grow. You’ve got to practice. The more the better.
Doing more with less. This is a recent revelation for me. It’s exciting to constantly move to new things. Have you noticed that getting a new book is very exciting? But after you put the book on a shelf and it sits there for a while, something happens. Your interest in that book decreases after a while. It’s not new anymore. Not in your mind. You have discovered something else that’s new. Maybe you got a different book. So you focus shifts, that new thing is more “interesting.” It’s the same with reading. Once I am almost at the end of a book, I’d like to move on to the next. Even writing a review for that book seems tedious. I’d like to start reading a new book right away. But I have to break that cycle. I noticed that this is one of the BIG reasons why I don’t learn as much as I’d like. I’m trying to do too many things. Not good. Here’s what I am trying to do now to break this cycle. Before I move on to the next great thing, I have to make sure that I really learned it. And that means re-reading the book. That means writing a project based on the new information. That means writing a blog entry. That means creating a wiki/learning page. You see: that means doing more with less!
I know that the old way didn’t work for me. It’s something that I had to change. It’s still too early for me to report the results. It’s not easy to adjust. But I believe it’s the right path for me.
Staying sharp is not easy. But if you read a few books a year, you will learn more than most. Steve McConnell is Code Complete says: “One book is more than most programmers read each year (DeMarco and Lister 1999). A little reading goes a long way toward professional advancement. If you read even one good programming book every two months, roughly 35 pages a week, you’ll soon have a firm grasp on the industry and distinguish yourself from nearly everyone around you.” You just have to remember to do something with that knowledge to make it “stick.”
Just as it is a good practice to make all fields private unless they need greater visibility, it is a good practice to make all fields final unless they need to be mutable.
in Java Concurrency in Practice (page 48)
Are you following these fundamental principles?
Just so we’re on the same page, an immutable object is on whose state cannot be changed after construction.
This view is supported by Joshua Bloch in Effective Java (2nd). Item 13 states: “Minimize the accessibility of classes and members.”
The single most important factor that distinguishes a well-designed module from a poorly designed one is the degree to which the module hides its internal data and other implementation details from other modules.
He goes on to say some fundamental principles.
A well designed module hides all of its implementation details, cleanly separating its API from its implementation. Modules then communicate only through their APIs and are oblivious to each others’ inner workings.
Effective Java (2nd), page 67
These are really the basics of information hiding or encapsulation. Basics of OOP programming! It’s a good idea to learn these well.
Think twice before making any fields public. Hold it. No, don’t make it public! Think twice before making it any other than private!
But to make sure you only expose what is absolutely needed requires some thought. You need your own judgment and experience.
As for the second part, item 15 states: “Minimize mutability.”
I think this one is a little harder to justify and not so obvious. But Bloch has some very good arguments. Together with Goetz, they convinced me that I should utilize immutability more often when I’m designing classes.
Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.
But how? Follow these 5 steps (as per Bloch).
1. Don’t provide any methods that modify the object’s state.
2. Ensure the class can’t be extended.
3. Make all fields final.
4. Make all fields private.
5. Ensure exclusive access to any mutable components.
Goets says it a little bit differently.
An object is immutable if:
– Its state cannot be modified after construction;
– All its fields are final;
– It is properly constructed (the this reference does not escape during construction)
Immutable objects pack a lot of goodies in them.
One more time. Tell me what are the benefits of immutable objects!
They are simple to understand.
They are thread safe.
They require no synchronization.
Let’s end with a great summary note from Bloch, “Classes should be immutable unless there’s a very good reason to make t hem mutable.”
“If a class cannot be made immutable, limit its mutablity as much as possible.”
Learn these design principles!
All in all, I recommend reading Item 15 from the Effective Java book. And re-read a few times until it becomes part of your design logic.
It’s all about getting better.
It’s all about improving.
It’s good to learn from the pros. Everybody needs a little guidance. I know I do. (These 2 books are excellent! Recommended.)
Here’s my take on the qualities from the post.
Always do it the right wayI cannot agree more. There are always people that will say that they’ll improve it later; that this is special and it needs a special condition. It’s a big bull… You do it the right way ALL THE TIME. Really no exceptions.
Good engineers know that the right way applies to all situations and circumstances. If there’s not enough time to do something the right way, then there’s really not enough time to do it. Don’t make compromises, the quality of your work is what ultimately defines you as an engineer. Make sure that all of the code you write is done the right way 100% of the time. Expect excellence from yourself.
Be willing to sufferI never considered this as an asset before. On the contrary, I thought that it must be something wrong with me. I like to develop solutions in my head, thinking hard about them, then implementing. And later find a better solution. I rarely ask others for help. And I usually come up with good solutions. Hmm, maybe there’s hope in my software engineering skills.
Great engineers first and foremost want to solve the problem on their own. Problem solving is a skill, a skill that great engineers take seriously.
Never stop learningIf you have been reading what I write on this blog, I don’t need to say anything else. This is an absolute must if you want to be considered a great software engineer.
In order to be a great engineer you must first admit that you don’t know everything, and then you must seek out more knowledge in every way you can.
Share your knowledgeI believe that’s what makes you valuable to the company you work for. That’s how you distinguish yourself from others. This is how you think “big picture”.
Great engineers want others to know what they know. They aren’t afraid of losing their position because someone else can do the same thing. Great engineers want to see their peers succeed and grow.
Lend a helping hand
Great engineers are team-focused and therefore are willing to do whatever it takes to help the team.
Do I need to argue with that?
Take your timeIt takes time to develop and improve on your skills. The only way to do that is by learning iteratively, practicing. It probably will take 5 to 10 years, or even more, for you to acquire great skills. To acquire that craftsman’s touch.
ReferenceWhat makes a great software engineer?, Nicholas C. Zakas
As programmers, we want to finish things fast. We want to impress our boss. We want to be better and always finish before others.
So we do. We finish things as fast as possible. Because the requirement was to complete the things that were on the list.
Just make it work.
What’s the end result? Code that is hard to read by others. Code that is rigid. Code that is fragile. Code that is over complicated. Basically, code that has the characteristic of “fast food” — it does what is supposed to, right?
Wouldn’t things be different if one of the requirements was “high quality.”
The statement is ambiguous. Sure. It means different things to different people. It could be more specific: “code should be easy to read, easy to extend, and easy to modify.”
High Quality. Enough said.
You could argue what quality really means. That’s not the point. Just stating that it has to be of high quality puts everyone on the same page: it communicates the expectation to the team.
“Why don’t we just add a special exception here.” No, you would say. That’s going to lower the quality of the code. That’s going to make the code more fragile and harder to extend. It does not meet the quality requirement.
I personally don’t need to be told that — quality is always on my list. I always try to make the code that I write be of high quality. I put focus on that. I don’t always get the results I want, especially after I look at my code after a period of time. But I learn. I improve.
There is just too much of low-quality code around. Too much pressure to finish fast and no pressure on quality.
Having quality a requirement would make a huge difference. I strongly believe that.
Even if your manager does not require it, “High Quality” should be one of the most important requirements when you write code. It’s not easy to write high quality code. That’s for sure. You learn with experience, by trying things out. Patterns develop after a while. Then you study a bit more. But having that focus we’ll make you a better coder and distinguish you from the others.
Code quality and the fat developer, very good post by Consulting jiujitsu
I am reading Kent Beck’s book Implementation Patterns (which is great so far) and he talks about three values that are consistent with excellence in programming: communication, simplicity, and flexibility.
Kent put it so well, and these values are so timeless… that I had to write about it.
Communication“Code communicates well when a reader can understand it, modify it, or use it,” Beck writes.
Programming for the computer works fine. For the computer! Not for the person modifying it. “Good things happen when I think of others while I program,” Kent writes. Program for the other person!
But who cares? I just want to write the code as fast as possible and be done with it. Wrong! Beck writes, “The majority of the cost of software is incurred after the software has been first deployed.” From Kent’s experience, he sees that he spends much more time reading the existing code, than writing new code. And that’s a fact! Is your experience different?
When you think “How would someone else see this?,” you see your code from a perspective of another person.
SimplicityWhy would you make your code simple? For economic reasons, of course. “Eliminating excess complexity enables those reading, using, and modifying programs to understand them more quickly,” writes Beck.
A little complexity is unavoidable. How much? It depends who your audience is. But Kent puts it perfectly, “Challenging your audience a little is fine, but too much complexity will lose them.”
“Pursuing simplicity enables innovation.” I can’t agree more with Kent.
FlexibilityPrograms should be easy to change. Simplicity can encourage flexibility. Enhancing the communicability of software also adds to flexibility.
The bottom line: create simple, understandable applications that can easily be changed.