Friday, 20 May 2016

Inverting Ansibe execution flow. The Pull Mode


In most cases,  where I've seen Ansible being implemented to automate ops taks is using the Push mode. On this approach, playbooks start running from a given host where Ansible is set. The Ansible host is gonna interpret the tasks and apply   "pushing" them to all target hosts through SSH.
What is maybe unnoticed when start playing with It, is the fact that the same results can be achieved by using a totally different flow, the Pull Mode.


There isn't much about It on the official documentation, but the idea is pretty simple.Instead of pushing playbooks to  the target hosts, using pull mode you can make target host "pull" them from a given repository.  By doing this, there is no need to have a single machine playing the ansible-host role, in this scenario, this responsibility is spread on the machines on the datacenter..
There is nothing special in order to get It running.Both, Pull and Push will be available after following the installing steps available here.
Lets say I want to deploy the application I build here using the Pull mode in all my cluster machines. After having Ansible properly installed  on the target hosts, the following command should be raised:


This command will connect on Github and download the entire repository locally. After doing this, Ansible will look for a file named as Local.yml. This file should contains all tasks, or a reference to the ones who have them in order to perform  a playbook.
An interesting approach is to make the target hosts pull the remote repository times to times. By doing this, changes will be applied on all target machines asynchronously and in background as soon they are available on the repository.That could be quite interesting when talking about provision hundreds or thousands of machines. This mode will scale much better than the Push mode. This can be achieved by just setting a cron job.  and calling a script that encapsulates the pull command described before, like this:

The Pull mode can be useful also to  change application configuration more dynamically. By using tags, I can update the log4j config as soon they hit the remote repository:

As we can see, there are a range of scenarios where the Pull mode can be useful. BTW, It could be a bit more flexible by letting the user specify which playbook to run (It only look or a file named as Local.yml, something different  than that is gonna produce an error).  Users need also be careful when sending code to repository when using this feature. Code badly written can break an entire datacenter without you notice.

Cheers,











Sunday, 1 May 2016

Organizing Automation - Ansible Roles

When talking about automation, Ansible is definitely one of the most simple and easy to use frameworks. It has a pretty low learning curve due Its comprehensive DSL, which is easy to understand. You also don't need to install anything on the server that will be provisioned (agent less architecture), which makes the setup simple. Everything looks great when the provisioning process has only two or three script files, but as soon you add more functionalities ,there will be some issues to deal with:

  • Reuse: there are certain provisioning tasks that are common to all servers, how to organise them in a such way they can be reused easily?
  • Organisation: similar as any programming code, without maintenance and good engineering practices,  the provisioning process will be difficult to maintain and understand. Naming,  modules organisation, conventions are all aspects that needs to be taken into account.

Ansible Roles

Ansible Roles are conventions that as a programmer you need to follow in order to achieve good level of reuse and modularisation. These conventions were added on version 1.2  and before this, the way to achieve better level of reuse was separating scripts into different files and including them on other scripts you want to reuse.
The documentation is very sparse when describing how Roles work, but the idea is pretty simple. Using Roles, you will be able to automatically load tasks, variables, files and handlers when provisioning a server or a group of them. 
Lets look to an example, here I'm provisioning a Java application service. The server to run this application will need to have the following roles:


The role common is a role that any server in my infrastructure will need to have (reuse), which in this case is have JDK installed. The other role is called service, which is basically the things needed to run the service run the service Itself.

Ansible will automatically look for a directories called commons and service inside the main directory roles and execute all steps defined for them.
For the role service, we have:

  • vars


  • tasks



  • handlers


  • files: All files used on tasks will loaded from there.
There is still more directories that can be defined like templates and defaults. They aren't  present on this example but are still useful. This is the full working example that provision a server that is able to run this Java application.

Using roles is great because they are expressive. Working with them properly you will be able to say what a given server is, which is much more declarative than just use the include directives. The directory conventions are good to define patterns to the whole team follow since day one and reuse achieved by defining very granular roles that can be set on different play books. 

Cheers,

Friday, 15 April 2016

Releasing Applications as Native OS Packages

Agility when building, testing, packing and deploying Software  is certainly a key quality aspect to pursue. BTW, there is no specific recipe to get there, among several other things that needs to done, avoid manual steps and not reinvent the wheel  by relying on well established solutions on the community are some of them. Going on this direction, there is very interesting project maintained by Netflix that is called Nebula.

Nebula Project is a series of individual Gradle plugins, each focused on providing a very specific functionality in an usual Development Pipeline tasks. Today I'm gonna talk about one of those, nebula-os-package.

The main idea

The main idea behind It is to pack a JVM based application and Its metadata as a native OS package. The plugin is able to generate Deb and RPM packages, which are the most popular package formats on the Linux world.

Using


First of all, add the plugin on your build.gradle file.


Then, add the specify the plugin dependency

Now you need to say how the application is gonna be set on Host, after the package is installed.

Couple of important things that are happening here:
  • Specifying package name and version (lines 2 and 3)
  • Under which directory the package is gonna be placed after installed on the target Host (line 5).
  •  All jars produced by Gradle during the build (the application jar and Its dependencies), are gonna be placed under /opt/packageName/lib on the target Host. (line 8)
  • Same thing  for configuration files under the resource folder (line 18).
  • The scripts generated by Gradle when building a Java application are gonna be used to start It up on the target Host (line 11).
With everything property set, just execute the build command accomplished by the package task specified on the build file.  The Debian package is gonna be placed at projectName/build/distributions

So What?


Someone could be arguing: 
  • Why should I use this? 
  • Is It better than build a  Fat jar with all Its dependencies inside! 
  • Gradle application plugin takes care of the whole Application start up for me generating  useful scripts.
Yes, these are all valid points. Actually, this is the way we've being done so far when releasing applications outside of the J2EE world. But doing like this tasks like: deploy, start/stop, update and removing applications are all on you. Scripts will need to be create to manage all these, so one more thing that Ops and Dev teams will need to care about.
When deploying applications as Native OS packages,  you can leverage a whole set of tools that are already there and none of the scripts mentioned before would be needed. This is a valid point when that affects agility when releasing and maintaining software.

Here  I have a working example in case you wanna try It out.

Cheers,



Friday, 8 April 2016

Google Pub/Sub. An Alternative Tool for Data Ingestion.

Less than one year ago, Google launched officially on the market a new cloud messaging service,  Google Pub/Sub. I've to confess I just looked at It more carefully after reading a very nice Blog post made by Spotify engineering team, describing their experience when testing this service.
As the name suggests, the processing model is based on  the publishing/subscribing, pattern implemented by most of the best brokers available on the market.
The message consumption works in two models:
  • Polling: You can configure your client o poll the topics times to times. 
  • Push: You register an URL that the Google Pub/Sub service is gonna call when messages arrive to the topic (web hook like)

Besides that, here are some characteristics that, in my opinion, makes this tool an interesting solution:

Durability

Messages sent to Google Pub/Sub messing system  wont be lost lost. Google guarantee message retention up to  7 days, which pretty resealable. This is a must in scenarios where back pressure needs to implemented and some other consistency requirements needs to be attended.


Reliability 

The Google Pub/Sub  messaging service is available in almost all regions where their cloud service is working (North America, Europe and Asia). The advantage here is, Multi Region availability and replication. It is all google responsibility keep everything in sync and available for you. The operational costs to make systems like this work on promise are sky high, so rely on a third party service is a very relevant point to consider.


Low Latency and High Throughput

Results shown by the Spotify Engineering team and the Google documentations itself are  very enthusiastic (1M messages/second). That makes It a considerable option for near real time processing systems. We should never trust 100% on benchmarks, ideally we should try It by ourselves, but similar number are on the Google documentation also, so It's relevant.


APIs

Choose your flavor

  • Java
  • Python
  • Objective C
  • GO
  • PHP
  • Javascript
  • REST
Once you pick one, It's resealable to check the performance to be sure It meet your needs. The Spotify team had some issues with the Java API, so they move to REST.

Billing model

It looks pretty fair ($0.40 /million messages on the first 250M). Just be aware that the real cost is gonna consider also:
  • Number or API calls: The process of sent, consume and ack a message are considered 3 separated API calls. The massage size is also taken into account. Google charges by blocks of 64 KB, so if the message contains 128 KB It's gonna take 2 calls.
  • Storage
  • Network
So, the final price may be tricky to calculate. Be aware that It may cost more than you expect It be.

When talking about data ingestion, this is definitively a tool to keep on the radar. The comparison with Apache Kafka is inevitable at this point, but in my opinion they are similar in some aspects but differ in others:

  • They are both production ready for Real time Log Analytics. There are several benchmarks on the Web using both and showing they are robust alternatives. BTW, Apache Kafka is more time on the market, which gives It some advantage.
  • They differ on the processing model. Differently than Kakfa, Google Pub/Sub doesn't let consumers rewind back  on the topic. On this point, Google Pub/Sub works more like a traditional messaging system (without the overheads).  Before being released as a product, Google Pub/Sub was a tool used internally by Google team and they didn't have this requirement so far. BTW, I won't be surprised seeing this feature on the next releases.
In my opinion, the ability to reprocess messages in a topic makes Apache Kafka a more relevant option when implementing Kappa Architecture. BTW, It's always interesting see another option for data ingestion on the market. More use cases would definitely make It more popular.

There is some producer example here. Google lets you use this service for free during 60 days. which is awesome for POCs in case you wanna try It.

Cheers,





Monday, 3 August 2015

SOA/MSA design - Isolating contract dependencies

Contract is a crucial part of any services anatomy. In a SOA/MSA approach, contracts exposes the services behaviour that consumers will rely on. This behaviour is usually exposed as series of interfaces and input/output structures and implemented by internal components. The last is usually hidden from external consumers. The previous described structure may look like this:


On this example, modules are splitted, there is only one dependency flow (internal modules doesn't know external ones), each module has Its own set of dependencies, consumers rely on abstractions (the contract), so far so good.
When consuming services through REST or SOAP, consumers will need to serialise and deserialise the structures service exposes. It means they will need to hold a copy of these structures locally in order to get this job done. Now lets say you want to avoid this structure replication through all consumers inside your company. Considering services are built following the structure illustrated before, the contract module could be splitted apart and then shared with the consumers. In this scenario, you may get ride of the structure replication issue, but will running into another. When issuing the contract module as is to consumers, they will now depend on the same libraries that contract depends, otherwise consumers wont be able to use them. What about services moving to a different library-A version that isn't compatible with previous ones? A scenario like this:



If all consumers don't upgrade to the same library-A version than service is they will be broken. More consumers you have on this model, more synchronisation between them will be needed to deploy. More services you have worst It get. The expected agility when choosing this architecture approach will be harder to achieve.
One possible solution for this problem is, accept that consumers will hold local copies and just deal with It. Accepting they will have some extra work is still better than the coupling scenario described before.
You can also design your service keeping the contract module with less dependencies as possible. It may looks like this:



This design guideline can increase services flexibility when sharing contract as library. Consumers would need be affected only contract behaviour changes.even here but there are techniques to mitigate these effects. It is also an example that being succeed on going for SOA/MSA approaches depends also on good design and architectures choices.









Sunday, 28 June 2015

AWS-Lambdas - Automating function deploys

On this post, I talked about the ideas behind AWS-Lambdas computation service and how It works.The presented example shows how It can be be deployed and used. Even having an working example, there is an issue on the way I'm using It. All steps regarding the deploy process are manual. It just goes against agility. Manual deploys as such are error prone. More complex the application get, more expansive It will be to maintain.The side-effects when maintaining manual deploy steps are endless, so there should be an alternative to automate It and make AWS-Lambdas really cost effective as It promises to be.
Kappa seems to fill this gap. It is a command line tool that greatly simplifies the process of having lambdas deployed on the cloud. All steps described on the mentioned post can be automated. Now are talking!

Setup

Before start, be sure you have python (2.7.x)  and pip available on the command line.

Installing kappa: 

I strongly advice build It from sources as far there are important bug fixes that seems to be fixed recently:

git clone https://github.com/garnaat/kappa.git
cd kappa
pip install -r requirements.txt
python setup.py install

Instaling awscli:


sudo pip install awscli


Configuration:

First thing to do is create the the kappa configuration file. This is where I'm gonna tell It how to deploy my lambda function (config.yml).
---
profile: my-default-profile
region: us-west-2
iam:
  policy:
    name: AWSLambdaExecuteRole
  role:
    name: lambda_s3_exec_role
lambda:
  name: myLambdaFuncId
  zipfile_name: integrator.zip
  description: Somethhing that helps describe your lambda function
  path: src/
  handler: Integrator.handler
  runtime: nodejs
  memory_size: 128
  timeout: 3
  mode: event
  test_data: input.json
  event_sources:
    -
      arn: arn:aws:s3:::[set your bucket name]
      events:
        - s3:ObjectCreated:*


Lets see what is going on:

Line 2: There should be a profile that kappa will use to authenticate Itself on amazon and create the function in my behalf. We are gonna see it later on the awscli  configuration;
Line 4: The policies assigned to this lambda. In case they aren't there yet, kappa will create them for me.
Line 9 - 18: function Runtime configs.
Line 19: This is the file that contains an example request in order to test the function. It is useful once we want to be sure everything is working fine after the deploy is over.
Line 20: Here I'm setting from where events will come from. In this case, any changes on the given bucket, will trigger a call to my function.

Now It's time to configure aws-cli. The only configuration needed is the security profile. Kappa will use It as stated before:

Create the following file in case Isn't already there: ~/aws/credentials and put the following content
[my-default-profile]
aws_access_key_id=[YOUR KEY ID ]
aws_secret_access_key=[YOUR ACCESS KEY ]


Having it set, It's time to deploy it using kappa tasks:
kappa config.yml create
kappa config.yml add_event_source
kappa config.yml invoke
kappa config.yml status


It should be enough to see the function deployed on the aws-console. The previous commands in order did:

  • create the function on the amazon
  • Make it listen changes on a given bucket
  • Test the deployed function using fake data (simulating an event)
  • Check the status of the deployed function on amazon.


As far Kappa let me automate all deploy tasks,I'm able to create a smarter deploy process. I worked in an example about how could It be done here. I may forgot to mention some detail about the process of having It work, so in this case leave me message and I'll be glad to help.



Sunday, 7 June 2015

AWS Lambda - Computation as Service

Less than one year ago, Amazon launched  a new computation service, the AWS-Lambda. It promises simplify the process of building applications, by hosting and running code for you.  All the infrastructure and some scalability and fail over aspects are Amazon's concerns. It also integrates pretty well with other Amazon's services like SQS, SNS, DynamoDB, S3, etc. The code hosted there can even be called externally by other applications using the aws-sdk.

Here, I'll show how to use this service by doing something very simple. It idea is implement some code that will listen to an event (PUT) in a given S3 bucket, apply some processing on the file content, and send It to a SQS Queue.

This service restricts the language and platform where the code is implemented. A NodeJS module needs to be exported and called after deployed into the Amazon infrastructure, So, if you are not familiarised with Javascript and Nodejs, I would advice you to step back and look some documentation first.

var AWS = require('aws-sdk');
var parser = require('xml2js').parseString;
var async = require('async');

var s3 = new AWS.S3();
var sqs = new AWS.SQS();

exports.handler =  function(event, context) {
 var bucketName = event.Records[0].s3.bucket.name;
 var fileName = event.Records[0].s3.object.key;

 async.waterfall([
  function download(next) {
   s3.getObject({Bucket: bucketName,  Key: fileName}, function (err, data) {
    next(err, data);
   })
  },
  function parseXml(response, next) {
   parser(response.Body.toString(), function(err, result) {
    next(err, result);
   })
  },
  function sendMessage(result, next) {
   var message = {
    MessageBody: JSON.stringify(result),
    QueueUrl: "[YOUR QUEUE URL: i.e: https://....]"
   };
   
   sqs.sendMessage(message, function(err, data) {
      if(err) {
         context.fail("Error: " + err);
       } else {
         context.succeed("Message sent succefully: " + data.MessageId);
       }
       context.done();
   });
  }
 ], function(err) {
  if (err) {
   context.fail("Error: " + err);
   throw err;
  }
 });

}

Lets see what is happening here:

  • From line 1 to 3: Importing the modules needed on the implementation. All these modules needs to be packed when deploying the application, except by the aws-sdk, which is available by default in runtime.
  • Line 9 and 10:  Getting information from the event. When listing to an event from a S3 bucket, what you receive is the event metadata. So, if you want to do something with the object that uploaded, you need to extract the event metadata and then get the uploaded object and do something with the content.
  •  Line 12: The code from this point is a series of callbacks that depends from each other's results. So, to avoid the callback hell scenario, I used an external lib that make these functions dependencies a bit more clear to read.
In order to sure It's everything ok before deploying It, go to the console and perform a "npm install" command. It should check all code dependencies and put them into a specific directory.

Now It's time to set It up on Amazon infrastructure. The AWS-Lambda service let you upload a zip file with Its dependencies inside a Zip file. When using this option, be careful when creating the zip file. The Javascript file that will contains the code shown before needs to be at "/" on the zip file, otherwise It wont work. Worst than that, when running the code, the error message on the console is gonna show an error message that does not point on this direction.

Once is you have your code properly packed, go to the AWS console, access the "Lambda" option and and ask to create a new function. The  presented screen should look like this:



There, I'm putting basic information about what I'm uploading. The most relevant information are the Handler (Javascript file + the module name to be called) and Memory and Timeout values (Amazon will use this information billing). There is still the execution role. If you don't have one yet, create It using the options available on the combo box.  Once you managed to finish this step, the module is ready to be called. Now, the last step is just go to the bucket and I'm interested to monitor, and trigger this this function every time a new event happens by changing the bucket properties.

An additional and reasonable step would be test this deployed function in order be sure It's everything ok. In order to do that , go the console where all the functions are listed, select the function you want to test, press the "Actions" and select "Edit/Test". A new screen will be  presented. On the left side, there is a section called "Sample Events". It simulates some real use cases. To test this function, pick "S3 Put" option and  adapt the event setting valid bucket and file names. 
If everything went fine, you should able see a message looking like this on the Execution result area:

"Message sent successfully: 9431465....."

Some additional billing information should be displayed also and that is It. From this point you are sure that the function is properly deployed and ready to be used.
The working example can be found here.

Sunday, 10 May 2015

Devops Culture - Why Silos are an issue?

Devops is becoming a hot subject nowadays. There are some nice materials here and here explaining the principles behind It. At this point, we know that Deveops isn't only about automation tools and frameworks. It's about a different way to thing I.T, One of these principle is the Culture.
This is actually an essential dimension when talking about changing the way companies build software. They can pick the best automation tools available or hire the best market consultants to built their architecture, but if cultural aspects aren't improved, they may wont ship software as they expect. Today I'm gonna talk about one these cultural aspects, the Silos.


The Traditional Division


It's very commons see companies splitting up teams by their skills. A traditional division that follows this idea would look like that:







On this model, the software creation will be supported by a series of  specialised teams. These teams will "somehow" be talking to each other in order to build a solution. Using this structure, companies can have specialists on each that will lead people, ensuring issues/solutions are addressed properly. This structure can change a bit depending on the case. There are cases where companies nominate people to supervision (manage) to whole pipeline. They can be responsible by make everybody talk, that environments are delivered on schedule, issues are addressed by the right people/groups, etc.
Software has been delivered on top of this model during years. But we're living in a different era now and there are some scenarios this model does not handle well.

The Software Complexity


The problems we need to solve with software today are different than the ones we needed 10 years ago. Lets see some examples that illustrate this:

  • The data volume systems need to handle is way bigger than before. Architectural decisions need to take place in order to build systems that met business expectations. Such decisions can even change the way business sells their products to Its consumers.
  • The decision of moving to the cloud or not is today a strategic business decision not from some geek on the ops area. 
  • Solutions needs to support traffic growth in terms of seconds. Systems need to be elastic, but architectural decisions can make it impossible to achieve. Ops and arch teams need to be on the same page here before take any architectural decision.
  • How to test a solution with the characteristics  as highlighted before? QA team will need special skills.

Teams needs to be on the same page since the beginning here. Even small decisions can affect everybody's and make the release process slower release after release as far  application grows. What happens with the traditional model is that people tend to ignore the software complexity as whole and focus the area where they are experts. People  can workaround this issue and achieve the necessary coordination even on the traditional model, BTW, It is gonna demand more effort from everybody involved.
The complexity is well handled when people understand the system as whole. Adding barriers between teams does not help achieve this goal.

The Barriers Between Teams


When workstreams are used as silos, the development cycle is over simplified. Software is treated as a simple package that could be sent here and there. The issue is that the whole software complexity described before is ignored. As the complexity grows, releases  and maintenance start take more time and then became more expansive.  When dealing with complex software,  communication, alignment and proper architectural understanding are essential to support the whole process. The barriers created due oversimplification wont help on this scenario. Companies tend to normalise the communication between teams in  order to reduce misunderstanding but they actually just add more noise. The idea behind "breaking Silos" is remove the barriers to let people collaborate and then understand the system as whole.

As more barriers are created between business and production less agile the development cycle will be. Does not matter how many experts are on each Silo or how many automation tools they implement, The barriers between them will be always something to improve. By removing Silos, people are able to see the system as whole rather than only their "working-area". The real benefits became when system is optimised as whole instead of specific parts.

Saturday, 2 May 2015

Apache camel - Testing integrations

As far Systems are became more complex, It turns out that Test Automation is a mandatory Software Engineering discipline that needs to be followed. It is specially true when talking about Integrations between systems.On such scenarios, there are some challenges
  • Hard to isolate components - to test a single component, call to other components may need to be made in order to make the test possible, which makes the test process expansive
  • How to simulate system failures -  How to test the implementation behaviour in case one of the system being integrated fails? It is gonna be complicated or at least very time consuming simulate this test scenario because we need to control components that we usually can't.
  • Slow Build  - calls to external systems can be slow (slow connection, external system unavailability, etc). If your tests are build calling external systems, the build time might get slower over time as far you test coverage grows.
At the end of the day, these are things we need to workaround because tests would need to be done anyway. The good news is that It is possible to achieve certain level of test coverage even  on such scenarios. By using some DI techniques and a couple of frameworks I'm gonna make it happen.
I'm gonna use my last post as base. Actually I'll keep It as It is and create a different implementation applying modifications that will let It testable.

What is worth to test?


Looking to the implementation as It were, would be desirable test if the routing logic works as we expect on both cases (when it finishes successfully and when there is an error). To achieve that, I don't necessarily need  to rely on Amazon S3 or a different external component. I can "mock" them and then test the routing logic isolatedly.

How to do that?


In order to not depend on Amazon S3 on my tests, I need somehow  "replace" It only during the tests by "mocked" endpoints. By doing that, I'll be able to isolate what needs to be tested (the routing logic) and also control the input data, then simulate the behaviour I want.
First thing to do is to remove the hard coded references to S3 externalising them. The code will look as follows:

 @Component
class FileRouter extends RouteBuilder {
  @Autowired val sourceJsonIn: String = null
  @Autowired val targetJsonOut: String = null
  @Autowired var targetJsonError: String = null

  override def configure(): Unit = {
    from(sourceJsonIn).
      to("bean:fileProcessor").
      choice().
        when(header("status").isEqualTo("ok")).
          to(targetJsonOut).
        otherwise().
          to(targetJsonError)
  }

}

Here I'm using Camel Spring support for java. The FileRouter class will receive the endpoints from the spring context in runtime. In fact, these endpoints are now spring beans defined as follows:

trait S3Beans {
  @Bean
  def sourceJsonIn = "aws-s3://json-in?amazonS3Client=#client&maxMessagesPerPoll=15&delay=3000&region=sa-east-1"
  @Bean
  def targetJsonOut = "aws-s3://json-out?amazonS3Client=#client&region=sa-east-1"
  @Bean
  def targetJsonError = "aws-s3://json-error?amazonS3Client=#client&region=sa-east-1"
  @Bean
  def client = new AmazonS3Client(new BasicAWSCredentials("[use your credentials]", "[use your credentials]"))

}

There is also the FileProcessor that handles the file content. It is also defined as a spring bean as follows:

trait NoThirdPartBeans {
  @Bean def fileProcessor() = new FileProcessor
}

The S3 endpoints,  FileProcessor and FileRouter classes are ready to be added into the spring context. As far we are using spring support from camel, they will on be available on the camel context as well. It's being done as following:

@Configuration
@ComponentScan(Array("com.example"))
class MyApplicationContext extends CamelConfiguration with S3Beans with NoThirdPartBeans {}


Now the implementation is ready to be tested. In order to achieve to behaviour I want, I need to replace all endpoints set on S3Beans class by "mocked" endpoints. By doing that, I'll be able to "control" the external dependencies and then simulate different scenarios. To do that, I'll create a different "test context"but only replacing the beans I need to mock.

@Configuration
class TestApplicationContext extends SingleRouteCamelConfiguration with NoThirdPartBeans {
  @Bean override def route() = new FileRouter
  @Bean def sourceJsonIn = "direct:in"
  @Bean def targetJsonOut = "mock:success"
  @Bean def targetJsonError = "mock:error"
}

Direct is a camel component that works as a "memory" queue. It is gonna replace the S3 bucket where the files come from. Mock is another camel component that we can assert in runtime.  They are replacing the output S3 buckets. I can now check whether they receive messages or not.
Now It's time to create the test class. It' s gonna use the"test context" I just created and then validate different test scenarios. It's being done as follows:

@RunWith(classOf[CamelSpringJUnit4ClassRunner])
@ContextConfiguration(classes = Array(classOf[TestApplicationContext]))
class SimpleTest {
  @EndpointInject(uri =  "mock:success")
  val mockSuccess:MockEndpoint = null

  @EndpointInject(uri =  "mock:error")
  val mockError:MockEndpoint = null

  @Produce(uri = "direct:in")
  val template:ProducerTemplate = null

  @Test
  def shouldHitTheSuccesEndpoiny(): Unit ={
    val fileContent =  IOUtils.toString(getClass.getResourceAsStream("/json-file.json"))
    template.sendBody(fileContent)
    mockError.expectedMessageCount(0)
    mockSuccess.message(0).body().convertToString().isEqualTo(fileContent)
    mockSuccess.assertIsSatisfied()
    mockError.assertIsSatisfied()
  }

}

Conclusion

Real world integrations can be much more complex than the example I used. But they still need to be tested somehow. Systems like these without tests will became unmaintainable soon. The test approach i used fits well on case there is routing logic or between the components being integrated.
It is also  important to notice how the spring api made the implementation simpler and testable. As It was implemented before (without spring or any DI technique) would be very hard to achieve the result.
The working example can be found here.

Tuesday, 21 April 2015

Apache Camel - AWS3 Integration - Moving files between buckets

Apache Camel is a great tool that helps when integrating heterogeneous systems. I'd say is the best one I've seen. By using Its comprehensive DSL, you can implement several integration patterns very easily. It also offers  well modularised APIs  ready to set and use and an extensive active community. On this post, I'll talk about one of these APIs, which is camel-aws3.
AWS3 is  a very popular storage service offered by Amazon and camel-aws3 is an API that let you manage files stored there. It is different than camel-file component where the idea is to deal with files stored in a given file system.
In order to use camel-aws3,  first thing we need to do is add It as dependency in our project.  Here, I'm using SBT, but it works on the same way for any other build/dependency/management tool.

libraryDependencies ++= Seq(
  "org.apache.camel" % "camel-core" % "2.15.0",
  "org.apache.camel" % "camel-aws" % "2.15.0",
  "commons-io" % "commons-io" % "2.4"
)

The lib commons-io (declared at line 4) isn't mandatory. I'm just using It to make my life easier when dealing with streams coming from AWS3.

Next thing to do is define a route. By defining a route, you tell camel to do things for you. Here I'm using the Java DSL, but you can achieve the same thing by using the  XML configuration support. Here is my route definition:

 
class MyRouteBuilder extends RouteBuilder { 
    override def configure(): Unit ={
        from("aws-s3://json-in?amazonS3Client=#client&maxMessagesPerPoll=15&delay=3000&region=sa-east-1").
         to("bean:fileProcessor").
         choice().
           when(header("status").isEqualTo("ok")).
            to("aws-s3://json-out?amazonS3Client=#client&region=sa-east-1").
           otherwise().
            to("aws-s3://json-error?amazonS3Client=#client&region=sa-east-1")
    }

}


Let's see what is going on here:
  • Defining the target:  on line 4, I'm setting from where files are coming from and how. Camel-aws3 API accepts parameters that specify how files will be fetched.  This is mostly what the rest of the parameters are doing. For more detail about those, check the website documentation.
  • Defining what happens after files are fetched - on line 5, I'm setting who is gonna process each file downloaded from AWS3. It's a simple scala class that is defined on the camel context. You'll more about this one in a sec.
  • Processing output results  - from line 6 until the end, I'm setting what is gonna happen based on the result from fileProcessor. This is the Control based router API acting. Here we have the logic that will move files from the origin bucket or another based on the output from fileProcessor.

The File Processor.


This is the implementation that will be called for each file arriving from AWS3. Nothing special about that. Ideally,this is where we need to apply any logic on the file being processed.
 
class FileProcessor extends Processor {
  import java.util.logging.Logger
  
  val logger = Logger.getLogger(classOf[FileProcessor].getName)

  override def process(msg: Exchange): Unit ={
    val content = msg.getIn.getBody(classOf[String])
    // Do Whatever you need with the content
    logger.info(content)
    Messenger.send(message = msg, status = Some("ok"))
  }

}


Actually, there is something specific happening on line 11. There, I'm sending content that will be used by the next step on the flow. The next step I'm referring here is the one currently implemented by MyRouterBuilder from line 6, that will decide whether it needs to move the file to a given bucket or another.

 
object Messenger {
  import org.apache.commons.io.IOUtils

  def send(message: Exchange, status: Option[String]): Unit ={
    message.getOut.setHeader("status", status.getOrElse("error"))
    message.getOut.setHeader(S3Constants.KEY,  message.getIn.getHeader(S3Constants.KEY).asInstanceOf[String])
    message.getOut.setHeader(S3Constants.BUCKET_NAME, message.getIn.getHeader(S3Constants.BUCKET_NAME))
    message.getOut.setBody(IOUtils.toInputStream(message.getIn.getBody(classOf[String])))
  }

}

By adding information on the output structure, the next step on the process will be able to decide what happens next based on the content. MessageSender isn't actually sending anything. It is just changing the Exchange object by reference. These names were picked just to make what is going on more explicitly to the user, once changing structures by reference makes the code a bit hard to understand.

 
object CamelContext {
  import com.amazonaws.auth.BasicAWSCredentials
  import com.amazonaws.services.s3.AmazonS3Client
  import org.apache.camel.main.Main

  val accessKey = ""
  val secretKey = ""

  def start(): Unit ={

    val camel  = new Main
    camel.bind("client", new AmazonS3Client(new BasicAWSCredentials(accessKey, secretKey)))
    camel.bind("fileProcessor", new FileProcessor)
    camel.addRouteBuilder(new MyRouteBuilder)
    camel.enableHangupSupport()
    camel.run()
  }

}

Here I'm initialising the Camel context.  The client (line 13)  will be used for authorisation and the fileProcessor  (line 14)  will be used to process files. From this point, they can be referenced by any router (as MyRouterBuilder is doing).
Keep in mind you still need to define your own keys on lines 7 and 8.
From this point,  you just need to call the start method, like this:

 

object Main extends App {
  CamelContext.start()
}


That is It. If you want to look into details, a working example can be checked here.

Sunday, 15 March 2015

SOA - Dealing with Consumers Requirements

Services are created to be consumed. In case a Service isn't good enough (does not provide enough value), It fails on Its primary reason to exist. This makes sense for most of the companies I know and It is not different when talking about SOA. The goal of this post isn't advocate about SOA itself or disvantages/advantages of this Architectural Style. The idea  is highlight the consequences of drive Services requirements based only on consumers needs.

What is a Service?


It is a high level abstractions exposed as a business functionality to be consumed. By mentioning "high level abstraction", I mean, It should shape a business functionality as It really is (how It behaves). Low level details like  protocols, security, infrastructure, specific data consumer structures should  be out of the scope here.
Some of the ideas behind this definition are:
  1. If business change, Service needs to change quickly - The advantage of dealing with high level business abstractions is because Service will need to change only the when business behaviour changess and not other layers. By avoiding introducing low level details on the Service design, you'll be able to respond quickly to business changes than doing the opposite.
  2. Stay aligned with Business Strategies - That means, if companies wants to be able to consider expose business functionality for different consumers/medias/plataforms or compose several services to create  new business functionality, for instance, Service design should support It.

Dealing with Consumers Requirements


During the development life cycle, there will be cases where might be easier accommodate modifications on Services side in order to attend specifc consumer needs. By following this approach, you are creating a coupling on the Services design that isn't desirable. Services may looses It's capacity to quickly respond to changes without affect It's consumers.

Consider  a Sales Service that returns alls sales for a given Customer. Lets say there is a consumer (an UI) that needs display the sales in a specific order, different than the one returned by the Sales Service. For the UI point of view, would be easier have the sales returned on the order It needs. It may advocates the Service is much closer to the data. So ordering information there would be faster than iterating the sales  again on  the UI side and order the data as It needs.  
But now, lets consider the same services needs to be consumed by another API. What about this API needs the same information in a different order than UI?  
See, consumers driven  decisions increases the coupling by making Services harder to change without breaking other consumers. Services loose the capacity to quickly respond to business changes on these cases


Conclusion


The "sorting" example may looks a bit silly, maybe yes.. but consequences are the same when changing contract data structures/behaviour just to make consumer's life easier. So, be cautious when dealing with consumers driven requirements.  To avoid It, make your services Consumers Agnostic by avoiding  consumer specific requirements fall into the your Service design.


Thursday, 26 February 2015

Requirements - Problem Discovery

When Eliciting requirements, these are question I usually raise independently on the domain:

  • Why It is a Problems for you?
  • Why do you need this?
  • Why It needs to be different?

I believe the answers are crucial for the requirement analysis. They basically will show the customer's real needs, their business problems. Detail requirements from this point is supposed to be safer and we'll see why.


What is a Business Problem?


A problem on this context is something that does not let business goes forward as it needs. You can think on it as the reason why you (Software Engineer) was called. A Problem is usually characterised as something that involves money somehow. When talking with business people about some problem, try to get from him how the problem (usually mentioned as a business need) he is talking about makes his company loose money.


Why Identify Problems is Important?


As a Software Engineer, have you received a complied requirements list ready to be implemented? If your answer is yes, how were you sure these requirements are really the ones your customer is waiting for? If you manage to correlate requirements to business problems to be solved, you'll  be able to have this answer. By doing that,  you avoid resources to be wasted by implementing features that are not valuable to business. 
Spreading this mindset to the whole tech team is also valuable due several reasons:

  • Team can prioritise refactorings and design efforts on parts of the systems that will really makes the difference.
  • The feeling that the team is building something really valuable.
  • Team is able to understand what makes business slow down, then create solutions that properly  address these issues.


How to Identify Business Problems?


Looking for business problems when eliciting requirements may seem too vague, a good tip here is look for problems that make the company loose money directly or indirectly. Business people usually report them as ".. this process it taking too long .. " or ".. Because it is too complex and involves too many people be coordinated..", etc. Even not mentioning the word "money" explicitly, they are talking about time, resources, etc. 
Achieve this point may be tricky and will demand you some experience on the field depending the domain you are. BTW, a technique is which is helpful is here to use Business Objective Models. It helps to identify business problems  and objectives. Going through this process, you will also be able to have a set of high level features that the final solution will need to provide. 



Even looking obvious, there are projects where this process is just ignored.  By doing that, people are assuming the risk to be working on requirements that doesn't bring the value business is expecting.  Be suspicious when your customer came to saying: "My solution needs to do this and that...". You are may running in this scenario.
By doing the Problem Discovery approach, it is gonna be also easier to have everyone on the same page (business and tech team) on which regards where the efforts needs to be applied, once the objectives are clear to everybody.
It also works well with the Iterative approach. You'll may have a chance to work with your customer showing him business problems that even him isn't not aware of.








Sunday, 25 January 2015

Requirements Discovery - The Iterative approach.


Requirement Analysis is crucial part of development of any kind of system. This is the point where Engineers start shape the solution that  is gonna be built. During this phase, they also need to consider constraints that each particular project will demand (i.e cost, risk, time,quality, schedule, etc).On  the Requirement Analysis, business and IT people start get on the same page in which regards the problems that need to be addressed.
Without a proper Requirement Analysis, certain solutions are almost impossible to be built. There are some problems that are too complex to be solved without a proper understanding. It does not means Engineers will need to spend the whole budget available just be on the same than business. Here is where the agile mindsets and the lean principles came into the show. Ok, So far, so good, but why are we still seeing problems like misunderstanding on projects where there is time and space for Requirement Analysis? There can be plenty of reasons, Each project has It's own context with different problems, but I'll talk more about one I've seen several times in different projects. As  Engineers, we frequently fail to help business, go through the right direction.
I've seen quite often on projects of any size.  You may have experienced it already in case you are able to answer some of following questions:
  • As a software Engineer, have you received a list of requirements to be addressed and schedule already defined? 
  • Did someone get any input from the final user who is gonna be using the system?
  • Have someone thought  how complex is the architecture that needs to be built in order to attend the requirements?
  • What about some business concepts  that are still hidden on this requirements list that we may realise only few months after the project is already started?
All the aspects that involve the previous questions are the people usually ignore. Basically answering these questions will lead you to the symptoms the problem. Even in projects where people say they are agile, they are not free from situation. The issue to be solved here is not the methodology but involves approach and trust.


The Iterative Approach


In order to help business to find out the right requirements, the first step is to be more involved on the Requirements Elicitation process. The Iterative approach suggests this phase happens by constantly getting feedback from business. There are two main advantages by following this approach to Elicit requirements:

  • Engineers and Business people on the same page: By Applying series Engineering techniques, we can help business to find out the right requirements to solve the problem they have. Engineers and business tend to be on the same page once they get constant feedback from each other in which regards the how problems  will be addressed and  technical challenges around them.
  • Just enough analysis - As far it is a iterative process, business can see the list of requirements as they are being formed and they understand the challenges around them. They can decide the the right time stop and go forward with the release. On this way, you wont spend the whole budget available on the requirement analysis.
  • Looking for the right Architecture  - Make business understand the challenges sometimes pass through making proves that the architecture chosen will work as expected. By doing POCs, you can get these answers before making calls that will involve more money and risk.
The Iterative approach can actually be something continuous. It means the process can be repeated as soon you reach the Implementation phase. It also means you can go back to the modelling step once the result from the POCs does not attend the expectations. This approach works pretty well on cases where teams are looking for a MVP, for instance. It also means the cycle can restart as soon you  reach the implementation phase.(i.e plan the next release).

In order to make this approach works, collaboration is mandatory. Engineers needs to get feedback from people that fully understand the business and the problems they are trying to solve, otherwise the chances of wasting resources and time building a solution that wont attend the business expectations is high.














Sunday, 28 December 2014

Creating good interfaces - The Law of Demeter




For the ones who are used to the OOP approach, the term Interface,
may relates to a structure that will determine the behaviour that other structures will assume. However, when talking about Software Engineering concepts they are more than that. They help to define Software abstractions that can be widely used in a software system. Interfaces can also be seen as what structures exposes (i.e make public), to the world. Once you make something public, you're creating a chance to other structures rely on and from this point, you'll need to maintain this relationship.
Such definition help us to understand why some software implementations are so hard o maintain.
Sometimes people don't get it right and make things public when they actually should not. Structures that exposes functionality more than needed, are actually creating a new chance to be coupled to other structures. More coupling means a software that is hard to change . A software that is hard to change is expansive. A software that is expansive... well, you may know what is gonna happen from this point...

The Law of Demeter


It is a Software Design technique that aims  to help create low coupled structures. It's based on the Information Hiding principle where structures know less as possible about each other.  It states that structures should only "talk" with his "close friends" not with strangers. Even when talking with "friends", they should avoid go into "details" about how they internally do things.
As far you manage to create a solution where structures don't know about how internally each other work, you are gonna create a solution that is more susceptible to change. It is certainly a property we look for when creating any software solution.

The problem


To understand the solution, would be better firstly understand the problem. Consider the following:





On the previous example, ClassA has a given responsibility. However, it exposes it's internal details like the ClassB usage. The scenario is even worst once ClassB also exposes the need of use ClassC. This last has actually a functionality that everyone else seems to be interested in. Here everybody knows everybody, this is actually creating a weak dependency chain. As far this system grows, other structures can do the same as ClassA, making the  whole system more coupled and harder to maintain. Here all classes are violating the Demeters's Law. More than that, they don't have good Interfaces.

The Solution


Good interfaces don't reveal its internal implementation details, they expose only what is enough to it's consumers, It provides more flexibility in which regards internal changes once the coupling between structures is well managed. Looking  at the previous solution, it stands out a design flaw once AnotherClass is using ClassC through ClassA and ClassB.
A possible solution would make ClassA manage the calls in a such way that ClassB and ClassC wouldn't need talk to each other. ClassA could also expose the functionality in a such way that AnotherClass wouldn't need to know any other internal structure.




Internal details in all classes are not exposed anymore to AnotherClass. Differently than the previous solution, small internal changes on ClassC are unlikely to break all other classes . The previous chain dependency is now broken into a more composable solution.


Pros

  • Low coupling. A solution that is simpler to maintain 
  • Interfaces that are simpler to use 
  • Improvement on the software testability once internal dependencies are no exposed.

Cons

  • It is common see on the web definitions that the Demeter's Law is a matter of counting the "dots" between method calls (i.e more than two dots violates the law). Look at this direction only can be pointless. Fluent Interfaces is an example that this definition alone can be wrong. The Law should be read as a low coupling principle than other thing. 
  • The Demeter's law issue lives on its own name. It's stated as a law but does not means it never needs to be violated. In cases where the changes on the design aren't worth compared with the benefits, would be ok live with it for a while. A good code/design pratic would help you and your team put a light on this.

Related links: 

Sunday, 14 December 2014

Being Explicit

Be explicit on what you mean can sometimes save from headaches and troubles. If you go to a restaurant, and there things you don't like to eat, you need to make it explicit to the Waiter (specially if you are allergic, which is my case), before ordering a dish. If you manage to make it right, your dish will be as you wish. Notice that to be successful here, you needed to be explicit with the Waiter, otherwise he wouldn't get your right,
Ok, lets see now hot  all these is relates with software development. Lets start with a couple of questions:
  • Have you already, debugged an API or any software unit in order to realise what it does? 
  • Have you spend hours using the approach "try and fail" to be sure about the side effects of a design change? 
  • Have you looked to a method/function/procedure that returns nothing, receives no parameters and throws meaningless exception?
If you said yes for any of these questions, then you have already dealt with a design that is not explicit enough about its intentions. On those scenarios, we are not able to be sure about the consequences of changes on the design or even be 100% sure about what expect from there, at least not easily. This is a problem I've seen quite often in some systems, and there are some variables that can make the scenario a bit more complex:
  • New people joining on the team.
  • Lack of tests
  • No "useful" documentation.

What means be Explicit?

First of all, lets look for a definition of the word explicit:
  • Fully and clearly expressed; leaving nothing implied. Meaningful
  • stated clearly and in detail, leaving no room for confusion or doubt. Fully Understanding.
  •  Fully and clearly defined or formulated: "generalizations that are powerful, precise, and explicit" (Frederick Turner)
Meaning and understanding are the key things here and that is why they are highlighted. A software unit is explicit enough when we make the right assumptions about what it does without go into details about how it does and also having full controls over its side effects. A whole design is explicit enough when we are able to recognise the right concepts/abstraction and be able to predict what is their behaviour when working together.

How to get there?

Here are some tips I use to make my designs more explicit:
  • Look for deep understanding on the domain - This a a pre-requisite to all items that are gonna follow. In order to find out the right abstractions, you need to understand the rules, see the entities, recognise its behaviour, the boundaries, etc. Everything starts from here. If you don't find the right abstractions, something will be missing in your design and the chances to achieve explicit will be smaller. This knowledge usually comes with time but as soon you get there, the explicit we are talking about Will emerge.
  • Minimise the side effects - side effects are hard to make explicit. When trying to make them explicit we usually end up with a complicated and unclear solution (i.e, checked exceptions, sharing state). On the other hand, hide it totally sounds unnatural  couse it will hard to predict them when using the system. If you can't get right of them, try to minimise shared state internally and use other software design techniques to deal with failures on the right place.
  • Create meaningful interfaces - In the end of the day,  we  expose APIs and functionalities through interfaces. Interfaces need to be clear enough about what they are suppose to do when used. It pass through finding the right abstractions giving to it the right names.
Be explicit is a matter of being honest about what are the intentions (Intention reve of your design. It is  It does not mean an implementation should reveal all its internal details but instead,  providing the necessary information to the that are interested use it safely, without misunderstanding.

Saturday, 6 December 2014

Paying debts


It is awesome the benefits  that credit cards brought to us. Where ever we go, for almost anything we buy, we can just use our credit cards! We almost don't  need cash on the wallet anymore, cards are enough! The way they work is quite simple. As far you use them, you accumulate debits with bank that needs to be payed later. Anything different than that will put you troubles and it will stop working.
Such example can be perfectly used as a metaphor for Software Development. From the technical side, we make agreements with business people in order to meet the schedule. We  implement short term solutions, we postpone design decisions that has huge impact on the software being delivered, etc. That is fine once all parts  keep in mind that, "there is no free lunch"! As using credit cards, there will be a time we need the pay for our expanses, otherwise we will be in troubles. It means that business and tech side will need to review the debits created along the way and "pay" for them at some point.

As  Software Engineers, I'd say we fail very often in order to show it to business. If we manage to release the product two, three, four times without even touch on the Tech Debt subject, business could argue "why wouldn't the Engineers make it once more"? Then Releases will take more time to be delivered, developers will be under pressure, more and more bugs appearing on production, etc. Suddenly the software that was released just few years ago to production now is being called "legacy... Well, you may have seeing it already, and you also may now what happens from this point....

I've  been approaching this scenarios using some techniques, some of them I'm able to describe:


  • The new Bridge Metaphor: Believe me, nobody from business will easily accept stop everything in order to pay Tech Debts. I'd say it is at least unlikely to happen. Things need to keep moving and that is natural. So if we find a way to conciliate delivery and improvements would be perfect, wouldn't it? So, there is a Software Design technique I've been using during few years that works well on this cases,  the new Bridge Metaphor. The main idea is try to conciliate delivery and improvements all at the same time. Well, this is what business people want to listen when approaching them with problems i described on the beginning of this post, don't you think?
  • We need to show to business clearly the problems on not picking up tech debts. Sure, there several other variables that will weight here that makes it easier or harder, i.e: Organisation Mature, how business trust on tech team, complexity and risks involved, etc. BTW, another thing that I'll  look on such scenarios  prioritise the debts that if payed now, will have immediate effects on the following releases.Following this approach, the task of showing the importance of prioritise debts becomes easier. I'm telling that couse there are times where there are some many debts to pay, that picking try to prioritise them aleatory usually ends in long meetings with frustrations on both sides (business and IT).

As mentioned before, the point sometimes is more complex than that. Even the techniques i mentioned will demand some effort and flexibility from both sides (business and IT people). BTW, i believe these tips can help even in more complex scenarios.





Monday, 24 November 2014

An important Software Design Property - Context Independence

We could start by asking what Context really means in terms of Software Design and why having Context Independence is good? Firstly, lets define Context:

Context -  it is  everything that needs to be set in order to use a given data structure (i.e a Class). This is mostly about its relationships and their dependencies.

Basically the Context of a given structure is what it needs to be functional, so without Context you can't use It. In other words, this is something that you can't avoid, you need to deal with it when designing your software. BTW, there are some very known design issues that follow  Data Structures with Heavy Context. Some of them are:
  • Make them hard to test;
  • Make them hard to use/reuse and extend;
  • Deal with this kind of structures is always hard, so it'll naturally make the them hard to change and maintain
Lets look to an example, Consider the following classes relationship:


Here are them exchanging messages:


AS far we can see, Class B, Class C and Class D have their own Context. This something they need in order to make their job. Class A is using them, and also it dealing with their contexts, as soon it needs to initialize them.  Here is where problems get started. What about the effort needed to test Class A? Avoid dealing with each individual Context  would be something desirable by any  Class which needs to the those classes. The property we are looking forward here is Context Independence.

A technique that can be used on this case is Dependency Injection. DI can make Class A free from the Context Initialization. By consequence it will also be flexible and make the design more susceptible to changes. This is how  it could looks like:



Now Class A is Context Free once it does not deal with all details with Context from other classes. Implementation on Class A will be more clear, testable and easier to extend and change.

Another technique that can be used in order to be sure if a given Structure is Context Free is checking how it is communicating  with other Structures. If it is asking other Structures How to things instead of What,  it means you are on the wrong. You probably have a Structure that knows too much about others  and it is probably dealing Contexts you should avoid.

Context Independence is a technique that can help you to keep the healthiness  of your design. It works pretty well with SOLID principles. I am actually not able to see them work separately  in a more complex solution.




Monday, 10 November 2014

Building Changeable Software - The new Bridge Metaphor

In a Software Engineer daily job, there are several situations where a complete redesign needs to take place in order to make things work as they ideally need. The reasons to that happen (sometimes often than we'd like to see) can be many. I'll try to list some of them, but i can be missing some:

  • As developers we make mistakes - this one is obvious, knowledge about the domain  will come with time, the same is also valid for engineering techniques and principles. Until there we are gonna make mistakes and lack of  Code Review and design sessions  can just potentialize it.
  • Pressure to deliver - there are scenarios where we just need make things as faster as we can. Issues in Production that affecting the user experience can be damaging to business. So on this scenarios there is few space to huge refactorings  and redesigns and that is reasonable. The problem start when people start use this excuse to put pressure on anything we do, even it is not Production specific.
  • Fear to touch on production code - lack of test coverage can make it worst.
  • A mix between all them.
Understand the reasons why it happens and learn how deal with them is important for a Software Engineer also. Given the frequency it is scenario is presented to us, know how to deal it sometimes is the key in order to start introduce changes.

The new Bridge Metaphor

Let's say there is a bridge over a river. It lets people go here and there with their cars, but it is becoming too old. It's maintenance is becoming expansive and it is no long supporting the traffic volume. A new solutions needs to take place, otherwise users will suffer on the next years with the problems the current bridge is gonna present.
Ok, what about rebuild the current bridge in order to attend the new demands? The idea looks promising in terms of costs, but in the end of the day, it'll represent the bridge unusable during days or even weeks, which is unacceptable. Does not matter what happens, people needs to be able to keep using it.
Well, what could be done then? An alternative is keep the old bridge working and build a new one. At some point, when the new bridge is ready, the whole traffic can be switched to the new and fresh bridge disabling the old one.
Even more expansive, this is the most feasible thing that can be done once the other approach would bring several headaches to the users

Ok, but what it is the relationship with software development? I'd say it is all.
Business needs to keep moving, most part of the time there isn't much space to stop deliver functionality to make big redesigns. Try to sell this approach to business usually does not work. Moving things little by little is much easier to sell once it can be conciliated with functionality being delivered to production. This is like keep the old bridge working while new one is being  built, as far you can see on the picture.

As a Software  Engineer, I usually spend most part of my time maintaining software rather than working on green field projects  On such scenarios i have been following this approach in order to delivery good software and keep things moving. It also fits pretty well when dealing with legacy software.
The downside when following this metaphor is that at some point you will need to accept some code replication and some "ifs" on the code being delivered while the new bridge isn't done.