Code Smell

Posted by epicdev Archive : 2011. 11. 15. 15:17
출처: http://en.wikipedia.org/wiki/Code_smell

In computer programmingcode smell is any symptom in the source code of a program that possibly indicates a deeper problem.

Often the deeper problem hinted by a code smell can be uncovered when the code is subjected to a short feedback cycle where it is refactored in small, controlled steps, and the resulting design is examined to see if there are any further code smells that indicate the need of more refactoring. From the point of view of a programmer charged with performing refactoring, code smells are heuristics to indicate when to refactor, and what specific refactoring techniques to use. Thus, a code smell is a driver for refactoring.

The term appears to have been coined by Kent Beck on WardsWiki in the late 1990s. Usage of the term increased after it was featured in Refactoring. Improving the Design of Existing Code.[1] Code Smell is also a term used by agile programmers. [2]

Determining what is and is not a code smell is often a subjective judgment, and will often vary by language, developer and development methodology. There are tools, such as Checkstyle, PMD and FindBugs for Java, to automatically check for certain kinds of code smells. 

Common Code Smells
  • Duplicated code: identical or very similar code exists in more than one location.
  • Long method: a method, function, or procedure that has grown too large.
  • Large class: a class that has grown too large. See God object.
  • Too many parameters: a long list of parameters in a procedure or function make readability and code quality worse.
  • Feature envy: a class that uses methods of another class excessively.
  • Inappropriate intimacy: a class that has dependencies on implementation details of another class.
  • Refused bequest: a class that overrides a method of a base class in such a way that the contract of the base class is not honored by the derived class. See Liskov substitution principle.
  • Lazy class / Freeloader: a class that does too little.
  • Contrived complexity: forced usage of overly complicated design patterns where simpler design would suffice.
  • Excessively long identifiers: in particular, the use of naming conventions to provide disambiguation that should be implicit in the software architecture.
  • Excessively short identifiers: the name of a variable should reflect its function unless it's obvious.
  • Excessive use of literals: these should be coded as named constants, to improve readability and to avoid programming errors. Additionally, literals can and should be externalized into resource files/scripts where possible, to facilitate localization of software if it is intended to be deployed in different regions. 

출처:  http://c2.com/cgi/wiki?CodeSmell

 code smell is a hint that something has gone wrong somewhere in your code. Use the smell to track down the problem. KentBeck (with inspiration from the nose of MassimoArnoldi) seems to have coined the phrase in the "OnceAndOnlyOnce" page, where he also said that code "wants to be simple". Bad Smells in Code was an essay by KentBeck and MartinFowler, published as Chapter 3 of RefactoringImprovingTheDesignOfExistingCode.

Highly experienced and knowledgeable developers have a "feel" for good design. Having reached a state of "UnconsciousCompetence," where they routinely practice good design without thinking about it too much, they find that they can look at a design or the code and immediately get a "feel" for its quality, without getting bogged down in extensive "logically detailed arguments".

Note that a CodeSmell is a hint that something might be wrong, not a certainty. A perfectly good idiom may be considered a CodeSmell because it's often misused, or because there's a simpler alternative that works in most cases. Calling something a CodeSmell is not an attack; it's simply a sign that a closer look is warranted.

[Copied from GotoConsideredHarmful:]

There are two major approaches to programming: [is there a page that covers this? there should be]
  • Pragmatic: CodeSmells should be considered on a case by case basis
  • Purist: all CodeSmells should be avoided, no exceptions
...And therefore a CodeSmell is a hint of possible bad practice to a pragmatist, but a sure sign of bad practice to a purist.

If I recall correctly, this is part of the reason why (was it KentBeck or MartinFowler) chose this name for the term. They wanted to emphasize the pragmatic view of CodeSmells by the connotation of the word smell. If something smells, it definitely needs to be checked out, but it may not actually need fixing or might have to just be tolerated.

See also

Here are some Code Smells that tell you something might be wrong.

Too much code, time to take something off the stove before it boils over:

Not enough code, better put the half-baked code back in the oven a while:

  • Classes with too few instance variables
  • Classes with too little code - See: OneResponsibilityRule
  • Methods with no messages to self - See: UtilityMethod
  • EmptyCatchClauses
  • Explicitly setting variables to null. Can indicate that either
    • there are references to things that this code has no business referencing, or
    • the structure is so complex that the programmer doesn't really understand it and feels the need to do this to be safe.
    • Is this too language specific? For example in Perl and other agile/scripting languages setting a variable to null can be the equivalent of destroying an object. -- MarkAufflick

Not actually the code:

Problems with the way the code is changing:

  • Sporadic ChangeVelocity - Different rates of change in the same object.
  • ShotgunSurgery - The same rate of change in different, disconnected objects.

Other code problems:

  • ContrivedInterfaces - A smell of PrematureGeneralization.
  • AsymmetricalCode/Imbalance
  • ArrowAntiPattern (nested if statements), Complex Conditionals
  • LawOfDemeter Violations - Messages to the results of messages.
  • Dependency cycles among packages or classes within a package.
  • Concrete classes that depend on other concrete classes
  • Methods requiring SpecialFormatting to be readable
  • BackPedalling (loss of context)
  • Long method names. Seriously: If you follow good naming standards, long method names are often an indication that the method is in the wrong class. For example, createWhateverFromWhateverOtherClass(OtherClass? creator) vs creator.createWhatever(). See UsingGoodNamingToDetectBadCode.
  • VagueIdentifiers
  • Procedural code masquerading as objects. See DontNameClassesObjectManagerHandlerOrData
  • Embedded code strings. Large chunks of SQL, HTML or XML (for example) are not best read, edited or tested in the code. They start there because its simpler, but end up making both languages unreadable as they get more complex, and require developers to know both languages.
  • PassingNullsToConstructors - use a FactoryMethod
  • TooManyParametersLongParameterList
  • VariableNameSameAsType
  • WhileNotDoneLoops
  • False unification of procedures. A procedure, function, or method has a boolean that provides a variation on its behavior, but the two variations in fact have completely different semantics. It would be better to refactor the common code into another method and split the remainder into two separate methods, removing the boolean.
  • False unification of interfaces. An interface has two implementors. One implementor implements half of the interface and throws UnsupportedOperationException for the other half. The second implementor implements the other half and throws UnsupportedOperationException for the first half. It would be better to split the interface into two. Similar to RefusedBequest?.
  • Hidden coupling. Code depends on completely non-obvious characteristics, such as relying on reference equality instead of value equality.
  • Hardwired policy. Instead of policy being wrapped around a mechanism, the policy is wired directly into the mechanism. Often, implementation of the policy requires additional information not available, so it has to be fetched from outside, creating an implicit external dependency. Instead of a simple, self-contained mechanism, you now have a fragile, context-sensitive mechanism.

From BadSmellsInCode?: The list of canonical smells found in RefactoringImprovingTheDesignOfExistingCode can be found at: http://jexp.de/papers/refactoring/refactoring/node26.html (we're slowly making sure they're all here).

-- updated broken link, Michael Hunger

Some Principles for judging whether code smells bad or good are defined in PrinciplesOfObjectOrientedDesign.

See Also:

[This list needs refactoring to above:] CodeSmells referenced in:

'Archive' 카테고리의 다른 글

Hollywood Principle  (0) 2011.11.15
A Taxonomy for "Bad Code Smells"  (0) 2011.11.15
테스트가 코드를 향상시키도록 하라  (0) 2011.11.15
Agile 원칙 12가지  (0) 2011.11.14
다섯가지의 소프트웨어 테스트  (0) 2011.11.14