Related
In POODR, author Sandi Metz gives an example a Trip class, that needs to be prepared.
The Trip class defines a method prepare, which from the outside appears to say it can prepare it self,
but in fact it does so by internally asking some other object to prepare it, like bellow
class Trip
def initialize(preparers)
#preparers = preparers || []
end
def prepare
#preparers.each do |preparer|
preparer.prepare(self)
end
end
end
Given we never know of an object's internals, looking only from the outside this
seems a bit odd as it makes the object appear to be clever. I mean how can a trip
know how to prepare it self.
However, if we don't do this we go back to just having data structures
whose state is controlled by some outside function.
Thinking more of it, IRL I usually tell my baby brother "cut your hair", but in fact,
what happens is he goes to the barber shop, and has them cut his hair.
So the notion is not that weird and might apply to objects.
I can't put a name to this yet, but it makes me think I've been misunderstanding
messages for what an object can do, when in fact they're just what an object
can accept and respond to. We never know an object's internals so who
cares about how it goes about responding to messages.
Is this line of thinking correct?
Is this what it means by intent and implementation separation?
Or the analogy doesn't fall it line at all.
Cheers
If I send you a letter saying "please, compute 2+2 for me", and I get a letter back which says "4", I have no idea how you come up with that answer, you may have memorized it, you may have looked it up, you may have computed it by hand, you may have used a calculator, you may have sent a letter to someone else asking them to compute 2+2, you may have sent several letters to several other people asking them to compute sub-problems of 2+2, you may have read the letter and decided based on its contents to pass it on to a specialist, you may have not read the letter and just blindly passed it on to someone else without even opening it, or your secretary may have opened it and answered on your behalf without you even knowing about it.
That's the fundamental nature of messaging: I cannot, should not, and must not know how you were able to answer. The only thing I can observe is the answer. As long as the answer is correct, it doesn't matter to me how the answer was obtained. Maybe it was printed out, mailed to China, computed by hand in an office, then mailed back and scanned. I don't know and I don't care.
Is this line of thinking correct?
Yes.
Is this what it means by intent and implementation separation?
I am not familiar with that phrase. Is that something from the book? If yes, you should explain what it means in your question.
Or the analogy doesn't fall it line at all.
No, the messaging metaphor is a good one. It is the fundamental idea of OO. Classes are irrelevant, even objects are irrelevant. Messaging is what it's all about.
In my opinion, the problem is the lack of context / domain. If this Trip is used, for example, by the hotel / resort, then this is a mistake. If Trip exists in the minds of travelers, then this is a good design. For people, a trip is, in particular, a list of people traveling with them and the opportunity to notify them of the preparation for the trip.
I would solve this problem by more expressive naming of classes, modules / packages, etc.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Do you ever run into a bug where you are just out of ideas and don't know what to try next, and you're getting really annoyed? Are there any general ideas on how to break out of this mode?
When I get blocked like that, the best advice I've found is leave for a while. Whether it's going for a long lunch or leave for the day. Come back fresh and take a new look. Most of the time the answer will be staring you in the face. So far a 10 minute coffee break hasn't been enough for me, but your mileage may vary.
Second, talk to your peers. Walk through everything you've tried. Just ask them to listen, and while you're talking it through, a lot of times, the answer will come to you.
Those are just the two that I use most often when I'm debugging blocked.
Five minute break
Utterly critical, lest you smash your keyboard.
Explain the problem in an email to your sister
Or your two year old son. Someone who wouldn't understand a word* unless you explained it very clearly. You don't need to send the email, you just need to be certain that you understand it inside out. You be surprised at how many times simply restating the problem suddenly makes it obvious to you where you went wrong. This is a good way of discovering what your assumptions were about the problem, and how they might not necessarily be correct.
*That link is to an excellent answer by JaredPar on a different SO question.
Talk to a colleague
By this point you've already 'emailed' the family pet, so you know that you've hopefully covered all the stupid aspects, it's time to talk to a real person. They may have experienced some obscure thing in the past that reminds them of this situation, and they'll definitly have a different perspective. Try to make sure you are clear about what the problem is, not what you think it is. You don't want to bias them. You can and should talk about what they've tried, and explain why you think the problem is in that area (you're probably right) but you don't want to close your mind to their suggestions, even if they don't seem right.
Look at the code again
By this time, you should hopefully be less violent, and you should be armed with new ideas. Start by re-verifying the bug. A simple step, but I've been frustrated for hours on a bug that was in our test script and not in our code. Once you've verified the bug again, start at the top. Verify EVERYTHING. Put a breakpoint at the last point you are 100% confident in, and then work your way forward until you find that the output is broken again. That's a huge success because you now have a hopefully smaller code block to investigate. Then, if necessary, pull in a colleague to look at the actual running code.
I usually take a break... if that doesn't work, I sleep on the problem. (Actually, to be honest, I should say that I spend a sleepless night mulling over the problem).
I almost always have a list of possible solutions ready by morning. :-)
I usually take a few steps:
look at the code that is involved in the functionality that has the bug and place logger messages in a way that they will help me narrow the problem (this allows you to look at the logger later on when you are not that annoyed anymore, and maybe find useful hints :P)
ask my senior collegues for hints
call the client to have a clear understanding of when the problem arises
I usually end up in that mood when I didn't take a structural approach from the beginning.
By iteratively narrowing the area where the problem can live and trying to write the smallest code base that can reproduce the error, I haven't failed yet.
Others have mentioned taking a break or "sleeping on it". This technique is known as (amongst other things) Incubation. Once you embrace the idea you can take it further too.
One important aspect as to really leave the problem behind, confident that you'll have answers later. The dangerous otherwise, especially if sleeping on it, is that you'll be worrying over it up to the last minute, then this becomes an endless cycle that your mind gets caught in overnight. You'll probably end up waking up not too well rested having dreamt many circular dreams. Do this too much and it's a path to depression.
I think if you run into that kind of problem it is time to do some serious refactoring...
Also it could indicate false assumptions. Try to assume programmatically all that you are 'just' assuming. See to it no method-invariants are broken of any methods that are in the stack.
Another good option is to bounce ideas off other developers/team members. Sometimes they will ask you questions you hadn't considered.
If you work alone, it's a good idea to have a few fellow developers who you can chat to to troubleshoot with some different approaches. You'd be amazed how often a fresh perspective can be the breakthrough you need.
Try David Ungars "Shower Methodology":
"If you know what to type, type. If you don't know what to type, take a shower and stay in the shower until you know what to type"
This kind of summons up what the majority likes to do. Take a break ! Doesn't matter what kind of break it is, as long as you are not thinking of the things you were doing before the break. Distraction in any form is good.
Cheers !
I usually take a dry run through the offending method/function, step by step. And don't assume the bug is coming from there, it could be coming from anywhere before it.
Use a proper debugger, don't use a series of printfs.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
When is it the right time and when is it the wrong time to take the quick and dirty approach versus the proper elegant solution?
This started from the comments on my question: Decode Base64 data in Java.
I wanted a way to do something using only internal Java or something I wrote. The only built in way is to use the sun.* package which is unsupported. So when is it the right time and when is it the wrong time to take that approach?
In my opinion the only "right time" to use a quick and dirty solution (aka hack) is when...
There is a mission-critical bug that needs immediate fixing and the proper solution is significantly complicated to implement.
It's an internal application and some higher ups need a quick feature implemented (hey, neither you nor your customers use it).
In any situation, you have to balance the time that will be spent on solving the problem, and then the time that will be spent in maintaining that solution. If the lifetime of whatever you do is expected to be lengthy, then the extra time spent up front to do things the right way will, presumably, be easier to maintain and will save you in the long run.
However, if there are time constraints, the penalties for going over may far outweigh the maintenance cost. For example, if you MUST get a product out the door, do a quick-and-dirty solution now, and then log it as a bug to get fixed later in a patch, or the next version. That will require you to re-do the work, but like I said, it is all a balancing act, and often driven by cost at it's root.
The right answer is that its never time to do the quick and dirty solution.
But sometimes (when having a big customerbase and lots of programs out there) its better to ship a fix with a Q&D that maybe breaks something, but FOR SURE fix more.
I dont know if I understand the question right but Ill leave it with this.
If there exists a simple but less elegant solution that closely matches the style and techniques used elsewhere in the code base (and consequently, is more easily understood by your colleagues), it may be safer to take that path -- compared to the solution that is perfect from an academic point of view, but difficult to understand if you never happened to read that specific paper.
Similarly, a small change may be considerably safer than a major refactoring effort that the elegant solution would basically require. This is especially relevant in any world that lacks unit tests.
If the project is a "proof of concept" work rather than a production implementation, it may be the right time for a quick and dirty solution that gets the job done of illustrating how easy or hard some particular part is of a system. I'm thinking of where one may want to test out a new ERP or CRM system and just want to see the mechanics of it without spending a ton of time and money to get a more realistic prototype working.
In most other cases, it is a question of trade offs. How many defects can something have that gets released into the wild? Are just no showstoppers bugs OK or does there have to be few only a few minor or cosmetic bugs left. If some project managers or business units want something quick but not necessarily fully working then it the quick and dirty solution may work if those asking understand the risks. In a way this is like the question of how many tests should a doctor give before making a diagnosis: Should you be examined head to toe through a variety of different waves of energy, e.g. X-ray, CT scan, MRI, etc. Or can the doctor just look at what you are doing and know what is wrong like Dr. House does from time to time.
It seems to me that quick and dirty solution is more often necessitated by a lack of planning somewhere moreso than it is because of a sudden change of business rules (not to say that doesn't happen though!). Either someone wasn't given appropriate tools to do their job, someone vastly underestimated the amount of time something will take, or someone got too attached to a feature that is overly complicated. In most of those cases, it's best to push back your release or scale back the features in the release.
In the case that it was necessitated by a business priority that you have no control over (like a legal issue), then you need to get it out the door as quickly as possible. But you should make the fix better for the next release!
It's the right time to use a quick and dirty solution when:
You need the solution to be quick (assuming no professional solution exists that is approximately as quick), and
You don't suffer consequences for it being dirty.
In some ways, that's a flippant answer, but it does cover it.
In your situation, you can't introduce a new library quickly. And you do have a process to mitigate the risk of using experimental code. As long as that process is reliable, and you are confident that production code won't include your quick & dirty solution, then go ahead.
Once my company was struggling to get some code working for a demo at a trade show. They were running out of time, the demo just one day away. I suggested they hard-code some options instead of making them configurable and dynamic.
It worked -- they got the demo running for the next day's show. Then when they got back to the office, they immediately removed the hard-coded part and finished their feature.
If you can rely on replacing the quick & dirty hack being top priority, then quick & dirty can be appropriate. It's just so seldom the case that it's top priority, that using this solution is usually a bad idea.
As noted by tj111 and others, there are times when the risk of an elegant solution are greater than that of the quick and dirty. I.e., you deliver something beautiful, but by that time the customers no longer want it, want something different, or are pissed off.
To be sure though, there is always a long-term cost with doing a quick and dirty solution and it is important to deliver a firm and forceful "by the way" caveat to management. Else the quick and dirty becomes like crack to management who often do not know or care of the difference between the elegant and dirty (especially when it is under the hood). That is until things start to go to hell, and even then the fixitnow stress is offloaded to the hapless (often new) technical team.
So yeah, sometimes you have to do it because of $$ and time considerations, but don't cloak it or forget it and strive and push to re-factor soon when the crisis wanes.
Remember a lot Application get built off of their prototypes.
We always want to think its throw away code. But it will grow!
In my case I work in a research and development position where we have a long process for getting approval when adding external libraries.
If code is marked as experimental it will be cleaned up before moving to production. I needed this for a quick experiment to see if something was even going to make sense for us to work on and needed to get the data processing quickly. So the quick and dirty approach was the right one to get things done asap. If we decide to work on the experiment I will have time to replace the functionality properly.
In the standard case where as kdgregory put it in the comments of one answer:
Bzzt. In a professional environment,
using an unsupported, undocumented
feature is never the correct decision.
And in a corporate environment,
"experiments" become "production code"
with no chance to fix the hacks.
I think he is correct that it is not the appropriate approach when you work in a position where you have even a doubt that it may go into production. The only exception with this is if you absolutely do not have the time for a proper fix but can mark it as being a high priority issue in some visible public place (bug tracker) and will definitely be able to fix it in a future release.
Sometimes a quick and dirty solution is synonymous with an unmaintainable solution. Other times it just means solving the (simple) problem you actually have, not the (more complex) generalization of that problem. I'm a grad student doing research in bioinformatics and I often need to write small programs that do simple things like reformat or summarize a few hundred megs of data. Occasionally I need to write several of these apps per day. If I wrote "proper" solutions to these I'd never get anything done.
Solving the general case (not quick and dirty) would mean making an app that handled errors robustly, was usable by people other than me, was configurable, etc. This would solve lots of problems that I don't have. I'm probably the only one that will ever use these programs. All the configurability I need is a few command line options and the ability to edit the source file as needed. All the error handling I need is displaying a decent error message and exiting if there's a problem.
Of course, sometimes these programs do grow into something more important and sometimes I do end up reusing code from them. Maintainability counts. Even in a quick and dirty solution, magic numbers should not be hard coded, variables should not be named "foo", "bar", and "stuff", and programs should not be written as one giant 400-line main() function. I learned these the hard way.
Sometimes you have to do things in Q&D way. What you need to do in that circumstance is to protect yourself by hiding the dirty implementation behind an interface or an adapter.
To use the cited example, the Sun.* package works for now, but may not sometime in the future. Fine. Then wrap it in an adapter that implements the desired interface. Then, when Sun changes the API (hopefully providing something permanent like Java.BASE64), you can quickly update your implementation to cope with the change.
I do a quick and dirty fix when three conditions are met:
There isn't enough time to do a proper solution
The fix and it's scope are clear and contained (it's easy to come back, know what the fix addressed, can be easily removed and replaced by a proper implementation)
The fix is atomic or has no dependencies
"Quick and Dirty", is often synonymous with "cheap yet actually works", which is generally all you need to get the job done. If anybody criticizes your code, pretty much the best defence is to say "yeah- it was just a quick and dirty solution". That way your coder colleagues can feel superior to you, whilst you pointy haired boss looks on, rubbing his chin in silent approval.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
When I am stuck with a problem:
I search Google for code snippets.
I look at isolating the problem, so that I can better explain it to others in order to get answers.
What search techniques do you use to find the solution to your problem?
I started asking questions in Stack Overflow.
What other techniques or methods do you follow, to fix the problem more quickly?
Go and do something else. No, really. I've found that putting the problem away in the back of my mind helps. I can't count the number of times I thought of a great solution to something I've been working on when I was working on something else, or watching TV, or eating. It seems your brain is still working on the problem in the background.
If that fails to solve your problem, try talking to someone. You'd be surprised how often others can give solutions to your problem that are so simple you'd facepalm.
Well there's:
Google
Google
Google
Stack Overflow
Google
Google
Maybe a book if I have one.
Seriously, I started (hobby) programming in the 1980s and even into the mid 90s you had to know things and have a technical library. Then Google came along and it's easier to Google something than it is to look up (bookmarked!) API documentation (Google "java stringbuilder" will get me there faster than navigating will) let alone an actual book (electronic or paper).
Most problems you're trying to solve have been solved before. Many times.
The rest of debugging comes down to decomposition, possibly unit testing (which is related to decomposition) and verifying your assumptions.
By "decomposition", I mean that your solution is structured in such a way that small pieces can be individually tested and readily understood. If you have a 7000 line method you're (probably) doing something wrong.
Understanding what assumptions you've made is key too so you can verify them. For example, when I started with PHP I wrote a piece of code like this:
$fields = $_SESSION["fields"]; // $fields is an associative array
$fields["blah"] = "foo";
and I was scratching my head trying to figure out why it didn't work (the array wasn't being updated next time I queried $_SESSION). I came from a Java background where you might do this:
Map fields = (Map)httpSession.get("fields");
fields.put("blah", "foo");
and that would most definitely work. PHP however copies the array. A working solution is to use references:
$fields =& $_SESSION["fields"]; // $fields is an associative array
$fields["blah"] = "foo";
or simply:
$_SESSION["fields"]["blah"] = "foo";
The last thing I'll say about debugging and writing robust code in general is to understand the boundaries of your solution. By this I mean if you're implementing a linked list then the boundary conditions will revolve around when the list is empty.
Explain the problem to a colleague, or write it down to describe it. That will makes you think a different way, from a different perspective. In order to be more accurate, and to describe the context of the problem, you'll step back, get a higher level view of the problem, you may find out think you overlooked something that is actually important.
Sometimes, you even find the explanation before ending your description.
My best friend for many years has been to jump on my bike and go home. Just getting away from the keyboard has solved many problems over the years for me.
If the problem lasts to the end of the day, I try and consciously lock the problem away for solving before I go to sleep.
I realise this sounds a bit out there, but it has been very common in my experience that I'll wake up with at least an alternate approach to the problem, if not the full-on solution. The idea is not to stress about it - but actively decide to solve it over night. That way you can go to sleep without worry.
I think eating well, regular exercise and good sleep are huge contributors to the problem-solving process.
Usually I'll try nut out the problem for a few hours or so, trying different things writing it on paper, making diagrams. If none of that works I'll usually work through the following options.
Put a sticky note on my monitor and keep going with something else
Glance at the note through out the next few hours to keep the problem in the back of my mind
Google for similar problems and the methods used
Consult a co-worker or a friend
Ask on a forum such as stackoverflow
Give up and design the problem away or design a way around the problem so it can be dealt with some other time and stick a TODO note at the site of said workaround
Don't forget Google Code Search
It's often best to clear your head by doing something other than programming for a little while. See this answer for an example - I did it while struggling with a particularly thorny bug, and when I came back to the problem I solved it in about a minute.
Usually I try to solve it until I go to sleep.. Sometimes I write on paper what the code is doing and then I divide it in pieces; I try to know how the variables of the program change when it's running.
Try solving a much smaller version of the problem first and see how you get on with that.
Once you've done that the bigger problem won't look so scary.
Ask yourself: is solving this particular tricky problem really important to what you doing?
For the purposes of your application (or whatever the big picture is) is there a similar but easier problem that you could address to accomplish broadly the same thing.
Normally, I would get pen and paper and try to work out the details of the problem there. If that doesn't help, Google. Failing that, I'd do something else for a while, or ask online. Worked for me so far.
The fact you are stuck might be a 'code-smell'. Suggesting that their is something wrong with the design or approach somewhere else. Try to put your finger on what's causing this and fix this instead.
When you come back to your problem it might no longer exist.
One more time, browse thru what I think might be relevant, then take nap.
There are two other answers which mention sleeping or napping, but this deserves more emphasis. It is now known that there's SERIOUS machinery in there which goes to work when you sleep. Google (( CBS SCIENCE SLEEP )) will get you to a great free video.
If I can't figure out how to solve the real problem, I try to consider a simplified version of the problem. To take a simple example: I recently had the problem of finding a set of shipping routes to get an item from point A to point B, when there is not necessarily a direct route from A to B, but there might be an A to C and then C to B, or A to C, C to D, and then D to B. (I'm sure the airlines and railroads do this all the time.) That was fairly complex, so I tried looking first at the simple case: a direct A to B. That was easy. Then consider how I'd handle it with one stop along the way. Then consider two stops. At that point I was able to see the pattern to a solution.
Solutions to a simplified version of the problem may end up being a part of the bigger solution, with some additional complexity wrapped around them. But even if not, the exercise of solving the easier problem often gives you ideas on how to solve the real problem.
The main techniques I use (should be followed in order so that you can reuse what you have done in previous steps to be more efficient):
Define your issue: Try to clearly define what's the problem, and what's expected. See 2 to help you.
Collect data about the bug: Log everything: your attempts, the expected result, the observed result. This will avoid the need to redo several times the same tests (because your mind cannot memorize it all), and probably help you see the bigger picture.
Reduce your problem. This is true in general for any abstract modelling of natural phenomenons, but it's even more true of programming, because programs are very complex entities. You should try to reduce your code to a minimal program that reproduces your issue. Automated tools exist.
Talk to someone: several anecdotes affirm than about 2/3 of the bugs are resolved just by talking about it. See the Helpful Teddy Bear anecdote. If you have previously reduced your program to a minimal program, and have a clear definition of your issue, both will be useful to your explanation.
Reach for collaborative help: search on Google and on StackOverflow, and post if you can't find anything that answers your problem (but first see 1, you must have a clear definition of your problem).
As you can see, I put the collaborative help as the last step, because you should only ask for help after you have clearly defined your issue and tried to reduce the problem and fix it by yourself. If you reach for collaborative help before having tried the previous steps, you will either end up with a poor help or figure it out by yourself as soon as you have posted.
Also you can be interested in the Coursera Software Debugging course, which also describes several automated debugging methods.
Go to the toilet.
You move, so your brain gets oxygen.
You relax, so you focus on other things.
Peeing for innovation! :)
Closed. This question is off-topic. It is not currently accepting answers.
Closed 10 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I've been working with a small group of people on a coding project for fun. It's an organized and fairly cohesive group. The people I work with all have various skill sets related to programming, but some of them use older or outright wrong methods, such as excessive global variables, poor naming conventions, and other things. While things work, the implementation is poor. What's a good way to politely ask or introduce them to use better methodology, without it coming across as questioning (or insulting) their experience and/or education?
Introduce questions to make them realise that what they are doing is wrong. For example, ask these sort of questions:
Why did you decide to make that a global variable?
Why did you give it that name?
That's interesting. I usually do mine this way because [Insert reason why you are better]
Does that way work? I usually [Insert how you would make them look silly]
I think the ideal way of going about this is subtly asking them why they code a certain way. You may find that they believe that there are benefits to other methods. Unless I knew the reason for their coding style was due to misinformation I would never judge my way as better without good reason. The best way to go about this is to just ask them why they chose that way; be sure to sound interested in their reasoning, because that is what you need to attack, not their ability.
A coding standard will definitely help, but if it were the answer to every software project then we'd all be sipping cocktails on our private islands in paradise. In reality, we're all prone to problems and software projects still have a low success rate. I think the problem would mostly stem from individual ability rather than a problem with convention, which is why I'd suggest working through the problems as a group when a problem rears its ugly head.
Most importantly, do NOT immediately assume that your way is better. In reality, it probably is, but we're dealing with another person's opinion and to them there is only one solution. Never say that your way is the better way of doing it unless you want them to see you as a smug loser.
Start doing code reviews or pair programming.
If the team won't go for those, try weekly design reviews. Each week, meet for an hour and talk about a peice of code. If people seem defensive, pick old code that no one is emotionally attached to any more, at least at the beginning.
As #JesperE: said, focus on the code, not the coder.
When you see something you think should be different, but others don't see it the same way, then start by asking questions that lead to the deficiencies, instead of pointing them out. For example:
Globals: Do you think we'll ever want to have more than one of these? Do you think we will want to control access to this?
Mutable state: Do you think we'll want to manipulate this from another thread?
I also find it helpful to focus on my limitations, which can help people relax. For example:
long functions: My brain isn't big enough to hold all of this at once. How can we make smaller pieces that I can handle?
bad names: I get confused easily enough when reading clear code; when names are misleading, there's no hope for me.
Ultimately, the goal is not for you to teach your team how to code better. It's to establish a culture of learning in your team. Where each person looks to the others for help in becoming a better programmer.
Introduce the idea of a code standard. The most important thing about a code standard is that it proposes the idea of consistency in the code base (ideally, all of the code should look like it was written by one person in one sitting) which will lead to more understandable and maintainable code.
You have to explain why your way is better.
Explain why a function is better than cutting & pasting.
Explain why an array is better than $foo1, $foo2, $foo3.
Explain why global variables are dangerous, and that local variables will make life easier.
Simply whipping out a coding standard and saying "do this" is worthless because it doesn't explain to the programmer why it's a good thing.
First, I'd be careful not to judge too quickly. It's easy to dismiss some code as bad, when there might be good reasons why it's so (eg: working with legacy code with weird conventions). But let's assume for the moment that they're really bad.
You could suggest establishing a coding standard, based on the team's input. But you really need to take their opinions into account then, not just impose your vision of what good code should be.
Another option is to bring technical books into the office (Code Complete, Effective C++, the Pragmatic Programmer...) and offer to lend it to others ("Hey, I'm finished with this, anyone would like to borrow it?")
If possible, make sure they understand that you're critizising their code, not them personally.
Suggest a better alternative in a non-confrontational way.
"Hey, I think this way will work too. What do you guys think?" [Gesture to obviously better code on your screen]
Have code reviews, and start by reviewing YOUR code.
It will put people at ease with the whole code review process because you are beginning the process by reviewing your own code instead of theirs. Starting off with your code will also give them good examples of how to do things.
They may think your style stinks too. Get the team together to discuss a consistent set of coding style guidelines. Agree to something. Whether that fits your style isn't the issue, settling on any style as long as it's consistent is what matters.
By example. Show them the right way.
Take it slow. Don't thrash them for every little mistake right off the bat, just start with things that really matter.
The code standard idea is a good one.
But consider not saying anything, especially since it is for fun, with, presumably, people you are friends with. It's just code...
There's some really good advice in Gerry Weinberg's book "The Psychology of Computer Programming" - his whole notion of "egoless programming" is all about how to help people accept criticism of their code as distinct from criticism of themselves.
Bad naming practices: Always inexcusable.
And yes, do no always assume that your way is better... It can be difficult, but objectivity must be maintained.
I've had an experience with a coder that had such horrible naming of functions, the code was worse than unreadable. The functions lied about what they did, the code was nonsensical. And they were protective/resistant to having someone else change their code. when confronted very politely, they admitted it was poorly named, but wanted to retain their ownership of the code and would go back and fix it up "at a later date."
This is in the past now, but how do you deal with a situation where they error is ACKNOWLEDGED, but then protected? This went on for a long time and I had no idea how to break through that barrier.
Global variables: I myself am not THAT fond of global variables, but I know a few otherwise excellent programmers that like them A LOT. So much so that I've come to believe they are not actually all that bad in many situations, as they allow for clarity, ease of debugging. (please don't flame/downvote me :) ) It comes down to, I've seen a lot of very good, effective, bug free code that used global variables (not put in by me!) and great deal of buggy, impossible to read/maintain/fix code that meticulously used proper patterns. Maybe there IS a place (though shrinking perhaps) for global variables? I'm considering rethinking my position based on evidence.
Start a wiki on your network using some wiki software.
Start a category on your site called "best practices" or "coding standards" or something.
Point everyone to it. Allow for feedback.
When you do releases of the software, have the person whose job it is to put code into the build push back on developers, pointing them to the Wiki pages on it.
I've done this in my organization and it took several months for people to really get into the hang of using the Wiki but now it's this indispensable resource.
If you have even a loose standard of coding, being able to point to that, or indicating that you can't follow the code because it's not the correct format may be worthwhile.
If you don't have a coding format, now would be a good time to get one in place. Something like the answers to this question may be helpful: https://stackoverflow.com/questions/4121/team-coding-styles
I always go with the line 'This is what I would do'. I don't try and lecture them and tell them their code is rubbish but just give an alternative viewpoint that can hopefully show them something that is obviously a bit neater.
Have the person(s) in question prepare a presentation to the rest of the group on the code for a representative module they have written, and let the Q&A take care of it (trust me, it will, and if it's a good group, it shouldn't even get ugly).
I do love code, and never had any course in my live about anything related to informatics I started very bad and started to learn from examples, but what I always remember and kept in my mind since I read the "Gang Of Four" book was:
"Everyone can write code that is understood by a machine, but not all can write code that is understood by a human being"
with this in mind, there is a lot to be done in the code ;)
I can't emphasize patience enough. I've seen this exact sort of thing completely backfire mostly because someone wanted the changes to happen NOW. Quite a few environments need the benefits of evolution, not revolution. And by forcing change today, it can make for a very unhappy environment for all.
Buy-in is key. And your approach needs to take into account the environment you are in.
It sounds like you're in an environment that has a lot of "individuality" to it. So... I wouldn't suggest a set of coding standards. It will come across that you want to take this "fun" project and turn it into a highly structured work project (oh great, what's next... functional documents?). Instead, as someone else said, you'll have to deal with it to a certain extent.
Stay patient and work toward educating others in your direction. Start with the edges (points where your code interacts with others) and when interacting with their code try to take it as an opportunity to discuss the interface they've created and ask them if it would be okay with them if it was changed (by you or them). And fully explain why you want the change ("it will help deal with changing subsystem attributes better" or whatever). Don't nit-pick and try to change everything you see as being wrong. Once you interact with others on the edge, they should start to see how it would benefit them at the core of their code (and if you get enough momentum, go deeper and truly start to discuss modern techniques and the benefits of coding standards). If they still don't see it... maybe you'll need to deal with that within yourself (especially on a "fun" project).
Patience. Evolution, not revolution.
Good luck.
I don a toga and open a can of socratic method.
The Socratic Method named after the Classical Greek philosopher Socrates, is a form of philosophical inquiry in which the questioner explores the implications of others' positions, to stimulate rational thinking and illuminate ideas. This dialectical method often involves an oppositional discussion in which the defense of one point of view is pitted against another; one participant may lead another to contradict himself in some way, strengthening the inquirer's own point.
A lot of the answers here relate to code formatting which these days is not particularly relevant, as most IDEs will reformat your code in the style you choose. What really matters is how the code works, and the poster is right to look at global variables, copy & paste code, and my pet peeve, naming conventions. There is such a thing as bad code and it has little to do with format.
The good part is that most of it is bad for a very good reason, and these reasons are generally quantifiable and explainable. So, in a non-confrontational way, explain the reasons. In many cases, you can even give the writer scenarios where the problems become obvious.
I'm not the lead developer on my project and therefore can't impose coding standards but I have found that bad code usually causes an issue sooner rather than later, and when it does i'm there with a cleaner idea or solution.
By not interjecting at the time and taking a more natural approach i've gained more trust with the lead and he often turns to me for ideas and includes me on the architectural design and deployment strategy used for the project.
People writing bad code is just a symptom of ignorance (which is different from being dumb). Here's some tips for dealing with those people.
Peoples own experience leaves a stronger impression than something you will say.
Some people are not passionate about the code they produce and will not listen to anything you say
Paired Programming can help share ideas but switch who's driving or they'll just be checking email on their phone
Don't drown them with too much, I've found even Continuous Integration needed to be explained a few times to some older devs
Get them excited again and they will want to learn. It could be something as simple as programming robots for a day
TRUST YOUR TEAM, coding standards and tools that check them at build time are often never read or annoying.
Remove Code Ownership, on some projects you will see code silos or ant hills where people say thats my code and you can't change it, this is very bad and you can use paired programming to remove this.
Instead of having them write code, have them maintain their code.
Until they have to maintain their steaming pile of spaghetti, they will never understand how bad they are at coding.
Nobody likes to listen someone saying their work sucks, but any sane person would welcome mentoring and ways of avoiding unnecessary work.
One school of teaching even says that you should not point out mistakes, but focus what is done right. For instance, instead of pointing out incomprehensible code as bad, you should point out where their code is particularly easy to read. In the first case you are priming others to think and act like crappy programmers. In the later case you are priming for thinking like a skilled professional.
I have a similar senario with the guys i work with.. They dont have the exposure to coding as much as i do but they are still usefull at coding.
Rather than me letting the do what they want and go back and edit the whole thing. I usually just sit them down and show them two ways of doing things. Thier way and My way, From this we discuss the pro's and cons of each method and therefore come to a better understanding and a better conclusion on how should we go about programming.
Here is the really suprizing part. Sometimes they will come up with questions that even i dont have answers to, and after research we all get a better concept of methodology and structure.
Discuss.
Show them Why
Don't even think you are always right.. Sometimes even they will teach you something new.
Thats what i would do if i was you :D
Probably a bit late after the effect, but that's where an agreed coding standard is a good thing.
I frankly believe that someone's code is better when it's easier to change, debug, navigate, understand, configure, test and publish (whew).
That said I think it is impossible to tell someone his/her code is bad without having a first go at having him / her explaining what it does or how is anyone supposed to enhance it afterwards (like, creating new funcionality or debugging it).
Only then their mind snaps and anyone will be able to see that:
Global variables value changes are almost always untrackable
Huge functions are hard to read and understand
Patterns make your code easier to enhance (as long as you obay to their rules)
( etc...)
Perhaps a session of pair programming should do the trick.
As for enforcing coding standards - it helps but they are too far away from really defining what is good code.
You probably want to focus on the impact of the bad code, rather than what might be dismissed as just your subjective opinion of whether it's good or bad style.
Privately inquire about some of the "bad" code segments with an eye toward the possibility that it is actually reasonable code, (no matter how predisposed you may be), or that there are perhaps extenuating circumstances. If you are still convinced that the code is just plain bad -- and that the source actually is this person -- just go away. One of several things may happen: 1) the person notices and takes some corrective action, 2) the person does nothing (is oblivious, or doesn't care as much as you do).
If #2 happens, or #1 does not result in sufficient improvement from your point of view, AND it is hurting the project, and/or impinging on you enough, then it may be time to start a campaign to establish/enforce standards within the team. That requires management buy-in, but is most effective when instigated from grass roots.
Good luck with that. I feel your pain brother.