Cross-functional teams are groups of people from different departments within an organization who collaborate to achieve a common goal. They are frequently formed to complete a specific project but can also be formed with a longer-term goal in mind. Working with members with different perspectives, expertise, and backgrounds allows the collective team to tackle problems and achieve project goals more efficiently. Moreover, teams can also anticipate roadblocks earlier in the process because each department has input instead of a project moving from department to department.
Cross-functional teams in a particular organization can be built around its microservices or business features. In this post, we will compare both of these options. So let’s dive in!
What Are the Benefits of Cross Functional Teams?
Before getting into any technicalities, one should know the general advantages of cross-functional teams:
- Leads to a collaborative culture: Cross-functional teamwork naturally creates a collaborative culture because it gets more team members working together, regardless of their department.
- Team members learn from one another: Cross-functional teamwork also enables team members to learn about the various tools used by other departments and determine whether or not they can benefit from incorporating them into their work.
- Fosters Employee Engagement: When cross-functional teams collaborate, they feel more connected, especially across departments. Moreover, when team members feel connected, have common goals, and trust one another, they are better at problem-solving and conflict resolution.
- Enhances leadership skills: It is possible to experiment with different team members in leadership roles to see how they perform and thrive.
- Teamwork keeps work interesting: Cross-functional teams are stimulating simply because they disrupt the status quo and allow for the flow of innovative ideas in a diverse group.
- Enhanced Productivity: Cross-functional teamwork allows different departments to share their best practices while collaborating toward a common goal.
What is a Microservice?
For future discussion, you should also have basic knowledge of microservices.
Microservices, also known as microservices architecture, is a method of building large applications out of smaller, modular components or services. Each module supports a particular task or business objective and interacts with other services using a clear, straightforward interface, such as an application programming interface (API).
With that in mind, it is quite easy to set up microservices in Ruby. Again, we can take inspiration from online resources with thousands of online templates.
Let us create a microservice whose responsibility it is to send mail and gets a message such as this:
{
'provider': 'mandrill',
'template': 'invoice',
'from': '',
'to': '',
'replacements': {
'salutation': 'Jack',
'year': '2016'
}
}
Moreover, we want it to be aware that it needs to change a few variables before sending the invoice email template to . For this, we will be using the mandrill API. Its small, focused piece of functionality and well-defined interface makes it the ideal candidate for a microservice.
Now, we need a way to communicate with the microservice. We can use a message queue to help us out. For this article, RabbitMQ will be used.
With RabbitMQ, adding a message to a queue is simple and looks like this:
require 'bunny'
require 'json'
connection = Bunny.new
connection.start
channel = connection.create_channel
queue = channel.queue 'mails', durable: true
json = { ... }.to_json
queue.publish json
connection.close
bunny is the official RabbitMQ gem. So when we don’t pass any arguments to Bunny.new, it will simply run on localhost:5672 with the default credentials:
Now that we’ve covered the producer side, we still need an application that takes and processes the message. For that, we used sneakers, a wrapper gem around RabbitMQ.
With sneakers (which is heavily inspired by sidekiq), we can define a “worker” to process our mail-sending requests:
require 'sneakers'
require 'json'
require 'mandrill_api/provider'
class Mailer
include Sneakers::Worker
from_queue 'mails'
def work(message)
puts "RECEIVED: #{message}"
option = JSON.parse(message)
MandrillApi::Provider.new.deliver(options)
ack!
end
end
The work method will consume the message after we specify the queue (“mails”) from which we’re reading. RabbitMQ or sneakers couldn’t care less about your choice; we just parse the message, which we know is JSON because that’s what we previously agreed upon. We then pass the message hash to an internal class that performs the necessary work. Finally, the message must be acknowledged for RabbitMQ to remove it from the queue. We also added some logging to keep track of what was happening.
However, one class does not make an entire microservice, so we will have to do an entire project around this. But overall, this example helps cover the basics of creating your own microservice in Ruby.
Cross-functional Teams Revolving Around Microservices Versus Business Features
Above all, microservices should enable you to move as quickly as possible. They should be easy to replace, quick to scale, and fault-tolerant.
Teams working in silos devote weeks to iterations. Manual tests must be run concurrently for all services because the teams create tightly coupled services. The tests frequently last weeks, so this is by no means moving quickly.
Moreover, teams can be structured around a single business goal and concentrate on continuous delivery when developing microservices to avoid lengthy test phases.
Everyone involved in the delivery process needs to work in a collaborative environment to accomplish this. The first step toward having cross-functional teams in this environment. It means combining the development, operations, testing, and architects teams into a single cross-functional team. This way, teams can deliver services frequently instead of passing projects back and forth until they receive the required feedback.
However, product companies can make cross-functional teams according to their business features. For example, one business feature could consist of many microservices, or one microservice could cover several similar business features. To clarify, you can take the personal suggestions feature of Netflix as a business feature.
Netflix employs cross-functional teams that are highly aligned but loosely coupled. The company established goals that were clear, specific, and widely understood. Interactions between teams are centered on strategy and objectives rather than tactics. Although transparency necessitates a significant investment in management time, Netflix believes it is worthwhile.
Nevertheless, cross-functional teams around business features introduce complexity to the company. A team based on business roles requires a high level of communication between Teams of UI developers, Middleware devs, and DBAs, which may become overwhelming and is reflected in the product itself.
No matter how often developers meet or check their Slack, life becomes complicated, and finishing integration in a single Sprint may become challenging.
Final Thoughts
Overall, after some comparisons, it seems that the best option for companies in most cases is a domain-driven design leading to microservices and a cross-functional team around that. Domain-driven design (DDD) is a software engineering approach to solving a specific domain model. The solution circles around the business model by connecting execution to the key business principles. So DDD covers business features and narrows them down to build microservices on them.
Conclusively, companies should be urged to follow DDD as its four primary principles are: an emphasis on business value, cross-functional collaboration, and a focus on the big picture, all while employing software best practices.