Welcome Developers


My name is Luis Atencio. Currently, I am Lead Software Developer at Citrix Systems. Programming languages, design patterns, and techniques are my passion. If you are interested in programming or just technology in general, please follow my blog!

Sunday, April 21, 2013

Notes on Continuous Delivery - Implementing a Testing Strategy

Overview

There are three things in life that are always held to be true: we will die someday; we will pay taxes; and software will have bugs.... LOL

Welcome to part 4 of our Continuous Delivery series that continues from part 3. This time, we spend a little time talking about Testing.

A testing strategy is often overlooked in software projects. This should not be too surprising, we want to build applications quickly and release them quickly. However, leaving quality out of the picture or towards the end are terrible mistakes.

Another case, which occurs more frequently, is the notion that testing is done entirely by a QA team. Part of implementing Continuous Delivery is getting rid of this antiquated notion. Testing is an interconnected responsibility shared amongst the software team. As a result, software teams must have QA engineers in their roster. This becomes extremely important when it comes time to creating test Automation, the core of CD. I think we can build the best automated tests when QA and development work closely together --you get the best of both worlds.

In previous posts, we went over the different types of tests. It is important to allocate automation for all of these different kinds into your deployment pipeline. We will spend a lot of time talking about your this later on.

In addition, automation of test suites make exceptional regression tests. Focus on automating just repeatable tasks. Exploratory testing, typically called manual testing should continue to be done throughout the project, but only to aspects of the testing effort that are very difficult to automate or are only done sporadically.

Types of Tests

Tests have multiple dimensions: business facing and technology facing; each one can either support the programming efforts or just critique the project. Since this is a blog posts for developers, I will focus on tests that support the development endeavors.

How much of your application should you test?

Some people have proposed 80% to be a comprehensive goal to reach for your code coverage. It kind of makes sense when you put it in context of the "80/20" rule: test features that 80% of your customers will use.

Business-Facing

These are the functional or acceptance tests. Acceptance tests can do various things such as test functional as well as non-functional requirements. They should be part of your "done" definition for a specific story, like a completion criteria.

Examples of non-functional requirements include: security, capacity, usability, performance, etc. Acceptance tests that pertain to the functionality of the system (the behavior of the system according to specifications) fall into the functional acceptance tests. The authors mention different tools to automate this such as JBehave, Cucumber, Twist, etc. I have not had first-hand experience with this, so I can't share my own two cents on this.

In my mind, however, I deem impossible to automate the coverage of ALL acceptance criteria (100%), perhaps just focusing on happy path testing is a good alternative. In an ideal situation, the test scripts can be written by the customers; developers and testers can work on the implementation together. This can be facilitated by a high-level DSL tailored for this task. These customer-crafted scripts using a DSL can be handed to development to be turned into acceptance tests. As I said before, this to me sounds very utopian and theoretical, but if you are interested in pursuing it, Ruby or Groovy are programming languages ideal for writing DSLs. Leave a comment and let me know how it goes...

It really depends on your situation and your project. I imagine, mission critical projects like airplane control systems, automotive software, etc, probably have much more testing code done than actual application code. James Shore, a leader in the Agile community, does not believe on automating acceptance tests. I provided the link to his article in the Resources section below.

Business facing tests can also be included as part of the demo. Certainly, the business owners would be interested in seeing their tests pass every iteration.

Technology-Facing

These are the unit tests, component or integration tests, and deployment tests. I'll reiterate: unit tests focus on isolating a very granular piece of code. They should NOT test any other code other than the immediate method or function. Therefore, typically UTs are written against Test Doubles or Test Stubs or some Mock framework such as JMock or PHPMock.

Unit tests are expected to be very fast since they shall not make any database calls, Web Service calls, filesystem operations, asynchronous or threaded calls, etc. These are all meant to be part of  component tests, which will be slower since they exercise the IO ports of the system.

Also, you may decide to write deployment tests. Deployments tests can be written to make sure the build worked as expected. For instance, you may assert that configuration parameters were applied correctly or that certain files were written to the right directories.

Conclusion

In sum, always incorporate testing as part of development from project inception and sizing. Doing it at the beginning will require much less effort than doing it mid-way or till the end. Make it an essential part of your "done" manifest and keep development and QA interconnected on this undertaking.

The most important automated tests to write are the happy path tests, focus on these first before implementing sad tests (exceptional conditions).

A good testing strategy provides a level of confidence that the system behaves and performs the way it should at every commit. This investment has many positive effects which will translate into fewer bugs, reduced support costs, and improved reputation.  

I've heard many people say testing also provides a way of documenting the application. By looking at a test suite of a particular component of an application, you can understand in detail how that component should work. People often prefer tests to any sort of markdown documentation. Combine this with good up to date source documentation (javadocs or phpdocs), and should be on track.

Automate repeatable acceptance tests to free up QA to do more difficult or elaborate exploratory testing. Also, build automated scripts to aid exploratory testing, i.e inputing data into the system.

In agile, you are expected to ruthless refactor. Building a comprehensive suite of unit, component, and acceptance tests can heavy project refactoring much less risky. For instance, imagine you are using an ORM such as Hibernate as the persistence layer for your application against a Microsoft SQL database. You could really use all the power of your automated regression tests, when it comes time to move your project to a database such as MySQL.

There are other types of testing that are meant to critique the project such as: usability testing, showcases, exploratory testing, etc. These are very hard to automate so they are typically done manually.

If you are dealing with a legacy systems, focus on testing what you changed. The worst situation to be in is an untested legacy system. Often times, if you don't have access to the source code, then opt for distributed approaches via a Proxy or Adapter patterns, so that you can isolate and test only the new code. Testing for legacy systems oftentimes is not seen as a high priority from the business owners. However, it is important to emphasize and instruct them on the value of having this as a regression suite and the protection against possible new bugs.

Finally, managing a defect backlog is very important. Ideally, if we implemented all of the different types of tests I mentioned before you would not have any bugs in your system. Right... We know this will never be true. Even if we had 100% code and branch coverage on all types of tests, QA and external users will always find bugs. Prioritize bugs first at the beginning of your iteration planning. For instance, you can catalogue defects in different levels of severity and make it a team policy to always get rid of defects severity one and two (i.e. blockers and critical). Remember to keep the business owner in the loop; when you might think a defect is critical, the customer might not think the same way.

Stay tuned for more!

Resources
  1. Humble, Jez and Farley David. Continuous Delivery: A Reliable Software Releases through Build, Test, and Deployment Automation. Addison Wesley. 2011
  2. http://www.jamesshore.com/Blog/The-Problems-With-Acceptance-Testing.html
  3. http://refcardz.dzone.com/refcardz/continuous-delivery-patterns
  4. http://refcardz.dzone.com/refcardz/preparing-continuous-delivery?utm_source=feedly&utm_medium=feed&utm_campaign=Feed%3A+zones%2Frefcardz+(DZone+Refcardz)

Sunday, March 24, 2013

Notes on Continuous Delivery - Continuous Integration

Overview

This is a continuation from my previous post and overall the series on Continuous Delivery. If you haven't been following, that's okay, every topic is self-contained, so read along. The contents of these posts are taken from the book titled "Continuous Delivery" by Humble and Farley (resources below) overlaid with my own professional experience. In this article, we talk a bit more about Continuous Integration (CI) and some practices developers should follow to ensure a smooth environment.

CI requires that an entire application's build process executes on every commit. This includes compilation, running automated test cases, code minification, packaging, static analysis tools, etc. In general, everything that you do when deploying code to production, should also run at every build. If the build breaks, development stops whatever they were working on and focus on getting the build back to a stable state.

Automation is very important. Devote time to build automation into your CI process from the beginning, you will reap the benefits later. The more automated tests you have and code coverage you have, the better. You should write tests of different types, in order of priority:
  1. Unit tests: fast do not require any external dependencies (eg. database). Use an XUnit tool such as JUnit, PHPUnit, etc.
  2. Integration tests (component tests): slower, require database setup
  3. Acceptance tests: slowest, run some kind of acceptance test software (eg. Fitnesse)

Having a comprehensive test suite will give you peace of mind that your application is behaving the way you expect it to at every commit; think about how important this is when you are refactoring code. I really believe in Refactoring, it's essential in order to keep the code base clean and relevant, yet hard to sell it to your business owner. If you break the application as a result of refactoring, then you can kiss away any other opportunity to do so. A good resource for this is the book: Refactoring to Patterns by Joshua Kerievsky.

Continuous Integration is very important in this process because you can discover issues early. Lots of unit tests can uncover bugs, lots of integration tests can also uncover issues with external or third party dependencies, such as your database or Web Services.

On a personal note: do not refrain from using command line tools or using the command line version of any tool in your CI environment, they are by far the most stable. IDEs and different tools have gotten more sophisticated and user friendly over the years, but all in all, nothing beats the CLI.

Theoretically, you don't require a tool or application to perform CI, it is a process, you can home grow your own. However, it is recommended you have one in place. I have had really good experience with the open source application called Jenkins. It integrates nicely with Maven using the Jenkins Maven plugin. There are others such as  CruiseControl and commercial ones like Atlassian Bamboo, to name a few. The way most Continuous Integration software works is by continuously polling your version control server for changes. When a change is detected, the software runs the commands you have specified in the build job. 


Essential Practices

Here are some simple tips to ensure a smooth CI environment:

1. Don't check in on a broken build

Fix it quick. The check-in following the failure should be that which addresses the problem. Beware of this is a slippery slope.


2. Pause before commit

Before committing, update your code to the latest release and run all of your unit tests. Commits should be painless, do not try to do too much by using commit triggers, such as running static analysis, updating change logs, etc. This will slow down your pace tremendously; promote the habit of checking in frequently.


3. Keep a stable build at all times

Take active responsibility for your actions. Breaking the build is a normal part of  development. A broken build once in a while is good because it validates that the process is actually doing something right. If the builds never break, then you should be suspicious. Sometimes, a defect might catch you by surprise on a Friday afternoon at 5:30 pm as your are getting ready to head out. At this point, you can either: 1) Accept it, take a deep breath, stay and fix it (recommended); or 2) Revert your change. In any case, you don't want to hinder your co-workers. Specially, if you are part of a distant distributed team as they will be trying to work while you are sleeping. Fixing it on the spot is always preferable while the code is fresh in your mind.

The point to get across here is that by getting in the habit of checking in frequently, your CI process will do the heavy lifting for you and proof your code. Checking in frequently will build small incremental changes into your system. If 5:00 pm rolls around, and you are not certain about your code, don't commit your change.  This shouldn't be very risky if you have just small changes. This leads me straight into the fourth point...


4. Anticipate being able to revert your changes

I think this is super important and could potentially be very challenging. The reason this is extremely important is because you will want your production environment to be able to be rolled back at any point in time. Meaning, strive to have working code at every check in. In my experience, this can be very difficult when you are dealing with something like a schema change or a data change. Older code might not work with new schema changes. For instance, for every ALTER, DELETE, INSERT, UPDATE script, you should have the corresponding undo of that change. Establish a naming convention for your scripts; it should be very clear and obvious that as part of reverting your change, you should find and execute a rollback script.


4. Don't comment out tests

This is obviously a bad practice and should be done as an extremely last resort. If there are other developers waiting on a particular piece of code to be there, and they cannot move forward because of this, you may decide to comment out a test and commit your code to get them going. However, you MUST jump back to this as soon as possible. If it was an existing test that used to pass, you have just checked in a bug into the system.

5. TDD

It seems no agile development book is complete without some mention to Test Driven Development. To be honest, I am not really big on it. I don't promote it on any team that I lead or am part of. If you do it, awesome! Keep it up. However, I think developers should be very diligent writing tests and strive for high code coverage. And this should apply to both back-end as well as front-end code. Running tests should be part of every commit and are crucial of your are to do any code Refactoring.

I don't want to slip into a tangent here. In theory TDD, sounds like a good idea, but in practice extremely hard to do. Many people claim they do it, and I think they confuse this with writing a unit test for every method. I don't to aggravate the TDD community, so that's all I will say on this topic...  for now.

5. Distributed Version Control

We have already talked about how important this is for CD. Currently, I use Subversion but I am starting to explore Git more and more (Mercurial is another option). I believe that Git contains everything SVN does plus a lot more. With DVCS the ability to work offline and to cooperate across remote teams becomes so much easier. I would NOT dare write a single line without some sort of version control.

Alternatively, you can use the mainline model of version control with Git as though you are using a centralized versioning control system such as Subversion: simply create a master branch, point your CI environment to it, and have every developer push changes directly to it. The contrary is not true, however. When you think about how an open source project works (whether that's your situation or not), you would understand you can only do this with a DVCS such as Git.

Conclusion

The main selling point for Continuous Integration is that you are exercising your process at every commit, a production push becomes just another iteration of this process. This is extremely valuable.

If you are waiting on a build for some reason, use your this spare time wisely: walk around, start a quick chat, check your email, stretch your muscles, etc; the benefits of stepping away from code for a few minutes are wonderful. 

Expect to break builds once in a while, this is normal. You might even break other code that was not directly related to your task. It is still your responsibility to fix it --take active responsibility for the build!

Stay tuned for the next post as we will take a look at implementing a testing strategy!

Resources

  1. Humble, Jez and Farley David. Continuous Delivery: A Reliable Software Releases through Build, Test, and Deployment Automation. Addison Wesley. 2011
  2. Extreme Programming Rules - http://www.extremeprogramming.org/rules.html

Sunday, February 24, 2013

Notes on Continuous Delivery - Configuration Management

Overview

I will be continuing the topic on Continuous Delivery which began in my previous post: Notes on Continuous Integration; this time we will start looking at the first and most important step, Configuration Management. In the words of the authors (resource below):
Configuration Management refers to the process by which all artifacts ... and the relationships between them, are stored, retrieved, uniquely identified, and modified.
Configuration Management involves four principles:

1. Keep everything in version control

Source control is just for source code, version control is for any type of artifact your project has: source code, tests, database scripts, wireframes, high definition mock-ups, build scripts, documentation, libraries, configuration files, release plans, requirements documents, architecture diagrams, virtual machine configuration, virtual machine images and so on. I challenge you to change this in your geeky vocabulary, if you haven't already.

A little ambitious, I agree. The metadata stored within your version control system enables to access every version of every file you have ever stored as well as facilitates collaboration amongst distributed teams in space and time. 

The level of sophistication in your continuous delivery process will depend on how mature your configuration management strategy is. If storing absolutely everything is not feasible, or requires too much work and money, start with a few artifacts (in addition so source code, of course) and you will see the improvements in your process almost instantly.

Promote the idea of checking-in code frequently followed with useful commit messages. Make use of the typical "-m" switch in your version control command line tool, almost all of them support it.

Version control gives you the freedom to delete files;  worst case scenario, you can always retrieve it easily. It's like refactoring code with endless "Undo" history.

2. Manage dependencies

Dependencies constitute any external libraries, components, and modules that your application uses. For instance:
  • JAR files - Java or JVM language
  • PEAR, PECL modules or PHAR files - PHP
  • DLLs - .NET
  • Ruby Gems - Ruby
  • Bindings - Python
  • NPM - Node.js
Also under this category would be any extensions or libraries your operating system is configured with.

Build tools make it easier (not easy) to manage dependencies. I have had success with tools such as Maven, Ant, and Phing. There are many others that have gotten a lot of traction lately such as: Gradle and Ivy. I would recommend a tool like Maven because it makes it possible to recreate environments on different machines as well as manage your dependencies in centralized fashion by setting a package repository.

3. Manage software configuration

Perhaps the most important principle of all, configuration management requires that you have a strategy for automating the injection of configuration properties to your software. This is critical if you are planning to support different environments: QA, Staging, Preview, and Production. 

Configuration information can be injected:
  • At build time or packaging time: use Maven to read property files and inject configuration information into them. This is usually seen as property files with name-value pair records. These are common in Java and PHP; YAML files are common in the Ruby and Python worlds. XML is even a good contender here too supported in all platforms.
  • At startup time: usually done via environment variables or command line arguments.
  • At runtime: say you store configuration information in the database or in an external system. Then your application can fetch configuration information from the web or via scripts and apply them. For this, some bootstrapping information is always necessary such as: database connections and external URIs. 
Whichever mechanism you use, make sure everything is version controlled. One immediate question is, how can we store sensitive information like passwords? Here is one way to do that:


Another is to store passwords together with the code so that it gets compiled and obfuscated. This is not good practice, especially in interpreted  languages.

I recommend using secure certificates, SSL keys, or encrypted information at the very least.

The simplest approach to configuration management with which I have had success implementing is via build time injection of property files as mentioned above. These vary depending on the following:
  1. The application
  2. The version of the application
  3. The environment (QA, Production, UAT, Preview, Staging, etc)
With Maven, you can easily inject configuration information into the application before packaging it into a deployable artifact. This is a very nice and simple approach because all of the configuration is stored in version control and uses the file system, which is widely supported in all platforms.

Disclaimer: If you are actually developing Java Applets (I don't why someone would still want to do that...), then access to the file system might not be an option. In that case, storing your configuration in an external system that can be fetched via RESTful calls is a good solution, all of the same principles mentioned thus far still apply.

Something to keep in mind, consider configuration management early in the development lifecycle. Create patterns for your organization so that every application does it the same way: convention over configuration. Often, it is an after thought and teams tend to develop their own ad-hoc configuration management strategy. This will make it really hard for your Ops and DevOps teams to automate, waste time reinventing the wheel, and you are very likely to make the same mistakes someone else already made.

4. Manage environments

The configuration of the environment is as important as that of the application's. Your application might need specific system level configuration such as number of file handles, memory limits, firewall or networking, connections pools, etc. This is very important to get right, and can vary from one application to the other.

The same principles from above apply here to. Do not reinvent the wheel, do not implement ad-hoc solutions, and keep everything in version control. Obviously you cannot check in your OS into version control, but it's configuration and the scripts can.

I would say that without a doubt, managing environments is probably one of the hardest things to automate. The end goal is to be able to recreate full environment baselines at the touch of a button, including different versions in time. In order for this to work, you absolutely must create a strong synergy with a very agile IT environment, which is not necessarily the case in most organizations and can be very costly. Different departments can have very different philosophies when it comes to managing their environments -- these silos must be broken.

As a result, many organizations resort to virtual environments powered by Citrix or VMWare or cloud environments such as AppEngine, Amazon EC2, Rackspace, Heroku, Azure, etc. You need to be able to fully control the environments you deploy to. As I said before, start by automating as much as you can, little steps towards this will reap lots of benefits down the line.

I don't have any experience with environment management, but I've heard good things about systems like Puppet. 

Conclusion

Configuration managent sits at the core of continuous delivery.

Store all application and infrastructure information so that you can recreate environments: configuration, database, DNS zone files, firewall configuration, patches, libraries installed, extensions, etc. The automation process (as we will see in later posts) will depend on having every artifact your application needs to be accessible on demand.

In the projects I have worked on, I always promote checking in to version control frequently, as well as its counterpart updating from version control frequently. It helps a lot with resolving conflicts and tedious merges.

One caveat of continuous delivery is to go against branching. Branching is antithetical for continuous integration. If you are using Git or Mercurial where branching and merging is the norm, establish a commit and push policy that works for your team, you want to have a stable and updated main trunk line from which you can deploy your code.


One piece of advice, meet with your Ops team to determine how to properly implement configuration management for your applications. This is an aspect of the system everyone should be aware of.

If you will be using key-value paris for your configuration options, use descriptive names for your property keys. The name should express very clearly and concisely what the configuration is for. Use lots of comments on your property files to add more description is necessary. Have a look at a PHP installation's php.ini file for a good example. Do not hard code property keys everywhere you need to access them, wrap them with some sort of ConfigurationService that makes this access simple and testable.

Finally, it is typical for web systems to expose your application's configuration in some sort of management console for super user admins to change. While this sounds like a good idea, and up until this point I thought it was, it's not. Unless you can write that change back into version control, runtime system configuration is not a good idea. In addition, a simple change to a property file can potentially break or degrade the entire system. Therefore, it should follow the same mechanisms in place for source code changes.

Stay Tuned for more on this topic in the posts to come!

Resources

  1. Humble, Jez and Farley David. Continuous Delivery: A Reliable Software Releases through Build, Test, and Deployment Automation. Addison Wesley. 2011

Sunday, February 3, 2013

Notes on Continuos Delivery

Overview

In the rapid changing software world of today, companies and individuals have come up with many methods in order to minimize the time to market gap, i.e the time it takes for your idea to materialize in production. Specially in the very competitive world of mobile and web applications.

The success of many companies and individuals have a temporal dimension: they happen to be the first to create an application that solves a specific problem or addresses a particular issue. Tapping into this value stream early is important. As a result, most companies do not pay attention to a product's build lifecycle -- this is usually the last thing if ever to worry about, and your build process is manual and prone to errors.

We want our Operations team to be able to deploy correct and tested code in a manner that is automated and not stressful. It almost seems like we have the predisposition that things will go terribly wrong in production resulting in a constant stand-by, which is why you get the silly rules like "avoid Friday pushes..." or "avoid end of day pushes...", among others.

However, there is a down side to this: while it is important to beat the market and be innovative, it is also equally important to do this with a process that allows you to have a reliable product release, to be responsive to production issues, and manage the lifecycle of the product in an agile fashion. As important as it is to get your name out there, it's also important to avoid building a bad reputation. You don't want to lose the few users that tried your application.

Continuous Delivery has its roots in the lean  movement. Central to this philosophy is to make the interstitial stages of software delivery as fast as possible and remove waste at every step of the way. An example of such waste is having manual processes. Essentially, any process that is to be repeated, should be automated and carried out by a computer, no exceptions.

With that in mind, what we need to build is a deployment pipeline.

Deployment pipelines will contain different steps, according to what you are trying to build and what makes sense for your team, but in general it will look like the diagram above. By automating this deployment pipeline we address the anti-patterns of manual software releases. Basically, after an Operations (preferably DevOps team) has architected the deployment pipeline, the only human intervention remaining would be the manual testing or some exploratory testing; everything else would be triggered by the push of the deploy button, including the business acceptance tests.

Benefits


1. No stale documentation needed. Let the scripts and code documentation be the all the documentation needed for the development pipeline. If you need to create richer documentation such as design graphs and UML class diagrams, create these in increments. Add documentation to the definition of "done" for each task instead of leaving everything to the last minute.

2. No intermediate human errors, automate everything. The resulting process is repeatable, reliable, and predictable.

3. Easy auditing and versioning. You can enable logging at every step. In addition, Continuous Integration advocates that all configuration be stored and applied from version control.

4. Quicker deployments since there is no human interaction involved. Quicker deployments mean reduced cycle time and tighter feedback loop. Releasing frequently will take the stress away from releases.

5. All systems (development, staging, QA, and production) are deployed by the same scripts. So your process gets tested a lot. This also has the added benefit of bridging the enormous gap between the development, testing, and operations silos.

Challenges


Creating similar development and production-like environments can be difficult and costly. If you work in a cloud environment such as Amazon EC2,  Heroku, Google App Engine, PHP Cloud, to new a few, these companies must provide suitable APIs or scripts that you can plug into your deployment pipeline. The same applies if you are bound to an outside IT environment that does not have support for Continuous Delivery. Building quality into the software lifecycle is very important, even if this means spending a few weeks/months architecting the delivery mechanism.

In addition, aligning different teams with different priorities and resources will be difficult, especially when they have different/conflicting goals. Continuous Delivery promotes building cross-functional teams; as a result, QA, development, DBAs, and DevOps must come together to build this process in unison.

Conclusion


So, how can we make the deployment process on production release date a bit less stressful? Well, if you can avoid the following ceremony: sending a long chain of emails orchestrating the entire team, database administrators updating unfamiliar tables, operations engineers deploying unfamiliar code, having different testing and production environments added to the mix, and trying to find that document you jotted down all of the release notes; maybe it wouldn't by that stressful.

In software, there is opportunity cost to not delivering software, and Continuous Delivery can help facilitate rapid, frequent, quality releases.

Before we finish, I'll leave you with the principles of software delivery:

1. Create repeatable, reliable release process -> Continuous Improvement.

2. Automate everything.

3. Keep everything in version control.

4. Build quality in from the beginning.

5. "Done" = "Released".

6. All team is responsible for delivery,

In later posts, I will spending more time talking about how to implement this process in more detail.

Stay tuned for more.

Resources


  1. Humble, Jez and Farley David. Continuous Delivery: A Reliable Software Releases through Build, Test, and Deployment Automation. Addison Wesley. 2011

Friday, January 18, 2013

Fluent Object Creation

Many posts have been written on this subject (overwhelmingly many) but I just wanted to contribute my two-cents and write a short post about how I use the Fluent Object Creation pattern or object builders in Java to instantiate Value Objects.

Value Objects are abstractions that are defined by their state (value) rather than their address in memory. Examples of value objects are things like money, a number, a coordinate, etc. They are used not to describe Business Objects but rather descriptions of concrete indivisible entities.  Also, they make great candidates for adding them to collections and maps.

In Java, Value Objects should be declared final and provide no setter methods, basically making it's state immutable after creation, this is a very important requirement. Declaring them final makes them unable to serve as parent objects. This is done by design since value objects should model small and concrete entities. The reason being is that we should be able to create and compare multiple copies of these objects, which is always done by state not by reference. In addition, you should declare proper equals() and hashCode() methods to qualify for a proper value object.

In C++, the same principles apply. In C++ you should make use of the Copy Constructor and overload the assignment and comparison operators.  

The Fluent Object Creation pattern makes value object instantiation elegant and clean. There are many benefits that can be gained by using fluent object creation as we will see shortly. 

The end result of applying this pattern from the API user's perspective will look like the following:


Money fiveEuros = new Money.Builder()
   .currency(Currency.EURO)
   .value(5.0L)
   .countryOfOrigin("Spain")
   .type("Coin")
   .reverse("Map of Europe")
   .obverse("Map of Spain")
   .addColor("Bronze")
   .addColor("Silver")
   .year("1880")
.build();



I think you would agree that this pattern flows a lot more smoother as opposed to this:


Money fiveEuros = new Money();
fiveEuros.setCurrency(Currency.EURO);
fiveEuros.setValue(5.0L);
fiveEuros.countryOfOrigin("Spain");
fiveEuros.type("Coin");
fiveEuros.reverse("Map of Europe");
fiveEuros.obverse("Map of Spain");

List<String> colors = new ArrayList<String>();
for(String color: new String[] {"Bronze", "Silver"}) {
   colors.add(color);
}

fiveEuros.setColors(colors);
fiveEuros.setYear("1880");



Which seems broken and has lots of typing and repetition. This is an example of building a pretty big  value object in my opinion, most of tend to be very small.

Before we talk about the benefits of creating objects this way, let's have a look at the structure of this pattern:


public final class Money {
   
      private Long value;
      private String countryOfOrigin;     
      private Currency currency;
      private String type; 
      private String reverse;
      private String obverse;    
      private List<String> colors;
   private Date year;    
 
      private Money() {   }

     // -- getters, hashCode, equals -- //

     // Static inner Builder class
   public static class Builder {
        private Money _temp = new Money();
public Builder value(Long val) {
_temp.value = val;
return this;
}
public Builder countryOfOrigin(String countryOfOrigin) {
_temp.contryOfOrigin = countryOfOrigin;
         return this;
}
public Builder currency(Currency c) {
_temp.currency = c;
return this;
}
public Builder type(String t) {
_temp.type = t;
return this;
}
public Builder reverse(String r) {
_temp.reverse = r;
return this;
}


       public Builder obverse(String o) {
_temp.obverse = o;
return this;
}


public Builder addColor(String c) {
if(_temp.colors == null) {
              _temp.colors = new ArrayList<String>(); 
           }
           _temp.colors.add(c);
return this;
}

         public Builder year(String y) {
              if(y == null || y.isEmpty()) {
                  _temp.year = new Date();
              }
              else {
                  _temp.year = DateFormat.parse(y);
              }
return this;
}
public Money build() {
                // Validate object
               if(Strings.isNullOrEmpty(_temp.name) || _temp.currency == null) {
                  throw new IllegalArgumentException("Coin currency and value required");
               }
return _temp;
}
    }
}


This is also a matter of taste, but I prefer the static inner class approach. I like the canonical nature of referring to the builder as Money.Builder. Also making it static is required since the builder instance needs to live independently of the enclosing class.

I like this pattern because it has the following benefits:
  1. Greater object encapsulation: I can easily enforce object construction using builders by making the Money constructor private (this is just stylistic). This completely hides all of the intricacies of creating this object: list creation, date parsing, etc. From the user's perspective, what we end up with is an object that is simple to instantiate. My illustration is a very simple one, but imagine more complex object graphs.
  2. Code readability: Using this pattern to create objects, makes unit tests and code very easy to read and follow. 
  3. Less typing in the long run: Even though you have to add an extra builder method for every added attributes, the amount of typing you save in the long run makes it worth while. 

Conclusion

Using the fluent creation pattern is more work up front, but the benefits of having it pays off at the end. It makes instantiating objects very elegant and clean. You don't have to use it with Value Objects, most of the benefit of using Fluent Object Creation is when you need to build pretty complex object graphs, but I wanted to show that it can also suit small value objects.


Stay Tuned! visit http://reflectivethought.net