The Pragmatic Craftsman         :: Simplicity from complexity :: | About Me |

You are here: The Pragmatic Craftsman > Better Coder

Values for Excellence in Programming November 23, 2007
Martin's Object-Oriented Principles May 25, 2007
Martin's Object-Oriented Principles May 25, 2007
Good Code May 16, 2007
PPP: Practice, practice, practice February 2, 2007
Simple is Beautiful January 19, 2007
Read Books November 13, 2006
Use an Expert October 6, 2006
Code Reviews Are Good August 21, 2006
Single Responsibility Principle July 14, 2006
Special Exceptions Ruin OO Projects June 26, 2006
OO Design Heuristics for Classes and Objects (Riel) June 20, 2006
Keep Your Methods Cohesive: Short and Concrete June 14, 2006
Write Self-Documented Code June 6, 2006
Thoughts on Object Oriented Programming May 30, 2006
Code Style Is Important May 18, 2006
Never Duplicate May 16, 2006
Encapsulation vs Abstraction May 4, 2006
Duplication Principle April 25, 2006
Special Exceptions April 24, 2006
Better Object Oriented ... April 24, 2006
Ten Commandments of Egoless Programming January 24, 2006
Continuous Learning by Reading May 16, 2005
Coding Style -- from Slashdot March 8, 2005
What is good code? February 26, 2005
Improve, Not Degrade January 27, 2005
What is Good Code? October 26, 2004
Debugging October 22, 2004
A Pragmatic Quick Reference October 11, 2004
Your Code Sucks September 27, 2004

Values for Excellence in Programming

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.

Simplicity
Why 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.

Flexibility
Programs 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.


Martin's Object-Oriented Principles

I have said it many times... programming is easy. It's easy to just write a few classes, add functions and have a running program. Anyone can learn that. However, to program well, you have to be able to design classes that have good structure, are easy to modify, easy to understand, and are able to withstand business changes. Now, to do all of that well is hard. Very hard. Object oriented programming helped in that area. But to do it well is also hard.

To me, Robert Martin has had the most influence on the OO world. The OO principles/patterns he created are hard to understand. But they are timeless and fundamental. If you learn them, follow them, and can identify them in your code, then I think you are a good OO programmer. If not, keep learning.

I was happy to come across this site that lists all of Martin's principles. Study them. Learn them by heart. And start using them. You will become a better designer. Only after you master them, I think, you can call yourself a good OO programmer.

If you have not seen the books I recommend, I truly recommend reading Martin's book, Agile Software Development.

I also recommend reading anything Uncle Bob writes. You will not be dissappointed.

Reference
Object-Oriented Design Solutions or Services

Uncle Bob's blog


Martin's Object-Oriented Principles

I have said it many times... programming is easy. It's easy to just write a few classes, add functions and have a running program. Anyone can learn that. However, to program well, you have to be able to design classes that have good structure, are easy to modify, easy to understand, and are able to withstand business changes. Now, to do all of that well is hard. Very hard. Object oriented programming helped in that area. But to do it well is also hard.

To me, Robert Martin has had the most influence on the OO world. The OO principles/patterns he created are hard to understand. But they are timeless and fundamental. If you learn them, follow them, and can identify them in your code, then I think you are a good OO programmer. If not, keep learning.

I was happy to come across this site that lists all of Martin's principles. Study them. Learn them by heart. And start using them. You will become a better designer. Only after you master them, I think, you can call yourself a good OO programmer.

If you have not seen the books I recommend, I truly recommend reading Martin's book, Agile Software Development.

I also recommend reading anything Uncle Bob writes. You will not be dissappointed.

Reference
Object-Oriented Design Solutions or Services

Uncle Bob's blog


Good Code

Good code is easy to change.
--Manuel Klimek


I strongly agree with Manuel. Keep in mind that you write code for somebody else to modify. If it is not easy to do so, then your code is not good! Remember that maintainance is 70%+ of the project's life. If you cannot make modifications easily, then you really are wasting time. It's good to keep that in mind when you're rushed and "hacking" instead of producing good code. In the end, you pay handsomely if you speeded initially. :-)

Some excerpts from Manual's excellent blog entry.

Make the code easy to change. This means modularity, abstraction, low coupling and high cohesion and all the other wisdoms of software development that are known for ages.

Find the model that fits best for your team and make the code easy to change so that the poor souls that will maintain your code when you leave earth on your mission to Pluto are able to refactor it to make change even more easy for themselves.
An automated test suite makes it easier to change the system without breaking it. Even if you never implemented a new feature and later realized that you've broken a different feature, remember that you write code not for yourself, but for other people who have to maintain your code.

Reference
Manuel Klimek > Blog Archive > Good Code: A Value-Oriented Approach


PPP: Practice, practice, practice

Practice makes perfect.

I think you can agree with me on that. To become a craftsman, you not only need to acquire new knowledge and new skills, you need to be able to apply that knowledge, be able to polish your skills, and improve the output every time. I don't remember who said it, Mozart I think, that every time he played the same piece, he did it differently. He was always looking to improve it. That's the type of mentality of a true craftsman. And that's what I need to develop to become a true craftsman.

Practice new technologies: put your knowledge to the test
Over the last few years, I must have read 20-30 software books. I learn a lot, no doubt. But rarely do I actually put that knowledge to test. I just read, make notes (sometimes), and move on to another book. Doing it this way, I think my knowledge is not deep enough. I really cannot do anything with it, and I easily forget it.

I need to read a little and be able to put that knowledge to practice: I need to apply it. How do I do that? By writing a project based on that technology. By practicing -- playing -- with the new technology.

For instance, I want to learn Ruby (and Rails). Before I can say that I learned it, I should build a website or another project in Ruby. Only then I can say that I learned Ruby.

Same with any new technology. To really learn it, I should create my own project based on it. Anything new, whether it is a pattern or a technique, before you really learn it, you need to be able to put it into context. Ask yourself, how can I put that technology to use?

Practice to polish your skills
In an ideal work environment, we would get to work on new and different technologies fairly often. That does not happen in the real world too often (or you're lucky). As a result, we stagnate and get used to our working environment. I don't think that's a good situation. As a craftsman, you can never let your skills stagnate -- lose freshness. You have to stay abreast with new technologies, acquire new skills constantly. But how? On your own!

Use your down time at work to freshen up on your skills. Once again, practice comes into play. Think the project you're working on could benefit from migration to a newer, better technology. Do it! On your own. Start a new project, and migrate the old project to the new technology. Doing this keeps your skills fresh. You're gaining new skills.

Playing with new technologies is very important. If you cannot do it at work, you need to find time for it, whether at work or at home.

Practice to polish -- improve -- the product
Every time you build a product, always strive to make it better. Better than your previous one. That's the mentality of Mozart. I think that's a mentality of a craftsman. And that's what you want to become, right? Then you have to have that mentality! In design meetings, suggest a better way; when designing on your own, reflect and see what could be improved from your last project.

By practicing continuously, you'll be able to see how things can improve. You'll be able to build on your skills. You'll be able to keep your skills up to date. This is key to getting better, improving your skills, and becoming a better developer, a craftsman. And remember: you can never stop practicing!

Once again, and that's the bottom line, to move into architecture, to move up, to become a craftsman, you need a lot of practice. You need to continue practicing or you will not be "crafting" but "hacking." Practicing takes time, but that's the only way to make sure that you "got it." BTW, as a craftsman, you should be loving it! :-)


Simple is Beautiful

Programmers love complexity. We love to make things that are complicated.

Why is that? I think it's because programmers think that it makes them look good. :-) I think they feel they accomplished something big. Or is it that it gives them job security? (probably not) :-)

What's the root of the problem? I think it's jumping into code right away. We all love to code, and the first thing we do when we have a problem to solve is try to hash it out in code. Once you start, you try to resolve any issues that arise any way you can. It's harder to make changes once you start coding, though. Especially when you're working on something complex and the deadline approaches... So you're trapped.

The issue here is that programmers forget about a fundamental step in good design: to think about the problem first and design it at high level first. Go through the problem at high level, even if it's just in your head, or on a piece of paper. Go through the whole scenario. Simple UML here helps as well. By doing so, you might encounter issues that are easy to solve at this high level, but not when you're coding.

Thinking through the problem usually results in good layers. It usually results in a good domain logic. It usually results in better architecture. It results in higher quality code.

This way of high-level thinking introduces you to thinking abstractly: a required skill in design/architecture.

Not thinking through the problem usually results in spaghetti code. That's just the way it is, whether you like it or not. And even though you might think it does not happen to you, I think it happens to everyone. You might be an expert in refactoring, and you might be able to get a clean solution, but I say you have a higher chance of just leaving things the way they are.

Here's what Allen Holub had to say in Holub on Patterns.

"Simple systems are easier to build, easier to maintain, smaller, and faster than complex ones. ... Simplicity is often not an easy goal to achieve. Programmers love complexity, so they have a strong tendency to over complicate their work. It's often easier to quickly build an overly complex system than it is to spend the time required to make the system simple."

To me, the hardest thing in programming is making things simple. Programming itself, is like managing complexity. In my opinion, that's the single most important quality of a good programmer: the ability to make complex things look simple. I think the lack of it keeps people programming, instead of moving on to designing and architecting. I think most of us want to eventually be more involved in design and architecture, but until we master the principle of making things simple, we'll be stuck programming -- even though we might have a title of an "architect."

Look at design patterns. They changed the way we look at design. But fundamentally, behind the scenes, design patterns make complicated problems simple. Patterns are really a facade to complicated problems/issues. And that's the beauty of patterns.

"Simplicity is prerequisite for reliability," said Edsger W. Dijkstra.

On a related note, if you're working on something that's complex and not very pretty, try not to make it worse. Refactor it to make it easier. We don't usually have the time to do a "big bang" refactoring, but a little here and there helps. One of the principles that I try to follow is to never make things worse than they are. I always try to look for ways to make things better. To me, simple is beautiful.

Stanley


Read Books

What was the last book you read?

Has it been long?

The bottom line, to become a better coder, better [anything], you have to do the things you are used to do... better. Reading books is one of the best ways to acquire knowledge, to deepen your knowledge, to improve yourself: to become better.

How much do you have to read?

The Pragmatic Programmers (very good book, btw), recommend reading a book every quarter. Steve McConnell in Code Complete (excellent book), recommends reading around 35 pages a week.

Is that a lot?

My guess it is that you're most likely reading that much already, so keep doing it. Shifting to a book a month might make it more challenging, :-)

The software development world is constantly changing. If you're not following it, by reading and practicing, you're falling behind.

Nowadays, though, it seems to me that people are reading everything but books. People read blogs, articles, etc. I don't think that's bad, I just think that a good book is more valuable. You should still have books as your primary source of knowledge. A book gives you a more complete knowledge. A book requires a lot more knowledge to create than a blog entry or an article.

Where to start? What to read?

We don't have the time to read all of the books (I wish). So read the best. Read the classics. Just start reading and applying the knowledge you gain. A great book to start is Code Complete. It will help you guide your career.

One effective way to stay on top is to read and then apply the knowledge you learned. Repeat continuously.

Related
Continuous Learning by Reading, my previous entry


Use an Expert

Adding new responsibilities to a class is a fairly common thing in coding. We do that when we get a request from a business person. We do that also when we refactor parts of a project. It's an everyday activity you can say.

But here's a question? How do you determine where to put the responsibility? What is the best place?

By the Information Expert pattern, you should add it to the class that has the information. It's almost like in real life, you ask people that have the necessary tools and knowledge to do a job.

What is the Information Expert pattern? It is discussed in Applying UML and Patterns book. It is part of the GRASP patterns, which describe fundamental principles of object design and responsibility assignment. We hear a lot about GoF patterns but, in my opinion, not enough about GRASP patterns.

This pattern is simple and results in objects that do things related to the information they have.

However, if you applied this pattern everywhere, you would end up with a class that knows how to load its information, persist to db, etc. That's not good. You are violating a lot of patterns by doing that (high coupling, low cohesion, too many responsibilities, and many more). Or, as author says, you are violating "basic architectural principle: design for a seperation of major system concerns. Keep application logic in one place (such as the domain software objects), keep database logic in another place (such as a seperate persistence services sybsystem), and so forth."

What major benefits does the Information Expert give you?

"Information encapsulation is maintained, since objects use their own information to fulfill tasks. This usually supports low coupling, which leads to more robust and maintanable systems."

"Behavior is distributed across the classes that have the required information, thus encouraging more cohesive 'lighweight' class definitions that are easier to understand and maintain. High cohesion is usually supported."

So next time you are asking somebody to do something for you, see if he has the required information. If not, find somebody else that does. You want the job done well, right? Use an Information Expert for such a job. :-)

Reference
Applying UML and Patterns by Craig Larman, p221

It's one of my favorite and most-referred to books. It's one of 10 Books Every Java Software Engineer Must Own.


Code Reviews Are Good

I hesitated posting this... The last thing I want is more red tape. However, after reading about code reviews in several sources, I am convinced that the reward is worth the price. The bottom line, code reviews improve code quality. While no silver bullet, they force us to write better code -- knowing that somebody else will evaluate it makes us do it.

I have never been part of a company where code reviews worked effectively, but at the same time, if implemented properly into the development process, they have the potential to improve the quality code in a significant way.

What's more, they enable cross-training programmers, mentoring, and enforcement of code conventions. Code reviews allow us to make sure that new people are "adopting" to "our" way of doing things, if there are any. They're the extra guard to protect the most-valued property: code.

A lot of the prominent IT gurus, like Grady Booch, Jerry Weinberg, Cedric Otaku (those are sitting on top of my mind now), are big proponents of code reivews. I believe Weigers even wrote a book on the subject.

What prompted me to write this is an excellent blog entry by Cedric Beaust, Why Code Reviews Are Good For You, http://beust.com/weblog/archives/000393.html. He explains why it's good and the different types of reviews. The following sums it up nicely:

"I strongly believe that projects that work without any peer review will end up with code of significantly worse quality, regardless of how talented or experienced the developers are. It doesn't matter how good you are, you can't produce top quality code all the time. We all get sloppy at time, and code reviews are here to address these times."


I think we should consider implementing non-blocking code reviews. Let's be honest, we all check in code that is sometimes sloppy, we could all use a little incentive to do better, and a lot of times we write code that only we can understand. Code reviews would be an improvement in this area.

How do we implement it? Good question. I believe that there should be some communication system in place. But the bottom line, each line of code should be looked at by somebody else and suggestions how to make it better should be requested of each reviewer (no heart feelings).

At my current job we have JIRA and SVN integrated, doing code reviews would be simple. Every SVN check in has to have a ticket ID. Before a ticket can be closed and the project released, every change has to be reviewed by somebody else and commented on. Before it can be closed, the reviewer would have to approve that the changes have actually been implemented.

We all strive to write good quality code whether we do code reviews or not, but it does not always happen. Knowing that our code would be reviewed would force us to do it every time.

Reference
Why Code Reviews Are Good For You, Cedric Otaku

Related
Code Reviews, very good java.net article


Single Responsibility Principle

A fairly common occurence I've come across in software development is that a class I'm working on
changes for various non-related reasons. For one type of change, I modify a portion of it, and for another, another portion. That's not a good situation.

Martin Fowler calls this "divergent change" under the Code Smells category. He says the
following,

"Programs should be structured in such a way that we can make changes easily. When we make a change we want to be able to jump to a single clear point in the system and make the change.

Divergent change occurs when one class is commonly changed in different ways for different reasons. If
you look at the class and say, "Well, I will have to change these three methods every time I get a new database; I have to change these four methods every time there is a new financial instrument," you likely have a situation in which two objects are better than one. That way each object is changed only as a result of one kind of change."

Robert Martin calls this principle The Single-Responsibility Principle: A class should have only one reason to change.

In this context, he defines responsibility as "a reason for change." If you can think of more than one motive for changing a class, then that class has more than one responsibility. "It's not easy to see that because we usually think of responsibilites in groups."

What's an example of a responsibility coupling? Martin gives a common violation of the SRP: Employee class containing business rules and persistence control. Business rules tend to change frequently, and persistence usually changes for completely different reasons. A clear violation.

Interestingly, Martin calls this principle one of the simplest, and at the same time, one of the hardest to get right. "Conjoining responsibilities is something that we do naturally. Finding and seperating those responsibilites from one another is much of what software design is really about."

Thus, when adding new functionality to a class, I think it's important to keep in mind that they don't violate the Single-Responsibilty Principle. This has a side effect of keeping your classes cohesive. And you know
that is a good thing.

Once again, if over time you make changes to a class that touch completely different parts of the class, you have a violation of the principle. Split the class in two. Put the parts that change together into their own class. You'll be glad that you did. :-)

Reference

More Info on SRP

Single-Responsibility principle is a fundamental principle in software design. It is a good idea to
"embed" it into your software development knowledge. http://www.objectmentor.com/resources/articles/srp

Refactoring, Martin Fowler's influential and still relative book on refactoring (Code Smells section is invaluable).


Agile Software Development
, Robert Martin's book on patterns, a great book. He talks about fundamental patterns in OO development. A must read.


Special Exceptions Ruin OO Projects

In an object-oriented world, special exceptions are evil. To me, they ruin a well-structured framework/project. Yet in the business world, they are fairly common. What do you do?

I think the worse thing you can do is to actually add a special exception to a special-case free project. Once you do that, your project will take a downhill drive towards unmaintainability.

Let's say that you have a nice inheritance and polymorphism in place: a well-structured OO system. To be more specific, let's say you have a base class Shape and a Circle and a Square as subclasses. Everything works nicely: you only care about the Shape class and everything else takes its polymorphic runtime form.

Then, a business person comes in, with the usual time pressure, and asks you to implement something that resembles a Shape but it works a little differently. What do you do? You don't want to spend some extra time to refactor the original structure. And you don't want to implement a new structure as well -- too time consuming.

So what do you do? You add a special exception: you create a special-cased Shape. From now on, whenever you use the Shape object, you add the special exception to make sure something different is performed. Just a few lines of code. Everything works. You're happy. You're done. Quick.

But you did something else. You just ruined a well structured OO project. From now on, anytime you use the Shape object, you have to duplicate the special exception. It's only a matter of time when somebody forgets to do that. Ooops. A bug is let into the system. You created the opening with the special exception.

What else did you do? A level of frustration to the maintainer. The system is much more difficult to maintain after that.

Never do that! Take the time to do it right. Never put a special condition to a perfectly working OO system (with inheritance and polymporphism). Unless, of course, you don't care... and you consider yourself a crappy programmer.

I like the following saying: If you don't have the time to do it right, will you have the time to do it over?

You save some time at the time of implementation, but you will pay for it several times later.

So, anytime you need to add a special condition, and it's inevitable, refactor the code to support that, but don't add a special condition. It never works.

A better coder is a happy coder, don't spoil that. :-)


OO Design Heuristics for Classes and Objects (Riel)

Writing good OO code is not easy. Here's a set of rules of thumb when creating classes. These are taken from the Object-Oriented Design Heuristics book by Riel -- good stuff.

    2.1 All data should be hidden within its class.

    2.2 Users of a class must be dependent on its public interface, but a class should not be dependent on its users.

    2.3 Minimize the number of messages in the protocol of a class.

    2.4 Implement a minimal public interface that all classes understand [e.g., operations such as copy (deep versus shallow), equality testing, pretty printing, parsing from an ASCII description, etc.].

    2.5 Do not put implementation details such as common-code private functions into the public interface of a class.

    2.6 Do not clutter the public interface of a class with things that users of that class are not able to use or are not interested in using.

    2.7 Classes should only exhibit nil or export coupling with other classes, that is, a class should only use operations in the public interface of another class or have nothing to do with that class.

    2.8 A class should capture one and only one key abstraction.

    2.9 Keep related data and behavior in one place.

    2.10 Spin off nonrelated information into another class (i.e., noncommunicating behavior).

    2.11 Be sure the abstractions that you model are classes and not simply the roles objects play.


Reference
Object-Oriented Design Heuristics, Riel


Keep Your Methods Cohesive: Short and Concrete

Creating methods is probably the single most often performed activity during programming. Thus, it is crucial that it is performed well. When creating a method, I think the most important thing is that it should perform one task and do it well: it should have high cohesion.

High cohesion is the fundamental principle in object oriented programming (probably the most important). If there was a way to require high cohesive methods, then it should be a requirement. I'm all for it. :-)

If you have cohesive methods then it is a good sign that you are a good Object Oriented developer. It shows that you program for a human to read, not the computer. Having high cohesion is hard, you have to have one-task methods with good method names. It is a constant struggle to keep it cohesive with the additions/modifications. But if you accomplish that, then you're good. :- )

So do you have to care about the method size?

Actually, you should not. But somehow, you find a lot of methods that are very long. A lot of them are over 100 lines, some are over 150 lines. I've seen even longer than that. :-(

I think a good rule of thumb to adopt is to have methods that do not exceed your screen's size. It's a good rule. It allows you to see the whole method without scrolling. Which means your method should not be longer than 70-100 lines, roughly.

Alternatively, if you have a generic method name and your method is long, it should (be required to) be refactored and the related things put into its own method.

In the Signs You're a Crappy Programmer (and don't know it) article, the author states [that you are a crappy programmer] if:

You are adamantly opposed to function/methods over 20 lines of code. (or 30 or 10 or whatever number of lines) Sorry, sometimes a really long function is just what's needed for the problem at hand. Usually shorter functions are easier to understand, but sometimes things are most simply expressed in one long function. Code should not be made more complex to meet some arbitrary standard.
I think the key word is "sometimes." It's OK to have a long method here and there, the problem is when you have it in a lot of places -- in too many places. If your method does one function -- one responsibility -- and it takes over X lines, it's fine, no reason to break it up. But a lot of times, those long methods "accrue" extra responsibilties, making them harder to maintain. I think everyone can agree that a long method is harder to understand and modify than a shorter one.

Actually, I think you are a crappy programmer if you have a lot of those long methods with non-specific names.

The bottom line is to have functions that do one task and do it well. If you do that, you don't have to worry about the length, your methods will be short and easy to modify.

Everybody would benefit if you adhered to the rule of thumb, especially the maintainers of the code.

Reference
Signs You're a Crappy Programmer (and don't know it), Damien Katz

Related
Write English the Way You Write Code - very good post


Write Self-Documented Code

I don't know if anybody actually reads the comments that we sometimes write as Javadoc. Do you? I don't, most of the time.

That's why I think it's important to write code that speaks for itself and that does not need a comment. I'd go this far: if you need a comment, your code should be refactored and made easier to understand. (What does it mean easy? Easy for somebody else to understand -- important to keep this in mind as well.)

So how do you write self-documented code?

Use good names. For class names. For variable names. And for method names. Don't name your class WriteData or ConnectionInfo. They should have better names. They should be more specific. You should be able to tell what a class or a method does by its name.

Be short and specific. I hate it when I have to modify a 1000+ line class. I hate it when I have to modify a method over 100+ lines (you should have rules for these :- )). Have classes that have a specific set of tasks to accomplish. Have methods that do one thing and do it well. In this regard, it helps to have good and specific names so you know exactly what your class or method is doing, and whether you need to assign the new responsibility to a new class (assigning responsibility is crucial in OO development, as I said before).

Abstract it when you can. When you have some complicated logic, encapsulate it in a class, hide the complexity. By doing so, you're putting it in one place and you don't have to delve into details of how it works, as long as it works -- you assign it a responsibility and you hold it accountable. If you keep adding complicated logic to a class or a method, you're messing up the class, making it harder to undertand and modify. If it was seperate and nicely abstracted, you can modify it with more confidence. Maybe it's better to add a new class, a new method? Ask yourself that before adding any complex logic.

When writing a comment, focus on "why" not "how." Make every comment be of substance. Comment surprises.

In some cases you have to have complex logic. Add a comment then. Make it easier for you and for others. Prepare the reader for complex logic with a comment, explain why it is being done that way.

I think writing a self-commented code, code that is easy to read, is a crucial part in our day-to-day programming. It's one of the things that has huge effect -- in both positive and negative direction.

To be a good coder, to become a better coder, make sure your code is easy to read.

Related
Code Complete, Steve McConnell's excellent book (my previous recommendation), required if you want to become a better coder


Thoughts on Object Oriented Programming

Object Oriented programming is hard. It's easy to program in a language like Java, but hard to get it right. Why?

Because Object-Oriented programming is more than just writing classes and methods. OO programming is way more than that.

I think the hardest thing in OO programming is the ability to create objects with cohesive functionality. The ability to assign responsibility well is the key to object oriented programming. And that is hard.

To see where you are, ask yourself this question: what is an object? Is it an instance of a class? Or is it a data structure? If any of those two, you don't think in objects.

I think to truly program in an object-oriented way, you have to treat your objects as a set of responsibilities. Object oriented programming then is creating and assigning responsibilites to different objects. OO programming is creating a set of objects that are able to collaborate to achieve a task.

Also, it's important to spread the functionalities (more or less) equally to several objects. It's important to have objects that do several (Grady Booch recommends 3 to 5) of related tasks and do it well: specialized (cohesive) objects. That's why your classes should not be too large. It is a sign that your class does too much -- it has too many responsibilities -- if it is large. It's usually good then to break up that class into more specialized classes.

The biggest benefit of OO, I think, is the ability to think more abstractly. It's the ability to concentrate on a higher level. It's like programming in Java vs C++. In Java, you don't have to worry about pointers and references. You are working on a higher level. I think you can accomplish more that way (and save your brain for other tasks ;-)).

To be a good programmer, better coder, you have to be a good OO programmer. It's not an easy thing.


Code Style Is Important

Lessons from the Google Web Toolkit...

I've been looking at the sample projects from the Google Web Toolkit. Mostly looking at code and playing around with the apps. Based on this, I think I can learn couple things from the toolkit and the source they provide.

First of all, if you have not looked at the code, it might be a good time to do now (by downloading the tookit, you will have everything under the samples directory).

I love the samples' code style. I love its simplicity.

If I was an architect for a code style document, I would adopt the following things:

Simple, small classes. It's a joy to look at them; they're easy to understand and thus, I think, easy to modify.

Small methods. Show me a method that's over 100 lines. I'd like to see it. The way they built the framework, the abstractions they have, allows them to have small methods. This is a key to having maintainable code.

Using intefaces a lot. Using inheritance. It allows them to keep their classes small, highly specialized.

Self-commented code. They don't use too many comments. They use self-commented code. The source speaks for itself. That's beauty.

A one sentence summary of what the class does. If you can't fit it in one sentence, it means that you don't have a good class. It should probably be renamed, broken up, refactored. But this one sentence should always be there.

Comments to explain more complex code. Writing self-commenting code is crucial, but not always possible. Adding a comment where it helps is important.

Not going over 80-character margin. I've been trying to do that (in Eclipse you can set a visible margin at 80 - search for "margin" in preferences). It makes the code more readable.

Having 2-character tabs. I like that. The code looks better. Plus, you can fit more into 80 characters. :-)

Effort put into making code readable. I can't stress this enough. Put your name on the code, make it look good, make it elegant. Your code is your public face to other programmers, believe it or not.

I think it's important to have a mindset that a quality code is a requirement (and an asset).

P.S. One thing I did not like is the package structure. They just put everyting into one big package. Not the optimal way, I think, but maybe they did not want to expose too much.


Never Duplicate

How many times have you been thinking "let me just copy this here. It's not going to change. And if it changes, I'm going to modify it in both places."

I think that's a critical sin.

You might remember, but the next maintainer might not.

I have commited it many times, no doubt about it. But it was never a good thing. I have also experienced the benefit of having a single place to make changes. And it feels great.

In my opinion, duplicating code is the single biggest sin that you can commit. Always try to refactor the code to avoid duplication.

What invites duplication is code complexity, I think. If I find a code that is hard to understand, I am afraid to modify it. I'd rather copy it and modify it than refactor it. But I'm still commiting the sin. So you should try to make our code as simple as possible (it is a lot harder to do than writing complex code, believe me). Whenever I see code that is simple, easy to understand, I have high regard for the developer that wrote it (imagine what I feel when I'm frustrated :-)).

Avoiding duplication is tough sometimes. Sometimes it cannot be avoided. But you should have a mindset of never duplicating, be it the last resort. And if you do, you should feel that you did something wrong (write a comment to indicate that you're duplicating; admit the sin :-)).

Whenever I see a lot of duplication in a project, I know it's not a quality project (no matter what it does). Youl want to write high-quality projects, right? Youl want to become a better developer, right? Avoiding duplication is a required route to take in that direction.

Good developers always strive to avoid duplication.


Encapsulation vs Abstraction

I must admit. I am still having hard time seeing a real difference. I am still having hard time defining them both.
One thing I am sure: both are fundamental principles of object oriented programming. I am going to try to learn them here and explain the differences. Just so I know for future.

"Abstraction and encapsulation are not synomous," says P.J. Plauger in Programming on Purpose.

Encapsulation is information hiding. I think that's the best way to define it and remember it. "Information hiding allows for implementation of a feature to change without affecting other parts that are depending on it."

P.J. Plauger has a great analogy and definition of information hiding.
"Information hiding is not the same as secrecy. The idea is not to prevent outsiders from knowing what you are doing inside a module. Rather, it is to encourage them not to depend on that knowledge. That leads to a kind of secondary coupling which is more pernicious than obvios dependency because it is less visible. You should encapsulate information to keep it private, not secret. (What you do in the bathroom is no secret, but it is private.)"

"Stuff all of the code that is likely to change in a module [class] and hide its innards." That not only defines information hiding, but it is also a fundamental principle developing: when to create a new class, when to refactor.

Abstraction. Look at it as "what" the method or a module does not "how" it does it. I just found a great definition of abstraction: "The notion abstraction is to distill a complicated system down to its most fundamental parts and describe these parts in a simple, precise language."

Let's compare Java and C++. We have a good example of abstraction. In C++, you have to deal with pointers and references a lot. You have to deal a lot of garbage collection. In essence, you have to work on a low level. (C and C++ in turn abstracted a lot of even lower level machine code.) In Java, those things are abstracted away. You just assume they exist. In essence, abstraction means that you are working on a higher level. You don't care how pointers work in Java, you just assume that they work. You don't have to concentrate on the lower level stuff, you work on higher level.

I think abstraction is extremely important. By working more abstractly we can solve more and more difficult problems because we don't have to concentrate on the lower level details. As Steve McConnel puts it, we are working closer to the business domain.

So to summarize, I think I got it now. Encapsulation is information hiding. Abstraction means working on a higher level, not worrying about the internal details. They go hand in hand. The bottom line, even if you still don't know the differences, utilize information hiding; make your programs more abstract by creating classes with responsibility and then talk about the feature by the name of the class, but what it does, not by how it is doing it (that's abstraction, I think).


Duplication Principle

What's the single most important thing when writing code? And practical? To me, it's the DRY, OAOO principle.

Don't know what those acronyms mean? :-) Don't Repeat Yourself, and Once And Only Once principle. Not repeating the same code in different places is the single most important thing you can do to make your project easy to maintain and to modify in the future. There are no exceptions to this rule. If you have repeated code in different places, it is a matter of time when you will see the project disintegrate. Do yourself a favor: don't copy and paste. Modify the method, break it up into two. But don't make it wet. :-)

I broke this rule numerous times. And numerous times I was sorry that I did. I did it, and I got burned. It's tempting to do so: easy and fast. But always consider the consequences.

I like my code to be clean: I like "girly" code. Duplication makes it dirty.

I can say with certainty: If your project has any duplication of logic, it is not a quality project. And after the first copy and paste, you take an express ride to a restaurant for a pasta meal. I mean "spaghetti." I mean spagheti code. :-) Do you want that?

I understand that you cannot always avoid duplication. For instance, if I have to modify an existing project, I might have to work with a lot of duplication (I hate it when I do), but for any new code that I write I have the following principle:

DUPLICATION PRINCIPLE
Duplication is my enemy. I want no enemies; therefore, I will not create any duplication and I will try to kill it whenever I see it.

References
The Pragmatic Programmers: The DRY Principle
Code like a girl, Creating Passionate Users blog
Once And Only Once, WikiWiki


Special Exceptions

I'm working on a legacy project and I'm frustrated. It's a mess. It seems that it was built to never be modified. It is just a pain to make even a small change to it.

I hate when I'm working on an Object-Oriented project and it contains special exceptions. C’mon, use polymorphism, use template methods, whatever, no special exceptions. I think what happens is that people design it nicely at first but then when a change is requested they just create a special exception because it is faster. Don't fall into that trap. In essence, with that one exception they broke the system. The next change is "just another" exception. On and on... the system becomes a nightmare to modify for a new person on the project.

In any case, a system like that is slow to modify. You make changes to the system and you are scared that the roof will fall -- problems appear in different places. That's not object oriented programming, that's hacking and destroying the system. So, next time you want to add a special exception to a fully working system, think twice, because, in essence, you are breaking the system. Put the time in and refactor it. Keep it object oriented and you will be glad that you did.

So how do you make your system better, more object-oriented? Keep it that way! Don't break it by putting special exceptions. No exceptions. Really.

One of the rules that I have when working on any type of a change is to make the system better. Better for me, and better for someone after me. I always do that. Whether it is breaking it into a smaller method, creating a new class, renaming a method. Whatever works, whatever makes it better.


Better Object Oriented ...

I have around 6 years of development experience. I have worked for several companies now. I can tell you one thing: a lot of developers don't know how to write object oriented code. They write Java and they assume they write objects. But those are not objects; they're more like data structures. Objects are not data structures, objects have to have a clear responsibility, a clear purpose. Object should do one thing and do it well.

Anyway, I am going to put my thoughts on object oriented systems here in this category. My thoughts, learning experiences, etc. Hey, I learn as I gain experience. I'm not perfect and I don't want to be. But there are some principles that I have already learned that work for me. One thing I'm sure: writing objects is hard, very hard. It takes real effort and dedication. It takes years of experience to do it well. But modifying a nicely structured object-oriented system is a joy. It's fun. I like to program, but it has to be fun. "Hacking" might be fun, but it is fun in only one direction: it's not fun when you have to modify it and undo your "hack." :-)


Ten Commandments of Egoless Programming

I believe that good programmers are egoless and humble. There is no room in software development for attitude. Of course, you can be that way, and a lot of people are, but what they fail to recognize is that the path takes them downwards. That path will not make you better, that's for sure. So be humble, admit mistakes, learn from others, and you'll do well.

Lamont Adams has a list of 10 Commandments of Egoless Programming. It's good stuff, read it.

Ten Commandments of Egoless Programming - (Lamont Adams, Builder.com | Sunday, July 14 2002)

1. Understand and accept that you will make mistakes.
2. You are not your code.
3. No matter how much "karate" you know, someone else will always know more.
4. Don't rewrite code without consultation.
5. Treat people who know less than you with respect, deference, and patience.
6. The only constant in the world is change. Be open to it and accept it with a smile.
7. The only true authority stems from knowledge, not from position.
8. Fight for what you believe, but gracefully accept defeat.
9. Don't be "the guy in the room."
10. Critique code instead of people傭e kind to the coder, not to the code.

For a more detailed version, go to the article, below.

Reference
Ten Commandments of Egoless Programming, Lamont Adams

Related
Every Craftsman Is Dump and Lazy, my post


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.

Reading
Reading 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, source
code for the examples, up-to-date pointers to Web resources, and an
online 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 someone
    else'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 is
    most 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
    Exceptions
    can suffer from all the readability and maintainability problems of
    classic 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 might
    weed and rearrange a garden, rewrite, rework, and re-architect code
    when 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 surface. 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 the
    abstraction, not the implementation. Abstractions can survive the
    barrage 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 to
    be 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, it
    should be the last time a human tester finds that bug. Automatic tests
    should 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.


© getCopyDate() ?>

Random Quote

Search

 

Topics

Architecture & Design :12
Better Coder :30
Books :43
Books Recommended :18
Buzzwords :5
Career :25
Craftsmanship :15
Java :15
Quotes :25
Recommended :9
Software Engineering :3
Uncategorized :33
Web Development :1

Archive

May 2008 (1)
April 2008 (2)
March 2008 (1)
February 2008 (1)
January 2008 (2)
November 2007 (1)
October 2007 (3)
August 2007 (3)

...since January 2002

Currently Reading


:: See list of books I finished reading

Info

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