Search This Blog

Tech Book Face-Off: Design Patterns vs Object-Oriented Design Heuristics

When learning something new, try reading books on the topic in pairs. Learning about something this way has a number of advantages, and you can consciously pick the books depending on what you're trying to achieve. Sometimes you're trying to learn a new programming language quickly. Sometimes you want to learn about different development processes, like agile vs. waterfall, for instance. Sometimes you just want to learn some new design techniques and happen to pick a couple of great books that compliment each other nicely. That would be the case with these two books:

Design Patterns Front Cover.jpg VS. Object Oriented Design Heuristics Front Cover

The first, of course, is the famous Gang of Four book on design patterns. Almost every programmer has heard of it, and it is considered the definitive work on software patterns. The second is less well known, but provides great insights and is quite well-written and easy to read. Each of them stands on its own as a great book of design knowledge, but together they can really improve the way you approach software design. Let's take a look at each one and then see how they fit together.

Design Patterns: Elements of Reusable Object-Oriented Software

The basic premise of this book is that software design has a number of recurring patterns that can be systematically described and cataloged. Once you know the names of the patterns, you can easily discuss them without having to describe the design in detail, and other software engineers will know what you're talking about. Since these patterns come up again and again, there is no need to redesign them from scratch. The implementations given in the book can be applied to new designs to quickly solve common problems with known solutions. Convenient!

The bulk of the book is the catalog of 23 design patterns. The authors go through every aspect of each pattern from why you would use it, how to apply it, what are the advantages and disadvantages of it, and a concise example of it. It's all very methodical, but I really got into it. I was amazed at how many patterns applied to the code base I'm working on. Factory Method, Adapter, Facade, Command, and the infamous Singleton were all present, and learning about them greatly improved my understanding of the code I was working on. I could categorize entire sections of code based on the pattern used, and as a result, I had a much more organized picture of the code in my head.

I could also see where things could be improved. After reorganizing one set of classes into the Strategy pattern, I was able to easily extend it with a ton of new functionality that was just a bunch of additional strategies. The next thing I want to tackle is the state machine that currently manages the overall execution of the program. Right now it's a giant switch statement that's just crying out to be refactored into the State pattern. It would be so much more maintainable and understandable. I love books that are immediately applicable to what I'm working on.

Object-Oriented Design Heuristics

This book addresses object-oriented design from a different angle. Instead of categorizing design problems and solutions into a set of patterns, it lays out a set of heuristics to guide you while making  the nitty-gritty choices that go into designing software. Since they're more what you'd call guidelines than actual rules, the heuristics can sometimes be contradictory, and intentionally so. Through the heuristics, Riel brings out the tension inherent in all design trade-offs in software engineering.

Bringing this tension to the forefront really helps crystallize your understanding of the reasoning behind design choices, and why you would make one choice in this situation, but take the opposite route if the requirements changed slightly. There are rarely definitive answers, only shades of gray. Sometimes it's better to encapsulate behavior into lower level classes. Other times doing so would make things messier because the necessary data is spread out among numerous classes. In that case it might be better to move that behavior up a level and just access the data from the lower-level classes.

I'm making decisions like these constantly while programming, and having a well-thought out set of heuristics is invaluable. I can see much more clearly what the design trade-offs are, and my designs are much cleaner and more elegant as a result. I certainly have a long way to go on improving as a programmer, but this book has helped me suck less in the last year.

Putting Them Together

How do these books complement each other? They attack software design from different angles. Design Patterns gives you a collection of patterns to choose from when you're trying to organize a program at a higher level, either when doing the architectural design, or more likely when refactoring after you actually know how the program works and fits together. On the other hand, Object-Oriented Design Heuristics gives you a collection of heuristics to use when deciding where to put this data or that function, and is incredibly useful while actually writing code.

Patterns help organize in larger chunks while heuristics help refine and massage the design at a finer level of detail. Their interplay is similar to how a house is constructed. The patterns would be like the foundation and frame of the house. They provide its structure and support, and the rest of the house hangs on that structure. The heuristics are like the fit and finish of the house. The shelving, trim, paint, and floor coverings that give the house its look and feel. They're both necessary, and when they're both done right, you have a beautiful, functional home.

So how do you build a better house? Reading about these patterns and heuristics isn't enough. You have to put them into practice to really understand them and see how they work. The examples in the book are nice and clean and well thought out, but they likely won't transfer exactly into your own designs. Don't be afraid to experiment and see how they can be implemented in your own projects. At the same time, don't try to force them into a design that doesn't really need it. Patterns especially can be overused and abused if you're not careful, so don't over-engineer. Simpler is almost always better. If a particular pattern doesn't provide the benefits necessary to outweigh its complexity, use a simpler pattern or none at all. How will you know? The only way to find out is to give it a try.

Learning How to Learn (Part 3): Hitting a Wall

Let's say you have a great love of learning. You have a passion for learning new things and make the time to pursue that passion. You know how you learn best, and it works quite well for you. Learning is exciting and satisfying. And then you hit a wall. What do you do now?

This very thing happened to me after I finished my Master's Degree and started working full time. Although I did not realize it was happening at the time, I let my love of learning languish for years after finishing college. A number of factors came into play during those years to distract me from learning. That is not to say that they were bad things. Some of them were wonderful life experiences, as you will see. In looking back, though, I can see there were times when I could have and should have been more thoughtful of my professional development. Here are the main reasons why my learning stagnated. Maybe some of them will be familiar to you, as I am sure many of us tend to forget about learning through the years.

1. Burnout

Towards the end of my Master's Degree, I just wanted college to be over. Don't get me wrong, I loved college. It was the most fun I had ever had in my life, but after six years, it was wearing me down. It wasn't just the six years of college, though. It was the 18 years of school. I had worked extremely hard through high school and college, including holding a part-time job as an intern at the company that I would later work for full-time, and I needed a break. 

After studying solidly for that long, the last thing I wanted to do was pick up another textbook, but I probably shouldn't have taken such a long break. A few months would have been enough time to recover, and then I could have picked up a software design book or discovered and started reading some of the excellent blogs that were popping up at that time - something to stay current and keep my mind nimble. I picked up something else instead.

2. Distractions

I had build up quite a backlog of video games that I had bought but hadn't played during college. After my freshman year, I didn't have much time to play anymore, but I still accumulated plenty of games that I figured I would get to later. Post-college was the time to relax and catch up on some great games. I probably went a bit overboard, not leaving time for much else in the evenings. That would include learning something new, like a new programming language.

3. Family

I met a wonderful woman in college, and we got married and started a family. I now have two incredible young children that bring me joy every day of my life. Obviously, I don't have any misgivings about the choice to start a family. I list it here because a family definitely takes time, and you should spend as much time as you can with your family because that time is short. 

So how do you make time for learning when you have a family? I've found that once the kids are in bed, there's enough time in the evening to pursue my own interests. It just takes more discipline and dedication. If the motivation is there, the energy to keep learning will be there. And once the kids are older, we can learn together. Teaching is a great way to learn. I already have plenty of fun projects in mind.

4. Home Ownership

While I have no regrets in starting a family, I cannot say the same thing about home ownership. Owning a home is a tremendous time sink. It took us years to get settled in our new house to the point where it no longer takes so much of our time, but yard maintenance is still a lot of work. If I had to pick one thing on this list that I would have done differently, I would seriously consider living in an apartment or condo instead of a house. The extra space of a house is nice, especially with children, but I'm not convinced that the trade-off is worth it. (My wife agrees.)

5. Career

This one takes a little explaining. It would seem that a career shouldn't be an impediment to learning and professional development. An engineering career should be a vehicle for learning plenty of new things. While it is true that I learned a great deal while working as a test engineer and IC designer, I wasn't learning anything new on my own. That's important. If you're not learning outside of your career, it's very easy to become complacent. To let the tide take hold of you, and just drift along. The pursuit of knowledge is an active endeavor, and I should have taken more control of what I was learning on my own time. I could have been picking up new programming languages, or understanding current development best practices, or paying more attention to where the industry was headed. Instead, I was going with the flow.

Getting Beyond the Wall

So what changed? My job disappeared. My previous company decided to close down the design center where I was located. I was given an offer to relocate overseas, but it was a difficult decision. My coworkers and I did know at some level that that day was coming. There were plenty of signs of the impending shutdown for months prior, but we were actively ignoring them. So the news came as quite a shock, and I was painfully aware of all the things that I should have been learning over the years to be more professionally valuable. There's nothing like having the blindfold whipped off while standing at the edge of a cliff. 

I didn't waste any time. I dove back into learning with a rediscovered passion that I had forgotten was there. Luckily, I found a great new job much more easily than I expected, yet the learning continued beyond getting the job. What I quickly found was that I didn't need the external motivation of losing my job to pursue learning again. That was just the spark that started the fire. My internal desire to learn was still there, buried, but easily uncovered. Once it was rekindled, it took on a life of its own. I've been devouring books like crazy since then, reading everything I can for over a year now, and I think that my software engineering abilities have dramatically improved. I certainly still have a lot to learn, but now I know where I'm going.

Cultivating a Lifelong Love of Learning

Once I had gotten into the swing of things again, I realized that learning outside of school is much different than it was before. I have total control over what I learn in my free time, and total responsibility. I need to carve out the time to study, pick out the materials I'll use, and devise my own projects to do for practice. It's entirely on me to improve my knowledge in a way that's more self-driven than even my favorite graduate courses were. That's very empowering and satisfying.

I wish I had come to this realization sooner. I could have been continuing my education all along. A little time off after college was warranted, but not years off. The technology industries move fast, especially software, and letting years of development in the software industry go by will leave your knowledge pretty obsolete. You should always be learning.

I am not advocating the pursuit of knowledge to the detriment of all else. Maintaining a lifelong love of learning requires balance. Learning how to learn involves developing an awareness of that balance between your personal, family, social, and professional lives. Without balance, the pursuit of knowledge could become meaningless, or worse, draining, instead of fulfilling. If you hit a wall, take a short break. Then find the right balance, and pace yourself.

Learning How to Learn (Part 2): How Do You Learn

Last week I developed the idea of prerequisites to learning how to learn, namely curiosity, motivation and time. All three aspects are necessary for us to be driven to learn and retain a lasting understanding of any subject, yet they only point us in the right direction for learning. They don't actually get us to our destination. To go the distance, and actually do so efficiently and effectively, you should learn the best ways that you learn, and that is a deeply personal experience.

The best way I can describe this personal awareness is to tell you how I learn, as an example. I am certainly not advocating this approach to everyone because everyone learns differently. This approach works for me, but it may not work for you. Let's say I want to learn a new programming language. How about JavaScript, for the sake of a concrete example, since I'm learning that language right now. I got a couple books on it, one moderately large, and one ridiculously large. I'll read through those, and do some more reading on the internet at and I always read at least two different sources on a subject because different authors hit the subject from different angles, and that diverse treatment helps me make better connections in my brain. I remember things better that way. So foremost, I learn by reading. A lot.

Then I'll think up a project that I can do in JavaScript, like a card game or a paint program or even a script that parses my Amazon wishlists and finds all of the publication dates and page lengths of the books and writes them out to an XML file so I can sort them by title or date or length. You know, something more useful that Amazon's lists don't already do. The important thing is to come up with a project that I'm interested in - a project that will do something significant with the language - and then do it. So I learn by reading a lot and then doing.

If I want to further solidify my understanding, I can discuss with other people what JavaScript is good for. What are its trade-offs? What features really stand out? What features should be avoided or used with caution so I don't shoot myself in the foot? Once I have a decent foundation, these discussions can take my understanding to the next level. And that's about it. I learn by reading a lot, then doing, and sometimes discussing.

This realization of my learning style came together for me after that Grey-box Systems course in graduate school. That course was all about reading and discussing and a final research project that really showed me how I learn best. I learned faster and more profoundly than I ever had before. My head was buzzing with the mental connections that were being made. The course also made me more aware of the ways that I don't learn nearly as well.

I do not learn well in lectures or training courses. In those situations, I can't go at my own pace. I can't delve into topics that I find particularly interesting. I can't stop the proceedings to work something out that I didn't fully understand. I end up getting bored and my mind wanders to what I could be doing instead. In college I could never fully grasp why most professors would constantly rehash the material that I had just read in the textbook without ever deviating or expounding on it with their own experience or insight. The best ones did do this, but they were the exception.

Training courses are even worse because they are short and trivial by design. I attended a two-day MATLAB course a couple years ago, and I didn't learn anything that I hadn't already learned in the first couple hours of reading the documentation and experimenting with the program. When the course ended without covering any of the more advanced features that I was hoping to learn, I asked the trainer what the best resources would be to pursue MATLAB in more depth. He suggested some more training courses that were offered in other major cities. That was not terribly helpful, considering my learning style, so I found some more books and online references, and that suited me much better. I actively avoid training courses now.

Even worse than training courses are online educational or training videos. I simply cannot stand these things. Sure, with a video I can pause or skip around at will, but how can I know where the interesting bits are, if they even exist. The lecturer has no idea how the audience is responding since there is no interaction whatsoever. Online videos succeed in completely removing the one aspect of lectures that I find remotely useful - asking questions to go into an interesting topic in more depth. The few times I've tried watching them, I end up watching the time tick away on the position slider while trying earnestly not to pull my hair out.

I'm sure each of these ways of learning are invaluable to other people because everyone learns differently. I'm sure there are plenty of people that can't stand reading to understand concepts and get lost when experimenting on their own. They may find lectures and guidance and coaching extremely helpful, and that is a great way for them to learn.

My wife learns in a completely different way than I do. She takes copious amounts of notes. I am astounded by the volume of notes that she can take, and she can remember where she's written stuff on any given topic. This is all entirely foreign to me. Even if I could continue to follow a lecture while taking notes, which I can't, I would never find a use for the notes after I'd taken them anyway. She has a chronological memory, though, and she can pull up old notes in her notebooks quite easily to refresh her memory on something. I bet the act of taking notes also helps her more fully understand what she's hearing. I know plenty of people learn that way, it just never worked for me.

What is even stranger to me is the way my wife learns by asking questions, and I mean a lot of questions. If it were me, I would be expending so much mental energy coming up with all of those questions that I would quickly become thoroughly confused about what we were even talking about anymore. I'm still trying to figure out how her extensive questioning works exactly, but I do know that it works well for her. She is wickedly smart when it comes to understanding human interaction and emotions, and this way of learning probably accentuates that ability. She can easily interpret underlying motives and concerns in group settings of which I am completely unaware. So her ways of learning are completely different than mine, and incredibly effective for her.

These methods are certainly not the only ways that we learn. Learning styles is its own field of pedagogical research, although studies on proving the beneficial link between learning style and student are mostly inconclusive. Learning a bit about the research may help give you ideas for how you learn best, but I pretty much came to the realization on my own. I'm sure you already have a pretty good idea of how you learn best as well. I imagine the research was running into problems with the prerequisites to learning because they would have to standardize what was being learned, likely on some mundane topic. If you aren't interested in the topic, how you learn it isn't going to make one whit of difference. However, if you really want to learn something, I'm convinced that how you learn it can mean the difference between frustratingly slow progress and quick, clear understanding. I encourage you to experiment with your learning style on something that you have been meaning to teach yourself lately. Go on and find out how you learn best. I'd love to hear about it.

Learning How to Learn (Part 1): Necessary Conditions

Learning is fundamental to modern life, and learning continuously is fundamental to modern technology fields. Since learning is so important, I'll devote the next few posts to exploring different aspects of learning, and hopefully tie them into software development. Let's start with learning how to learn.

I'm certainly not an expert in educational pedagogy, so I'm going to depend exclusively on my own experience here. However, I have been learning my entire life, and those who know me know I have a passion for it. Over thirty years of experience should count for something, and I want to explore learning how to learn, not how to teach.

I'll start with this: you probably won't learn how to learn until graduate school. I'm not saying you have to go to grad school to figure out how to learn. I'm sure there are plenty of people who didn't go to college and figured it out anyway. But that's not my own experience, and I'm willing to bet that you're much less likely to learn how to learn if you don't go to grad school. It is, after all, one of the major focuses of grad school. Whereas, there are innumerable reasons to not go to grad school, and a desire to learn how to learn is not one of them.

So why don't we learn to learn until grad school; why not learn it earlier? First of all, we are too busy learning what to learn to spend any time learning how to learn. The entire curriculum is laid out for students from kindergarten to college graduation. Sure, that curriculum varies from school to school, although less so now with education standards mandated by the government. And in secondary and undergraduate education, students get more freedom to choose their own classes and fields of study, although schools always require certain amounts of gen-ed subjects. If you look back at your own path through school, what you learned in all of those classes, or what you were supposed to learn, was predetermined. Whether you picked the classes or not, you read the assigned books, did the assigned homework, were lectured on the class material, did projects on the class material, and took test after test after test.

I'm not criticizing this educational structure or the dedicated educators that work so hard to teach our students. I'm just saying this is primarily how I was taught in school, as was almost everyone else, since that has been the basic model of education since the industrial revolution. It's practically a necessity to teach this way if the premise is to teach 20-30+ kids per class period (or 100+ students in a college lecture hall) under the constraints of federal government and school district level initiatives to increase standardization and testing. It's extremely difficult to teach under this model and not fall into the empty vessel mode of teaching, even if the teachers are consciously trying to avoid it. The empty vessel would be the student's head, and the teachers pour in the knowledge that they possess, filling the empty vessel. This mode does assume a great many things about the vessel - that it's not already full of other thoughts, isn't closed off to the knowledge being imparted, doesn't have any leaks, and isn't moving around randomly from various other distractions. At any rate, this mode of teaching doesn't leave any room for learning how to learn.

It takes a special kind of teacher, and a great deal of effort to avoid the trap of teaching as if students are empty vessels. I had a few teachers during high school that I'll always remember. They leave a lasting impression. They change the way you think about the world. One teacher in particular that did this for me was my AP Chemistry teacher. She would let us design our own experiments as extra credit, and as long as we did them safely, we could do almost anything. One of my experiments was to make nitrogen triiodide, a highly unstable contact explosive. I only made an amount small enough to be safe, but boy was it fun to make it and then set it off. Actually choosing our own experiments made it exciting and motivating to learn more, but those fleeting moments were the closest I came to learning how to learn before grad school. They were the rare exception, while the norm was to be taught the things we should know without any significant digressions.

That gap between student-driven lessons and the empty vessel model highlights two necessary conditions for learning how to learn: motivation and curiosity. If you aren't motivated to learn something by your own volition, you won't pursue it with the focus to fully absorb it. If you don't go through the process of discovery born of curiosity, and instead are just handed the information in a lecture, you won't make enough mental connections to retain the things you are being taught.

How do we cultivate these qualities?

We don't have to. We have to reacquire them. Do you remember your life before school, or even the first couple years of school? I don't remember much, but I have a couple of young children that show me daily what life for me was like back then. They are constantly discovering new things because everything is new to them, and they love it. They laugh out loud and bounce around like jack rabbits when something clicks. They get engrossed in a project and won't come to dinner, even if it's macaroni and cheese. They will not go to bed. Don't get me started about that. I think the main reason they won't is that they would have to stop learning, so they put it off as long as possible.

My major problem over the next 15 years is to not stifle this love of learning. That's it. The most important thing I can do is not get in the way. For the rest of us, we have to get that love of learning back. We went through years of being spoon feed material and then being tested on it relentlessly. We got bored. We lost our motivation. We forgot about our curiosity. College is a time to start rediscovering that love of learning, but it isn't enough.

You see, there still isn't enough time during undergrad to learn how to learn. Even though you get to choose what to study, the classes are basically structured the same way as they were in high school with a lot more work to get done. Then there are all of the... well... social obligations. It wasn't until grad school that I had the necessary time and academic schedule. Specifically, I had less classes, and half of those classes were completely self-directed.

One class that comes to mind was called "Grey Box Systems," taught by David Wood at UW-Madison. There was no textbook, no lectures, and no tests. What we did was read and discuss recent papers on chip-multiprocessors and then do a semester research project of our own design. We even decided as a group which papers we discussed. This class was hands-down the best class I ever took, and not because of what I learned, but how I learned. In this class more than any other, I learned how to think critically, how to analyze, and how to research. I spent more time on this class than all the previous semester's classes put together, and it was worth it. I was learning how to learn.

More importantly, I was learning how I learn. That knowledge is critical to improving as a software engineer. The technology is constantly changing. The tools I need to do my job are constantly moving. I need to be constantly learning to stay in the game. I need to know how I learn. That may be different than the way you learn. If you don't already know, you should learn how you learn. You can start by picking something you're curious about, something you'll be motivated to learn, whether it is related to your career field or not. Then make the time to learn it. Along the way you might just learn a thing or two about how you learn best.