In Praise Of Small Code

Posted by epicdev Archive : 2011. 11. 15. 16:08
출처: http://www.informationweek.com/news/development/architecture-design/231000038

In Praise Of Small Code

Keeping class size small--no more than fits on one screen--goes a long way to reducing complexity in code, which also leads to code that's easier to test.

If you've been doing object-oriented programming for a while, you've surely run into the seemingly endless essays on testability. The debate focuses on how to write code to make it more amenable to automated testing. The topic is particularly intriguing to exponents of test-driven development, who argue that if you write tests first, your code will be inherently testable.

In real life, however, this is not always how it happens. Developers using test-driven development frequently shift to the standard code-before-tests approach when hacking away at a complex problem or one in which testability isn't easily attained. They then write tests after the fact to exercise the code; then modify the code to increase code coverage. There are good reasons why code can be hard to test, even for the most disciplined developers.

What makes code untestable, however, frequently isn't any of these things. Rather, it's excessive complexity. High levels of complexity, generally measured with the suboptimal cyclomatic complexity measure (CCR), is what the agile folks correctly term a "code smell." Intricate code doesn't smell right. It generally contains a higher number of defects and it's hard--sometimes impossible--to maintain. Fortunately, there are many techniques available to the modern programmer to reduce complexity. One could argue that Martin Fowler's masterpiece, Refactoring, is dedicated almost entirely to this topic. (Michael Feathers' Working Effectively With Legacy Code is the equivalent tome for the poor schlemiels who are handed a high-CCR code base and told to fix it.)A simple example is testing private methods; a more complex one is handling singletons. These are issues at the unit testing level. At higher levels, such as user acceptance testing (UAT), a host of tools help provide testability. Those products, however, tend to focus principally on the user interface aspect (and startlingly few handle GUIs on mobile devices). In other areas, such as document creation, there is no software that provides automated UAT-level validation because parsing and recreating the content of a report or output document is often an insuperable task.

My question, though, is how do you avoid creating complexity in the first place? This topic too has been richly mined by agile trainers, who offer the same basic advice: Follow the open-closed principle, obey the Hollywood principle, use the full panoply of design patterns, and so on. All of this is good advice; but ultimately, it doesn't cut it. When you're deep into a problem such as parsing text or writing business logic for a process that calls on many feeder processes, you don't think about Liskov substitution or the open-closed principle. Typically, you write the code that works, and you change it minimally once it passes the essential tests. In other words, as you're writing the code there is little to tell you, "Whoa! You're doing it wrong."

For that, you need another measure, and I've found one that is extraordinarily effective in reducing initial complexity and greatly expanding testability: class size. Small classes are much easier to understand and to test.

If small size is an objective, then the next question is, "How small?" Jeff Bay, in a brilliant essay entitled "Object Calisthenics" (in the book The Thoughtworks Anthology), suggests the number should be in the 50- to 60-line range--essentially, what fits on one screen.

Most developers, endowed as we are with the belief that our craft does not and should not be constrained to hard numerical limits, will scoff at this number of lines--or any number of lines--and will surely conjure up an example that is irreducible to such a small size. Let them enjoy their big classes. But I suspect they are wrong about the irreducibility.

Lately, I've been doing a complete rewrite of some major packages in a project I contribute to. These are packages that were written in part by a contributor whose style I never got the hang of. Now that he's moved on, I want to understand what he wrote and convert it to a development style that looks familiar to me and is more or less consistent with the rest of the project. Since I was dealing with lots of large classes, I decided this would be a good time to hew closely to Bay's guideline. At first, predictably, it felt like a silly straitjacket. But I persevered, and things began to change under my feet. Here is what was different.

Big classes became collections of small classes. I began to group these classes in a natural way at the package level. My packages became a lot "bushier." I also found that I spent more time managing the package tree, but this grouping feels more natural. Previously, packages were broken up at a rough level that dealt with major program components, and they were rarely more than two or three levels deep. Now, their structure is deeper and wider and is a useful road map to the project.

Testability jumped dramatically. By breaking down complex classes into their organic parts and then reducing those parts to the minimum number of lines, each class did one small thing I could test. The top-level class, which replaced its complex forebear, became a sort of main line that simply coordinated the actions of multiple subordinate classes. This top class generally was best tested at the UAT level, rather than with unit tests.

The single-responsibility principle, which states that each class should do only one thing, became the natural result of the new code, rather than a maxim I needed to apply consciously.

And finally, I have enjoyed an advantage foretold by Bay's essay: I can see the entire class in the integrated development environment without having to scroll. Dropping in to look at something is now quick. If I use the IDE to search, the correct hit is easy to locate, because the package structure leads me directly to the right class. In sum, everything is more readable, and on a conceptual level, everything is more manageable.

  

Hollywood Principle

Posted by epicdev Archive : 2011. 11. 15. 15:55
From Wikipedia, the free encyclopedia

In computer programming, the Hollywood Principle is stated as "don't call us, we'll call you." It has applications in software engineering; see also implicit invocation for a related architectural principle.

[edit]Overview

The Hollywood principle is a software design methodology that takes its name from the cliché response given to amateurs auditioning in Hollywood: "Don't call us, we'll call you". It is a useful paradigm that assists in the development of code with high cohesionand low coupling that is easier to debug, maintain and test.

Most beginners are first introduced to programming from a diametrically opposed viewpoint. Programs such as Hello World take control of the running environment and make calls on the underlying system to do their work. A considerable amount of successful software has been developed using the same principles, and indeed many developers need never think there is any other approach. After all, programs with linear flow are generally easy to understand.

As systems increase in complexity, the linear model becomes less maintainable. Consider for example a simple program to bounce a square around a window in your favorite operating system or window manager. The linear approach may work, up to a point. You can keep the moving and drawing code in separate procedures, but soon the logic begins to branch.

  • What happens if the user resizes the window?
  • Or if the square is partially off-screen?
  • Are all those system calls to get such resources as device contexts and interacting with the graphical user interface really part of the solution domain?

It would be much more elegant if the programmer could concentrate on the application (in this case, updating the coordinates of the box) and leave the parts common to every application to "something else".

The key to making this possible is to sacrifice the element of control. Instead of your program running the system, the system runs your program. In our example, our program could register for timer events, and write a corresponding event handler that updates the coordinates. The program would include other callbacks to respond to other events, such as when the system requires part of a window to be redrawn. The system should provide suitable context information so the handler can perform the task and return. The user's program no longer includes an explicit control path, aside from initialization and registration.

Event loop programming, however, is merely the beginning of software development following the Hollywood principle. More advanced schemes such as event-driven object-orientation go further along the path, by software components sending messages to each other and reacting to the messages they receive. Each message handler merely has to perform its own local processing. It becomes very easy to unit test individual components of the system in isolation, while integration of all the components typically does not have to concern itself excessively with the dependencies between them.

Software architecture that encourages the Hollywood principle typically becomes more than "just" an API - instead, it may take on more dominant roles such as a software framework or container. Examples:

All of these mechanisms require some cooperation from the developer. To integrate seamlessly with the framework, the developer must produce code that follows some conventions and requirements of the framework. This may be something as simple as implementing a specific interface, or, as in the case of EJB, a significant amount of wrapper code, often produced by code generation tools.

[edit]Recent paradigms

More recent paradigms and design patterns go even further in pursuit of the Hollywood principle. Inversion of control for instance takes even the integration and configuration of the system out of the application, and instead performs dependency injection.

Again, this is most easily illustrated by an example. A more complex program such as a financial application is likely to depend on several external resources, such as database connections. Traditionally, the code to connect to the database ends up as a procedure somewhere in the program. It becomes difficult to change the database or test the code without one. The same is true for every other external resource that the application uses.

Various design patterns exist to try to reduce the coupling in such applications. In the Java world, the Service locator pattern exists to look up resources in a directory, such as JNDI. This reduces the dependency - now, instead of every separate resource having its own initialization code, the program depends only on the service locator.

[edit]Inversion of control

Inversion of control containers take the next logical step. In this example, the configuration and location of the database (and all the other resources) is kept in a configuration file external from the code. The container is responsible for resolution of these dependencies, and delivers them to the other software components - for example by calling a setter method. The code itself does not contain any configuration. Changing the database, or replacing it with a suitable mock object for unit testing, becomes a relatively simple matter of changing the external configuration. Integration of software components is facilitated, and the individual components get even closer to the Hollywood principle. 
  

A Taxonomy for "Bad Code Smells"

Posted by epicdev Archive : 2011. 11. 15. 15:18
출처: http://www.soberit.hut.fi/mmantyla/BadCodeSmellsTaxonomy.htm

A Taxonomy for "Bad Code Smells"

Citation

If you wish to cite this taxonomy please use the following article

Mäntylä, M. V. and Lassenius, C. "Subjective Evaluation of Software Evolvability Using Code Smells: An Empirical Study". Journal of Empirical Software Engineering, vol. 11, no. 3, 2006, pp. 395-431. (pdf)

Taxonomy

The reason for creating the taxonomy is to provide better understanding of the smells and to recognize the relationships between smells. I feel that with a long flat list of the code smells it is easy to lose the overall picture (at least that happened to me when I first studied the list of code smells in (Fowler&Beck 2000)). Thus, here is a taxonomy of five groups.

Group name

Smells in group

Discussion

The Bloaters -Long Method
-Large Class
-Primitive Obsession
-Long Parameter List
-DataClumps
Bloater smells represents something that has grown so large that it cannot be effectively handled.

It seems likely that these smells grow a little bit at a time. Hopefully nobody designs, e.g., Long Methods.

Primitive Obsession is actually more of a symptom that causes bloats than a bloat itself. The same holds for Data ClumpsWhen a Primitive Obsession exists, there are no small classes for small entities (e.g. phone numbers). Thus, the functionality is added to some other class, which increases the class and method size in the software. With Data Clumps there exists a set of primitives that always appear together (e.g. 3 integers for RGB colors). Since these data items are not encapsulated in a class this increases the sizes of methods and classes. 

The Object-Orientation Abusers -Switch Statements
-Temporary Field
-Refused Bequest
-Alternative Classes with Different Interfaces
The common denominator for the smells in the Object-Orientation Abuser category is that they represent cases where the solution does not fully exploit the possibilities of object-oriented design.

For example, a Switch Statement might be considered acceptable or even good design in procedural programming, but is something that should be avoided in object-oriented programming. The situation where switch statements or type codes are needed should be handled by creating subclasses. Parallel Inheritance Hierarchies and Refused Bequest smells lack proper inheritance design, which is one of the key elements in object-oriented programming. The Alternative Classes with Different Interfaces smell lacks a common interface for closely related classes, so it can also be considered a certain type of inheritance misuse. The Temporary Field smell means a case in which a variable is in the class scope, when it should be in method scope. This violates the information hiding principle.

The Change Preventers -Divergent Change
-Shotgun Surgery 
-Parallel Inheritance Hierarchies
Change Preventers are smells is that hinder changing or further developing the software

These smells violate the rule suggested by Fowler and Beck which says that classes and possible changes should have a one-to-one relationship. For example, changes to the database only affect one class, while changes to calculation formulas only affect the other class.

The Divergent Change smell means that we have a single class that needs to be modified by many different types of changes. With the Shotgun Surgery smell the situation is the opposite, we need to modify many classes when making a single change to a system (change several classes when changing database from one vendor to another)

Parallel Inheritance Hierarchies, which means a duplicated class hierarchy, was originally placed in OO-abusers. One could also place it inside of The Dispensables since there is redundant logic that should be replaced.

The Dispensables -Lazy class
-Data class 
-Duplicate Code
-Dead Code, 
-Speculative Generality
The common thing for the Dispensable smells is that they all represent something unnecessary that should be removed from the source code.

This group contains two types of smells (dispensable classes and dispensable code), but since they violate the same principle, we will look at them together. If a class is not doing enough it needs to be removed or its responsibility needs to be increased. This is the case with the Lazy class and the Data class smells. Code that is not used or is redundant needs to be removed. This is the case with Duplicate Code, Speculative Generality and Dead Code smells. 

The Couplers -Feature Envy
-Inappropriate Intimacy
-Message Chains 
-Middle Man
This group has four coupling-related smells.

One design principle that has been around for decades is low coupling (Stevens et al. 1974) . This group has 3 smells that represent high coupling. Middle Man smell on the other hand represent a problem that might be created when trying to avoid high coupling with constant delegation. Middle Man is a class that is doing too much simple delegation instead of really contributing to the application.

The Feature Envy smell means a case where one method is too interested in other classes, and the Inappropriate Intimacy smell means that two classes are coupled tightly to each other. Message Chains is a smell where class A needs data from class D. To access this data, class A needs to retrieve object C from object B (A and B have a direct reference). When class A gets object C it then asks C to get object D. When class A finally has a reference to class D, A asks D for the data it needs. The problem here is that A becomes unnecessarily coupled to classes B, C, and D, when it only needs some piece of data from class D. The following example illustrates the message chain smell: A.getB().getC().getD().getTheNeededData()

Of course, I could make an argument that these smells should belong to the Object-Orientation abusers group, but since they all focus strictly on coupling, I think it makes the taxonomy more understandable if they are introduced in a group of their own.

FAQ

In what way is this taxonomy better than the one provided in the Refactoring Workbook (Wake 2003)? 
It is shorter ;-). Seriously, this is left as an exercise for the reader. If you like mine better - great. If you like their better - fine.

Hey, I could argue that all smells should be placed inside a certain group (Change Preventers or OO abusers) since they all prevent change / abuse OO principles. 
This is true. However, then we would not receive any increased understanding from the classification.

I want to learn more about refactoring and code smells
Try (Fowler 2000) or www.refactoring.com

I need to find a really good agile process framework to help our process improvement!
Great, try the SEMS-approach

References

M. Fowler, Refactoring: Improving the Design of Existing Code, Canada: Addison-Wesley, 2000.

M. Fowler and K. Beck, "Bad Smells in Code," in Refactoring: Improving the Design of Existing Code, Addison-Wesley, 2000, pp. 75-88.

W. Stevens, G. Myers and L. Constantine, "Structured Design," IBM Syst J, vol. 13, no. 2, pp. 115-139, 1974.

W.C. Wake, Refactoring Workbook, Addison Wesley, 2003.


comments / feedback: Mika Mäntylä

  

'Archive' 카테고리의 다른 글

In Praise Of Small Code  (0) 2011.11.15
Hollywood Principle  (0) 2011.11.15
Code Smell  (0) 2011.11.15
테스트가 코드를 향상시키도록 하라  (0) 2011.11.15
Agile 원칙 12가지  (0) 2011.11.14
  

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
  

테스트가 코드를 향상시키도록 하라

Posted by epicdev Archive : 2011. 11. 15. 14:58
Writing unit tests often helps you write better code. The reason is simple: a test case is a user of your code. It's only when using code that you find its shortcomings. Don't hesitate to listen to your tests and refactor your code so that it's easier to use. The practice of test-driven development relies on this principle. By writing the tests first, you develop your classes from the point of view of a user of your code.


JUnitinAction
카테고리 과학/기술 > 컴퓨터
지은이 Massol (Manning, 2004년)
상세보기
 

'Archive' 카테고리의 다른 글

A Taxonomy for "Bad Code Smells"  (0) 2011.11.15
Code Smell  (0) 2011.11.15
Agile 원칙 12가지  (0) 2011.11.14
다섯가지의 소프트웨어 테스트  (0) 2011.11.14
Java에서 static method가 오버라이드 될 수 없는 이유  (0) 2011.11.14
  

Agile 원칙 12가지

Posted by epicdev Archive : 2011. 11. 14. 17:01
출처: http://telaga.cs.ui.ac.id/~wibowo/publik/PDF/PRES/SEPA7eSlidesCh3.pdf

1. Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.
2. Welcome changing requirements, even late in development. Agile processes harness change for the customer's competitive advantage.
3. Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.
4. Business people and developers must work together daily throughout the project.
5. Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.
6. The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.
7. Working software is the primary measure of progress.
8. Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely.
9. Continuous attention to technical excellence and good design enhances agility.
10. Simplicity - the art of maximizing the amount of work not done - is essential.
11. The best architectures, requirements, and designs emerge from self-organizing teams.
12. At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.
  

다섯가지의 소프트웨어 테스트

Posted by epicdev Archive : 2011. 11. 14. 16:08
큰 개념의 순으로

1. Acceptance testing
2. Stress/load testing
3. Functional testing
4. Integration testing
5. Unit testing


JUnitinAction
카테고리 과학/기술 > 컴퓨터
지은이 Massol (Manning, 2004년)
상세보기
 
  
출처: http://stackoverflow.com/questions/2223386/why-doesnt-java-allow-overriding-of-static-methods

Overriding depends on having an instance of a class. The point of polymorphism is that you can subclass a class and the objects implementing those subclasses will have different behaviors for the same methods defined in the superclass (and overridden in the subclasses). A static method is not associated with any instance of a class so the concept is not applicable.


  

Unit test와 functional test의 차이점

Posted by epicdev Archive : 2011. 11. 14. 14:09
출처: http://software-testing-zone.blogspot.com/2007/01/unit-testing-versus-functional-tests.html

Unit tests tell a developer that the code is doing things right; functional tests tell a developer that the code is doing the right things.

Unit tests:
Unit tests are written from a programmer's perspective. They ensure that a particular method of a class successfully performs a set of specific tasks. Each test confirms that a method produces the expected output when given a known input.

Writing a suite of maintainable, automated unit tests without a testing framework is virtually impossible. Before you begin, choose a framework that your team agrees upon. You will be using it constantly, so you better like it. There are several unit-testing frameworks available from the Extreme Programming Web site. The one I am most familiar with is JUnit for testing Java code.

Functional tests:
Functional tests are written from a user's perspective. These tests confirm that the system does what users are expecting it to.

Many times the development of a system is likened to the building of a house. While this analogy isn't quite correct, we can extend it for the purposes of understanding the difference between unit and functional tests. Unit testing is analogous to a building inspector visiting a house's construction site. He is focused on the various internal systems of the house, the foundation, framing, electrical, plumbing, and so on. He ensures (tests) that the parts of the house will work correctly and safely, that is, meet the building code. Functional tests in this scenario are analogous to the homeowner visiting this same construction site. He assumes that the internal systems will behave appropriately, that the building inspector is performing his task. The homeowner is focused on what it will be like to live in this house. He is concerned with how the house looks, are the various rooms a comfortable size, does the house fit the family's needs, are the windows in a good spot to catch the morning sun. The homeowner is performing functional tests on the house. He has the user's perspective. The building inspector is performing unit tests on the house. He has the builder's perspective.

Like unit tests, writing a suite of maintainable, automated functional tests without a testing framework is virtually impossible. JUnit is very good at unit testing; however, it unravels when attempting to write functional tests. There is no equivalent of JUnit for functional testing. There are products available for this purpose, but I have never seen these products used in a production environment. If you can't find a testing framework that meets your needs, you'll have to build one.

No matter how clever we are at building the projects we work on, no matter how flexible the systems are that we build, if what we produce isn't usable, we've wasted our time. As a result, functional testing is the most important part of development.

Because both types of tests are necessary, you'll need guidelines for writing them. 
  

출처: http://tech-read.com/2008/06/19/why-inner-class-can-access-only-final-variable/

Local classes can most definitely reference instance variables. The reason they cannot reference non final local variables is because the local class instance can remain in memory after the method returns. When the method returns the local variables go out of scope, so a copy of them is needed. If the variables weren’t final then the copy of the variable in the method could change, while the copy in the local class didn’t, so they’d be out of synch.

Anonymous inner classes require final variables because of the way they are implemented in Java. An anonymous inner class (AIC) uses local variables by creating a private instance field which holds a copy of the value of the local variable. The inner class isn’t actually using the local variable, but a copy. It should be fairly obvious at this point that a “Bad Thing”™ can happen if either the original value or the copied value changes; there will be some unexpected data synchronization problems. In order to prevent this kind of problem, Java requires you to mark local variables that will be used by the AIC as final (i.e., unchangeable). This guarantees that the inner class’ copies of local variables will always match the actual values.

  
 «이전 1 ··· 6 7 8 9 10 11 12 ··· 17  다음»