views:

1989

answers:

33

Hi, I'm a community college student graduating this year. Over the last couple of years I learned HTML, CSS, VB.NET, C#, PHP, and to a lesser extent some other languages. I have no problems whatsoever with assignments given in class. In fact, I always get A's and I'm never challenged. But when I to go ahead and try to write something bigger from scratch, I have a hard time organizing or designing my programs. I'm thinking this might be due to the fact that I have too much freedom, but I don't know for sure. Often I'll write a bigger program (say, a few hundred of lines) only to realize that what I wrote is neither elegant nor maintainable. How do I overcome this deficiency? Books? Tutorials? An actual job (who'd hire a student that can't design)? Or does it come to you with time?

+27  A: 

I think time is the biggest factor...

  • Learn from your mistakes. Look carefully at what's worked for you and what hasn't.
  • Read: blogs, books, whatever. Don't trust anything you read, but see what makes sense to you. Effective Java has a lot of good design advice, even if you're not a Java programmer. Ideally, read where other people criticise their own mistakes, and learn from that.
  • Write. Blog about what you've done and how well it's worked. This goes beyond looking carefully - just working out how to express your successes and failures will make them clearer in your own mind. Be warned: writing can be addictive and time-consuming.
  • Program. Lots. Experiment - try using different techniques, try different technologies (e.g. AOP, IOC etc).
Jon Skeet
I agree 100% There's definitely no substitute for experience and constant learning.
David Stratton
I think this is good general advice, but for a student I would put more emphasis on learning by imitation. When you are first starting out, it's hard to tell good from bad design. You are better off learning how to apply good designs. As you get better you can see how to adapt them to apply to your specific problem and still retain a good design. Eventually, as the principles behind good design become deeply ingrained you can develop new patterns that exactly match your needs and even know when it's appropriate to violate a principle to get to a better design. Imitate, deviate, innovate.
tvanfosson
I think one of the most important things to remember when faced with the good vs. bad divide is simply to see if you are fighting against the language to do what you are trying to do. If you are, then there's a good chance that you've messed up the design and you should revisit that.
Matthew Scharley
+5  A: 

Practice. Read. And then practice some more.

You learn how to design by continually revisiting your code and learning from your mistakes. For example, go back to an assignment from a year ago and figure out how you can refactor it to apply (if feasible and warranted of course) a new design pattern you've read about.

Franci Penov
Dang, beaten by Jon Skeet by 20sec... :-)
Franci Penov
That doesn't surprise me anymore. I think Jon is really the remnants of an MIT graduate project in AI that has gained self-awareness.
Eric J.
+3  A: 

New hires can't design and they usually know it. Mid-level developers can't design but think they can. Experienced developers might be able to, but will claim they can't.

Code design and architecture is an art. Getting good at it takes practice. Lots and lots of practice (as an example I don't think started getting even decent at it until I'd been programming for over 20 years). People aren't going to be looking at hiring you to do design, so don't worry about your lack of ability to design affecting your ability to get hired.

You'll learn code design by simply working on projects that have been designed well (just as you'll earn poor design by working on projects porrly designed). Reading about best practives, looking at open projects and things like that will certainly help you understand concepts, but really, it's just going to take time.

ctacke
As a corollary to learning good or bad design from what you're working on, make the effort to get hired somewhere that does good design. It matters.
Paul McMillan
How do u know said company(wherever he may be) does good design?
non sequitor
+1  A: 

Great question!

I think you are in the right direction. You can read hundreds of books and tutorials but the real progress will come from writing code. do not give up if your code is not maintainable or scalable as you wish it would be. you have to see the problems before finding the solutions!

lets take the dependency injection pattern for example. you can read a lot of great articles about it and think you got it. but you will never really get it until you will write your own coupled program.

to sum it up, read books and articles about architecture and design patterns to know what tools you have but keep writing those programs that you write in order to FEEL it. you can only progress by doing some mistakes!

Moshe Levi
A: 

While reading (both books and other people's code) can help, I think the only way to really to develop a taste for what works and what doesn't is experience. You wrote "Often I'll write a bigger program (say, a few hundred of lines) only to realize that what I wrote is neither elegant nor maintainable." - so, iterate! The first revision of any program, written by even the best programmer, is not likely to be elegant or maintainable - but the best programmers have the drive and ability to keep at it (polishing the turd, if you will) until something beautiful, or at least useful, comes out. When you hit this step, figure out some way that you might make the program more elegant or maintainable, and try it. It's not unlikely the first dozen, two dozen, three dozen things you will think to try will not help, or even make things worse, but the learning experience from that will beat anything else.

Jack Lloyd
I've been refactoring a small project of mine from the very beginning and it's been fun. I'm well past the 50th revision now and it's pretty good, significantly better than in the beginning, but still far from perfect. It's comforting to hear that nobody gets it right the first time.
Peter
+3  A: 

That is part of learning to program, you will always look at stuff you wrote before and think it is terrible (even though it seemed like the smartest thing you'd ever done). That being said, just keep writing code and making those mistakes, you'll learn from them.

It also helps to read lots of code. Check out open source projects and see how they are doing things.

Thirdly, I would recommend looking for some books. Steve McConnell's Code Complete has been very valuable to me. I'd also recommend Bob Martin's Clean Code and The Pragmatic Programmer from Andy Hunt and Dave Thomas.

Good luck and enjoy the ride as you learn more and more.

brentkeller
+1 for Clean Code!
TrueWill
+9  A: 

(who'd hire a student that can't design)?

Frankly, that's many/most students leaving college. You are not alone and it sounds like you are on track and perhaps ahead since you are asking this question.

There are a lot of blogs and books out there on software design. I think reading books on object oriented design would be a great start as I found (at least for me straight out of College) I didn't know near as much as I thought I did on that topic and it is very important in design of systems today.

It can seem pretty heavy (at least it was for me) but I started reading books from Martin Fowler and others such as Refactoring, Design Patterns (GOF book), Heads First Design Patterns, etc...

I found these books challenged me greatly and forced me to learn. I started following blogs from many such as Ayende, Los Techies, Code Better. I also took everything I was reading and have FORCED myself to use them in real work so I can take it from a concept to reality to learn even more and create my own opinion about things. I also have started reading code from others and open source and have begun to try and contribute. The open source world is a great place to see how other's have solved ideas (good and bad).

klabranche
I'd agree that you're ahead since you are asking this question. heck, asking this question almost puts you ahead of so-called "seasoned" developers. luckily that's changing...but only slowly.
Epaga
+10  A: 

Use a discipline that encourages good design: TDD or DDD. Look at the practices of refactoring to learn how to detect code smells and refactor to a better design. Find good examples to emulate -- knowing design patterns and especially when to use them can lead to better designs out of the box. Be aware, though, you can get into a trap trying to force design patterns onto a problem. Patterns need to fit the problem, not the reverse.

The other thing I would encourage is to find a programming mentor -- someone who can critique your code and show you how to improve it. This might be hard to do as a student, but definitely pursue this as you move into the working world. User groups might be a way to find someone as a student. Perhaps you could attend a local Code Camp to find a mentor in your area.

Lastly, be passionate about writing good, clean code and find the right design for your application. Don't be afraid to improve it as you go along. Having a passion for it will drive the other activities you need to undertake to make it happen.

tvanfosson
+1, especially for the mentor suggestion. That was what I was going to add, but I see you already did that.
David Stratton
-1 to TDD right off the blocks. It's a great way to get code that's less buggy, but it doesn't really solve fundamental design problems and makes it FAR too easy to get so caught up in the details you don't see a bad design decision till it's too late.
Paul McMillan
TDD does not encourage good design. It is an excellent way to document and validate a software design, but that doesn't make the design a good one.
Robert Harvey
@Robert Harvey -- I couldn't disagree more. Testable designs are typically highly decoupled, encouraging the use of interfaces, and good design patterns, such as IoC and DI. The emphasis on consistent refactoring and the ability to refactor without fear of breaing working code leads to design improvements that would otherwise be discouraged.
tvanfosson
Note: I'm not saying that TDD is a magic bullet, but if you design for testability you will naturally be forced to choose some good design patterns and if your functionality is fully tested, you'll have tremendous freedom to refactor and improve.
tvanfosson
agree with tvanfosson, probably one of the biggest design traps most developers naturally fall into is high coupling and dependency messes. TDD forces you to decouple.
Epaga
A: 

The first part of gaining good design sense is experience. With experience, you can get a sense for what works well and what doesn't work well; you might be able to look at past projects and see what you wish you had done differently and remember those things in the future. Strive to get better every day and practice, practice, practice. Developers who understand good design generally do a lot of development. Finding a mentor can help, as well. Look for a more experienced colleague or someone whose skills you admire and see if the person will share insights with you. Over time, it will come more naturally and then you can give back by helping others around you!

bobbymcr
A: 

Review & Refactor your code, preferably have someone else review your code for constructive feedback. Review other people's code, see if there are things you would improve upon or tricks you'd like to use in the future. But be careful of working yourself into a corner in order to accommodate things - flexibility and maintainence should be high priorities.

Reading won't necessarily answer questions you might have while reading and it relies on experimentation to gain the experience you'll use for decisions in the future.

OMG Ponies
A: 

It will come with time you spent coding... Just try to spent as much time as you can writing code. After some period of time you will feel a need for reading a good book. =) You always can contact me or any experienced user from this community for an additional advice.

Restuta
+1  A: 

I enjoy learning new languages and frameworks because it always effects my code across the board.

i.e.

  • After learning rails, my php is cleaner
  • After learning mootools/jquery my "vanilla" javascript is cleaner
rpflo
I'm not sure that learning frameworks or libraries will teach me design, but it is definitely a good way to expand your horizons. When I learned CodeIgniter, I learned about MVC and ORM, for example, and my PHP work did become more organized and maintainable.
Peter
I guess my point is that frameworks tend to be based on design principles. Those principles are often portable.
rpflo
I definitely agree.For instance, if I need to do something quickly (or it has a library that I don't need the full rails stack for), I use php, but I typically stick with more classes, and use a view class etc.
CodeJoust
A: 

I think the very fact that you are asking this question attests to the fact that you care about design which is a great start. Like anything else, you learn and become expert by doing and doing and doing; so code lots. I agree with the other answerers here: read books and blogs on the subject and try out new techniques. Some books that had a big impact on my design skills were:

  1. The gof pattern book
  2. fowlers architectural design patterns
  3. eric evans' domain driven design
Matt Wrock
A: 

To add to other answers, my personal favorite was (and is) reading Refactoring and Design patterns materials (Fowler's Refactoring, GoF Patterns and similar), books, blogs, whatever.

You can find concrete examples of bad coding practices and ways to improve their design. After you do a bunch of refactoring of your own ugly code (speaking from my own experience), you get a better feeling of what's good design and what's not.

Groo
A: 

Practice. This is why it's hard to get a job right out of college: everyone knows this is how most people are right after graduation.

I use pen and paper to work out the first draft of a larger design, because it keeps me from getting too caught up in the details that don't matter, and encourages me to draw the bigger picture. Think of it as supplemental short-term memory to help keep you from forgetting your big picture.

Paul McMillan
A: 

great peter! a score of 120 in one hour. that is great. i also face the same problem when writing code. now i have got into the habit of digging deep into design. this has affected my performance in my college project with the result that nothing workable has been built. i feel i have this software engineering principle of deferring design decisions too literally. this has to be corrected. right!

iamrohitbanga
A: 

The book that introduced me to design (specifically design patters) was HeadFirst Design Patters. It's written in a very silly way but is accessible and has a surprising amount of depth!

And like everyone is saying, getting good at design is just a matter of time spent writing code and time thinking about the code you wrote. I've never written a program in which I haven't been able to look at it later and say, "Oh, I could have written it, or done things that way!". I think programming is a lot like writing in that your code can always be rewritten and improved. Then again, I could just be a terrible programmer :)!

Evan
A: 

I have to agree with many here that a firm grasp of Design Patterns is essential for making your code scalable, BUT, as said before, you have to know when to use a pattern and when not to. A few patterns that I recommend learning first might be,

Factory Method
Abstract Factory
Component Pattern
Decorator Pattern

These are just a few, and just suggestions, but are easier to grasp at first. Now, here is one of the most important lessons learned in writing software:

"Program to an interface, not an implementation!"

What does that mean? To put it in a nutshell, think about how you would like the code to be implemented and how it will interface with all your other code (classes). For example, I want to write a program that manipulate images. I'll first decide which methods I would like to implement.

i.e.
getImage(image)
getImageSize()
...etc.

I'm defining the interface, not the implementation! It may be hard at first to understand, but trust me, once you start coding this way you will never go back to implementation-specific code. It's a maintenance nightmare and that is what you want to avoid. You also want your code to be able to scale gracefully and play nice with all the other objects.

I have a couple of open-source programs available that include all the source code and an API. I originally had compiled the packages for students/developers to see how a simple application is put together from beginning to end. You can download at woven-media.com. Woven-media.com is NOT a commercial site, despite the dot com, and all downloads are free and have been tested by several software publishers. Maybe it will help!

BrentAllenParrish
A: 

Is not uncommon that what you think is a good design is not, and the other way around.

We change the perception of our own programs as we mature and learn new things.

One single advise for improve your design is to read the book "Refactoring: Improving the design of existing code" by Martin Fowler.

While the track to become a better designer may be large, the opportunity to refactor an existing piece of code is always there.

Don't get obssesed with perfect designs either. Too much upfront thinking may lead you to big designs that are useless ( beautiful but useless ) Better is to think what you want to achieve, make a quick simple design, and implement. If you need to adapt it, refactor.

Finally, don't be afraid to get a job even if it is not the your dream job, the experience you may get from a real living system ( and all the flaws they have ) will give you invaluable experience to judge what is useful and what is not.

Good designs comes from both the theory and the experience.

OscarRyz
A: 

A mindmap makes a huge difference e.g. freemind, or vym. They capture fleeting thoughts, stimulate and elaborate further thought, and ensure that your program will be clear as to its purpose and appearance. The great advantage about a mindmap over paper is that you can attach an item at the right branch and move them up or down into the right sequence. They also of course act as a to-do list and research list, i.e. basic project management. This advice may sound trivial but makes a huge difference. Its easy to spot where it HASN'T been used - there's so much software that plainly has never been 'thought through'.

Peter Erskine
A: 

Often I'll write a bigger program (say, a few hundred of lines) only to realize that what I wrote is neither elegant nor maintainable.

Fix it!

Go back and fix your existing programs so they become elegant an maintainable. Pick a specific problem (i.e. every time I add a feature I break some working code) and figure out how to resolve the issue (i.e. add unit tests). Once you apply the new technique reevaluate your code (i.e. do you feel comfortable adding new features now) as well as the technique you used (i.e. did it help solve the original problem).

Lawrence Barsanti
A: 

Simple!.. approach someone you know who owns a business, analyze how they operate it and design a system to automate their functions. Developing a system with a Relational Database Development Tool and CASE (Computer Assisted Software Engineering) will also be helpful!

Frank Rotolo
+1  A: 

Programming is a process. I consider myself a pretty good programmer, and looking back on code I've written in the past I realize things I could've done differently and how I could've improved on it. However, that's exactly how you know you are going in the right direction, when you look back at code you wrote 6 months ago and can't find any improvements you could've made, it's likely you either aren't improving yourself as a programmer (this is a bad thing)...or you work for Google.

Since you mentioned you don't have a job yet, I recommend finding something that is of personal use to you. Projects like these give you incentive to actually finish, but also give you the advantage of knowing the requirements/business rules behind the project, which can be some of the biggest hurdles in designing software/web applications.

Just a thought.

Jeremy Battle
A: 
  1. Analize how others applications are designed (the good ones).
  2. Know and learn common patterns and try to find them out in analized applications.
  3. Try to design small pieces of software, then bigger.
  4. Return to number one. I you found better approach try to redesing what you create.

Widen your knowlege and practice all the time.

cetnar
A: 

I learned syntax for a number of languages in college. I learned how to program in the real world. Want to learn how to design good code?

  1. Find a mentor who has experience and the time to help you develop your skills.
  2. Find a job that already has a healthy team environment. If you can't find a job or are not ready to work yet, find an open-source project and tackle something.
  3. Start writing useful code that solves real world problems and share your source.
  4. Have Experienced programmers read your code. They may tear you a new one if you do something poorly but just listen to what they have to say.
  5. Read other people's code. If you don't understand something, ask them why they did what they did.
  6. Don't program in the closet or you might develop bad habits that may be hard to un-learn later.
J.Hendrix
A: 

Write lots of code. Don't worry about design yet.

Read good code. There are quite a few books and articles out there which have good examples. One such book is "Structure and Interpretation of Computer Programs" [1], though some folks find it has too much math related problems in it. Try to solve the problems and compare with authors solutions. Where they differ? Why? These are the kinds of questions you should ask yourself. Also finding a mentor can be a big help.

Rewrite. This is probably the most important part. I've started programming 23 years ago, and I'm doing this professionally for about 15 years, and I still seldom manage to write well something non-trivial the first time around.

An interesting exercise is to try to understand something you've written several months ago. Is it easy for you to understand it? Would you write it differently? Try it and see (probably in a few more months) if it's easier to understand.

Don't rush it. You won't become expert overnight. (If you do, you probably don't need my advise, 'cause you're a genius.) And you're right about the "too much freedom" part as well. Designing is giving up some of this freedom in exchange for things that matter in your project, like readability, maintainability, fast release, fast code, etc. For example, if you're writing a commercial game, which needs to be in stores for the holidays, you'd probably sacrifice long turn maintainability for productivity, but if you're writing a web based system, which you're expecting will be evolving for years, you'd probably have to take different decisions.

Finding a job can also help, though it very much depend on where you end up. Anyway, there in most places you're not expected to be a pro designer to start working as a programmer.

This reply is getting too big already, so I'd add just one last thing. Learn different languages. They are more than just tools, they are cultures. You'd learn that things which are cannon in some languages are blasphemy in others.

Oh yeah. And HAVE FUN!

[1] Available on-line at http://mitpress.mit.edu/sicp/full-text/book/book.html

ivant
A: 

I would agree with those who've said imitate, emulate. Coming from a music education, this is how it is generally done. You have some musicians you respect, honor. You identify with their content and style. You study their solos, transcribing, imitating. You play gigs and learn from your mistakes, or things you like and work for you. You develop your voice. Then, one day, you realize you don't need to imitate any longer, you have acquired enough experience and knowledge to trust yourself. While you continue to learn from those with more experience all the time, you no longer need pure imitation to get the ball rolling. When I switched from music to computer science, I took the practice of dissecting scores and pieces to code. I studied code from those who I respected at work. I studied, tried to understand what was going on, and spent time writing my own program with what I remembered from this experience, attempting to duplicate functionality. It worked for me.

Epictetus
A: 

Some advice - I'll try to be concrete and not repeat too much of other answers:

comichael
A: 

Try and get a job, any good company won't expect you to be designing large projects from the get go. Once you have said job, try and figure out who there is a good designer and gravitate towards them, ask them questions about why they've designed something a specific way and read through specifications written by them. Learn by example is the best way I've observed, though I've been lucky enough to have good mentors.

Ross Anderson
A: 

Start by learning what good designs look like -- Read Design Patterns (See Also the c2 wiki). It's nearly impossible to pick the right patterns up front, so follow up immediately with Refactoring, which will show you how to ease your code in the right direction. (See Also Refactoring.) The best single resource for this is Agile Software Development, Principles, Patterns, and Practices (or Agile Software Development, Principles, Patterns, and Practices) which is good, but is certain that agile is the best way to get good design (So be prepared for that.) You can also get a bunch of the Principles Articles online.

Sean McMillan
A: 

I think the advice from Ross Anderson to get a job and gravitate towards the top designer is very good advice, mentorship is a powerful learning experience. But you can read about good design practices and principles in the mean time. One book I highly recommend is Contextual Design, Defining Customer-Centered Systems by Hugh Beyer and Karen Holtzblatt. I am not a programmer, but I have experience as a designer working with programmers to develop software interfaces. I found this book to be invaluable not only to the process of software design, but design in general.

David Ball
+1  A: 

Realize that there is more than one type of 'Design'. Design in the large turns into architecture and is something that really only comes with experience.

Designing at the lower levels, say at the individual class/object level is easier to cover.

The issues with designing a class is the same regardless of platform or language. The key is whether an object should be autonomous or whether it is better for any given behavior to be spread out among objects with limited scope and distributed responsibility.

For each class the answer might be different. We end up with a spectrum along which we can place classes based upon the Density of Responsibility.

                          (Level of responsibility for behavior)
         Autonomy - - - - - - - - - - - - - - - - - - - Dependence  
      High
  C      -   <<GOD object>>                            <<Spaghetti code>>
  l      -
  a      -  
  s      -                                      
  s      -                 
         -                        
  s      -  
  i      -  
  z      -
  e      -  <<Template>>                                <<Framework>>
       low

Let's say you favor letting the class perform all the behaviours itself, or as many as you can. Starting on the left side of this graph, when you make your class more autonomous, the size of the class will grow unless you continuously refactor it to make it more generic. This leads to a template. If no refactoring is done, the temdency is for the class to become more "god-like" because if there is some behavior it needs, it has a method for that. The number of fields and methods grow and soon become both unmanageable and unavoidable. Since the class already does so much, coders would rather add to the monstrosity than try to piece it apart and cut the Gordian knot.

The right side of the graph has classes that depend on other classes to a large degree. If the dependency level is high but the individual class is small, that is a sign of a framework; each class doesn't do much and requires lots of dependent classes to accomplish some function. On the other hand, a highly-dependent class that also has a large amount of code is a sign that the class is full of Spaghetti.

The key to this question is to determine where you feel more comfortable on the graph. In any event, individual classes will end up spread out on the graph unless some organizational principle is applied, which is how you can achieve the results of Template or Framework.

Having just written that, I would say that there is a correlation between class size and degree of organization. Robert C. Martin (or "Uncle Bob") covers similar ground with package dependencies in his very thorough paper on Design Principles and Design Patterns. JDepend is an implementation of the ideas behind the graph on page 26 and complements static analysis tools such as Checkstyle and PMD.

Kelly French