Skip to content

ilakkmanoharan/ConnectedCitiesAppV2FactoryPattern

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ConnectedCitiesAppV2FactoryPattern

Refactoring ConnectedCitiesApp - Spring Boot REST API to find connected cities Whats new: Factory Design Pattern, DisjointUnionSets

Changes in Technical Specifications from previous version:

Technology Stack:

Maven, Spring boot, Java8, Junit5, Swagger2, Factory Design Pattern

Graph Search Algorithm: The following graph search algorithms are implemented:

  1. Depth First Search (DFS)
  2. Breadth First Search (BFS)
  3. Disjoint Sets

The choice of the algorithm depends on the value of the connectedcities.graphsearch.algorithm property in the application.properties file.

Updated Design Considerations:

  1. Advantages of Spring boot:

    The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attributes

If there are beans/components in other packages that are not sub-packages of the main package, you should manually add them as @ComponentScan   In a non-Spring Boot Project, we would typically define the component scan explicitly in an XML application context or a Java Application Context

SpringBoot can autodetect the “application.properties” file in the “src/main/resources” directory and any loaded properties can be injected easily. There is no need to tell the Spring where the property file is located or even explicitly register a ‘PropertySource’.

  1. Advantages of using @GetMapping over @RequestMapping at the method level:

    At the handler methods level, It is best to use the more specific @GetMapping than the lengthier @RequestMapping(method=RequestMethod.GET) because with @RequestMapping, there is a possibility that the method attribute will be left off, as it is not mandatory. But it is always best practice to be specific about the HTTP method that will be handled and @GetMapping is specific for the GET requests.

  2. Advantages of using Adjacency List over Adjacency Matrix:

The graph is represented as an Adjacency List. Adjacency list uses less memory when to compared to Adjacency matrix, there is a lot of wastage of memory especially if the matrix is sparse. It is faster to iterate over all the edges in the Adjacency matrix as the adjacent vertices can be accessed directly. And it is faster to add/delete a vertex. Generally, Adjacency matrix representation is well suited when the graph is expected to be dense and Adjacency lists representation is well suited when the graph is expected to be sparse.

  1. In the City class, the instance variable Id is an Integer type and not an int. Because it is possible to check for null by using an Integer type.

  2. The city pairs from the input file is stored in a set to avoid duplicate entries.

  3. Enum Comparison. Enum members are compared using == operator rather than equals() methos. This is because == operator never throws a NullPointerException and is subject to type compatibility check at compile time and is faster than equals() method.

  4. Factory design pattern is used here to promote loose coupling, high cohesion and extensibility by extracting the responsibility of creating a new instance and handling it only in the factory class, it avoids repeatability of certain code. Since we are dealing with conditional instantiation of the graph search algorithms, Factory design pattern is a good choice.

  5. The package structure of the project is designed to reduce coupling across packages, avoid circular dependencies and support high cohesion.

  6. Switch statement is used in the place of if-else statement in the RouteFinderFactory.getFinderAlgorithm() method for the following reasons:

• Switch is better for multiway branching: In the case of switch statement, the compiler is aware that the case statements are all same type and simply must be compared for equality with the switch expression, while in case of if expressions, the compiler has no such knowledge. This is because when compiler compiles a switch statement, it will inspect each of the case constants and create a “jump table” that it will use for selecting the path of execution depending on the value of the expression. Therefore, if we need to select among a large group of values, a switch statement will run much faster than the equivalent logic coded using a sequence of if-elses.

• Speed: If a switch contains more than five items, it’s implemented using a lookup table or a hash list. This means that all items get the same access time, compared to a list of if:s where the last item takes much more time to reach as it has to evaluate every previous condition first.

Here we are having less than 5 case values where there is not much difference in speed between the switch statement and the if-else statement but we have preferred the use of switch statement for the purpose of extensibility

• Better Readability.

  1. We use if statement to check for null before entering the switch statement because switch(i) would throw a NullPointerException if i is null.

About

No description, website, or topics provided.

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages