Structural Design Patterns: Proxy Pattern

Previously we used the facade pattern in order to interact with a legacy application. Our next pattern would be the proxy pattern.

The proxy pattern is used when we want

  • Control the access to an object
  • Add extra functionality when accessing an object.

One of the most common usages is when we want to monitor specific actions and add some metrics.

For example we have a data upload service.

package com.gkatzioura.design.structural.proxy;

public interface DataUploadService {

    void upload(String payload);

}

And its http implementation

package com.gkatzioura.design.structural.proxy;

public class HttpDataUploadImpl implements DataUploadService {

    @Override
    public void upload(String payload) {

    }

}

We need to have some measures on the average time it takes to send our application’s payload, in order to decide wether our implementation is good enough. If not we might need to consider something more performant.

Instead of messing with our implementation and adding code that has nothing to do with the actual transmission of the payload we shall create a proxy of our implementation.

package com.gkatzioura.design.structural.proxy;

import java.nio.charset.Charset;
import java.time.Duration;
import java.time.Instant;

public class HttpDataUploadProxy implements DataUploadService {

    private final HttpDataUploadImpl httpDataUpload;

    public HttpDataUploadProxy(HttpDataUploadImpl httpDataUpload) {
        this.httpDataUpload = httpDataUpload;
    }

    @Override
    public void upload(String payload) {

        Instant start = Instant.now();

        httpDataUpload.upload(payload);

        Duration duration = Duration.between(start,Instant.now());
        int byteSize = payload.getBytes(Charset.defaultCharset()).length;

        /**
         * Log properly to splunk, cloudwatch etc
         */
    }
}

As you can see our implementation hasn’t changed and we do manage to send the metrics needed to the analytics service of your choice.

We can also apply the same pattern in case this service has some quota and thus we want to control it because it might lead us to be over budget.

package com.gkatzioura.design.structural.proxy;

public class HttpDataUploadQuotaProxy implements DataUploadService {

    private final HttpDataUploadImpl httpDataUpload;

    public HttpDataUploadQuotaProxy(HttpDataUploadImpl httpDataUpload) {
        this.httpDataUpload = httpDataUpload;
    }

    @Override
    public void upload(String payload) {

        if(quotaExceeded()) {
            throw new IllegalStateException("Quota exceeded cannot upload payload");
        }

        httpDataUpload.upload(payload);
    }

    private boolean quotaExceeded() {

        /**
         * Code that should check whether we exceeded our quota or not
         */

        return false;
    }

}

Summing up we just used the proxy pattern in order to control the access to our object and also to enhance its functionality.

You can also find the source code on github.

Also I have compiled a cheat sheet containing a summary of the Structural Design Patterns.
Sign up in the link to receive it.

Structural Design Patterns: Facade Pattern

As developers most of the time we have to deal with complex systems, with many dependencies and even non existing documentation at all.

In these situations finding a way to tackle those challenges is essential. The most common way to deal with it, is to hide all those dependencies and specify a front facing interface.

The pattern to use in order to achieve is the facade pattern.

Somehow you end it up with a very complex system which generates reports in various ways. The system generates reports as xml files, csv files and even generates reports from a database.
The report generated in xml files extracts statistics based on a location, the report generated in csv files has to do with timeseries data and the database report about usage data.

The functionalities described above need to be incorporated to a web application.

The first step would be to create some interfaces based on each report.
The first interface will be the Geolocation report. By giving a location and a distance, a report shall be generated with locations within the distance specified from the point.

package com.gkatzioura.design.structural.facade;

import java.util.List;

public interface GeolocationReport {

     List<LocationInformation> generate(Double lat, Double lng, Double distance);

}

The Geolation report will be based on the xml reports generated from our system. Thus the implementation would be based on the xml report.

package com.gkatzioura.design.structural.facade;

import java.util.ArrayList;
import java.util.List;

public class XMLGeolocationReport implements GeolocationReport {

    @Override
    public List<LocationInformation> generate(Double lat, Double lng, Double distance) {

        /**
         * http requests to retrieve the xml
         * iterate the xml using stax
        */

        return new ArrayList<>();
    }

}

Our next report will have to do with time series data. Two dates will be given as an argument and thus the data needed will be retrieved.

package com.gkatzioura.design.structural.facade;

import java.util.Date;
import java.util.List;

public interface TimeSeriesReport {

    List<TimeInformation> generate(Date start, Date end);

}

Since the csv report is the one generated with time series data, our implementation will be based on the csv report of our system.

package com.gkatzioura.design.structural.facade;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class CSVTimeSeriesReport implements TimeSeriesReport {

    @Override
    public List<TimeInformation> generate(Date start, Date end) {

        /**
         * retrieve the csv and iterate line by line with the time limits
         */

        return new ArrayList<>();
    }
}

The last step is the user usage report. A uuid representing the user shall be given.

package com.gkatzioura.design.structural.facade;

import java.util.List;
import java.util.UUID;

public interface UsageReport {

    List<Usage> report(UUID uuid);

}

The usage report will be based on the database report.

package com.gkatzioura.design.structural.facade;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class SQLUsageReport implements UsageReport {

    @Override
    public List<Usage> report(UUID uuid) {

        return new ArrayList<>();
    }

}

So far we have abstracted the main functionalities of our system. Our next step is to create the facade which uses all those functionalities and bridges the gap between our web application needs and the the system that provides the information.
For example based on the user’s usage we need to have data based on the time and location of the user.

package com.gkatzioura.design.structural.facade;

import java.util.Date;
import java.util.List;
import java.util.UUID;

public interface UserUsageFacade {

    List<UserUsage> usageOn(UUID user, Date from, Double lat, Double lng);

}

And the implementation will use the report implementations in order to create the report that suits our web application.

package com.gkatzioura.design.structural.facade;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

public class UserUsageFacadeImpl implements UserUsageFacade {

    private final GeolocationReport geolocationReport;
    private final TimeSeriesReport timeSeriesReport;
    private final UsageReport usageReport;

    private final double DEFAULT_DISTANCE = 20d;
    private final int DEFAULT_TIME_RANGE = 20;

    public UserUsageFacadeImpl(GeolocationReport geolocationReport, TimeSeriesReport timeSeriesReport, UsageReport usageReport) {
        this.geolocationReport = geolocationReport;
        this.timeSeriesReport = timeSeriesReport;
        this.usageReport = usageReport;
    }

    @Override
    public List<UserUsage> usageOn(UUID user, Date from, Double lat, Double lng) {

        List locationInformationData = geolocationReport.generate(lat, lng, DEFAULT_DISTANCE);
        Date to = Date.from(from.toInstant().plusSeconds(DEFAULT_TIME_RANGE));
        List timeSetiesData = timeSeriesReport.generate(from, to);
        List usageData = usageReport.report(user);

        /**
         * Generate the report based on the data retrieved
         */

        return new ArrayList<>();
    }
}

You can find the source code on github.
Also you can find some helpful articles on the Adapter Pattern, the Decorator Pattern, the Composite Pattern and the Bridge Pattern.

Plus I have compiled a cheat sheet containing a summary of the Structural Design Patterns.
Sign up in the link to receive it.

Structural Design Patterns: Decorator Pattern

Previously we altered the behaviour of our abstract objects using the bridge pattern and we implemented a tree like structure for our components using the composite pattern and delegating the requests.

The decorator pattern allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.

So imagine the scenario of applying various discounts to one of our products.

We will start with the discount interface to specify the discount action.

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public interface Discount {
    
    BigDecimal apply(BigDecimal originalPrice);
    
}

An object which shall implement the discount will apply the discount and give back the discounted price.
One of the discounts that we want to apply is a special discount for newly registered members.
Newly registered members will have 20% off on their first order

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class NewlyRegisteredDiscount implements Discount {

    public static final BigDecimal SEVENTY_FIVE = new BigDecimal(75);
    public static final BigDecimal ONE_HUNDRED = new BigDecimal(100);

    @Override
    public BigDecimal apply(BigDecimal originalPrice) {

        return originalPrice.multiply(SEVENTY_FIVE).divide(ONE_HUNDRED);
    }

}

As you have experienced sometimes more than one discounts are applied.
Our system also provides our customers with coupon discounts of 5 dollars off.

It is very comon to apply multiple discounts and our systems has to support this action. It is common to create discount packages which in reality are just a compination of packages.
To do so we will utilize the decorator pattern.
We will create the discount decorator.

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class DiscountDecorator implements Discount {

    protected Discount discount;

    public DiscountDecorator(Discount discount) {
        this.discount = discount;
    }

    @Override
    public BigDecimal apply(BigDecimal originalPrice) {
        return discount.apply(originalPrice);
    }
}

So we want to have a first purchase discount and a 5 dollars of discount for new users referenced by other users.
We will call this discount as ‘referenced user’ discount.
The goal is to have 5 dollars off and a discount applied to the original price.

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class ReferencedUserDiscount extends DiscountDecorator {

    public static final BigDecimal FIVE = new BigDecimal(5);

    public ReferencedUserDiscount(Discount discount) {
        super(discount);
    }
    
    @Override
    public BigDecimal apply(BigDecimal originalPrice) {

        BigDecimal discountedPrice = super.apply(originalPrice);

        if(discountedPrice.compareTo(FIVE)<=0) {
            return discountedPrice;
        }

        return discountedPrice.subtract(FIVE);
    }
}

Imagine now the scenario of a loyalty discount. We want a two year plan for our users with a discount of 5% for each one of their orders.

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class TwoYearPlanDiscount extends DiscountDecorator {

    public static final BigDecimal NINETY_NINE = new BigDecimal(95);
    public static final BigDecimal ONE_HUNDRED = new BigDecimal(100);

    public TwoYearPlanDiscount(Discount discount) {
        super(discount);
    }

    @Override
    public BigDecimal apply(BigDecimal originalPrice) {
        return super.apply(originalPrice).multiply(NINETY_NINE).divide(ONE_HUNDRED);
    }

}

As you can see both in the cases of the referenced user discount and both in the case of the two years plan discount we didn’t alter our original discount for our newly registered users. What we did is decorating the original discount and giving back the discount by taking into account the various options.

The decorator pattern is about

  • Add Responsibilities or remove them from an object dynamically at run-time.
  • Extend functionality in a flexible way without subclassing

So let’s put our plan into action.

package com.gkatzioura.design.structural.decorator;

import java.math.BigDecimal;

public class DecoratorScenario {

    public static void main(String args[]) {

        NewlyRegisteredDiscount newlyRegisteredDiscount = new NewlyRegisteredDiscount();
        ReferencedUserDiscount referencedUserDiscount = new ReferencedUserDiscount(newlyRegisteredDiscount);
        TwoYearPlanDiscount twoYearPlanDiscount = new TwoYearPlanDiscount(referencedUserDiscount);
        BigDecimal discountPrice = twoYearPlanDiscount.apply(new BigDecimal(100));
    }

}

Our newly registered users will have three types of discounts.

You can find the sourcecode on github.

Also I have compiled a cheat sheet containing a summary of the Structural Design Patterns.
Sign up in the link to receive it.

Structural Design Patterns: Composite Pattern

Previously we checked the adapter pattern the use cases and the bridge pattern. The pattern we will examine in this post is the composite pattern.
By following the composite pattern we “compose” objects into tree structures representing part-whole hierarchies, therefore clients can treat individual objects and compositions uniformly.

By referencing the word hierarchies the first thing that comes to mind is organisations. A military organisation is a great example for the composite pattern.

One of the most basic actions of military personnel is to execute orders.
Thus we will make an interface which specifies the ability to execute orders.

package com.gkatzioura.design.structural.composite;

public interface MilitaryPersonnel {

    void executeOrder();

}

The private is the lowest rank in a military organisation. A private cannot delegate a task or give orders. Therefore he will just execute an order.

package com.gkatzioura.design.structural.composite;

public class Private implements MilitaryPersonnel {

    @Override
    public void executeOrder() {

    }

}

Above the private there are other ranks like Major, Lieutenant, Colonel etc. Those are officer ranks and officers execute orders but also they can assign orders.
So the Officer interface will specify the ability to assign orders.

package com.gkatzioura.design.structural.composite;

public interface Officer {

    void assignOrder();

}

Be aware that an officer in order to execute an order he will take some actions on his own and he might as well assign some orders to lower rank personnel.

So the Lieutenant will be able to execute orders but also to assign orders to ranks lower that him.

package com.gkatzioura.design.structural.composite;

import java.util.ArrayList;
import java.util.List;

public class Lieutenant implements MilitaryPersonnel, Officer {

    private List<MilitaryPersonnel> lowerRankersonel = new ArrayList<>();

    public Lieutenant(List<MilitaryPersonnel> lowerRankersonel) {
        this.lowerRankersonel = lowerRankersonel;
    }

    public void addPrivateUnderCommand(Private soldier) {
        lowerRankersonel.add(soldier);
    }
    
    @Override
    public void executeOrder() {
        
        //other actions

        assignOrder();

        //other actions.
    }

    @Override
    public void assignOrder() {

        lowerRankersonel.forEach(lr->lr.executeOrder());
    }
}

The same that applies to the lieutenant applies to the major who is able to execute orders and assign orders to lower ranks.

package com.gkatzioura.design.structural.composite;

import java.util.ArrayList;
import java.util.List;

public class Colonel implements MilitaryPersonnel, Officer {

    private List<MilitaryPersonnel> lowerRankersonel = new ArrayList<>();

    public Colonel(List<MilitaryPersonnel> lowerRankersonel) {
        this.lowerRankersonel = lowerRankersonel;
    }

    public void addPrivateUnderCommand(Private soldier) {
        lowerRankersonel.add(soldier);
    }

    public void addLieutenantUnderCommand(Lieutenant lieutenant) {
        lowerRankersonel.add(lieutenant);
    }

    @Override
    public void executeOrder() {
        //other actions

        assignOrder();

        //other actions
    }

    @Override
    public void assignOrder() {
        lowerRankersonel.forEach(lr->lr.executeOrder());
    }
}

In our scenario the general is the highest rank and thus when he assigns an order this order will be executed by the composite we implemented.

package com.gkatzioura.design.structural.composite;

import java.util.ArrayList;
import java.util.List;

public class General implements  Officer {

    private List<MilitaryPersonnel> lowerRankersonel = new ArrayList<>();

    public General(List<MilitaryPersonnel> lowerRankersonel) {
        this.lowerRankersonel = lowerRankersonel;
    }

    @Override
    public void assignOrder(MilitaryPersonnel militaryPersonnel) {
        militaryPersonnel.executeOrder();
    }
}

And a main class will display the composite’s functionality.

package com.gkatzioura.design.structural.composite;

import java.util.Collections;

public class CompositeScenario {

    public static void main(String[] args) {

        Private ryan = new Private();
        Lieutenant lieutenant = new Lieutenant(Collections.singletonList(ryan));
        Major major = new Major(Collections.singletonList(lieutenant));
        General general = new General();
        general.assignOrder(major);
    }
}

As you can see the general object, which is the client treated all the objects uniformly.
The whole hierarchy is represented in a tree structure.
The private is the leaf the major and the lieutenant represent the Composite that forwards the requests to the corresponding child components.

You can find the source code on github.

Also I have compiled a cheat sheet containing a summary of the Structural Design Patterns.
Sign up in the link to receive it.

Use properties with your gradle project.

Most of us are used in the maven way of specifying properties by using the properties tag


    2.0.9.RELEASE

and then when it comes to a dependency it can be easily referenced as ${springdata.commons}.


	org.springframework.data
	spring-data-commons
	${springdata.commons}

This is a bit tricky when it comes to gradle. The way  to do so is by using the extra properties extension.

ext{
  springdataCommons = "2.0.9.RELEASE"
}
dependencies {
    compile "org.springframework.data:spring-data-commons:${springdataCommons}"
}

Be aware that in order for this to work you should use double quotes, since in groovy double-quoted String literals support String interpolation while single quoted don’t.

This might work for you but you might want to use the dot character, for example springdata.commons .

That’s not possible using the previous way due to confusing the springdata as a symbol.
A workaround is to use the set method from ext.

ext{
    set('springdata.commons', "2.0.9.RELEASE")
}

dependencies {
    compile "org.springframework.data:spring-data-commons:${property('springdata.commons')}"
}

Pay attention to the compile section since you are going to have the same problem there regarding your name, thus you need to use an expression.

The other way around is to use a gradle.properties file and add there your properties.

springdata.commons=2.0.9.RELEASE

You compile section will be just the same.

dependencies {
    compile "org.springframework.data:spring-data-commons:${property('springdata.commons')}"
}

Structural Design Patterns: Bridge Pattern

On the previous post we had a look at the adapter pattern. On this blog we are going to use the bridge pattern.
As mentioned by GOF the bridge pattern usage is to “decouple an abstraction from its implementation so that the two can vary independently”.
How this translates to a software problem?
Imagine that you need to implement software for missiles.

You have Ballistic missiles, Cruise missiles, Rockets etc. Although they are all missiles and they may explode, their mechanisms differ a lot from type to type.

Taking the above into consideration most probably you are going to end with many layers of abstractions.
The missile and what it does vary a lot. And this is what the bridge pattern is all about. There is going to be a rocket abstraction and it’s behaviour will become largely different by providing a different component implementation, in our case the igniter.

We have one rocket interface specifying the missile actions.

package com.gkatzioura.design.structural.bridge;

public interface Missile {

    void explode();

}

And another interface which specifies the igniter actions.

package com.gkatzioura.design.structural.bridge;

public interface Igniter {

    void ignite();
}

And we are going to have a pyrogenic igniter implementation

package com.gkatzioura.design.structural.bridge;

public class PyrogenIgniter implements Igniter {

    public void ignite() {

    }
}

Last but not least we are going to have an AirToAirMissile implementation.

package com.gkatzioura.design.structural.bridge;

public class AirToAirMissile implements Missile {

    private Igniter igniter;

    public AirToAirMissile(Igniter igniter) {
        this.igniter = igniter;
    }

    public void explode() {

        //Actions relation to explosion

        igniter.ignite();
    }
}

So we will implement an air to air missile.

AirToAirMissile airToAirMissile = new AirToAirMissile(new PyrogenIgniter());

As you can understand missile components vary and based on the components their functionality changes.

You can find the source code on github.

Also I have compiled a cheat sheet containing a summary of the Structural Design Patterns.
Sign up in the link to receive it.

Structural Design Patterns: Adapter Pattern

On previous blog posts we focused on creational design patterns such as the builder pattern, the abstract factory/factory pattern, the singleton and the prototype pattern.

We will switch our focus to the structural design patterns. By using structural design patterns our goal is to ease the design by identifying a simple way to realize relationships between entities.

Adapter pattern is one of the most used and well known structural patterns.
Its major usage is when you want to make classes work with other classes without having to change its source code.

Imagine the scenario of refactoring some code and you stumble upon a class sending emails.

package com.gkatzioura.design.structural.adapter;

import java.util.List;

public class MailSender {

    private String title;
    private String message;
    private List<String> recipients;

    public MailSender(String title, String message, List<String> recipients) {
        this.title = title;
        this.message = message;
        this.recipients = recipients;
    }

    public void sendMessage() {

    }

    public void sendHtmlMessage(String htmlTemplate) {

    }

}

The MailSender class has the ability to send an email but also you can use it in order to send an email containing html.

We want to add some subscribe/notify functionality in our code base so that people could receive a simple message in the form of sms, email, webhooks etc.

We have also come up with an interface for the notify functionality.

package com.gkatzioura.design.structural.adapter;

public interface Notifier {

    void notify(String recipients,String message);

}

As you can see our notify action does not really care about the subject or formatting of the message. You just have to notify the subscribes.
Among the rest implementation an email implementation should be provided.
We can either provide a new email implementation which implements the notifier interface or we can change the original email class.

However there is a third option. You can use the adapter pattern and create a class so that you can reuse your old email class.

By doing this you don’t alter your old email class and therefore the code which uses its functionality and also you skip creating a new class therefore having to maintain one extra class.

package com.gkatzioura.design.structural.adapter;

import java.util.List;

public class MailNotifierAdapter implements Notifier {

    private static final String NOTIFICATION_TITLE = "System notification";
    
    public void notify(List<String> recipients, String message) {
        
        MailSender mailSender = new MailSender(NOTIFICATION_TITLE,message,recipients);
        mailSender.sendMessage();
    }
}

You can find the sourcecode on github.

Also I have compiled a cheat sheet containing a summary of the Structural Design Patterns.
Sign up in the link to receive it.

Gradle multi project build – parent pom like structure

When you come from a maven background most probably you have been used to the parent pom structure.

Now when it comes to gradle things are a little bit different.

Imagine the scenario of having a project including the interfaces and various other implementations.
This is going to be our project structure.

multi-project-gradle
-- specification
-- core
-- implementation-a
-- implementation-b

The specification project contains the interfaces, which the implementations will be based upon. The core project will contain functionality which needs to be shared among implementations.

The next step is to create each project inside the multi-project-gradle.

Each project is actually a directory with the builde.gradle file.

plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

Once done you need to do the linking between the parent project and the child project.
to do so you create the multi-project-gradle/settings.gradle and include the other projects.

rootProject.name = 'com.gkatzioura'
include 'specification'
include 'core'
include 'implementation-a'
include 'implementation- b'

Now if you set the build.gradle file for every sub project you’ve just realised that you include the junit dependency and the mavencentral repository everywhere.

One of the main benefits on using multi-project builds, is removing duplication.

To do so we shall create the multi-project-gradle/build.gradle file add the junit dependency and the maven central reference there.

subprojects {
    apply plugin: 'java'

    repositories {
        mavenCentral()
    }

    dependencies {
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }

}

Now we can add our dependencies to each project and even specify the dependencies needed from the sub-projects.

For example the core project uses the specification project

dependencies {
  compile project(':specification')
}

and each implementation project uses the core project

dependencies {
    compile project(':core')
}

You can find the project on github.

Migrate your elastic beanstalk workers to docker containers

Amazon Elastic Beanstalk is one of the most popular services that aws provides. Elastic beanstalk comes with two options, the worker and the web application.

The worker application consumes the messages from a sqs queue and process them. If the process was successful the message is removed from the queue, if not the message shall remain in the queue or after some failed attempts it will go back to a dead letter queue. If you want to get more into elb I have made a tutorial on deploying you spring application using elb and cloudformation.

Elastic beanstalk workers are really great because they are managed, they can be scaled up/down depending on your workloads and they provide a wide variety of development environments like java, node.js and also you can use docker images.

Although elastic bean can work wonders if you have an aws based infrastructure you might face some issues when you will try to move to a container based infrastructure using a container orchestration engine.

Most probably your containerized worker application will work seamlessly without any extra configuration, however you need to find an alternative for the agent which dispatches the queue messages to your application.

In order to make things simple I implemented a mechanism which retrieves the messages from the queue and sends them to the worker application.

The container-queue-worker projects aims to provide an easy way to migrate your elastic beanstalk workers to a docker orchestration system.

Since the solution is Scala based it can either be used as a standalone jvm application or it can be run in a container using the image from dockerhub.

Once set up what you need to add the routing configurations.

This can be done using environmental variables

WORKER_TYPE=sqs
WORKER_SERVER_ENDPOINT=http://{docker-service}
WORKER_AWS_QUEUE_ENDPOINT=http://{amazon queue endpoint}

Or if you use it as a container you can add a config file on the /etc/worker/worker.conf path.

worker {
  type =  sqs
  server-endpoint = http://{docker-service}
  aws {
    queue-endpoint =  http://{amazon queue endpoint}
  }
}

In order to make thing easier for you I added a docker compose file simulating the desired outcome.

version: '3.5'
networks:
  queue-worker-network:
    name: queue-worker-network
services:
  worker-server:
    build:
      context: ./worker-server
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    networks:
      - queue-worker-network
  elasticmq:
    build:
      context: ./elasticmq
      dockerfile: Dockerfile
    ports:
      - 9324:9324
    networks:
      - queue-worker-network
  container-queue-worker:
    image: gkatzioura/container-queue-worker:0.1
    depends_on:
      - elasticmq
      - worker-server
    environment:
      WORKER_TYPE: sqs
      WORKER_SERVER_ENDPOINT: http://worker-server:8080/
      WORKER_AWS_QUEUE_ENDPOINT: http://elasticmq:9324/queue/test-queue
      AWS_DEFAULT_REGION: eu-west-1
      AWS_ACCESS_KEY_ID: access-key
      AWS_SECRET_ACCESS_KEY: secret-key
    networks:
      - queue-worker-network

Fixing the if smell

From time to time we might end up with some huge ‘if’ statements in our codebase. Those statements have to be maintained and change the same code block over and over again. This is common also in cases where the ‘if’ statement checks if a variable belongs in a certain range of values.

Supposing you have an enum

public enum FoodType {

    FRUIT,
    VEGETABLES,
    RED_MEAT,
    WHITE_MEAT,
    FISH,
    DIARY,
    CERIAL
}

And you have a function making some recommendations

    public String recommend(FoodType foodType) {

        if(foodType==FoodType.FISH||foodType==FoodType.RED_MEAT||foodType==FoodType.WHITE_MEAT) {

            //execute a procedure
        } else if(foodType==FoodType.FRUIT||foodType==FoodType.VEGETABLES) {
            //execute a procedure
        } else {
            //execute a procedure
        }
    }

Now as you can see, a decision is made. The decision has to do with certain types of food which happen to belong under a specific group.
Fish, red meat and white meat are good for a user who prefers protein for his meal while fruit and vegetables are suited more for a fiber based diet.
In future cases this enum might be enhanced and more food types added to it.
The ‘if’ code block will have to be changed. Also in case, this complex ‘if’ statement is used in other files you will have to alter each file.
Not only you will have a huge if block but also a block which has to be maintained on each file and this might be error prone.

In order to avoid that you can change the contents of the if statement into a function.

package com.gkatzioura;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import static com.gkatzioura.FoodType.*;

public class DietFilter {

    private static final Set FOODS_WITH_PROTEIN = Collections.unmodifiableSet(new HashSet(Arrays.asList(
            FISH,
            RED_MEAT,
            WHITE_MEAT)));

    private static final Set FOODS_WITH_FIBER = Collections.unmodifiableSet(new HashSet(Arrays.asList(
            FRUIT,
            VEGETABLES)));

    public static boolean proteinBased(FoodType foodType) {
        return FOODS_WITH_PROTEIN.contains(foodType);
    }

    public static boolean fiberBased(FoodType foodType) {
        return FOODS_WITH_FIBER.contains(foodType);
    }

}

So instead of adding each single case of food type, inside an ‘if’ statement we created a function which checks if the argument given belongs to a specific group.

Therefore your ‘if’ statement will change into this.

    public String recommend(FoodType foodType) {

        if(DietFilter.proteinBased(foodType)) {

            //execute a procedure
        } else if(DietFilter.fiberBased(foodType)) {
            //execute a procedure
        } else {
            //execute a procedure
        }
    }

If more food types are added to the enum, the developer will only have to change the construction of the set and add the extra food type.
It will be much easier than changing multiple parts of the code and it is way more readable.