Tuesday, August 30, 2011

Has the Software Craftsman movement successfully integrated with introductory software engineering?


By Nicholas Vaidyanathan

Abstract

In this paper, we explore whether undergraduate software engineering curriculums have successfully integrated some of the top advancements in the software industry from 2000-2010 into introductory software engineering courses. Advancements have touched all aspects of the software development lifecycle, including the advent of BDD/TDD, Continuous Integration and social Source Control, and the maturation of design patterns and domain driven design. In order to discover how many of these tools are being leveraged, we examined the offerings of the introductory software engineering course of the top 30 schools according to the US News & World Report and analyzed their course content to determine the penetration of these industrial innovations. We found low utilization of advancements in the field, and propose a roadmap for educators to apply moving forward.

Introduction – The Challenge

Software advances perhaps more quickly than any other field in the world. In the relatively limited time period between 1990 and 2010 alone, the industry saw dramatic shifts that changed the way the world views software. The advent of the World Wide Web, ubiquitous computing via mobile devices, and emerging virtualization have changed what industry partners seek in graduating computer science students. This monumental progression poses a challenge to software engineering educators: how can we properly prepare students to be effective professionals in such a rapidly changing field? How can educators avoid “teaching to the tool” and provide effective generalized knowledge about the software engineering discipline that doesn’t tie their students to the Vendor Lock-in AntiPattern? [1] What are the base set of skills a student needs, and tools a student should be familiar with, in order to be an effective professional in this dynamic environment?

Industrial Attention

Luckily, educators are not alone in having these concerns. Many professional software engineers have also recognized the need for sweeping changes in software engineering education. They have responded to the call by producing a deluge of important “industrial best practice” literature that seeks to educate neophytes. Andy Hunt and Dave Thomas The Pragmatic Programmer[2], Freeman and Freeman’s Head First Design Patterns[3], Fowler’s Patterns of Enterprise Application Architecture[4], Evan’s Domain Driven Design[5], Beck’s Test Driven Development by Example[6], Robert Martin’s Clean Code [7], and numerous others are vital sources that can educate and prepare students. But how effectively is such relatively recent literature being deployed in software engineering courses?

Evolution of Tools and Processes

Documentation of the sheer magnitude of the explosion of tools and processes from 1990-2010 could lead any well-meaning researcher to write thousands of pages and still fail to capture the magnitude of change, so we will full elaboration as future work. We will stick to the highlights.

Languages

The Java Programming Language[8] heralded the rise of an age of interpreted programming languages that sought to achieve platform independence. Extending this pursuit further, dynamic languages such as Python[9], Ruby[10], and others sought to eliminate unnecessary syntax and focus on allowing software engineers to build working systems quickly. These languages are now being used to explore the creation of Domain Specific Languages [11] that would allow engineers to program closer to the intended problem domain. Speed is of the essence, and is one of the hallmarks of Agile software development methodologies[12]. The rise of Agile Software Development as a methodology is well known and well-cited in the literature[], but its attendant ramifications have not been as well explored.

Requirements Specification techniques

The traditional days of SRS specifications have given way to the rise of agile tools such as CRC cards[], use cases/stories[]. Additionally, many tools such as Visual Studio Team Foundation Server 2010[] and JIRA allow business analysts to record requirements in a database driven system. This creates an emphasis on smaller artifacts that can be tied directly to the code that implements them.

Testing and Methodologies

Test Driven Development [] and Behavior Driven Development [] have sought to turn traditional development processes on their head by emphasizing testing from the beginning. Unit and integration testing have become a standard in almost every language with the rise of the xUnit family of tools. Mock Objects[] allow for simulating a live environment without directly having implementation available. BDD encourages leveraging tools like Cucumber[], which enable the creation of executable requirement specifications and end-user centered functionality evaluations.

Design and Analysis innovations

The GoF’s seminal work on Design Patterns[] has resulted in the codification of patterns in a variety of other formats. The enterprise has seen much innovation, including enterprise application architecture[4] and integration[] patterns. Patterns have also been leveraged in language implementation[], and many other areas. Patterns literature has led to evolution of architectural considerations, such as the rise of Domain Driven Design.

Source Control and Configuration Management improvements

While tools like CVS[] and Clearcase[] have offered source control and configuration management options for years, they are quickly giving way to a new breed. Recent innovations such as distributed source control with Mercurial[] and git[], web-based bug tracking and project management with JIRA[] and Lighthouse[], and continuous integration build servers like Hudson[] and Jenkins[] enable shorter development turn-around time, high project management visibility, and automated test and migration of applications between development and production environments.

Are these innovations being integrated into software engineering instruction?

Friday, August 12, 2011

An outline for open source "hack night"/mediated group coding activities

I've recently found myself proposing "hack nights" on multiple occasions in various different group contexts. I've been to a few "hack nights" in community spaces, and have typically ended up frustrated. Generally it either turns into a group of developers sitting with their laptops and working on their personal projects while occasionally trading banter/being lone code cowboys sharing space, or in-depth conversation with one or two people on topics that may or may not be related to coding and little progress on the project.

This is especially irksome, because I know these events could accomplish so much more. I love Free and Open-Source Software. But I also know that the quality assurance work on it is typically awful. Generally we blame and leave it up to the developer to solve problems. To be fair it is their responsibility...but community hack nights could be so much more.

We can use the "hack night" style of meetup as an opportunity to create a learning activity. We can use this meetup to help developers:
  • learn about best practices
  • learn about new technologies from a more hands-on approach than hearing someone else's "20 minute slideshow on Whiz-Bang.awesome. Go!"
  • adjust their workflow and style by integrating with others
  • express their own ideas about different architectural concepts and increase community feedback to their "I'm going to rewrite jQuery from scratch because it's a great idea" approach
  • make meaningful contributions to the open source community by actually doing all this on REAL SOFTWARE, Not HelloWorld.java or Yet Another Open Source Initiative to Add to the Community.
So I recently proposed a structured event in the Phoenix Grails User Group that I think will meet these challenges, centered around Grails plugins.

I think Grails offers the perfect environment for this type of activity because
  • it's modular
  • it has automated support for dependency tracking
  • it's built in a language and paradigm most people learn in school (Java)
What this means is that most Grails plugins are small, useful pieces. They often feature <10 domain classes [I should do some research to get an exact number], and because Groovy is a compact and expressive language each piece can have few LoC.

Rather than checking out Mozilla Firefox or Apache Tomcat and trying to navigate through a large code base, focusing on small plugins realistically allows "full comprehension of the system in question" in much smaller amount of time. Small, easily digestible systems are easy to digest, test, fix, and modify.

These plugins are typically built from a "functionality" perspective. This means that their test coverage is generally poor, their documentation is typically sparse or "non-enterprise quality" (no class diagrams or Javadocs for public APIs), the code "isn't clean", etc etc. But because they're so small, it doesn't take much effort to "whip them into shape." In theory, even a small team of talented developers could take small applications and dramatically improve their quality in a matter of hours.

But how do you ensure that such an activity is maximally productive? That people learn, good practices are followed, and is a fun event for all?

I propose the following structure:

Preconditions:
Establish a github repository for the group
Select a plugin (preferably prior to the hack session)
Everyone bring their laptops with a local Grails development setup
(perhaps on a special purpose VM. Sugar bear points for someone who rolls out a pre-bundled instance for VMWare Player that everyone can download and get started with)

Activity:
First 20 minutes: everyone individually reads through plugin source, takes notes and makes suggestions
Brainstorming activity (10 minutes): Group derives the intended functional requirements for the plugin by using white board/note cards and making user stories.
  • Does the plugin documentation reflect its functionality?
    • is there an overview paragraph?
    • A set of user stories?
    • a class diagram?
    • a JavaDoc for API type of stuff [I honestly have no idea how Grails Docs are generated]
  • Do the tests fully stress the constraints and methods of each (Should we explore translating the generated user stories into BDD style tests using functional plug/cuke for grails/something else?)
    • domain class
    • service
    • tag lib
    • controller
      • Does any security sexorcist wanna lead a session on common patterns of attack vectors that grails controllers could be vulnerable to and the types of tests we can write to test their efficacy?
  • Are there boundary conditions that the tests are missing? (i.e. things the app should NOT do that are not being tested)
Coding Activity (<=1 hour): write test code to achieve better test coverage and ensure that we don't "break the plugin" during later refactoring
  • How do we split this up? Each person takes a card and works on it? Work in pairs? I guess it depends on how many people show up. I'd love to do some XP with an experienced Grails dev myself.
Group Activity Refactoring Analysis (20 minutes):
  • Is localization well supported?
  • Is there clean separation and proper coordination between the controller layer, service layer, and domain object layer (e.g. is the controller doing heavy processing that should be moved to a service?)
  • Are the views too big (are there opportunities to break stuff up into partial templates?)
  • Does the domain model "do good things?"
    • (for example, I know Joseph showed off an example of doing M:M using two hasMany at the JUG presentation. I am *highly* of the opinion that that sucks, and these should be broken up into other classes via Scott Davis' Tutorial series and the Spring Security PersonRole approach...I am, however, open to persuasion after engaging discussion :)
  • is the code "clean"?
    • Good variable naming
    • short methods
    • classes that read like newspapers
    • ...other tidbits from Martin's book
Coding Activity (<=1 hour)
  • Fix problems identified in analysis. Fix them similar to style in testing phase, and run tests after changes to make sure stuff passes (Sugar points to someone who setups Jenkins for this. I would, but I've never used it. It seems like the "right kind of thing to do")
Extensibility Activity (20 minutes)
  • What functional extensions could the plugin accommodate?
Coding Activity(<=40 minutes)
  • write BDD functional spec, unit tests, and test driven approach to add features
  • add features
Wrapup activity (20 minutes)
  • finalize branch changes, send out announcement to grails mailing-list, merge changes into plugin repository and release
  • What other plugins may be advantageous to leverage?
  • What other plugins may use this one?
  • What did we learn?
  • What other plugins should we look at?
  • iPhone or Android? (HOLY WAR!)
  • MOAR Beer.
I surmise that activities such as these may actually be closer to the "missing piece" of the transition between "fresh out of school" and "experienced and effective practitioner." Repeated exposure and practice with activities such as these can potentially give developers a strategy for moving onto bigger applications, which they can then break down into chunks and attack in the same manner. This may actually be important.

For example, when you first start weight lifting, you don't start doing bicep curls with 50 lb dumbbells (unless you're He-Man). Yet this is the equivalent to what many CS new grads face when they're hired by a big company.

"Go do QA/maintenance work on this giant legacy system you have almost no hope of completely understanding. Don't worry, we'll start you with 'small, not important tasks' "

Or, perhaps even worse, they're loosed like cowboys to work on self-contained applications/pieces of functionality in individual or very small team environments. Hence they never gain the opportunity to learn best practices from other experienced people in the team and refine their workflow to be more effective.

But activities like these can serve as a bridge, because they add structure to the programming activity.

Typically, college and other programming courses give theoretical overviews of "concepts necessary", then assign the actual implementation of those concepts as "projects or homework." A requirements spec is given. Then the student programmer, like a painter, is loosed on a blank canvas and told to report back by X with output. Even lab sections in courses typically involve a TA giving an overview of the exercise, then sitting around to answer questions/provide assistance as the artists work on their canvas.

But what if we invert the model and bring it closer to the style of a Reniassance-era painting school? What if we have students reference an already constructed work, copy it, critique it, personalize and extend it? What if we work harder to work through that process, rather than leaving it as a nebulous "homework" phase?

Maybe they'll learn how to be better developers, while simultaneously improving the quality of open source software. I figure it's worth a try.