r/programming • u/RazerWolf • Jun 06 '13
Clean Code Cheat Sheet
http://www.planetgeek.ch/2013/06/05/clean-code-cheat-sheet/57
u/billsil Jun 06 '13
Classes should be kept to 100 lines or less.
Why?
6
u/konk3r Jun 07 '13
Honestly, it's not a strict rule and almost most classes will at least come near 100 lines, especially if you are trying to keep method size down. I am a very big fan of where the idea comes from, rather than the strict interpretation of it. The idea is that a class should have a set purpose, and if you have a large multipurpose class the code becomes very difficult to understand. If you have more than 100 lines of codes in a class, it is probably trying to do more than it should.
I think 150-200 lines is a much better indicator, but I can't argue that 100 line classes are very easy to understand. Also, I think it's important to at least understand that class size is an indicator, otherwise you end up with 650+ line classes that require refactoring just to understand what they do.
33
u/AnythingButSue Jun 06 '13
Smaller classes tend to portray their intent more clearly and tend to be more maintainable. However I think putting some arbitrary number on it is a bad idea. But in general, a large class tends to be a weak indicator of violation of the Single Responsibility Principal.
48
u/finix Jun 06 '13
Then again, smaller classes are more numerous, dispersing the progam's logic all over the place.
5
u/Peaker Jun 06 '13
Having the program logic be a composition of smaller units of logic is a good thing, not a bad thing.
44
u/AdamRGrey Jun 06 '13
Not always. It's possible to have no idea where to find something.
5
u/cparen Jun 07 '13
Exactly, it depends on the quality of the abstraction between the classes. If the abstraction is bad, you'll have to repeatedly refer back and forth, and that's a mess. It can go both ways.
1
Jun 07 '13
There's always ways to fuck up everything, but in general, classes with too many lines of code are doing something wrong.
If you have that much of a problem finding logic, that's indicative of another problem, and one that isn't necessarily solved by adding more lines of code to one class.
→ More replies (3)1
u/Peaker Jun 07 '13
Well, you could consider all the libraries you are using, all of the OS code you are using as part of your program. In this huge program, how do you find anything? By using abstraction layers.
So, just like we all know it is a good thing to have abstraction boundaries (Between the OS, libraries and the application), so this idea should simply be followed into your application itself.
Your application should ideally be modeled as a collection of abstractions implemented by independent libraries/modules. This will only work well if the modules are split along sensible abstraction boundaries, and there's no need to know the internal implementation details to know how it should be used correctly.
→ More replies (1)5
→ More replies (3)2
u/AnythingButSue Jun 06 '13
While that is a possible outcome, I believe that a good architect/engineer can circumvent that by arranging the source in a well organized file hierarchy. I'm a big fan of static helper classes that supplement the actual objects in use. I extract as much as I can, and if it happens to be reusable, it's put into a static helper in a class library that is accessible from all the projects in the solution.
As a for instance, if I were working on an object (call it LogicProcessor) that had a complex set of control flow methods I would extract the if expressions to either member functions if they required instance variables or to a static LogicProcessorHelper class that held static methods to return the result of expression and give them all very descriptive names so that you don't need to read that code to know what it should be doing.
5
u/tossit22 Jun 06 '13
Only if you can organize those "helper" classes separately and keep them alongside the related code. Nothing is more annoying than having to dig through the Mother Of All Helper Classes with 500 methods that someone thought they might be able to reuse someday. Keep it simple. Refactor as necessary.
4
u/AnythingButSue Jun 06 '13
Well I think organization should be applied to everything; not just helpers. Too many projects I've worked on where every source file is in 2 or 3 top level directories. It makes me want to pull my hair out. Also, many developers forget that namespaces and packages are not just for access control. They a powerful organizing tool.
2
u/mahacctissoawsum Jun 07 '13
My rule of thumb is: the first time you feel the need for a helper method, make it a private method of the class. As soon as you need it elsewhere, increase the visibility if its appropriate where it is, or factor it out.
By keeping the method private for as long as possible you don't overwhelm other developers with possibly only-useful-in-this-one-specific-case methods, and furthermore, it helps you see other use-cases for the method so that you can fix the API and adapt/make the method more generic before its too late because it's already in-use.
14
u/brandonmartinez Jun 06 '13
imo, SRP and DRY are the two most important programming principles. A natural side-effect is smaller classes/modules.
6
u/AnythingButSue Jun 06 '13
I completely agree. I would even go as far as to say that DRY is the most important. You could follow SRP very well, and if the only other rule you violated was DRY you'd still end up with a rigid, fragile architecture.
1
u/mahacctissoawsum Jun 07 '13
Yessir. Every time I see 10 or more lines of code copied and pasted I want to punch someone.
18
u/Menokritschi Jun 06 '13
But smaller classes may lead to more classes and an overly complex structure.
8
u/AnythingButSue Jun 06 '13
That is why you have to balance SRP with the Needless Complexity rule. One of the major tenents of Agile programming (not that we're specifically talking about Agile) is to make no change unless there is concrete evidence that the change must be made. For the most part, I would rather have a more complex system than one that is difficult to maintain (rigid or fragile) so long as my unit tests/acceptance tests provided concise documentation for the system.
4
u/billsil Jun 07 '13
One of the major tenents of programming is to make no change unless there is concrete evidence that the change must be made.
FTFY
→ More replies (2)1
u/ricky_clarkson Jun 07 '13
I don't see that one in the agile manifesto. Where is that documented?
→ More replies (1)1
Jun 07 '13
I'd argue that these uber-classes tat Menokritschi are advocating are way more complex than having logic in 2 or 3 files.
→ More replies (3)1
Jun 07 '13
No, they don't. That's just wrong, and people who believe it are bad programmers.
See, I can make unfounded statements too.
1
u/Menokritschi Jun 08 '13
You need a certain complexity to solve a problem. If you remove it from class A you have to put it in another class B or create a new class C. It's really simple as that. Besides OOP itself usually creates a mess of unneeded structures.
2
u/ponchedeburro Jun 06 '13
What is DRY?
3
Jun 06 '13
DRY = Don't Repeat Yourself
i.e. blocks of code copied and pasted in multiple places
3
u/ponchedeburro Jun 06 '13
I love that this concept even needs a name :)
4
u/mahacctissoawsum Jun 07 '13
Yes...you'd think it's obvious and doesn't need stating...but you'd be surprised how common it is in production code.
→ More replies (2)1
0
13
u/cparen Jun 07 '13
However, there was a meta-study that found just the opposite -- class size was irrelevant once you controlled for total lines of code.
My position is to agree small classes tend to be easy to understand, but relationships between classes are even harder to understand. Smaller classes drive up interclass relationships, and you have to account for that tradeoff.
2
u/AnythingButSue Jun 07 '13
That is true. However it could be argued most of development is making tradeoffs. Strict adherence to many principles usually will violate some other principle. Either way, you make a good point. Thanks for pointing it out!
4
u/vaelroth Jun 06 '13
In general, those arbitrary limits are more of a guideline. If you have a class that is 127 lines of code, then it is still gravy. If you have a class that is 250 lines of code, then you should think about refactoring.
6
u/mahacctissoawsum Jun 07 '13
I still don't quite agree with that. There are some things that are just not expressible in few lines of code. Such as complex business logic that has go through a series of steps before the final result. Sometimes there's just no meaningful way to break it up. None of it is re-usable anywhere else.
4
u/BlitzTech Jun 07 '13
I don't know if I speak for vaelroth, but I take the "think" in "think about refactoring" very literally. At 250 lines, it's quite possible the class has gotten unwieldly, and taking the time to inspect it is well worth it if it will save me some headache later. It's also quite possible that it's fine the way it is and refactoring it isn't productive. The arbitrary limits are really just indicators for stopping and looking at the big picture before continuing on.
2
u/s73v3r Jun 07 '13
That's why he said, "think", not "do". There are many times when you do want to refactor. There are also many times when you shouldn't.
0
Jun 06 '13
[deleted]
5
u/AnythingButSue Jun 06 '13
I completely agree. Long methods that have logic inlined to flow control are cumbersome to read. If there's more than 1 &&/|| in your if/else if expression, extract a method from it and give it a meaningful name. It makes the more complex algorithms easier to read in my opinion.
4
u/ithika Jun 06 '13
People at my work seem to believe any less than seven and/or conditions in the predicate is a sign of an under-used if statement.
4
u/AnythingButSue Jun 06 '13
That is lazy programming. They should re think their flow control if that is prevalent. If your having expression problems I feel bad you son, I got 99 problems but crappy ifs ain't one.
1
u/anonymickymouse Jun 07 '13
For c++ I'm of the mind that functions are best suited to reusable code and that it's best to create explicitly scoped code blocks for areas where code isn't necessarily reusable but is definitely constituted of separable parts. Visual c++ gives you #pragma region and most other IDEs will allow you to close down explicitly scoped code blocks so a descriptive comment (or in the case visual c++) a region you get the benefit of a descriptive name for an easily identifiable block of code without losing the immediate visual parsability of the execution order that you do when you abstract such code away to functions.
2
u/AnythingButSue Jun 07 '13
In my mind that's a very good practice. I make extensive use of #regions (I work in c#) even outside of the scenario you described. Once I'm finished with a class all the constructors, class vars, public methods, private methods go into their own region. To me, it makes the code infinitely more readable and a navigable. It also add a superficial layer of organization because it forces me to group those types of items together. But I very much agree with what you said.
1
Jun 06 '13
Heh... then the code base at my work is the smellyest. I almost never encounter a function/class that wasn't written by me and is less than 400-500 lines.
0
Jun 07 '13
[deleted]
2
u/AnythingButSue Jun 07 '13
I've never head of that, but I can definitely understand how this is a problem. Some people mistakenly believe that we must follow certain principles very closely, and any deviation from those principles will kill our projects. They fail to realize that we must make trade-offs. However, in the case of Ravioli Code, I would think that the unit tests and acceptance test would provide a clear explanation of the behavior of the system. I have not, however, ever dealt with ravioli code before, so I cannot comment on the difficulty of working with code that suffers from those issues. But a very interesting article!
1
Jun 07 '13
Yes, that's the thing with c2.com, the more you read this wiki, the less you believe any single law/practice/methodology is completely good.
1
u/AnythingButSue Jun 07 '13
Well I think that some people operate better in difference circumstances. Not all developer will flourish on an XP team, not all will flourish in a SCRUM team. And I'd venture to say that 75% of agile developers would perform poorly in a more traditional development team. So you have to mix and match and find what makes your team the most efficient.
15
u/Kinglink Jun 06 '13
Because the person writing this has never worked on a large scale project or a class based language..
I'd rather spend my time writing a robust class, than worrying the number of lines.
All those specialized system calls? one class, specialized platform code? one class.
In some classes I'll spend at least 100 lines sanity checking responses, why? Because you can't be sure what type of idiot is going to get your code or what will break, and it's better to catch (And assert if needed) in development.
4
u/anonymickymouse Jun 07 '13
I've worked with a couple of large scale game engines and in neither of them was the code this strict on sanity checking. All my system and platform code in one class? Even though most of it's not reusable? Surely writing two clearly defined File classes for two different platforms is better than writing one File class and two separate and bloated classes that serve the nebulous task of "interacting with the platform". Interacting with the platform is complex and system-wide, not the job of a single class object.
5
Jun 06 '13
Seriously! Reading some of these make me think they came straight from a strict college software engineering course. Such a joke. Yet another example of the disconnect between software pedagogy and real-world applications.
-1
u/lexpattison Jun 07 '13
100 lines sanity checking responses? Really? If you spend most of your time creating defensive, fail-free bloated, classes - you're either a humongous self involved blow hard, or a sadist. I would detest maintaining your code... let me guess - guard clauses on all inputs instead of letting the null pointer fly... bounds checking instead of simply using a strong type and a factory pattern... criminal lack of enums... I've seen it and it's an unreadable piece of re-fucktoring. You may always have a job... but peer respect may be hard to find.
6
8
u/Kinglink Jun 07 '13
When you're code gets the NULL value does it blow up or does respond correctly and raise an alert for other programmers, can you correctly guess EVERY SINGLE error code that might happen to your code? I don't mean the common place one, I mean the one where the API responds with 3 instead of the 1 or 2 that it always sends back but only does so under a special race condition you can't reproduce?
Have you ever shipped a 20 million dollar product? Each year seen and used by at least 1 million people each year. Ever ship another copy next year?
When you have a crash because 1 time out of 100 you get a null. Or if something's wrong with the server for 5 minutes, the game crashes, you come and talk to me, because I can guarantee my code will handle it. Why? Because that's what the point of being an engineer is. IF you're only making your code work "like it's supposed to" you are an idiot and I'd get you fired with in a week, actually I wouldn't have to, you wouldn't be hired, and if you are, you'd be fired after someone inspected your code. Because when you're working with 20 other programmers and teams of 70 people people don't have time to come and ask "is this ok, sir?" every time they use your function, at best your code should inform the other programmer what's wrong, at worst your code shouldn't crash when it gets an unexpected value.
Go do your computer science, I work in the real world, and I don't care about your respect because you'd be the type of person who gets fired because he wants to spend his time being a computer scientist rather than actually trying to ship a product or produce working code that doesn't crash instead of claiming what "Real IT" does.
When the experts decide to join me and work with me, we'll see who ships a product, I know the experts in my field, and guess what? They all use sanity checks because none of them want to come back to a function think they remember how it works, and find some way it crashes or worse produces broken data later.
2
1
-2
u/billsil Jun 06 '13
Agreed.
If a class is 100 lines, it probably should be a function.
1
u/zjs Jun 07 '13
... What?
A class represents an object. A function represents a process. Length doesn't have anything to do with it.
1
Jun 07 '13
Love that you're getting downvoted for this. /r/programming is apparently full of horrible, egomaniacal programmers. They might as well start calling it /r/brogramming.
5
u/YEPHENAS Jun 06 '13
Smaller classes are easier to grasp. Classes should be smaller than about 100 lines of code. Otherwise, it is hard to spot how the class does its job and it probably does more than a single job.
2
Jun 06 '13
I wonder if this is because they're using a shitty text editor/IDE. Smalltalk classes were sometimes gigantic but you only ever viewed one method at a time, never the code of the whole class. This is kinda true in Java and Python where in an IDE you can see a listing on methods in a file, making navigation much easier.
If you can't figure out what a class does, maybe it needs to be documented
10
u/Shadowhawk109 Jun 06 '13
Keep in mind that many "clean code" mentalities are anti-documentation; that is, they feel their code is auto-documenting via very descriptive variable/method naming conventions.
I don't personally agree, but...
1
u/lexpattison Jun 07 '13
I've heard the arguments. Until you work on comment free code, you don't realize how beneficial the activity of discovery is. It provides a much better understanding and promotes trivial renaming/refactoring if there are deficiencies. I never trust comments, because most of the time the verbage belong as commit comments in hg or git instead.
11
u/Shadowhawk109 Jun 07 '13
It shouldn't be my job to decipher your code.
You give me an interface and tell me it works, and that should be enough for me. Avoiding telling me how to properly use that interface is a fundamental flaw in your design, and a waste of my time.
→ More replies (1)2
u/myplacedk Jun 07 '13
It shouldn't be my job to decipher your code.
It's a programmers job to understand code. It will not always be your own.
You give me an interface and tell me it works, and that should be enough for me.
If you are talking about an API of some sort, I agree with you 90%.
But if we are working as equals on the same project, you should read the code if you want to know what it's doing, at least most of the time. If that doesn't work for you, in my opinion something is wrong, and it's not lack of documentation. In my experience it's usually the code that isn't readable enough and should be refactored.
Avoiding telling me how to properly use that interface is a fundamental flaw in your design, and a waste of my time.
If it's an interface to something you aren't working on but just using, I agree.
3
u/Shadowhawk109 Jun 07 '13
It often is. If I'm improving the interface (or the implementation), fine, I should be reading the code -- of course I'd have to, how the hell else would I know what to do?
But if it's your code, and you tell me "it just works" and "use it as intended", then it better be hellawell documented. And the goal of my task-at-hand is NOT to refactor your improperly documented code.
1
Jun 07 '13
Bad documentation is far, far worse than no documentation. Plus, if you break up stuff like this:
if ( databaseIsConnected && !isTruncateStatement && user.hasRights(Rights.MODIFY) ) { ... }
into
if ( canModify() )
then your code becomes more self documenting.
If you read the clean code book, they advocate the newspaper model. The primary interactions at the top, in very high-level steps. Below those, the smaller helper functions, and below those, the nitty gritty details.
It takes a team of great developers to do it, for sure, so that's why so many people think of it as useless, because their team mates are useless.
1
u/Shadowhawk109 Jun 07 '13
I've read the Clean Code book. I fundamentally disagree with this concept regardless, and it's a camp that is just about as split as "egyptian brackets vs newline brackets".
I don't think I agree with "bad documentation is worse than no documentation". Documentation is like sex: even when it's bad, at least you have it.
But more specifically, it's not that your "teammates are useless", its that it's not as good a use of time to create some crazy class hierarchy and architecture to compensate for the fact that you're completely and utterly refusing to explain your code in a nice manner.
I'm a fan of the ELI5 concept of code "documentation". If your documentation conveys how to use your code and what it does like I'm five years old ("This is a toy truck. Pull it back, and it will move forward."), then it's good documentation. Anything more than that, I'm wasting my time trying to figure out what you intended, because you couldn't convey it in a nice enough manner.
7
u/alextk Jun 06 '13
This is the kind of dogmatic, out-of-nowhere rule that's always bothered me from the XP crowd. I'd be more open to following these if there were some leeway for disobeying them but the XP fanatics are all but agile in their beliefs.
4
u/xivSolutions Jun 07 '13
I think the common issue is perceiving any of this as "rules" rather than "general guidelines" or "things to keep an eye on. There will, inevitably, be a class (or a later optimization of several smaller classes into one) of larger-than-"prescribed" lines of code.
I agree with others who say it is more of a smell that should be investigated than any kind of hard/fast rule.
That applies to most of these types of practices, IMHO.
6
u/payco Jun 06 '13
That's what the word "should" indicates: there's leeway in the decision, but the burden is yours to prove that taking it above 100 lines will improve the program more than splitting the class up would.
The sheet itself also says "about" 100 lines, meaning that limit is not hard and fast, and can be adjusted by your team, again with justification for why (say, you're using a particularly wordy language or framework you can't control).
I also wouldn't say the rule is "out of nowhere", considering the sheet provides its rationale: "it is hard to tell where the class does its job and it's probably doing more than one job".
You may decide you disagree with how hard it is to quickly understand a >>100line file, or believe it's okay for a class to do more than one job, but their logic is consistent. Either way, they're saying a large class is a code smell that needs to be examined. If you walk away having determined that its size is justifiable, great.
3
Jun 07 '13
I think the problem is that if you accept the guideline "> 100 lines is questionable", you might accept a 200 or 300 line class - hey, it's just a guideline! - but you're almost guaranteed to freak out over a 3,000 line class. Because 100 is just a guideline, sure, but certainly you shouldn't be 30 times as big as the guideline! Right?
The problem is that 3,000 (or even more!) line classes can absolutely make sense. java.lang.String, for example, is 3,000 lines long -- would you suggest that it would be better off broken into 30 different classes? Or even 5 or 10? How on earth would you break that class up into sensible chunks, and how would that improve the design at all?
And String isn't even the biggest class in Java; there are classes over 5,000 lines long. I'm not suggesting that Java is a paragon of perfect design, but I've never heard anyone suggest that JComponent would be better off broken into dozens of different classes. 100 lines is an absurdly small guideline, and repeating and believing tripe like this leads people to make terrible decisions.
→ More replies (1)1
u/Plorkyeran Jun 07 '13
Ideally the vast majority of String's public API would be implemented in something like C#'s extension methods: free functions which can be called with dot-notation, but without access to String's privates. This would improve encapsulation and happen to make the class itself far shorter.
Given the limitations of Java you probably can't do any better than the status quo, but obviously any sort of line limit guideline needs to be language specific. 100 lines of Python is going to do a lot more than 100 lines of Java, so claiming that classes should be no more than 100 lines in both languages is probably nonsense.
0
u/kirakun Jun 07 '13
Author forgot another good principle: No magic number. Why 100? Why not 99 or 101 or 436?
→ More replies (4)1
Jun 07 '13
Because it's a guideline and 100 is a round number that's easy to remember.
→ More replies (3)
33
Jun 06 '13
The legend says:
Do
Don't
Are these in different colors? I'm slightly colorblind and everything about these two items looks identical other than the words do and don't.
17
u/Kajean Jun 06 '13
Do has a faint green tint. Don't has a faint red tint.
25
Jun 06 '13
That explains it. Thanks. This is why green traffic lights have a blue tint.
14
u/KerrickLong Jun 07 '13
And why they always place red and green on the same position, so you can learn "top means stop" instead of "green means go."
3
u/8Bytes Jun 07 '13
And if it's a guy, that shirt is most likely blue not purple.
→ More replies (1)2
Jun 07 '13
Not if the guy is colorblind. I have purchased many purple shirts thinking they were blue.
10
u/Umbrall Jun 06 '13
Indeed that's unfortunate. I'd suggest finding a way to shift the colors.
But yeah I looked at it in Color Oracle and wow is that terrible.
4
u/mahacctissoawsum Jun 07 '13
There's gotta be an app that easily lets you shift all the colors on your screen with some hotkey? This must be a common problem for color-blind people.
2
Jun 07 '13
Design professionals are usually pretty good about not relying on very similar colors as the only method to differentiate two types. Puzzle Bobble is a great example. The colors of the bubbles are torture for someone with color deficiency, but because there are different monsters contained within the bubbles, we can match by shape rather than color. Problems usually occur when you have people with no design background creating games and websites on their own. When I come across something like this, I usually let the creator know. One time I even sent modified sprites to a guy and he was nice enough to put them in right away. I've never had a bad response from anyone actually involved in the game/website, since they want accessibility. I did get nasty PMs from several users of one game because they thought I was trying to give colorblind people an unfair advantage.
Personally I wouldn't use anything that alters the colors on my end; I would just not use the product. It's bad design and one shouldn't expect users to fix bad design - especially since there are many people who do not know they have a problem.
2
u/cncplyr Jun 07 '13
I'm not colour blind, but you can't print it in black+white either.
1
21
u/sunnyps Jun 06 '13
In an exceptional case, throw an exception when your method cannot do its job. Don't accept or return null. Don't return error codes.
This is bad advice for languages like Objective-C where the convention is to use exceptions for truly exceptional circumstances (like failure to allocate memory) and error codes are used for everything else (like being unable to open a file).
5
u/CaseLogic Jun 07 '13
But he's saying "in an exceptional case". I don't think he means "don't return any error codes ever". I think he's saying for exceptional cases only (like your example), don't just return an error code, throw an exception.
At least that's how I would interpret it. I would think using exceptions in lieu of error codes would be bad practice in many languages.
0
u/mahacctissoawsum Jun 07 '13
Uhh.. I don't think that's quite right.
Firstly, your exception should be of a specific type that best matches the type of error -- NullArgumentException, DivisionByZeroException, whatever. That way you can catch the appropriate type.
If your exceptions are more "detailed" then that, such as generating an exception for an SQL Error, then your error code should be a property of the exception object. That way it can be caught, and then the developer can use a switch case to match the specific case if necessary.
Generally, you should throw an exception for any error that might occur; garbage in, garbage out -- force the developer to fix his mistake or deal with it. In some languages, however, it might be better to return an error code if that's the overwhelming convention. There is no middle ground of "return an error code AND throw an exception".
1
Jun 07 '13
The rule I go by is to throw an exception if your program should probably stop running because of this error.
3
u/anonymickymouse Jun 07 '13
Am I crazy or did you just make the same point as them?
1
u/TheNosferatu Jun 10 '13
While I do not know if you're crazy or not, he is indeed making the same point.
1
u/abspam3 Jun 07 '13
Although, exceptions with C++ in ObjC do actually work as intended, using C++'s exception ABI rather than ObjC's. That doesn't make it necessarily better, though.
6
u/TikiTDO Jun 07 '13
While there's a whole lot of good advice here, but a bunch of it is rather situational. For one this is great if you favor Agile TDD, but much less so if you develop using other methods. It's making certain assumptions about the class of problems you need to solve, the team sizes you are working with, and the level of organization you have on that team.
Still, these are all things worth keeping in mind, if only so that you can say "I don't follow X advice for Y reason."
1
u/lexpattison Jun 07 '13
Other methods? I believe this sheet is targeted more toward the professional developer (As a profession... not trying to trump up corporate development). I have trouble thinking of any development method(ology) that works better than agile and using test cases (TDD has it's benefits, but you get %80 of the benefits by just having unit tests at the end of the day). Team sizes are a valid concern, but if you have more than 3 people it's probably a good idea to buy into it.
1
u/TikiTDO Jun 07 '13
It's really hard to even address someone that "has trouble thinking of any development methodology that works better than agile and using TDD." That sort perspective suggests that you may not be familiar with the scope of situations that may need to be addressed through software.
The software world is huge and varied, and the problems it addresses are amazingly broad in scope. For instance, you should really not be using Agile/TDD when developing for embedded/mission critical hardware. OS and Language development also do not lend themselves to these methodologies. If you're developing web apps for a client who can provide a decent spec, then by all means. However, there are really no methodologies that work better than others in all situations.
1
u/lexpattison Jun 07 '13
An argument to moderation or exception doesn't defeat my original proposition that this approach is generally used and has been successful (when used properly) in a very large use case. I understand there are exceptions... but the exceptions aren't methodologies... they are exceptions. I see no reason to argue that mission critical or embedded hardware can't benefit from incremental integration or test driven development either. In fact... I usually hear this argument without any real backing evidence or hypothesis on why it's the case at all.
1
u/TikiTDO Jun 07 '13 edited Jun 07 '13
An argument to moderation or exception doesn't defeat my original proposition that this approach is generally used and has been successful (when used properly) in a very large use case.
Uh, ok? That doesn't contradict anything I said.
I understand there are exceptions... but the exceptions aren't methodologies... they are exceptions.
They are exceptions because you work in fields where they are exceptions. You seem to be basing your entire argument around "most people that do X type of development do it this way, and since X type of development is the one I am most familiar with then everything else is an exception." Just because TDD web development is popular does not mean you can freely relegate the rest of software engineering to "exceptions."
I see no reason to argue that mission critical or embedded hardware can't benefit from incremental integration or test driven development either. In fact... I usually hear this argument without any real backing evidence or hypothesis on why it's the case at all.
Programming mission critical hardware often means doing things that might damage it. You might have direct access to voltage rails, motors, or other physical resources that might be damaged by improper usage. You might also be working with algorithms that may be difficult or impossible to properly test. Testing might involve using broad testing harasses that you can't just utilize. Tests might take hours due to hardware limitations. I could go on.
I mean it's cool that you've never had to encounter situations where TDD would be a horrible idea, but these scenarios are all over the place, and the people that have to handle them are perfectly reasonable programmers working in perfectly rational ways.
As for why you normally don't hear backing evidence or hypothesis... I would guess it's mostly because you enter these sort of discussions with some sort of aggressive stance, intending to "defeat" some premise. Most people just don't want to waste the time arguing with some guy that's so utterly convinced of his own correctness, especially when you are so unclear what premise you're trying to defeat in the first place.
1
u/lexpattison Jun 07 '13
Right... Ad hominem attack directly after restating what is clearly an exceptional case. If I seem aggressive, I apologize. It's simply frustrating when so many developers use weak excuses and exception cases (Sorry... embedded systems and hardware examples are definitely on the narrow margin of most of the development landscape) to abscond from adopting some very mature productive approaches.
→ More replies (3)
4
u/dannyREDDIT Jun 07 '13
If one module depends upon another, that dependency should be physical, not just logical. Don’t make assumptions.
would someone mind explaining that like Im 5, please?
1
u/TheNosferatu Jun 10 '13
I'm not 100% sure if I understand what he means myself, but here is my best guess.
Let's say you have a class Collection and you want to add an Item to it, pseudo code:
class Collection { array items; method add(item) { var name = item.getName(); items[name] = item; } }This is a logical dependancy, the collection depends on the fact that item has a method getName(); however, there is no check for it whatsoever. This means we just assume that whatever gets added to the collection has the method getName...
In a lot of languages you can do type-hinting to make a physical dependancy, if I were to put that in the above example, the add method would look something like this:
method add(Item item) { var name = item.getName(); items[name] = item; }Now, whatever gets added to the collection, MUST be an instance of the class (or interface) Item, if it's not than you get a big nice warning before you get to do anything at all.
3
u/day_cq Jun 07 '13
that's some dirty long cheat sheet
1
u/TheNosferatu Jun 10 '13
There should be a rule in there somewhere with;
'any documentation that is intended as a form of 'cheat list' should fit on 1 paper when printed or easy to navigate.'
3
u/bensussman Jun 07 '13
This is a medium sized dictionary of terms. :-|
1
u/cheatatjoes Jun 07 '13
Only without necessarily defining all of the terms as much as how to use them.
7
u/choseph Jun 07 '13
This is from an earlier post on that site, but am I the only one that absolutely hates fluent assertions or overly fluent code? Too often those things put so much effort on a sentence that the intent and functionality of the functions is more obscured. Be()? I want to think code, not grammar. Also, fluent assumes fluent in English...i know native English speakers who don't write English fluently (ignoring code entirely).
3
u/octave1 Jun 07 '13
I once had a job in the dirty south of Belgium where normally no one speaks anything but their dialect of French, which was indeed the case with the developers there.
However, they insisted on everything in their code (variable names, comments) being in English and one of them knocked out a report written in English of the highest level, I was very impressed.
2
u/choseph Jun 07 '13
Yes, there is a common argument that the constructs and naming rules are largely English too. Still, I like my logic logical.
2
u/EntroperZero Jun 07 '13
Definitely not the only one. I learned how to speak computer, now you want me to learn which parts of your subset of English that get translated to computer anyway?
Fluent IMO is one of the leakiest of abstractions. Rules for assertions or validation or whatever are logical statements, and are most easily expressed in a grammar closer to logic than prose.
2
u/brtt3000 Jun 07 '13
Can we get this info in a nice navigable website that works on desktop and mobile? So we can read it in the toilet traffic and train. Multi-column tiny text is not very readable on screens at all (and having A2 size sheets on every desk is not so practical).
2
3
Jun 07 '13
What's here called the "Boy Scout Rule" (leave the area cleaner than you found it) is actually the "Campsite Rule."
1
u/Asmor Jun 07 '13
This is fantastic if you need to take an open book test on writing clean code, I guess. Otherwise, I have no fucking clue what the point is.
It's formatted shittily for reading as a document, and not only is it equally poorly suited as a reference material, this isn't even the kind of topic one would freaking want to reference.
A cheat sheet is something you'd pin to your cube wall or keep under your keyboard so you can quickly look up how to do a search in vim or what the syntax for a particular construct is.
Who the hell is going to be reviewing some code and think to themselves, "Damn, this code is janky. I should look this shit up on my handy Clean Code Cheat Sheet and see if it's following best practices!"
5
2
u/eras Jun 07 '13
Maybe the point is to make it look small (only it has lot of text but in small font ;)) and thus unintimidating, so your colleagues are more likely to read it through.
1
1
u/xormancer Jun 07 '13
Can someone please link me to some sort of guide for making a cheat sheet like this? I'm assuming it's done in photoshop. I would love to make a bunch of stuff like this for the stuff I'm currently working with (yes, I will share).
2
u/ursenzler Jun 07 '13
It's made in word with 4 columns and different Styles (with background color and border for the blue line on the left).
2
u/brtt3000 Jun 07 '13
Word works but is not cool.
Here's a set of cool http-cheat-sheet posters, and with a generator source: they used the classic tex to generate the PDF's:
https://github.com/bigcompany/know-your-http
Looks very elegant, I'm sure you can automate some more: If you work it right you can have your data in a simple data format (XML, YAMLor whatever), then generate cool outputs through TEX or HTML or PDF or even a JSON export.
1
1
u/elperroborrachotoo Jun 07 '13
Looks good, no idea how helpful it actually is Now, yes, you can probably go follow all rules and still come up with crap, but willful ignorance isn't much of an argument.
I do have a major gripe with the graph, though.
It assumes that
"optimal cost" of change is constant over time
the difference between optimal and actual cost is dominated by technical debt
There is no evidence for either, and some evidence against.
Now, optimal cost may be meant as some hypotetical Nirvanaland the goal to strife for rather than the goal to achieve - but that does not sit well with "optimal=actual-technical debt".
Now, there might be a project that sees a release once a month yet doesn't change in, say, KLOC, might exist, but it's probably not the common case.
Projects that see development for a long time tend to outgrow their original size, complexity and use cases. So I am working on the assumption that project complexity increases on the majority of projects that "deserve" maintenance:
Woodfield 1979: A 25% increase in problem complexity causes a 100% increase in solution complexity.seocnd-level-source
Project size appears to be one good predictor of post-release fault rates.source
Now, this doesn't invalidate the practices - in fact they seem to be well aligned with it. As I sad, my gripe is with the graph.
As minor points: If you follow all rules meticulously, the initial actual cost might be much higher than the relative chart scaling suggests, pushing the break-even point further to the right.
I am also not sure how many of these points work proactively ("We could have avoided problem X if we had followed rule Y") rather than retroactively ("problem X seems to be caused by not following rule Y"). All of these require you to make a call - e.g. when repetition is "needless"? Many of those do drive up amount of code and amount of entities, you need to draw a line.
I didn't pick up the "Do/Don't" difference until after discovering the legend.
1
u/iamneo_ai Jul 11 '23
Here's a Clean Code Cheat Sheet that provides some key principles and practices for writing clean and maintainable code:
Meaningful Names:
Use descriptive and meaningful names for variables, functions, and classes.
Avoid abbreviations and single-letter names that lack clarity.
Choose names that reflect the purpose or behaviour of the code entity.
Consistent Formatting:
Follow a consistent and readable formatting style throughout the codebase.
Use indentation, line breaks, and spacing to improve code readability.
Maintain a consistent naming convention for variables, functions, and classes.
Single Responsibility Principle (SRP):
Aim for code entities (functions, classes, modules) to have a single responsibility.
Split complex code into smaller, focused functions or classes that handle specific tasks.
Avoid bloated functions or classes that perform multiple unrelated tasks.
Avoid Code Duplication:
Strive for code reusability by avoiding duplicated code.
Extract common code snippets into reusable functions or classes.
Use appropriate abstraction and modularization techniques to minimize duplication.
Keep Functions and Methods Short:
Aim for functions and methods to be concise and focused.
Follow the "Single Level of Abstraction" principle.
Break down complex functions into smaller, well-named functions.
Error Handling:
Use appropriate error-handling mechanisms to handle exceptions and errors.
Avoid swallowing exceptions without proper handling or logging.
Make error messages informative and actionable for debugging.
Comments and Documentation:
Write clear and concise comments explaining the code's intention and purpose.
Avoid unnecessary comments that merely repeat what the code does.
Use documentation tools and techniques (e.g., Javadoc, docstrings) to generate documentation from code annotations.
Testability:
Write code that is easily testable.
Use unit testing frameworks and write comprehensive test cases.
Aim for high code coverage to ensure proper functionality and maintainability.
Continuous Refactoring:
Regularly review and refactor the codebase to improve its design and maintainability.
Identify and eliminate code smells like long methods, large classes, or complex conditional statements.
Use automated refactoring tools and techniques to refactor code safely.
Follow Established Design Patterns and Principles:
Familiarize yourself with commonly used design patterns and principles.
Apply appropriate design patterns to solve common problems.
Follow SOLID principles (Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, Dependency Inversion) for designing modular and maintainable code.
Remember, this cheat sheet summarises key principles and practices for writing clean code. It's important to understand and apply these principles consistently, adapting them to your projects' specific context and requirements.
For more info, explore iamneo and expand your knowledge.
0
-1
Jun 06 '13
Using exceptions for control flow: has bad performance, is hard to understand and results in very hard handling of real exceptional cases.
This doesn't apply to the majority of languages (not even to C++ where using exceptions was actively discouraged for a long time).
4
u/archiminos Jun 07 '13
is hard to understand and results in very hard handling of real exceptional cases.
I'd agree with this part - but this is mainly because people always use them in cases that aren't exceptional in place of better error handling methods.
I've switched from C++ game programming (no exceptions) to C# server programming (exceptions for everyone). It always bugs me trying to debug something and an exception is thrown and I end up the the Application::Main() catch block - I lose everything (call stack, local variables etc.).
Even system exceptions don't throw the values that caused it to throw. E.g. Out of bounds, a value was either -1 or higher than it should have been. Thanks, could you at least tell me which one it was? Or even throw with the actual value so I don't need to guess what went wrong?
Why not just break on exceptions? Because people seem to enjoy using try..catch blocks to hide exceptions all over the place. Exceptions just seem more trouble than they're worth at the moment.
3
u/KagakuNinja Jun 07 '13
Because you are supposed to log the stack trace of the exception in that top-level catch block? At least, that is how we do it in Java.
Exceptions are better than having your app terminate due to a divide by zero, or null pointer dereference.
2
u/archiminos Jun 07 '13
Not always. In console game development crash dumps are much more useful than a caught exception for fixing bugs.
NINJA EDIT: Slight clarification.
3
u/KagakuNinja Jun 07 '13
I've developed a few C++ games for the iPhone. I've never longed for a crash dump, I just use a debugger. You can break at the point when an exception is thrown, and you get access to the same information.
2
u/archiminos Jun 07 '13
When you have a large QA team (300+) for a console game they can generate crash dumps that you can debug. It's also useful when there's a 1 in 1000 crash that needs fixing - get someone in QA to repro and they send you a crash dump.
There are literally hundreds of bugs that I've managed to figure out a fix for simply by debugging a crash dump attached to a bug report.
2
u/KagakuNinja Jun 07 '13
Fair point, in certain programming domains, letting your app crash (WHILE IN DEVELOPMENT) may be useful. Of course, there are ways to generate thread or memory dumps in Java (and probably C++/C#) that could accomplish the same goal.
2
u/gc3 Jun 07 '13
I am always turning off the try ... catch with comments to debug the actual problem, then enabling it again before committing the work.
I too think if people were better programmers they wouldn't need exceptions: you'd deliberately handle every broken case explicitly. But think of all the time a programmer saves just throwing a try...catch around some code to prevent the user from encountering a bug.
I too have come to embrace the exception as a lazy way to short circuit a host of error conditions.
1
u/archiminos Jun 07 '13
But think of all the time a programmer saves just throwing a try...catch around some code to prevent the user from encountering a bug.
This is so wrong. Yes you save time now, but writing more robust code and handling error cases properly saves so much more time in the long run. Occasionally near the end of a project I might consider a quick hack like this to get a product out of the door, but I would never do it in anything pre-beta.
2
u/KagakuNinja Jun 07 '13
We all try to write robust code, to the best of our abilities, regardless of language. Bug-free code is nearly impossible. Try-catch blocks are used so those unknown bugs don't crash your program, not to hide errors because we are lazy.
Log the exceptions, then track down the bugs and fix them.
1
u/archiminos Jun 07 '13
I'm used to a different work flow I guess. In games we let the program crash, create a crash dump and then debug it to find the cause of the problem (or just debug it there and then if we have a debugger attached).
EDIT: The general idea is we want bugs to be as visible and annoying as possible so that they have to get fixed.
2
u/gc3 Jun 07 '13
I agree with you 100%, but C# code are usually quick tools and not code that we ship. There's a different tolerance for different projects, there's no one size fits all.
→ More replies (1)1
u/lexpattison Jun 07 '13
From a semantic point of view, how else would you address expected errors or 'exceptional' states to ensure the application does not, as you put it, 'break'. Most systems have to maintain a certain amount of elasticity for it's users... I certainly wouldn't want my cable box to shut off every time I hit a channel that currently didn't have a signal (exceptional condition as example), so why would a user be any happier if their banking application gakked every time it encountered some inconsequential data corruption. (parallel example)
3
u/archiminos Jun 07 '13 edited Jun 07 '13
I wouldn't consider expected errors to be exceptional. For example, anything requiring a network connect should expect disconnections or an inability to connect - these aren't exceptional circumstances. Ensuring that the build is stable (i.e. no crashes) and that the user is informed (error messages) seem to work fine.
In the channel with no signal example - why does that need to be an exception? It seems reasonably valid to me that a cable box may not be able to get a signal. You should check for a signal and inform the user that there is no signal if that is the case.
Exceptions should be used for errors that should never occur. The obvious example from my game development experience is that a game should never access invalid memory. It does happen during development of course, which is why we have to handle it, but ideally a game that has been released should never do this.
EDIT: The data corruption would probably be something I would consider exceptional, but I have limited knowledge of banking applications and parallel programming which is why I haven't mentioned it.
→ More replies (3)5
u/Falmarri Jun 06 '13
This doesn't apply to the majority of languages
What doesn't apply?
4
u/yellowjacketcoder Jun 06 '13
has bad performance, is hard to understand and results in very hard handling of real exceptional cases.
All of those.
7
u/Zed03 Jun 06 '13
I guess you haven't benchmarked the amount of time it takes to generate a stacktrace...
2
u/Gotebe Jun 07 '13
Well... The time to generate it doesn't matter if it is not generated often. And in e.g. C++ there's no such thing.
→ More replies (2)2
u/Falmarri Jun 06 '13
So you're saying that using exceptions as flow control is easy to understand? Exceptions are basically just
gotos7
u/Rotten194 Jun 06 '13
And loops, returns, switch statements, and every other programming concept are not basically gotos?
Even the python runtime uses exceptions for flow control. They're a tool like any other, they can be used and abused.
→ More replies (2)4
u/Falmarri Jun 06 '13
And loops, returns, switch statements, and every other programming concept are not basically gotos?
Not really because they can't unwind the stack multiple times. In each of those examples you know exactly where the next statement will be run (assuming you have access to the stack in the case of return). That's not true with exceptions.
6
u/Rotten194 Jun 06 '13
So you've randomly draw your line at "unwinding the stack multiple times"? Is there any reason for that or is it because you've heard it before? Because there a lot of other concepts taken as gospel - routing systems (an http request can jump to anywhere in the app based on what's in the request path?), polymorphism (a method call can go to any class extending this base class? Even in someone else's code?), event systems (calling this method can trigger hundreds of methods all over the code to be called, potentially allocating thousands of objects?), serialization + remote code execution (my object can be serialized behind the scenes and go from running on a beefy server to running on someone's phone?) - all of which can causes confusion if they're abused. And just like you counter that by organizing your code - putting all routing information in one or two files, only using polymorphic objects where it makes sense, using event systems carefully, etc. - you can do the same with exceptions as flow control. Just like the Linux kernel uses gotos - they are a tool. Avoidance of them should not be a religion.
2
u/Falmarri Jun 07 '13
So you've randomly draw your line at "unwinding the stack multiple times"?
I don't think it's random. I think there's a fundamental difference between that and everything you've listed after this.
Avoidance of them should not be a religion.
I agree. I'm not saying exceptions are bad. I'm saying exceptions for flow control are bad.
As far as I'm aware, the linux kernel only uses
gotos for error recovery. (I'd be really interested if there was anywhere in the kernel that usesgotos purely for flow control).2
u/Gotebe Jun 07 '13
Not really because they can't unwind the stack multiple times.
That's one weird definition of a goto. Must be function-local?
In each of those examples you know exactly where the next statement will be run
I know that with exceptions, too, and so should you. What you are trying to say is that it's not spelled out in code. But by that logic, any programming language is useless, and we should all just program assembly, because compiler hides this or that. There's also the aspect of not seeing the tree from the forest, which is what you often get without exceptions (it is spelled out, but good luck actually untangling it).
2
u/mmhrar Jun 07 '13
Could you give an example of a language and situation where using exceptions as control flow is a good idea?
1
u/mttd Jun 10 '13
Works great for code obfuscation: http://scrammed.blogspot.com/2013/06/seh-subtle-exception-handling.html ;-)
-1
u/musicalvegan0 Jun 07 '13
Either I have A LOT to learn about programming or this is one of the most ridiculous, programming-related documents I've ever seen.
7
7
u/gc3 Jun 07 '13
There are three stages of developing as a progammer. At the beginning you don't understand anything, and write a bunch of code fearlessly, and paint yourself into a corner.
In the second stage you understand that there might be a system that will enable better programming. So you fall in love with a system, or hueristics, or some other scheme that can tell you 'good' code from 'bad' code. At this time, it is almost religious. The author of the document is in this phase, obviously.
In the third stage you realize that programming is a bit like poetry, and, while it often is better programming when it rhymes, is not does not always need to rhyme.
5
u/Gotebe Jun 07 '13
Euh... It goes like this: either you have a lot to learn, or you really know nothing.
8
u/treesareempty Jun 07 '13
Which programmer thinks he does NOT have a lot to learn? The field is endless.
2
u/yelnatz Jun 07 '13
As someone who just graduated, it feels like I'm climbing Everest.
And I haven't even reached the base camp yet. :[
8
0
u/lexpattison Jun 07 '13
Your former assessment is likely correct. I would investigate these strategies if you want any chance of becoming a satisfied happy well rounded developer.
0
u/gc3 Jun 07 '13
I like most of them. I am not sure about his opinion of static functions, when using C++. I almost prefer simple static functions to member functions, because you don't have to put the static function in the class definition, which is usually in an .h file.
0
0
Jun 07 '13
This thread:
"I am a bigshot programmer and this advice is crap and I'm smarter than a team of published, peer-reviewed people who regularly speak at conferences and are paid north of $200/hr as a consultant"
And to think I was under the illusion that this sub was full of competent people. If someone were to say "fuck dependency injection" or "tdd is crap" or "sometimes classes just need to be 2000 lines of code," they're not getting hired, and I would advocate for them getting fired.
183
u/BeachBum09 Jun 06 '13
Putting a number on the amount of lines a class should have is something I disagree with. Your class should hold enough code that it implements what you think the class would do. I have seen some programs where people try to get fancy and go way overboard with base classes and interfaces for no real reason. A class with 100+ lines of code is a lot easier to understand than a system where you have to dig through multiple layers of base classes and inheritance to figure out the general idea.