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.
I also recommend reading anything Uncle Bob writes. You will not be dissappointed.
Good code is easy to change.
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 yourcode 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 newfeature and later realized that you’ve broken a different feature, remember that you write code not for yourself, but forother people who have to maintain your code.
Reference Blog Archive -> Good Code: A Value-Oriented Approach” href=”http://klimek.box4.net/blog/2007/05/12/good-code-a-value-oriented-approach/”>Manuel Klimek > Blog Archive > Good Code: A Value-Oriented Approach
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 testOver 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 skillsIn 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 productEvery 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!
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.
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.
RelatedContinuous Learning by Reading, my previous entry
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.
ReferenceApplying 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.
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.
ReferenceWhy Code Reviews Are Good For You, Cedric Otaku
RelatedCode Reviews, very good java.net article
A fairly common occurence I’ve come across in software development is that a class I’m working onchanges 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 thefollowing,
“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 makethe change.
Divergent change occurs when one class is commonly changed in different ways for different reasons. Ifyou 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 knowthat 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.
ReferenceMore Info on SRPSingle-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.
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.
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.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.
ReferenceObject-Oriented Design Heuristics, Riel