<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Algorithm for Detecting Antipatterns in Microservices Pro jetcs</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>rigo Borg</string-name>
          <email>rodrigo.borges@tuni.fi</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Tampere University Tampere</institution>
          <country country="FI">Finland</country>
        </aff>
      </contrib-group>
      <abstract>
        <p>When migrating from a monolithic to a microservice-based architecture, one need to know patterns and antipatterns in order not to propagate old practices learned from centralized systems to a new structure where services are independent and distributed. We select 5 known antipatterns in microservices-based solutions and propose an algorithm for detecting them automatically. In a first round, all classes, methods and imports are registered and associated to its location in the source code. In a second round the usage of these resources is mapped and antipatterns are detected. The algorithm is also responsible for generating visual output of how resources are used in the project, so the developers can manage how resources are distributed in different files or concentrated in few ones. The solution can avoid common mistakes when deploying microservices-based projects and can help project managers to get an overview of the system as a whole. The algorithm is tested in a well-known open source project revealing possible improvements and resource allocation information.</p>
      </abstract>
      <kwd-group>
        <kwd>Microservices</kwd>
        <kwd>Monolithic</kwd>
        <kwd>Network Theory</kwd>
        <kwd>Antipatterns</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>-</title>
      <p>
        Microservices are now becoming a well known model for software engineers and
architect. It resembles divide and conquer approach in which a monolithic
software or system is decomposed into independent services 1. Currently,
microservices are adopted by big organizations such as Linked In, Amazon, Soundcloud
and Netflix. These microservices are small and autonomous services [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ]. All of
these services work together each of which has a clear define goal [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ].
      </p>
      <p>
        The monolithic software are being in use since computers are introduced.
These software are not only specific for a single task but perform each and
every step required for a particular function. In these type of applications the
developers have a broad access to a source code. In addition, all the dependencies
that are common have a single set. In short monolithic applications are adopted
because of [
        <xref ref-type="bibr" rid="ref5">5</xref>
        ]:
– Standardization: The engineers or developers are governed how to interact
with the code using a shared set of tools. Such as reviewing the code, building
and testing the code etc.
– Visibility: The code for monolithic softwares is available to all the developers
working in a team. Every one can see the work done by the rest of team
members.
– Completeness: A whole project can be built from a single repository using
all of its dependencies.
– Centralization: One single repository for the whole code is available.
– Synchronization: The team works and all the commits made are
synchronized.
      </p>
      <p>
        Google still uses this monolithic architecture in which the whole code for the
project is available in one single repository. This code is accessible by 20,000
engineers and consist of 2 billion lines of code [5, ?]. However, Monolithic
applications are hard to scale up both organizationally and technologically as the
whole team works on the same code stored in same database. The problem with
these application is, a small change in any part might have impact on the other
parts2. The redeployment of such application can take hours. Sometime for new
developers, go through the whole code is not an easy task. In short, Monolithic
applications are expensive, slower and even difficult for new developers to
understand the whole code[
        <xref ref-type="bibr" rid="ref2">2</xref>
        ].
      </p>
      <p>
        In order to improve the design and architect various principles are adopted.
The earliest principles being adopted are Information hiding [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ],
encapsulation [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ], separation of concerns [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ], modularity [
        <xref ref-type="bibr" rid="ref17">17</xref>
        ], service oriented
architecture [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] and then microservices.
      </p>
      <p>
        Now migrating from monolithic to microservices, one cannot only face certain
technology related issues but issues related to processes, strategy and
organization. There are problems while migrating for which a solution is available, but
that solution does not work well in these circumstances. 3. The reuse of a
software is a productive technique, having mixed success. There are a number of
anti patterns emerge while analyzing the reusability failure [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ]. In paper [
        <xref ref-type="bibr" rid="ref15">15</xref>
        ],
the authors focused on the architectural pattern of microservices. They identify
a number of agreed microservices architectural patterns. In a number of case
studies these microservices architectural patterns are adopted and reported.
      </p>
      <p>Some of the well known anti patterns are: 4
– Everything Micro: Among the common anti patterns is everything micro.</p>
      <p>This type of anti pattern is common to enterprise organization. In this case
one huge data store is available for all the microservices. The main challenge
with this type of anti-pattern is keeping track of the data.</p>
    </sec>
    <sec id="sec-2">
      <title>2 https://itnext.io/anti-patterns-of-microservices-6e802553bd46</title>
      <p>3
https://microservices.io/microservices/antipatterns/-/the/series/2019/06/18/microservicesadoption-antipatterns.html
4 https://dzone.com/articles/microservices-anti-patterns
– Break the Piggy Bank: Another most common anti pattern is break the
piggy bank. When an existing application is refactoring to microservices.</p>
      <p>The refactoring is risky and can take several hours if not days.
– We are Agile: Shifting from waterfall software development to agile software
development. Initially, the team start implementing a small initial version
of agile-fall. In this type, it is just like merging parts together that become
worst after time.</p>
      <p>The text is structured as follows. In a first section, we present the selected
anti-patterns to be detected, and a short description of how the algorithm was
implemented to detect them. In the following one, we present a methodology
for retrieving a general structure of a microservice-based project in terms of
resources, and bring two metrics for measuring closeness and betweenness of
complex networks. We then present a case study, applying the algorithm to an
open source project, pointing out its anti-patterns and a general description. We
conclude by evaluating the proposition and proposing some future work.
2</p>
      <sec id="sec-2-1">
        <title>Anti-patterns</title>
        <p>
          We have selected some of the anti-patterns from an online list5.
– Ambiguous Service - It refers to the situation when microservices interface
elements are named inappropriately [
          <xref ref-type="bibr" rid="ref10 ref11 ref9">10, 9, 11</xref>
          ]. It can occur that an
operation gets to be called with a too long name, or general messages with unclear
or ambiguous names. In these cases a threshold can be set for defining the
maximum length of elements, and certain terms can be considered as
inappropriate for a specific context.
– API Versioning - It can happen that a request to an external service is
updated in the code, and that the new call points to a newer version of the
API. This can promote lack of resources for the subsequent operations that
depend on this data. This is why API needs semantically consistent versions
descriptions (e.g. v1.1, v1.2), so developers have control of the content they
dealing with [
          <xref ref-type="bibr" rid="ref14">14</xref>
          ]. Detecting bad named API versions can be quite
challenging, since bad choices can have any format. We propose a simple solution
that can be further developed in future works.
– Hard-Coded Endpoints - IPs addresses and ports may be hard-coded for
each service [
          <xref ref-type="bibr" rid="ref14">14</xref>
          ], and this might provoke similar problems than the ones
described previously. IP addresses can change from time to time, specially
if they are defined dynamically by the hosting service, and fixing it would
require entering files and changing it one by one. In the present work we are
simply detected hard-coded IP addresses without going any further on the
analysis of the context it is happening.
– Bottleneck Service - A service consist of many consumers and one point
of failure [
          <xref ref-type="bibr" rid="ref11 ref8">8, 11</xref>
          ]. As this service is used by a large number of other clients
        </p>
      </sec>
    </sec>
    <sec id="sec-3">
      <title>5 https://xjreb.github.io/service-based-antipatterns/</title>
      <p>
        and services hence the incoming as well as the outgoing coupling is high for
bottleneck services. In addition, due to large number of external clients the
response time is also high. Consequently, due to huge traffic the availability
of these services is also low6. We propose detecting it by mapping the number
of different contexts in which the same service is requested.
– Bloated Service - A service having one large interface which consist of many
datatype parameters. All of them perform different operation with
cohesion [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ]. The output for this type of services are having less reusability,
testability and maintainability in other business processes7. In order to
detect it, the algorithm proposed here should check services definition and set
threshold for the number of types and parameters.
– Cyclic Dependency - A never ending cycle exist between the services. [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ].
– Service Chain - It is also known as message chain. A chain of services that
are reserved for one common functionality. When a client want to achieve
his goal by requesting a number of consecutive services this chain appears8.
[
        <xref ref-type="bibr" rid="ref6 ref8">8, 6</xref>
        ]
– Shared Persistency - One database is shared for multiple services. [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ]
– Stovepipe Service - Some of the functionalities are duplicated in on several
services [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ]. In this type of antipatterns a large number of protected and
private methods are available that perform utility, infrastructure and business
processes instead of focusing on the main goal 9.
– The Knot - This type of antipattern consist of a set of low cohesive
services. All of these low cohesive services are tightly coupled due to which
its reusability is very limited. These type of anti patterns have a complex
infrastructure due to which its availability is low have high response time10.
[
        <xref ref-type="bibr" rid="ref11 ref12 ref8">12, 8, 11</xref>
        ]
3
      </p>
      <sec id="sec-3-1">
        <title>General Structure</title>
        <p>Apart of detecting anti-patterns, we propose a methodology for retrieving the
general structure of the project in terms of resources. A good solution should
distribute resources along different files (library imports, method calls, etc.). In
order to achieve this, we have modeled the project as a complex network, in
which resources are represented by nodes and the paths by their usage.</p>
        <p>A general description of the network is given by two metrics, Closeness and
Betweenness:
Closeness Centrality (C) of a node in the network is the reciprocal of the
sum of the shortest path distances relative to all other nodes.
6 http://sofa.uqam.ca/resources/antipatterns.php#Bottleneck%20Service
7 http://sofa.uqam.ca/resources/antipatterns.php#Bloated%20Service
8 http://sofa.uqam.ca/resources/antipatterns.php#Service%20Chain
9 http://sofa.uqam.ca/resources/antipatterns.php
10 http://sofa.uqam.ca/resources/antipatterns.php</p>
        <p>C(u) =</p>
        <p>n − 1
vn=−11 d(v, u)
(1)
(2)</p>
        <p>The d(v, u) is the shortest path between v and u and n is the number of nodes
in the graph. High values for closeness represent central nodes in the network.
Betweenness Centrality (B) is the measure of the centrality of a node in a
network, and can be calculated as the proportion of shortest path between node
pairs that pass thought one node of interest.</p>
        <p>CB(v) =</p>
        <p>s∕=t∕=v∈V
αst(v)
αst
αst is the number of shortest paths from s to t, and αst(v) is the number of
shortest paths from s to t that pass through node v. Nodes with high betweenness
centrality are central in the network and attract the information flow.
4</p>
      </sec>
      <sec id="sec-3-2">
        <title>Case Study</title>
        <p>As a case study, we analyzed Spinnaker project source code11 for detecting the
selected anti-patterns and retrieve its general structure. We assume services
implemented as classes and a handcrafted set of words as forbidden for being used as
class or method names. The code is available for reproducing the experiment12.</p>
        <p>In a first round, the proposed algorithm iterates through every file inside the
project folder for detecting classes and imports names (in this case it is adjusted
for detecting only .py files). In a second round it applies a regular expression for
detecting occurrence of classes and its methods along the project and store all
occurrences in a dataframe. We differentiate between methods declared inside
classes from the ones declared outside. This provide sufficient information for
evaluating services independently.</p>
        <p>We have detected 3 hard-coded IP addresses and 82 version numbers. The
project imports 86 different libraries, as showed in Figure 2 . We have detected
three methods named as delete, now and run, considered as inappropriate.</p>
        <p>We set the maximun size of a class name as 30, as well as for methods, for
considering it too long. We have detected 3 methods and 13 classes with too longs
names. An example of a method name is determine subprocess outcome labels,
and of class name GcsArtifactStorageConfiguratorHelper. We argue that a name
with 30 characters long is not exactly big, but was selected as a threshold here
as an example.</p>
        <p>We count the number of parameters for each method for detecting too big
interfaces (it was not possible to detect how many types in the case of python
language). We set 5 arguments as the maximun allowed, and detected only one
method, names start subprocess.
11 https://github.com/spinnaker/spinnaker
12 https://github.com/rcaborges/microservices-antipatterns</p>
        <p>As the last anti-pattern, we detect methods and classes instantiated from too
many files. We set a threshold of 30 as a big number of files, and found 35 files
associated to a method called init argument
parser, 61 files associated to a class named ConfigError, and 31 files associated
to UnexpectedError.</p>
        <p>Regarding the general structure of the project in terms of resources, we build
a network out of the information acquired in the previous phase. Each node
represent one specific resource, ex. classes, and the connection between nodes
are formed when two files use the same resource, ex. instantiate the same class.</p>
        <p>Figure 1 show with logarithmic scale the fraction of nodes for each value of
degree for the case of classes declared inside the project. Few classes were found
in too many files, and most of them were detected in one single file. The shape
of the curve indicates regular distribution along the files in the project.</p>
        <p>Another information about the general structure of the project that may
help project managers are the closeness and betweennes of the resources in the
project. High values of closeness indicate resources that are close to others, and
high values of betweenness represent resources used by too many files, located
in the center of the network.</p>
        <p>ConfigError was detected as having highest closeness and betweenness, and
seems to be a widely used class along the project. Resources with high values of
betweenness represent high risk, once it is central to the project and its failure
would impact great part of the system. It is worth mentioning that most of
top 10 closeness indexes are configuration classes that need to operate in many
different contexts inside the project.</p>
        <p>Figure 2 shows the visualization of both networks, imports and classes, as
described earlier. It is possible to notice that libraries are imported from quite
many files inside the source code. Classes, on the other hand, show a more sparse
usage among the files, as expected for a good microservice architecture.
5</p>
      </sec>
      <sec id="sec-3-3">
        <title>Conclusions</title>
        <p>An algorithm was presented for detecting anti-patterns in microservices based
solutions. We have selected 5 anti-patterns and tried to detect them
automatically in order to avoid potential failure points when migrating from monolithic
architectures. We have also proposed a framework for describing the general
structure of the project in terms of resource consumption, which should help
project managers with a general overview.</p>
        <p>We still need to consider the situations where classes are imported with
different names, in this case there should be a proxy for considering extra calls
for the original class.</p>
        <p>We have simply detected IP addresses and version numbers, without
providing any further analysis of the context these are happening. As a future work we
plan to improve the algorithm so it can differentiate, for example, a request from
a declaration of an IP address, or keep track of version numbers for suggesting
consistency.</p>
      </sec>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <string-name>
            <surname>Arsanjani</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          :
          <article-title>Service-oriented modeling and architecture</article-title>
          .
          <source>IBM developer works 1</source>
          ,
          <issue>15</issue>
          (
          <year>2004</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <surname>Bennett</surname>
            ,
            <given-names>K.H.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Rajlich</surname>
          </string-name>
          , V.T.:
          <article-title>Software maintenance and evolution: a roadmap</article-title>
          .
          <source>In: Proceedings of the Conference on the Future of Software Engineering</source>
          . pp.
          <fpage>73</fpage>
          -
          <lpage>87</lpage>
          . ACM (
          <year>2000</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <surname>De Win</surname>
            ,
            <given-names>B.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Piessens</surname>
            ,
            <given-names>F.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Joosen</surname>
            ,
            <given-names>W.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Verhanneman</surname>
            ,
            <given-names>T.</given-names>
          </string-name>
          :
          <article-title>On the importance of the separation-of-concerns principle in secure software engineering</article-title>
          . In: Workshop on the Application of Engineering Principles to System Security Design. pp.
          <fpage>1</fpage>
          -
          <lpage>10</lpage>
          (
          <year>2002</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <string-name>
            <surname>Girard</surname>
            ,
            <given-names>J.F.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Koschke</surname>
          </string-name>
          , R.:
          <article-title>Finding components in a hierarchy of modules: a step towards architectural understanding</article-title>
          .
          <source>In: 1997 Proceedings International Conference on Software Maintenance</source>
          . pp.
          <fpage>58</fpage>
          -
          <lpage>65</lpage>
          . IEEE (
          <year>1997</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          5.
          <string-name>
            <surname>Jaspan</surname>
            ,
            <given-names>C.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Jorde</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Knight</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Sadowski</surname>
            ,
            <given-names>C.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Smith</surname>
            ,
            <given-names>E.K.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Winter</surname>
            ,
            <given-names>C.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>MurphyHill</surname>
          </string-name>
          , E.:
          <article-title>Advantages and disadvantages of a monolithic repository: a case study at google</article-title>
          .
          <source>In: Proceedings of the 40th International Conference on Software Engineering: Software Engineering in Practice</source>
          . pp.
          <fpage>225</fpage>
          -
          <lpage>234</lpage>
          . ACM (
          <year>2018</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          6.
          <string-name>
            <surname>Jones</surname>
            ,
            <given-names>S.:</given-names>
          </string-name>
          <article-title>SOA anti-patterns (</article-title>
          <year>2006</year>
          ), https://www.infoq.com/articles/SOA-antipatterns
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          7.
          <string-name>
            <surname>Long</surname>
          </string-name>
          , J.:
          <article-title>Software reuse antipatterns-revisited</article-title>
          .
          <source>Software Quality Professional</source>
          <volume>19</volume>
          (
          <issue>4</issue>
          ) (
          <year>2017</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          8.
          <string-name>
            <surname>Nayrolles</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Moha</surname>
            ,
            <given-names>N.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Valtchev</surname>
            ,
            <given-names>P.</given-names>
          </string-name>
          :
          <article-title>Improving soa antipatterns detection in service based systems by mining execution traces</article-title>
          . pp.
          <fpage>321</fpage>
          -
          <lpage>330</lpage>
          (
          <year>2013</year>
          ). https://doi.org/10.1109/WCRE.
          <year>2013</year>
          .6671307
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          9.
          <string-name>
            <surname>Ouni</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Kessentini</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Inoue</surname>
            ,
            <given-names>K.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Cinnide</surname>
            ,
            <given-names>M..</given-names>
          </string-name>
          <article-title>: Search-based web service antipatterns detection</article-title>
          .
          <source>IEEE Transactions on Services Computing</source>
          <volume>10</volume>
          (
          <issue>4</issue>
          ),
          <fpage>603</fpage>
          -
          <lpage>617</lpage>
          (7
          <year>2017</year>
          ). https://doi.org/10.1109/TSC.
          <year>2015</year>
          .2502595
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          10.
          <string-name>
            <surname>Palma</surname>
            ,
            <given-names>F.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Moha</surname>
            ,
            <given-names>N.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Tremblay</surname>
            ,
            <given-names>G.</given-names>
          </string-name>
          , Gu´eh´eneuc, Y.G.:
          <article-title>Specification and detection of soa antipatterns in web services</article-title>
          .
          <source>Lecture Notes in Computer Science (including subseries Lecture Notes in Artificial Intelligence and Lecture Notes in Bioinformatics)</source>
          <volume>8627</volume>
          ,
          <fpage>58</fpage>
          -
          <lpage>73</lpage>
          (
          <year>2014</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          11.
          <string-name>
            <surname>Palma</surname>
            ,
            <given-names>F.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Mohay</surname>
          </string-name>
          , N.:
          <article-title>A study on the taxonomy of service antipatterns</article-title>
          . pp.
          <fpage>5</fpage>
          -
          <lpage>8</lpage>
          (
          <year>2015</year>
          ). https://doi.org/10.1109/PPAP.
          <year>2015</year>
          .7076848
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          12.
          <string-name>
            <surname>Rotem-Gal-Oz</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Bruno</surname>
            ,
            <given-names>E.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Dahan</surname>
            ,
            <given-names>U.</given-names>
          </string-name>
          :
          <article-title>SOA patterns</article-title>
          .
          <source>Manning</source>
          (
          <year>2012</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          13.
          <string-name>
            <surname>Sharma</surname>
            ,
            <given-names>T.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Samarthyam</surname>
            ,
            <given-names>G.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Suryanarayana</surname>
          </string-name>
          , G.:
          <article-title>Applying design principles in practice</article-title>
          .
          <source>In: Proceedings of the 8th India Software Engineering Conference</source>
          . pp.
          <fpage>200</fpage>
          -
          <lpage>201</lpage>
          . ACM (
          <year>2015</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          14.
          <string-name>
            <surname>Taibi</surname>
            ,
            <given-names>D.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Lenarduzzi</surname>
          </string-name>
          , V.:
          <article-title>On the definition of microservice bad smells</article-title>
          .
          <source>IEEE software 35(3)</source>
          ,
          <fpage>56</fpage>
          -
          <lpage>62</lpage>
          (
          <year>2018</year>
          ). https://doi.org/10.1109/ms.
          <year>2018</year>
          .2141031
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          15.
          <string-name>
            <surname>Taibi</surname>
            ,
            <given-names>D.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Lenarduzzi</surname>
            ,
            <given-names>V.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Pahl</surname>
            ,
            <given-names>C.</given-names>
          </string-name>
          :
          <article-title>Architectural patterns for microservices: A systematic mapping study</article-title>
          .
          <source>In: CLOSER</source>
          (
          <year>2018</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          16.
          <string-name>
            <surname>Taibi</surname>
            ,
            <given-names>D.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Lenarduzzi</surname>
            ,
            <given-names>V.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Pahl</surname>
            ,
            <given-names>C.</given-names>
          </string-name>
          :
          <article-title>Continuous architecting with microservices and devops: A systematic mapping study</article-title>
          . In: Mun˜oz,
          <string-name>
            <given-names>V.M.</given-names>
            ,
            <surname>Ferguson</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            ,
            <surname>Helfert</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            ,
            <surname>Pahl</surname>
          </string-name>
          , C. (eds.)
          <source>Cloud Computing and Services Science</source>
          . pp.
          <fpage>126</fpage>
          -
          <lpage>151</lpage>
          . Springer International Publishing,
          <string-name>
            <surname>Cham</surname>
          </string-name>
          (
          <year>2019</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          17.
          <string-name>
            <surname>Wieringa</surname>
          </string-name>
          , R.:
          <article-title>Traceability and modularity in software design</article-title>
          .
          <source>In: Proceedings Ninth International Workshop on Software Specification and Design</source>
          . pp.
          <fpage>87</fpage>
          -
          <lpage>95</lpage>
          . IEEE (
          <year>1998</year>
          )
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>