Sunday, November 27, 2016

Performance and the Pipeline

- How can performance analysis keep up with ever faster and more frequent release cycles in the DevOps world?


by Felix Willnecker (@Floix), fortiss GmbH, Germany, Johannes Kroß, fortiss GmbH, Germany, and André van Hoorn (@andrevanhoorn), University of Stuttgart, Germany
Associate Editor: Zhen Ming (Jack) Jiang, York University, Canada

Back in the “good old days”, a release occurred every month, quarter, or year—leaving enough time for a thorough quality analysis and extensive performance/load tests. However, these times are coming to an end or are almost over. Deploying every day, minute, or every couple of seconds becomes the new normal [1]. Agile development, test automation, consequent automation in the delivery pipeline and the DevOps movement drive this trend that conquers the IT world [2]. In this world, performance analysis is left behind. Tasks like load tests take too long and have a lot of requirements on the test and delivery environment. Therefore, performance analysis tasks are nowadays skipped and performance bugs are only detected and fixed in production. However, this is not a willful decision but an act from necessity [3]. The rest of this blog post is organized as follows: First, we outlines the three strategies on including performance analysis in your automatic delivery pipeline without slowing down your release cycles. Then we introduce the accompanied survey to find out how performance concerns are currently addressed in industrial DevOps practice. Finally, we conclude this blog post. 


Strategy # 1: Rolling back and forward


The usual response that we get when talking about performance analysis in a continuous delivery pipeline is: “Well, we just roll back if something goes wrong”. This is a great plan: in theory. In practice, this often fails in emergency situations. First of all, this strategy requires not only a continuous delivery pipeline but also an automatic rollback mechanism. This is pretty easy on the level of an application server (just install release n-1), but is getting harder with databases (e.g., legacy table views for every change), and almost impossible if multiple applications and service dependencies are involved. Instead of rolling back, rolling forward is applied. Which means, we deploy as many fixes, until the issue is resolved. Such emergency fixes are often developed in a hurry or in war room sessions. When your company introduced continuous delivery pipeline they often promised that these war room sessions come to an end, just by releasing smaller incremental artifacts. Truth is, in case of emergency Murphy’s Law applies, your rollback mechanism fails and you spend the rest of the day/night resolving this issue. 


Strategy # 2: Functional tests applied on performance


Another common strategy is using functional tests and derive some metrics that act as indicator for performance bugs. Measuring the number of exceptions or SQL statements during a functional test and comparing these numbers with a former release or baseline are common practice. Some tool support like the PerfSig utilizing Dynatrace AM exist to automate such analysis using the Jenkins build server [4]. This approach acts pro-actively, so issues can be detected before release and requires no additional tests, just some tooling and analysis software in your delivery pipeline. However, the impact on the performance of your application are vague. Resource utilization or response time measurements conducted during short functional tests usually delivery no meaningful values, especially if the delivery pipeline runs in a virtualized environment. Exceptions and SQL statements act as an indicator and may reduce the number of performance issues in production but won’t identify a poorly developed algorithm.


Strategy # 3: Model-based performance analysis 


Performance models have their origin in academia and today are only rarely adopted by practitioners. However, such models can help to identify performance bugs in your software, without adding new tests. Nowadays, performance model generators exist that derive the performance characteristics of an application directly from a build system [5]. These approaches rely on measurements on operation and component level and require a good test coverage. A complete functional test run should execute each operation multiple times so that these generators can derive resource demands per operation. Changes in the resource demands indicate a performance change either for good (decreased resource demand) or for worse (increased resource demand). The main advantage compared to simple functional test analysis, is that a complete set of tests is analyzed and multiple runs of the same test set are supported. However, major changes in the test set, may require a new baseline for a model-based analysis.


Survey 



To identify and capture the current state-of-the-art of performance practices, but also present problems and issues, we have launched a survey that we would like to promote and encourage you or your organization to participate in. We would like to find out how performance concerns are currently addressed in industrial DevOps practice and plan to integrate the impressions and results in a blueprint for performance-aware DevOps. Furthermore, we would like to know whether classical paradigms still dominate in your organization, at what stages performance evaluations are conducted, what metrics are relevant for you, and what actions are applied after a performance evaluation.



Our long-term aim is to not only conduct this survey once, but to benchmark the state-of-the-art continuously, compare the results over a longer period, and to regularly incorporate outcomes to our blueprint. The results of this survey will be incorporated into our bigger project of building the reference infrastructure for performance-aware DevOps and helps to understand DevOps in industry today. 


Conclusions





Classical performance and load test phases may vanish and never come back. However, current strategies on reducing the risks of performance issues in production have a number of disadvantages. Rollback mechanisms might fail, functional tests only deliver indicators, and model-based evaluations lack of industrial tool support. Most of the time, performance does not receive enough or even any attention. In our opinion, this is primarily due to the fact that present performance management practices are not integrated and adapted to typical DevOps processes, especially in terms of automation and holistic tool support.

References


References

  1. J. Seiden, Amazon Deploys to Production Every 11.6 Seconds, http://joshuaseiden.com/blog/2013/12/amazon-deploys-to-production-every-11-6-seconds/.
  2. A. Brunnert, A. van Hoorn, F. Willnecker, A. Danciu, W. Hasselbring, C. Heger, N. Herbst, P. Jamshidi, R. Jung, J. von Kistowski, A. Koziolek. Performance-oriented devops: A research agenda. arXiv preprint arXiv:1508.04752. 2015.
  3. T-Systems MMS, PerfSig-jenkins. https://github.com/T-Systems-MMS/perfsig-jenkins,
  4. M. Dlugi, A. Brunnert, H. Krcmar. Model-based performance evaluations in continuous delivery pipelines. In Proceedings of the 1st International Workshop on Quality-Aware DevOps. 2015.

If you like this article, you might also enjoy reading:


    1. L. Zhu, L. Bass, G. Champlin-Scharff. DevOps and Its Practices. IEEE Software 33(3): 32-34. 2016.
    2. M. Callanan, A. Spillane. DevOps: Making It Easy to Do the Right Thing. IEEE Software 33(3): 53-59. 2016.
    3. Diomidis Spinellis. Being a DevOps Developer. IEEE Software 33(3): 4-5. 2016.

    Sunday, November 20, 2016

    Creativity in Requirements Engineering: Why and How?


    By: Tanmay Bhowmik, Mississippi State University
    Associate Editor: Mehdi Mirakhorli (@MehdiMirakhorli)

    Prologue. One day, I was giving a talk on creativity in requirements engineering (RE). A fellow colleague from the audience asked, “Why do you need to create requirements in the first place? Why don’t you just ask the customers what they want?” Well, from the traditional RE perspective, if we assume that requirements reside in stakeholders’ minds in an implicit manner [1] and the stakeholders know what they want, my colleague has a point. However, does this traditional view on the origin of requirements anymore hold in modern RE?

    Why creativity in RE? Software industry has become extremely competitive. These days, we usually choose from multiple software systems that strive to serve the users in the same application domain. Therefore, in order to sustain and grow in the market, a software system needs to distinguish itself from other similar products and consistently enchant customers with novel and useful features. As a result, the traditional view on the origin of requirements does not hold anymore. Modern requirements engineers need to create innovative requirements in order to equip the software with competitive advantage. It is no more an exaggeration to say that requirements engineers need to be trained with the concept of creativity in RE.     

    What is creativity in RE? Before looking into creativity from an RE perspective, we need to know what creativity is. Robert Sternberg has given a definition of creativity that is widely accepted by the scientific community. According to him, “creativity is the ability to produce work that is both novel (i.e., original and unexpected) and appropriate (i.e., useful and adaptive to the task constraints)” [2]. According to Neil Maiden and his colleagues [5], creativity in RE is the capture of requirements that are new to the project stakeholders but may not be historically new to humankind. For example, internet browsing using smartphone has become a very basic requirement for the smartphone domain. Even though the commercial Internet Service Providers emerged in the late 1980s, internet service on cell phones was not available until late 1990s. In 1999, when NTT DoCoMo in Japan introduced the first full internet service on mobile phones [6], it was a creative requirement to the stakeholders.

    How to obtain creative requirements? Depending on the techniques and heuristics used, Creative requirements could be obtained in three different ways [3, 7].
    • Exploratory Creativity: We can come up with creative requirements by exploring a set of possibilities in the search space guided by certain rules and constraints.
    • Combinational Creativity:  We can make unfamiliar connections between familiar possibilities or known requirements and obtain creative requirements.
    • Transformational Creativity: Creative requirements could also be obtained by changing/transforming the constraints on the search space and expanding the set of possibilities to be explored.



    Fig. 1. Different ways to obtain creative requirements (adapted from [7]).

    Figure 1 explains the three different ways of achieving creativity in RE with a simple example [8]. Assume a creativity scenario for a hypothetical software system that “should provide access control” for a classified laboratory facility. As an initial constraint, we have specific limitation on available hardware systems. Let XYZ in Figure 1 be a search space with three possibilities “log-in ID and password”, “fingerprint”, and “facial recognition”. Provided that these possibilities satisfy the initial constraint, using any of these as a means of access control is an instance of exploratory creativity. If we combine two apparently different means of providing access control, such as log-in ID and password along with fingerprint, or log-in ID and password combined with facial recognition, we have an example of combinational creativity. Now, let us relax our initial constraint on hardware limitation and expand the search space towards biometric direction. Thereby we get a new search space XYZ’ that includes “retina scan” and “DNA scan” as further possibilities. Using any of these options is an example of transformational creativity. 

    A framework to provide automated support for creativity in RE. In a recent work, we have developed a novel framework that utilizes stakeholders’ social interaction about an existing system and provides an automated support for combinational creativity. Figure 2 presents an overview of our framework [8]. In RE, combinational creativity can be achieved by making unfamiliar connections between familiar possibilities where the familiarity and unfamiliarity aspects are determined from the stakeholders’ perspective.   




     Fig. 2. A framework for combinational creativity in RE [8].

    Our framework starts with creating stakeholders’ social network based on their interaction about the software system. Then the network is clustered to find stakeholders’ groups, as discussion within a group generally revolves around ideas familiar to the group members. For each group, we apply topic modeling to interaction related documents, such as requirements and comments contributed by the group members. Thereby, we find familiar ideas discussed in a group in terms of dominant topics represented in terms of multiple topic words [8]. Such familiar ideas from all the stakeholder groups constitute a search space of familiar possibilities. In order to make an unfamiliar connection between these possibilities and to keep the number of options in the search space manageable, we develop a heuristic with two major phases.

    In the first phase, following Fillmore’s case theory [9] (it suggests that a requirement can be described in terms of a verb and a noun/object that the verb acts upon), we keep only the verbs and nouns in a dominant topic. In order to achieve unfamiliarity, we flip the part-of-speech of these words and transform the familiar verbs and a nouns into unfamiliar nouns and verbs respectively. In the second phase, we make verb-noun combinations by taking unfamiliar verbs from one group and nouns from another, and filter out verb-noun combinations showing higher textual similarity with existing requirements. To that end, we obtain the most unfamiliar idea combinations in terms of verb-noun pairs. Finally, a requirements engineer elaborates requirements by filling out some templates with the verb-noun pairs (as shown in Figure 3).    

     
    Fig. 3. An example of requirements elaboration [8].

    We have applied our framework on Firefox and Mylyn, two large-scale open source software systems, and created eight new requirements for Firefox and five for Mylyn. An associated human subject study further confirmed the creative merits of these requirements [8]. Although our current framework’s application is limited to existing systems, it is an initial step towards automated support for combinational creativity in RE.

    Epilogue. In our current world that can be defined by its high reliance on computing devices and software systems, competition within the software industry is ever increasing. This competition is going to be even fiercer over time. As software engineering practitioners and academicians, our priority should be to educate and train ourselves with the techniques of creativity in RE.

    Further interested in this topic? Please feel free to read our recent work presented in [8] and share your thoughts.

    References
    1.     J. Lemos, C. Alves, L. Duboc, and G. N. Rodrigues, “A systematic mapping study on creativity in requirements engineering,” in Proceedings of the Annual ACM Symposium on Applied Computing (SAC), 2012, pp. 1083–1088.
    2.     R. J. Sternberg, Handbook of creativity. Cambridge University Press, 1999.
    3.     M. A. Boden, The creative mind: Myths and mechanisms. Routledge, 2003.
    4.     M. Suwa, J. Gero, and T. Purcell, “Unexpected discoveries and Sinvention of design requirements: Important vehicles for a design process,” Design Studies, vol. 21, no. 6, pp. 539–567, 2000.
    5.     N. Maiden, S. Jones, K. Karlsen, R. Neill, K. Zachos, and A. Milne, “Requirements engineering as creative problem solving: A research agenda for idea finding,” in Proceedings of the International Requirements Engineering Conference (RE), 2010, pp. 57–66.
    6.     J. Blagdon, “How emoji conquered the world,” The Verge, Vox Media, 2013.
    7.     N. Maiden, “Requirements engineering as information search and idea discovery (keynote),” in Proceedings of the International Requirements Engineering Conference (RE), 2013, pp. 1–1.
    8.     T. Bhowmik, N. Niu, A. Mahmoud, and J. Savolainen, “Automated Support for Combinational Creativity in Requirements Engineering,” in Proceedings of the International Requirements Engineering Conference (RE), 2014, pp. 243-252.
    9.     C. Fillmore, “The case for case,” in Universals in Linguistic Theory, E. Bach and R. Harms, Eds. New York: Holt, Rinehart and Winston, 1968, pp. 1–88.

    Sunday, November 13, 2016

    Why we refactor? Here are 44 different reasons, according to GitHub contributors

    by Danilo Silva, Universidade Federal de Minas Gerais (danilofs@dcc.ufmg.br); Nikolaos Tsantalis, Concordia University (@NikosTsantalis); Marco Tulio Valente, Universidade Federal de Minas Gerais (@mtov)
    Associate Editor: Christoph Treude (@ctreude)

    The adoption of refactoring practices was fostered by the availability of refactoring catalogues, as the one proposed by Martin Fowler [1]. These catalogues propose a name and describe the mechanics of each refactoring, as well as demonstrate its application through code examples. They also provide a motivation for the refactoring, which is usually associated to the resolution of code smells. For example, Extract Method is recommended to decompose a large and complex method or to eliminate code duplication. However, there is a limited number of studies investigating the real motivations driving the refactoring practice. To fill this gap in the literature, we conducted an in-depth investigation on why developers refactor code.

    During 61 days, we monitored the refactoring activity of 748 GitHub Java repositories, using an automated infrastructure we built. Every time we identified a refactoring, we asked the developer who performed it to explain the reasons behind his/her decision to refactor the code. Next, we categorized their responses into different themes of motivations. The following table presents the results of this process, in the format of a catalogue with 44 distinct motivations for refactoring, grouped by 12 well-known refactoring types.

    Table 1: Motivations for each refactoring type.
    Ref. TypeMotivationOccurrences
    Extract MethodExtract a piece of reusable code from a single place and call the extracted method in multiple places.43
    Introduce an alternative signature for an existing method (e.g., with additional or different parameters) and make the original method delegate to the extracted one.25
    Extract a piece of code having a distinct functionality into a separate method to make the original method easier to understand.21
    Extract a piece of code in a new method to facilitate the implementation of a feature or bug fix, by adding extra code either in the extracted method, or in the original method.15
    Extract a piece of duplicated code from multiple places, and replace the duplicated code instances with calls to the extracted method.14
    Introduce a new method that replaces an existing one to improve its name or remove unused parameters. The original method is preserved for backward compatibility, it is marked as deprecated, and delegates to the extracted one.6
    Extract a piece of code in a separate method to enable its unit testing in isolation from the rest of the original method.6
    Extract a piece of code in a separate method to enable subclasses override the extracted behavior with more specialized behavior.4
    Extract a piece of code to make it a recursive method.2
    Extract a constructor call (class instance creation) into a separate method.1
    Extract a piece of code in a separate method to make it execute in a thread.1
    Move ClassMove a class to a package that is more functionally or conceptually relevant.13
    Move a group of related classes to a new subpackage.7
    Convert an inner class to a top-level class to broaden its scope.4
    Move an inner class out of a class that is marked deprecated or is being removed.3
    Move a class from a package that contains external API to an internal package, avoiding its unnecessary public exposure.2
    Convert a top-level class to an inner class to narrow its scope.2
    Move a class to another package to eliminate undesired dependencies between modules.1
    Eliminate a redundant nesting level in the package structure.1
    Move a class back to its original package to maintain backward compatibility.1
    Move AttributeMove an attribute to a class that is more functionally or conceptually relevant.15
    Move similar attributes to another class where a single copy of them can be shared, eliminating the duplication.4
    Rename PackageRename a package to better represent its purpose.8
    Rename a package to conform to project's naming conventions.3
    Move a package to a parent package that is more functionally or conceptually relevant.2
    Move MethodMove a method to a class that is more functionally or conceptually relevant.8
    Move a method to a class that permits its reuse by other classes.3
    Move a method to eliminate dependencies between classes.3
    Move similar methods to another class where a single copy of them can be shared, eliminating duplication.1
    Move a method to permit subclasses to override it.1
    Inline MethodInline and eliminate a method that is unnecessary or has become too trivial after code changes.13
    Inline and eliminate a method because its caller method has become too trivial after code changes, so that it can absorb the logic of the inlined method without compromising readability.2
    Inline a method because it is easier to understand the code without the method invocation.1
    Extract SuperclassIntroduce a new superclass that contains common state or behavior from its subclasses.7
    Introduce a new superclass that is decoupled from specific dependencies of a subclass.1
    Extract a superclass from a class that holds many responsibilities.1
    Pull Up MethodMove common methods to superclass.8
    Pull Up AttributeMove common attributes to superclass.7
    Extract InterfaceIntroduce an interface to enable different behavior.1
    Introduce an interface to facilitate the use of a dependency injection framework.1
    Introduce an interface to avoid depending on an existing class/interface.1
    Push Down AttributePush down an attribute to allow specialization by subclasses.2
    Push down attribute to subclass so that the superclass does not depend on a specific type.1
    Push Down MethodPush down a method to allow specialization by subclasses.1

    Our findings confirm that Extract Method is the "Swiss army knife of refactorings". It is the refactoring with the most motivations (11 in total), and the majority of them expresses an intention to facilitate or even enable the completion of the maintenance task the developer is working on. In contrast, only two motivations for Extract Method (decompose method to improve readability and remove duplication) are targeting code smells.

    The other refactorings are performed to improve the system design. For example, the most common motivation for Move Class, Move Attribute, and Move Method is to reorganize code elements, so that they have a stronger functional or conceptual relevance, or to eliminate dependencies between code elements.

    By comparing to the code symptoms that initiate refactoring reported in the study by Kim et al. [2], we found the readability, reuse, testability, duplication, and dependency concerns in common.

    Automated Refactoring Support

    We also asked developers whether they used the automated refactoring support of an IDE to perform refactorings. Thus, we could compare our finding with previous studies in this area, leading to the following conclusions.

    • Manual refactoring is still prevalent (55% of the developers refactored the code manually). Inheritance related refactoring tool support seems to be the most under-used (only 10% done automatically), while Move Class and Rename Package are the most trusted refactorings (over 50% done automatically). The prevalence of manually applied refactoring confirms the findings of Murphy-Hill et al. [3] and Negara et al. [4]. However, it seems that developers apply more automated refactorings nowadays.
    • The IDE plays an important role in the adoption of refactoring tool support. IntelliJ IDEA users perform more automated refactorings (71% done automatically) than Eclipse users (44%) and Netbeans users (50%).
    29 developers also explained why they did not use a refactoring tool, as summarized in the following table.

    Table 2: Reasons for not using refactoring tools.
    ReasonOccurrences
    The developer does not trust automated support for complex refactorings.10
    Automated refactoring is unnecessary, because the refactoring is trivial and can be manually applied.8
    The required modification is not supported by the IDE.6
    The developer is not familiar with the refactoring capabilities of his/her IDE.3
    The developer did not realize at the moment of the refactoring that he/she could have used refactoring tools.2

    If you are interested in our study, please refer to our paper accepted at FSE 2016:

    Danilo Silva, Nikolaos Tsantalis, Marco Tulio Valente. Why We Refactor? Confessions of GitHub Contributors. [pdf]

    References

    [1] M. Fowler. Refactoring: Improving the Design of Existing Code. Addison-Wesley, Boston, MA, USA, 1999.
    [2] M. Kim, T. Zimmermann, and N. Nagappan. An empirical study of refactoring challenges and benefits at Microsoft. IEEE Trans. Softw. Eng., 40(7), July 2014.
    [3] E. R. Murphy-Hill, C. Parnin, and A. P. Black. How we refactor, and how we know it. IEEE Trans. Softw. Eng., 38(1):5-18, 2012.
    [4] S. Negara, N. Chen, M. Vakilian, R. E. Johnson, and D. Dig. A comparative study of manual and automated refactorings. In Proceedings of the 27th European Conference on Object-Oriented Programming (ECOOP), pages 552-576, 2013.

    Sunday, November 6, 2016

    When and Why Your Code Starts to Smell Bad

    By: Michele Tufano, College of William and Mary, USA (@tufanomichele)
    Associate Editor: Sonia Haiduc, Florida State University, USA (@soniahaiduc

    Have you ever tried to modify a large class with too many methods? And what about those unnecessarily complicated multi-level nested loops? How did you feel about that? Those are code smells, and can make the evolution of your system a nightmare.

    More formally, code smells are the clues that indicate violations of fundamental design principles and negatively impact design quality [1]. Several studies demonstrated the negative impact of code smells on change- and fault-proneness [2], software understandability [3] and maintainability [4] [5].

    The question is: when and why those code smells are introduced? Common wisdom suggests that they are introduced during maintenance and evolution activities on software artifacts. However, such a conjecture has never been empirically verified. In this work, we empirically answer such questions by analyzing the complete change history of 200 Java software systems, belonging to three ecosystems - Apache, Android and Eclipse. We considered five types of code smells: Blob, Complex Class, Class Data Should Be Private, Functional Decomposition, and Spaghetti Code [1].

    Design


    When? - To answer this question we checked out every single commit of the analyzed systems and ran a code smell detector (i.e., DECOR [5]) on the Java classes introduced/modified in the commit. We also computed the value of quality metrics on such classes in order to obtain evolutionary metric trends. These steps allowed us to (i) understand after how many modifications on a software artifact code smells are usually introduced, and (ii) compare the metric trends of clean and smelly software artifacts, looking for significant differences in how fast their metrics’ values increase or decrease.

    Curiosity - How much did it take? Eight weeks on a Linux server with
    7 quad-core 2.67 GHz CPU (28 cores) and 24 Gb of RAM.

    Why? - Here we wanted to understand why developers introduce code smells. In particular, does their workload influence the probability of introducing a code smell? What about the deadline pressure for releases?  Which are the tasks (implementation of new features, bug fixing, refactoring, etc.) that developers perform when introducing code smells? To this aim, we tagged the commits that introduced the smells. To perform such an analysis, we needed to identify those commits responsible for the introduction of a code smell. When the code smell is introduced during the creation of the software artifact, trivially, we just analyzed the first commit, but what about code smell instances that appear after several commits? Which commits should we analyze? If we analyze only the one in which the code smell is identified, we would discard all the change history that led to a smelly artifact! For this reason we defined smell-introducing commits as commits which might have pushed a software artifact toward a smelly direction, looking at discriminating metrics’ trends. For example, in the following figure, commits c3, c5 and c7 are identified as smell-introducing commits and tagged as such.




    Results


    When? - While common wisdom suggests that smells are introduced after several activities made on a code component, we found instead that such a component is generally affected by a smell since its creation. Thus, developers introduce smells when they work on a code component for the very first time.

    However, there are also cases where the smells manifest themselves after several changes were performed on the code component. In these cases, files that will become smelly exhibit specific trends for some quality metric values that are significantly different than those of clean (non-smelly) files.





    For example, the Weighted Method Complexity (WMC) of classes that eventually become Blobs, increases more than 230 times faster with respect to clean classes, considering the same initial development time.

    Why? - Smells are generally introduced by developers when enhancing existing features or implementing new ones. As expected, smells are generally introduced in the last month before a deadline, while there is a considerable number of instances introduced in the first year from the project startup. Finally, developers that introduce smells are generally the owners of the file (i.e., they are responsible for at least 75% of the changes made to the file) and they are more prone to introducing smells when they have higher workloads.
                           

    References


    [1] M. Fowler, K. Beck, J. Brant, W. Opdyke, and D. Roberts, Refactoring: Improving the Design of Existing Code. Addison-Wesley, 1999.
    [2] F. Khomh, M. Di Penta, Y.-G. Gueheneuc, and G. Antoniol, “An exploratory study of the impact of antipatterns on class change- and fault-proneness,” Empirical Software Engineering, vol. 17, no. 3, pp. 243–275, 2012.
    [3] M.Abbes, F.Khomh, Y.-G. Gueheneuc, and G.Antoniol, “An empirical study of the impact of two antipatterns, Blob and Spaghetti Code, on program comprehension,” in 15th European Conference on Software Maintenance and Reengineering, CSMR 2011, 1-4 March 2011, Oldenburg, Germany. IEEE Computer Society, 2011, pp. 181–190.
    [4] D. I. K. Sjøberg, A. F. Yamashita, B. C. D. Anda, A. Mockus, and T. Dyba, “Quantifying the effect of code smells on maintenance effort,” IEEE Trans. Software Eng., vol. 39, no. 8, pp. 1144–1156, 2013.
    [5] Michele Tufano, Fabio Palomba, Gabriele Bavota, Rocco Oliveto, Massimiliano Di Penta, Andrea De Lucia, and Denys Poshyvanyk. 2015. When and why your code starts to smell bad. In Proceedings of the 37th International Conference on Software Engineering - Volume 1 (ICSE '15), Vol. 1. IEEE Press, Piscataway, NJ, USA, 403-414. Preprint available at: https://dibt.unimol.it/staff/fpalomba/documents/C4.pdf
    [6] N.Moha, Y.-G. Gueheneuc, L. Duchien, and A.-F.L. Meur, “DECOR: A method for the specification and detection of code and design smells,” IEEE Transactions on Software Engineering, vol. 36, pp. 20–36, 2010.

    Sunday, October 23, 2016

    Tabs or Spaces? What can we find by looking at white space?

    By: Dale Fletter, California State University, Sacramento. USA (dale.fletter@csus.edu)
    Associate Editor: Bogdan Vasilescu, Carnegie Mellon University. USA (@b_vasilescu)

    The TV show Silicon Valley had a scene that satirized a common cultural rift among coders, spaces or tabs? [1] What difference does it make? [2] I argue that it is very important and leads us to an understanding of how the software engineering community has not yet matured its understanding of the underlying processes and artifacts that are at the core of the work.

    Compilers for most languages, even those that use block structured statements, ignore most white space. To them a tab or spaces is the same. Software engineers many decades ago found value in "pretty printing", that is inserting white space with the intent of visually communicating the underlying blocks in the structures. [3] To the person writing the code, both will render identical code on their screen. Those who prefer the tab will cite the efficiency with which a coder can transfer their logic into the source code. Those who prefer spaces cite the control they have over the code presentation.

    The difference between them becomes clear as soon as one does a cut-and-paste from their editor/IDE into a word processing document. Those text editors were designed to bring forward the metaphor of the typewriter tab settings where the typist set the tabs manually. When one inserts text, it is a shortcut to manual entry. To ensure the same presentation in the word processing document as in the text editor used for composition requires the software engineer to set the tab stops to match the IDE and choose a uni-space font which mimics the text editor. Failing to do either will typically render the presentation of the code in a way that significantly differs from what the coder intended which will include the visual indication of blocks.

    If the only process that depended upon the visual presentation of the code were the compiler, for most languages it would be irrelevant. But the software engineer is a reader of code and the speed, accuracy and completeness with which the program is communicated is a key contributor to code comprehension. To change that presentation is to ignore the contribution the coder made to ensuring a particular layout on their device. This more expansive way of looking at code not just as a means to instruct the machine but as a human utterance worthy of consideration on its own merits is an exciting new direction of research. [4]

    It is also possible this is not a transitory effect of personal preference either. It parallels an equally divisive style issue in legal writing. Due to the limitations of the typewriter and the need for comprehension in legal writing, the convention of double space after a period was adopted. This artifact has continued on into the present day despite the objection of typographers who point out that with a proportionally spaced font that this is not needed. It is not just the local choice of each law office. The use of the double space following a period is found in different legal publishers as well. 

    One approach is seen in many IDEs that will do an automatic format of code to conform to style rules for the presentation of blocks. There are problems in this approach. First, it leaves the choice to do the format to the coder. If it is a choice some coders will use the tool and convert to the standard for that IDE. But as we know code is often edited with different editors by different people on different platforms. The result is a source code that has a mixture of tabs and space. Another problem is that those coders who invest a great deal of time to insert spaces to achieve a visual effect can have their work undone by the well intentioned rules. But for the coder who believes they achieve greater efficiency by using a tab instead of 4 spaces, this is an imperfect compromise.

    Is there any difference in coder productivity when the tab key is used? or is this a way of expressing a personal choice in a task that is limited in its humanity and expressiveness? Is there a real time savings from those who insert a tab character from those who have developed the nervous tic of hitting the space bar four times instead? This may be worthy of analysis since a coder may need to do this many times in the course of writing and editing code.

    If the informative use of white space were limited to marking off blocks of code, this might be too insignificant an issue to justify the attention. But we all know those coders who find very creative ways to draw attention to parallel structures in their code with only the use of spaces and line feeds. This visual information is as important to retain as is the code itself. This suggests that the creation of a code file is not merely the recording of a string of text but instead a form of visual communication as well.

    I believe this bit of comic relief informs the lack of understanding that is still pervasive in the community. Writing code that is understandable to a human is more important than merely marking blocks of code. A more complete look at how coders present their code can illustrate what they have found to be important clues to increased readability. Those who still prefer tabs seem to be blasé about the loss of control over presentation depending on the editor that is used to look at the text string.  

    [3] Programming with small blocks, Mark K. Joseph. SIGSOFT Softw. Eng. Notes 9, 5 (October 1984), 28-42.
    [4] New initiative: the naturalness of software. In Proceedings of the 37th International Conference on Software Engineering - Volume 2 (ICSE '15), Vol. 2. IEEE Press, Piscataway, NJ, USA, 543-546.
    [5] A metric for software readability. Raymond P.L. Buse and Westley R. Weimer. In Proceedings of the 2008 International Symposium on Software Testing and Analysis (ISSTA '08). ACM, New York, NY, USA, 121-130.

    Sunday, October 16, 2016

    JDeodorant: Clone Refactoring Support beyond IDEs

    By: Nikolaos Tsantalis, Concordia University, Montreal, Canada (@NikosTsantalis)
    Associate Editor: Sonia Haiduc, Florida State University, USA (@soniahaiduc)


    Why should I bother to refactor duplicated code in my project?
    Duplicated code (also known as code clones) can be a potential big trouble for the maintenance of your project. Not all clones are harmful [1] or equally harmful [2]. However, if you find yourself repeatedly applying the same changes (e.g., bug fix) in multiple places in your code, you should definitely consider to refactor [3] this duplication. Merging such clones into a single copy will make future maintenance faster and less error-prone.

    Why is tool support necessary for the refactoring of clones?
    Software clones tend to diverge after the initial copy-and-paste. This happens because developers have to adjust the copied code to a new context and/or different requirements. Therefore, clones tend to have non-trivial differences as the project evolves (e.g., different methods being called, or completely different logic in parts of the implemented algorithm). Unfortunately, the current state-of-the-art IDEs support the refactoring of clones with trivial differences (i.e., identical clones with variations in whitespace, layout, comments, and variable identifiers).

    JDeodorant [4] is an Eclipse plugin that can help developers to inspect the differences between clones in Java projects, and refactor them safely, if possible. More specifically, JDeodorant applies a sophisticated static source code analysis to examine whether the parameterization of the differences appearing in the clones is free of side effects. We refer to this feature as refactorability analysis [5]. If all examined preconditions pass successfully, JDeodorant can proceed with the refactoring of the clones.

    Feature 1: Clone import and clone group exploration
    • JDeodorant can import results from 5 popular clone detection tools, namely CCFinder, ConQAT, NiCad, Deckard, and CloneDR. In addition, JDeodorant can analyze any pair of methods selected by the developer from the Eclipse Package Explorer view.
    • While importing the results, JDeodorant automatically checks the syntactic correctness of the clone fragments, and fixes any discrepancies by removing incomplete statements and adding the missing closing brackets from incomplete blocks of code. Additionally, the tool filters out the clones that extend beyond the body of a method (i.e., class-level clones).
    • The imported results are presented to the user in a tree-like view, as shown in Figure 1. The clones are organized into groups based on their similarity (i.e., a clone group contains two or more clone instances).
    • The clone groups are also analyzed to discover subclone relationships between them. Group A is a subclone of group B, if every clone instance in A is a sub-clone (i.e., a partial code fragment) of an instance in B. The subclone information appears as a link in the last column of the clone group table to help the user navigate between clone groups having such a relationship.
    • By clicking on the “Show only clone groups for the files opened in the editor” checkbox, the user can filter the clone groups table to display only the clones being relevant to the context (i.e., appearing in the files) he/she is currently working on.
    • All clones are constantly monitored for modifications. If the developer refactors or updates some code associated with the imported clones, the clone group table is automatically updated by disabling the clones affected by the modification (disabled clones appear with strikethrough text), and by re-computing the offsets of other clones belonging to the same modified Java files (shifted clones appear with text highlighted in green). In this way, the user can continue with the inspection and refactoring of other clone groups without having to import new results from external tools. 

    Figure 1: Presentation of the imported clone detection results to the user

    Feature 2: Clone visualization and refactorability analysis
    The user can right-click on any pair of clones from the same clone group, or any pair of methods from the Eclipse Package Explorer and select “Refactor Duplicated Code…” from the popup menu. The outcome of the clone pair analysis is presented to the user as shown in Figure 2.


    Figure 2: Clone pair visualization and refactorability analysis

    The analyzed clone fragments appear as two side-by-side trees, where each pair of tree nodes in the same row represents a pair of mapped statements in the first and second clone fragment, respectively. The user can inspect the clones in a synchronized manner, by expanding and collapsing the nodes corresponding to control statements (i.e., loops, conditionals, try blocks). The code is highlighted in 3 different colors to help the developer inspect and understand the differences between the clones.
    • Yellow: Represents differences in expressions between matched statements. These expressions are evaluated to the same type, but have a different syntactic structure or identifier.
    • Red: Represents unmapped statements that do not have a matching statement in the other clone fragment (also known as clone gaps).
    • Green: Represents semantically equivalent statements, i.e., statements of different AST types performing exactly the same functionality. In Figure 2, we can see a for loop in the left clone matched with a while loop in the right clone having the same initializer and updater as separate statements.
    By hovering over a pair of statements highlighted in yellow, a tooltip appears providing semantic information about the type of each difference based on the program elements (e.g., variables, method calls, literals, class instantiations) appearing in the difference. Currently, JDeodorant supports over 20 difference types, including some more advanced ones, such as the replacement of a direct field access with the corresponding getter method call, and the replacement of a direct field assignment with the corresponding setter method call. In addition, the tooltip may also include information about precondition violations, if the expressions appearing in the differences cannot be safely parameterized.

    Semantically equivalent differences, and renamed variables are not examined against preconditions, since they should not be parameterized. JDeodorant automatically detects the local variables that have been consistently renamed between the clone fragments (as shown in the bottom-right side of Figure 2).

    Feature 3: Clone refactoring
    Based on the location of the clones, JDeodorant determines automatically the best refactoring strategy:

    1.  Extract Method (clones belong to the same Java file)
    2.  Extract and Pull Up Method (clones have a common superclass)
    a) Introduce Template Method (clones call local methods from the subclasses)
    b) Extract Superclass (clones have an external common superclass, or the common superclass has additional subclasses)
    3.  Introduce Utility Method (clones access/call only static fields/methods)

    As shown in Figure 3, JDeodorant can generate a detailed preview of the refactoring to be applied, where the developer can inspect all the changes that will take place at a fine-grained level. Finally, the user can undo and redo the applied refactorings, since they are recorded in the change history of Eclipse.


    Figure 3: Clone refactoring preview

    JDeodorant is an open-source project hosted on GitHub.
    Videos demonstrating the use and features of JDeodorant can be found on YouTube.


    References
    [1] Cory J. Kapser and Michael W. Godfrey, ""Cloning considered harmful" considered harmful: patterns of cloning in software," Empirical Software Engineering, vol. 13, no. 6, pp. 645-692, December 2008.
    [2] Foyzur Rahman, Christian Bird, and Premkumar Devanbu, "Clones: what is that smell?," Empirical Software Engineering, vol. 17, no. 4-5, pp. 503-530, August 2012.
    [3] Emerson Murphy-Hill, Don Roberts, Peter Sommerlad, and William F. Opdyke, "Refactoring [Guest editors' introduction]," IEEE Software, vol. 32, no. 6, pp. 27-29, November-December 2015.
    [4] Davood Mazinanian, Nikolaos Tsantalis, Raphael Stein, and Zackary Valenta, "JDeodorant: Clone Refactoring," 38th International Conference on Software Engineering (ICSE'2016), Formal Tool Demonstration Session, Austin, Texas, USA, May 14-22, pp. 613-616, 2016.
    [5] Nikolaos Tsantalis, Davood Mazinanian, and Giri Panamoottil Krishnan, "Assessing the Refactorability of Software Clones," IEEE Transactions on Software Engineering, vol. 41, no. 11, pp. 1055-1090, November 2015.