The Pragmatic Craftsman :: Simplicity from complexity : by Stanley Kubasek ::

Archive for the 'Better Coder' Category

Continuous Learning by Reading May 16th, 2005
Coding Style — from Slashdot March 8th, 2005
What is good code? February 26th, 2005
Improve, Not Degrade January 27th, 2005
What is Good Code? October 26th, 2004
Debugging October 22nd, 2004
A Pragmatic Quick Reference October 11th, 2004
Your Code Sucks September 27th, 2004

Continuous Learning by Reading

I was slipping…

I got my B.S. in Computer Science from NJIT after four years. I spent another two years there and got my M.S., in CS as well. In between, I got my first full-time job. I can say that everything was going well. What could be better? Yet, not realizing it, I was slipping. I wasn’t learning any new technologies. I wasn’t keeping up with new books. I wasn’t improving myself. Yet I thought I was doing fine.

So what happened? I came across Steve McConnell and The Pragmatic Programmers (Dave Thomas and Andrew Hunt). I met Steve through his classic book, Code Complete. It opened my eyes. It woke me up from my sleep. The Pragmatic Programmers made sure I’m awake.

Steve and The Pragmatic Programmers directed me to a path of continual improvement. In order to improve, they told me, I have to constantly read. They told me to constantly learn and practice new technologies. They told me to invest in my knowledge portfolio continuously, just like I invest in my stocks.

That’s why, I know now, to be a software craftsman, and stay a craftsman, the most critical element for me is to get better every month, every year. Constantly. Reading is a great way to accomplish that.

ReadingReading is probably the best way of improving yourself. There are a lot of experts in the software industry. But we don’t get to meet or hear them (unless we’re lucky). A lot of the experts want to share their information with those that want to learn, though. How do they do that? They do it by writing. We, on the other side, can receive that information by reading their works. Read…

Read books.Read at least 5 to 6 books per year. Steve McConnell recommends reading a book every two months (roughly 35 pages per week). The Pragmatic Programmers recommend reading a book every quarter, and then eventually moving to a book a month (mixing it with non-technical books). I think both of the recommendations are adequate. Steve goes on to say, that if you do that, you’ll distinguish yourself from everybody around you.

I have taken their recommendation to heart. I have started reading a technical book every two months. Recently, I’ve upped it to a book every month. I’ve been on this continuous reading path for over a year now. And you know what? I’ve never been more confident. I want to stay humble here, but I can see that I’m doing more than the guys around me. I’m distinguishing myself more and more every month. I知 feeling good. :-)

But there are so many books to read! Yes, that’s true. But I follow this approach: I read the best books. I read books with a 5-star rating on Amazon.com (or close to it). “I only read the great ones,” said Jerry Weinberg, when asked by Joshua Kerievski how he keeps up with all the books that come out. Follow this approach and you’ll be fine.

Read magazine articles and journals.Reading books is great, but you also have to keep up with the industry. You should know what new technology are coming up. You should be aware of your surroundings. The best way to do that is by reading magazines and journals.

I read a lot of magazines. I start off a week by checking out eWeek and InfoWorld (both free). Every other week I receive an issue of SD Times (free). These 3 magazines are the Newsweek for IT, they tell me what’s happening. Every month I get JDJ, Communications of the ACM, Queue, IEEE Computer, Software Development (very good; free), Better Software (very good), and an issue of CrossTalk (free). Every other month I receive the IEEE Software (my favorite). These magazines tell me about new technologies. They tell me about new development techniques. They teach me new ways of doing development. And they also lead me to good books. All of this for almost nothing (I only pay for IEEE Software).

Read blogs and newsletters.I read books every month, magazines every week, and I read software blogs every day. There are so many good, expert bloggers out there that I think it would be a waste not to check out what they have to say. You have to pick what you like as there are a lot of good developers writing/bloggin. Reading Joel on Software (especially the archive) is one of the best, though. (I have over 100 feeds at my Bloglines account.)

When I graduated from college, I thought I knew it all. I thought that on-the-job learning and experience will be enough. It might have been enough for my current job, but what would happen if I lost that job? Would I be prepared? No! I have to take things into my own hands. I have to learn for myself and by myself. Reading continuously is a great way to learn and has been my savior for my renewed confidence.

Steve made me realize that it doesn’t take that much to be one of the best in your group, to be on par with the best in the software industry, to feel like you belong in the software industry. My advice? Read constantly and you’ll get there.

I’ve recently changed the way I work as well. I said it to myself, I have two things to do at work: one, to do what’s asked of me in the best possible way, and two, to improve myself as a developer, and I do that by reading books and technical blogs. I have virtually eliminated reading news, sports, and other time consuming resources. I’m on a mission here: I want to be one of the best in the industry. I want to be a software craftsman.

Coding Style — from Slashdot

I checked out the entry on Slashdot about the Code Reading book (very good book, BTW). Scrolling down, I came across an interesting discussion about coding style. I found the two entries that I list below very insightful. What’s the point here? Good developers write code that is readable. Good developers know how to tackle complexity: they make hard things seem easy. That’s probably the single most important thing I look when I look at code. If it’s simple, it’s good. I love simplicity.

Toby Haynes on coding style:

Most critical is managing complexity. Large, complex functions are bad – they have more bugs, they are harder to maintain, harder to bug fix (a change has more likelihood of breaking something else). If a function has grown beyond a hundred lines of (real) code, it is almost certainly too large. If it has more than 4 levels of nesting, it is too large.

Comments also matter. It’s easy to code a couple of thousand lines of fresh code over a weekend if you get in the groove. It is almost impossible to unpick it one year later if you didn’t comment it as you go.

Variable and function names should be expressive. No single letter variable names! No obscure combinations of letters like words with no vowels (fnct could be function or function control, or even Function Numerical Constant Type). And personally I find that reverse Hungarian notation can be more trouble than it’s worth. Annoying!

Build in automatic checks on everything. If a pointer to a function should never be null, check it and stop if it is. If a variable should only have values 1 -> maxIterations, then check it. If you (or anyone else) ever breaks that assumption, the code will flag it for you.

Beyond that, nothing beats good design, especially designs where extending the original work is easy. So many designs end up as tangle knots of conflicts because they ended up trying to solve problems that the original code base never envisaged.

Re: Coding Style by AuMatar

The problem with hard fast rules like that is they’re frequently not right. Take a state machine for example. A simple one with 6 or 7 states will go over 100 lines, and will go over 4 nestings. Heck, you’ll take one up with the loop and one with the switch alone. You can break it into functions and hide some of the nesting in functions, but when doing that you frequently end up with functions that don’t make a lot of sense by themselves.

A better rule than size IMHO is the one logical operation rule. A function should do one logical operation (read a file, write a file, run a state machine, calculate something, etc). They should contain all the logic needed to do that operation plus any debug and error handling that makes sense at that level of code. They should be broken up into subfunctions ONLY if those subfunctions themselves follow the logical operation rule, and only if that logical operation makes sense outside of the context of the higher function.

Take the state machine example. If it needs to wait on a semaphore before each iteration, the wait should be its own function- waiting on a semaphore is a logical operation. The logic for each state should NOT be separate functions, they are part of the state machine and make no sense without the whole of the machine for context. Breaking them out results in harder to read code, even if you do lose the nesting. But if in case RUNNING_MOTOR you issue a stop command to the motor that probably makes sense to be its own function- how you actually stop the motor isn’t part of the core logic of the machine.

I guess my point is- lines of code isn’t the enemy, some things are complex and need many lines to do. Nesting isn’t the enemy, some things require many loops/ifs. The enemy is a lack of clear separation of functionality and lack of clear abstraction between parts. If you have separation and abstraction, it tends to hit the optimal readability. If you don’t, it will fail either because you broke it up too much (too little context) or too little (too much context).

What is good code?

I’ve heard many definitions, but the one below, by Kirk Knoernschild, seems closest to my heart.

Quality code is code that:

  • can adapt to change
  • performs well
  • is error free
  • is as simple as possible
  • does what my customer needs

On a related not, here’s what Robert Martin, a software craftsman, has to say how to write quality code:

The only way to go really fast is to write the best code you can possibly write, with the best design you can possibly give it. Any other technique will slow you down. … In my estimation the belief that quality is an expediter rather than an impediment is what separates professionals from amateurs.

Improve, Not Degrade

A lot of times we get to work on an existing system. We’re lucky if the system is of high quality: easy to read, easy to understand, and easy to maintain. A lot of times, though, we get a system that’s messy: long methods, complex code. Anotherwords, the code smells.

We are asked to make changes to the system. What do we do? We make the change, verify that the system works, and submit the changes. We keep the system in the same state. We don’t want to introduce other changes. We are afraid of taking the risk and moving some of the code out of long methods to a new method. We have deadlines to meet, we don’t mess around. We think copy and paste is not so bad under those conditions. We’re ordinary programmers. That’s not the way good programmers approach it.

Good programmers always, I mean always, try to make the system better after every change. The least they can do is keep the system the same. I like to think of myself as a decent programmer. How do I improve the system? Whenever I’m making a change and I see something that’s not clear to me, I refactor it. I don’t change the functionality; I just try to make the code look better. Why? Because I know when I come to fix something else here, I’ll have the same problem of trying to understand what’s happening. I don’t want to think hard on the same thing twice. I like things simple.

For me, a bad smell in the system is a smell of opportunity. Opportunity to improve the system. This applies to any type of a system in any state. No matter how good or how bad it is. How do good systems decay? Programmers don’t try to improve it. They just do their thing and they’re done. Ordinary programmers do that. Good programmers like to understand the code. They try to make it better every time. You might say, I don’t have time to do that, we have deadlines to meet. I don’t buy that. Not under any condition. Most likely, you don’t know how to make it better. You don’t know how to program well. You know how to hack.

Part of being a good programmer is keeping the codebase clean. To know that you’re programming for other people, not for computers. That’s why when you see a long method, duplicated code, or unclear piece of code, refactor it. How do you do that? Read Refactoring by Fowler and he’ll show you how. Keep your code DRY (Don’t Repeat Yourself); keep it SHY (don’t reveal too much — data hiding, encapsulation); and TELL the other guy (to do the work for you — ie, no getter methods). Or as Thomas and Hunt say: Keep it DRY, Shy, and Tell the Other Guy (great article — May 2004, IEEE Software).

The degrading of the system starts with a single broken window that’s not fixed. Don’t let that happen, always fix any code smell that you see. Be a good programmer, not ordinary one. Also, if you’re serious about improving, check out The Pragmatic Programmer and Code Complete 2, they’ll help you. They helped me. :-)

What is Good Code?

I recently discovered a pretty good discussion on what “good code” is. The original author, Bill Carlson, specified quite a few good points. Points that according to him make the code good. Before I list the summary of the points, let me just say that if you are interesting in writing quality code, I think you should (you must) read Steve McConnell’s Code Complete. It will open your eyes. It opened mine. :-) (See my review in Books I Recommend.)

Attributes of “Good Code:”

  • High “signal to noise” ratio.
  • Minimal algorithmic complexity.
  • Lack of “cuteness”.
  • Use of most primitive technology required.
  • Appropriate optimization.
  • Architectural simplicity.
  • Specificity (avoiding over-generalization).
  • When vs. How comments. Knowing how to use a class: useful. Knowing when to use a class: priceless.
  • Appropriate quality bar.
  • 100% reachable code.
  • Lack of cut-n-paste.
  • Lack of redundency.
  • Visual clarity. Is the code easy to read?

Read the whole discussion on The Old Joel on Software Forum: “Good Code” – What is it?

Debugging

Do you use a debugger? It seems like people that were exposed to programming without a debugger are against it. Their take: if you read the code, you will be able to understand it better and find any mistakes in it fast. I agree to a point, but debuggers are tools that help you become more productive. There is no question about it.

I totally agree with Otaku Cedric (read his very good post) with the following statement:

No matter how productive you are with your current tools, I guarantee you will be more productive with an IDE and with a debugger.

I use Eclipse and I love it. If you don’t use an IDE, you should try it. It makes life so much easier.

Talking about debuggers, how about a JavaScript debugger? Well, for the longest time, I couldn’t find one. Firefox to the rescue! Let me just tell you that Firefox should be your best friend if you are a web developer: it just kills IE in that regard. There are several extensions to Firefox that are very good if you’re involved with JavaScript: the Console (it actually comes with Firefox), and the Debugger, (and a Web Developer extension). Try them all. However, you are really going to appreciate the Debugger: you can step into code just like you can in your Java debugger. That’s great. :-) Since I’ve been using it, it has saved me a lot of time (and frustration).

A Pragmatic Quick Reference

You’ve probably heard about the Pragmatic Programmers — Hunt and Thomas — and their famous book: The Pragmatic Programmer: From Journeyman to Master (I’m currently reading it). I really recommend this book — I’ll do a formal review later, after finishing it. Anyway, in that book, they have quite a few really good — pragmatic — tips. I thought it would be nice to have those tips summarized. Sure enough, I found a summary today on CodingHorror.com. You will appreciate this reference more after you read the book.

The Pragmatic Programmer Quick Reference Guide

This page summarizes the tips and checklists found in The Pragmatic Programmer.

For more information about The Pragmatic Programmers LLC, sourcecode for the examples, up-to-date pointers to Web resources, and anonline bibiography, to to www.pragmaticprogrammer.com

  1. Care About Your Craft
    Why spend your life developing software unless you care about doing it well?
  2. Think! About Your Work
    Turn off the autopilot and take control. Constantly critique and appraise your work.
  3. Provide Options, Don’t Make Lame Excuses
    Instead of excuses, provide options. Don’t say it can’t be done; explain what can be done.
  4. Don’t Live with Broken Windows
    Fix bad designs, wrong decisions, and poor code when you see them.
  5. Be a Catalyst for Change
    You can’t force change on people. Instead, show them how the future might be and help them participate in creating it.
  6. Remember the Big Picture
    Don’t get so engrossed in the details that you forget to check what’s happening around you.
  7. Make Quality a Requirements Issue
    Involve your users in determining the project’s real quality requirements.
  8. Invest Regularly in Your Knowledge Portfolio
    Make learning a habit.
  9. Critically Analyze What You Read and Hear
    Don’t be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project.
  10. It’s Both What You Say and the Way You Say It
    There’s no point in having great ideas if you don’t communicate them effectively.
  11. DRY–Don’t Repeat Yourself
    Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
  12. Make It Easy to Reuse
    If it’s easy to reuse, people will. Create an environment that supports reuse.
  13. Eliminate Effects Between Unrelated Things
    Design components that are self-contained. independent, and have a single, well-defined purpose.
  14. There Are No Final Decisions
    No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change.
  15. Use Tracer Bullets to Find the Target
    Tracer bullets let you home in on your target by trying things and seeing how close they land.
  16. Prototype to Learn
    Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn.
  17. Program Close to the Problem Domain
    Design and code in your user’s language.
  18. Estimate to Avoid Surprises
    Estimate before you start. You’ll spot potential problems up front.
  19. Iterate the Schedule with the Code
    Use experience you gain as you implement to refine the project time scales.
  20. Keep Knowledge in Plain Text
    Plain text won’t become obsolete. It helps leverage your work and simplifies debugging and testing.
  21. Use the Power of Command Shells
    Use the shell when graphical user interfaces don’t cut it.
  22. Use a Single Editor Well
    The editor should be an extension of your hand; make sure your editor is configurable, extensible, and programmable.
  23. Always Use Source Code Control
    Source code control is a time machine for your work—you can go back.
  24. Fix the Problem, Not the Blame
    It doesn’t really matter whether the bug is your fault or someoneelse’s—it is still your problem, and it still needs to be fixed.
  25. Don’t Panic When Debugging
    Take a deep breath and THINK! about what could be causing the bug.
  26. “select” Isn’t Broken.
    It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug ismost likely in the application.
  27. Don’t Assume It—Prove It
    Prove your assumptions in the actual environment– with real data and boundary conditions.
  28. Learn a Text Manipulation Language.
    You spend a large part of each day working with text. Why not have the computer do some of it for you?
  29. Write Code That Writes Code
    Code generators increase your productivity and help avoid duplication.
  30. You Can’t Write Perfect Software
    Software can’t be perfect. Protect your code and users from the inevitable errors.
  31. Design with Contracts
    Use contracts to document and verify that code does no more and no less than it claims to do.
  32. Crash Early
    A dead program normally does a lot less damage than a crippled one.
  33. Use Assertions to Prevent the Impossible
    Assertions validate your assumptions. Use them to protect your code from an uncertain world.
  34. Use Exceptions for Exceptional Problems
    Exceptionscan suffer from all the readability and maintainability problems ofclassic spaghetti code. Reserve exceptions for exceptional things.
  35. Finish What You Start
    Where possible, the routine or object that allocates a resource should be responsible for deallocating it.
  36. Minimize Coupling Between Modules
    Avoid coupling by writing “shy” code and applying the Law of Demeter.
  37. Configure, Don’t Integrate
    Implement technology choices for an application as configuration options, not through integration or engineering.
  38. Put Abstractions in Code, Details in Metadata
    Program for the general case, and put the specifics outside the compiled code base.
  39. Analyze Workflow to Improve Concurrency
    Exploit concurrency in your user’s workflow.
  40. Design Using Services
    Design in terms of services—independent, concurrent objects behind well-defined, consistent interfaces.
  41. Always Design for Concurrency
    Allow for concurrency, and you’ll design cleaner interfaces with fewer assumptions.
  42. Separate Views from Models
    Gain flexibility at low cost by designing your application in terms of models and views.
  43. Use Blackboards to Coordinate Workflow
    Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants.
  44. Don’t Program by Coincidence
    Rely only on reliable things. Beware of accidental complexity, and don’t confuse a happy coincidence with a purposeful plan.
  45. Estimate the Order of Your Algorithms
    Get a feel for how long things are likely to take before you write code.
  46. Test Your Estimates
    Mathematical analysis of algorithms doesn’t tell you everything. Try timing your code in its target environment.
  47. Refactor Early, Refactor Often
    Just as you mightweed and rearrange a garden, rewrite, rework, and re-architect codewhen it needs it. Fix the root of the problem.
  48. Design to Test
    Start thinking about testing before you write a line of code.
  49. Test Your Software, or Your Users Will
    Test ruthlessly. Don’t make your users find bugs for you.
  50. Don’t Use Wizard Code You Don’t Understand
    Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project.
  51. Don’t Gather Requirements–Dig for Them
    Requirements rarely lie on the s
    urface. They’re buried deep beneath layers of assumptions, misconceptions, and politics.
  52. Workwith a User to Think Like a User
    It’s the best way to gain insight into how the system will really be used.
  53. Abstractions Live Longer than Details
    Invest in theabstraction, not the implementation. Abstractions can survive thebarrage of changes from different implementations and new technologies.
  54. Use a Project Glossary
    Create and maintain a single source of all the specific terms and vocabulary for a project.
  55. Don’t Think Outside the Box–Find the Box
    When faced with an impossible problem, identify the real constraints. Ask yourself: “Does it have tobe done this way? Does it have to be done at all?”
  56. Start When You’re Ready.
    You’ve been building experience all your life. Don’t ignore niggling doubts.
  57. Some Things Are Better Done than Described
    Don’t fall into the specification spiral—at some point you need to start coding.
  58. Don’t Be a Slave to Formal Methods.
    Don’t blindly adopt any technique without putting it into the context of your development practices and capabilities.
  59. Costly Tools Don’t Produce Better Designs
    Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits.
  60. Organize Teams Around Functionality
    Don’t separate designers from coders, testers from data modelers. Build teams the way you build code.
  61. Don’t Use Manual Procedures
    A shell script or batch file will execute the same instructions, in the same order, time after time.
  62. Test Early. Test Often. Test Automatically
    Tests that run with every build are much more effective than test plans that sit on a shelf.
  63. Coding Ain’t Done ‘Til All the Tests Run
    ‘Nuff said.
  64. Use Saboteurs to Test Your Testing
    Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them.
  65. Test State Coverage, Not Code Coverage
    Identify and test significant program states. Just testing lines of code isn’t enough.
  66. Find Bugs Once
    Once a human tester finds a bug, itshould be the last time a human tester finds that bug. Automatic testsshould check for it from then on.
  67. English is Just a Programming Language
    Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on.
  68. Build Documentation In, Don’t Bolt It On
    Documentation created separately from code is less likely to be correct and up to date.
  69. Gently Exceed Your Users’ Expectations
    Come to understand your users’ expectations, then deliver just that little bit more.
  70. Sign Your Work
    Craftsmen of an earlier age were proud to sign their work. You should be, too.

Your Code Sucks

Most likely, it does. Here is an article, Why Your Code Sucks by Dave Astels that will tell you why it does. Read the article as I think it’s great. After you read it, make sure you verify your code according to all of the points. Dave says that your code sucks if it meets the following criteria:

1. Your code sucks if it doesn’t work.2. Your code sucks if it isn’t testable.3. Your code sucks if it’s hard to read.4. Your code sucks if it’s not understandable.5. Your code sucks if it dogmatically conforms to a trendy framework at the cost of following good design/implementation practices.6. Your code sucks if it has duplication.

So, I ask you, does your code suck?

I think some of the code that I write sucks because it isn’t very easily testable. I think, though, that it is hard to test web applications and that’s the main reason behind it. I’m trying to find an easy way to do that so I can eliminate it. I agree with the author, your code should be easily testable. As far as the other points are concerned, I would say that my code is easy to read, easy to understand, and it does not have any duplication. I take extra care in those areas.

Favorite Quote

Topics

Tags

Archive

Currently Reading

Info

© 2001-2024 Stanley Kubasek About me :: Contact me

Me on Twitter

»see more

Recent Entries