Demystifying software architecture for the junior developer

Innocent Amadi
Apr 19, 2017 · 8 min read

You have an idea. Yes!

Your big idea - Help dog owners buy the dream collar. No, not the dog’s dream, the owner’s :)

As a software developer, it’s time to put your skills to use. The sooner you’re able to develop a working software solution, the happier the world will be.

The next step should be firing up your editor to start churning out code right?

Of course! As soon as you answer a few questions:

What would you like your users to do?

Easy. I want to help dog owners buy the dream collar for their dogs.

What roles might your software need to perform to help users in the way you intend?

Keeping it simple here, the software should:

  • allow different vendors upload pictures of different dog collars so users can buy their choice.
  • allow potential customers see and buy what’s being sold.
  • allow admins monitor what’s being sold.

How complex are the roles you just defined? Can they be broken down into smaller chunks?

Taking a closer look, “allow different vendors put up pictures of different dog collars” could be broken down into:

  • allow vendors register.
  • allow registered vendors put up details of dog collars they have in stock.

Similarly, “users can buy their choice” could be:

  • allow visitors sign up/login as users so they can make purchases.
  • allow users add a selected item to their cart.

The software should allow administrators monitor what’s being sold” could also could be decomposed into:

  • users can sign in as admin.
  • admins can view an admin dashboard that shows basic statistics of what’s being sold.

Now can you confidently represent these features in your software? Sure! Admins, vendors and users can be treated as different classes that will…

Wait …

What will these classes do?

How do they depend on each other?

Why aren’t they modules? Or a bunch of functions in one huge class?

How will your database be modeled? What relationships will need to be defined?

How heavy do you expect the application to be? What computing power will the server need? Private servers or cloud?

The list goes on ….

Ah. We’ve hit a point where you pause on your editor and look up. Maybe whip out a jotter. There are some decisions to be made. Some requirements to be defined. Some structures that need to be put in place to meet defined requirements.

When you catch yourself trying to figure out the answer to all these prerequisite questions, you are already architecting software.

Software architecture is the process of defining a structured solution that meets all the technical and business needs of an application, while optimizing common attributes like performance, security and manageability.”

— Software development and design, Microsoft Developer Network

Put more straightforward, Software architecture encompasses all the important decisions made when a software solution is being organized. Naturally, these decisions would include:

  • The structural elements (modules and/or classes)
  • Relationships between elements
  • Relationships between elements in one or more external environments

1. The structural elements

If you are building a software solution to sell dog collars, then different roles of the software might be:

  • Admin Management System
  • Authentication system (to distinguish between admins, vendors and customers)
  • Store content management systems (to enable vendors manage offerings)
  • Purchasing system (that helps users actually buy stuff)

Again, this is keeping it as simple as we possibly can.

If you can successfully break down the system to be built into different roles like this, then each role can be a class or a module assigned a specific responsibility (students admissions module concerned with only students admissions).

When building software systems, it is important to have this logical breakdown of roles into modules. If a module is too large, it can be further broken down into smaller compositions.

But how will you know when a module is too large?

Simple. Repeat the process you used to identify that the module needs to be created in the first place. What roles can be found within the module?

For example, a typical purchasing process usually involves users adding items to their cart, inspecting their cart and bill and then proceeding to checkout and pay for items in their cart. So within the ‘Purchasing system’, we could have:

  • Cart Management system
  • Billing systems (to handle billings and invoices)
  • Checkout systems (to handle payments or third party payment platform integration)

How do you know when to stop the breakdown process?

When a module becomes specific enough.

The Cart Management System will be concerned with creating a cart, adding and removing items from it, and keeping track of its content. That’s all. Sounds specific enough to me.

2. Relationship between elements

Now you have tiny building blocks all culminating to one giant system. Time to start implementing right? Wrong.

You need to define how the amazing modules and classes you have already defined will inter-relate.

I don’t know if there are existing formulas for doing this. When I get to this stage, I just look at each module or class and ask it:

  1. What would other modules or classes need from you? (interfaces)
  2. What would you need from other modules? (dependencies)

Defining interfaces

Interfaces are the connectors or plugs exposed by an entity (module or class) so other entities can interact with it. More popularly called APIs (application programming interfaces).

With our Cart Management System, we will need to create a new cart, add items to the cart, remove items from the cart and view items in the cart. This implies we need to have interfaces we can call to ask the Cart MS to do these operations for us.

Typed languages refer to these interfaces as public methods or functions. Our Cart MS could look like:

Cart MS

  • create_cart
  • add_item
  • delete_item
  • view_items

We’ve defined how to talk to our Cart, but who does it need to talk to? What external data does it need?

When understanding the relationship between entities, defining interfaces is the first step. We also need to document dependencies and how to access them.

Documenting dependencies

Would this module need most or some functionality in other modules? If it does, what is the best way to make this functionality accessible? Should it inherit, use an adapter or some other design pattern? Is the library external? Is it sharing any data?

Back to our Cart MS. Our solution for carts will need to know some detail about an item it is adding. Maybe an item_id will do. We can always look up other item details through the id.

Or can we?

What if item prices change while the user is still in the middle of a purchase? Two choices here — we might want to bill the user the new price, or allow them buy with the price they met. Whichever approach we choose will affect if we store price details with the items in our cart or not.

Quite explicitly, whether you do

items = [2, 4, 5]

or

items = [ {id: 2, price: 300}, {id: 4, price: 230}, {id: 5, price: 70} ]

Will depend on how much detail you will really need from a business standpoint.

Relationships between elements in one or more external environments

Now we’re talking both external APIs and DevOps.

External APIs

For our Checkout System, let’s assume we agree that asking users to give us their credit card information is not something we would want to do. We would rather use PayPal or Stripe.

We really can’t go ahead and plan out the Checkout system without first understanding how it’s going to interact with PayPal. What APIs does PayPal expose to developers? How is the data structure of the response sent back?

DevOps

Here’s an ideal setup: You (and your team) make a change to a version controlled source code. You push the code, compare with existing changes and merge in the new changes. Automatically, tests are run, lints (rules surrounding code style) are checked, the code is compiled/built and then deployed.

That’s continuous integration. DevOps encourages automation of the change, configuration, and deploy processes. But there’s more to it.

Let’s talk servers.

Which environment will you be hosting in? Something close to your development environment? Or something suitable for the kind of software you will be writing?

How much memory will the server need (RAM and Hard disk)? How much processing power will be sufficient?

How many users can you expect in the best case scenario or your peak periods? Might you need to scale up vertically (add more hardware to the server) and/or horizontally (add more servers)? How often do you need to scale?

Might it be valuable if your servers are elastic too? In other words, should they be added on the fly and decommissioned when requests drop?

Deeper still: How many dynos (or it’s equivalent in non-linux servers) will you need? What processes might your software start to run effectively?

Okay, yeah. DevOps is usually the scary conversation. The good news? You don’t need to figure everything out to start. God bless Platforms as a Service (PaaS) like Heroku that enable developers to build, run, and operate applications entirely in the cloud. So you really don’t need to think about all the hard details. Just spin up a free Heroku instance by creating a new app, and you’re a DevOps pro :)

Conclusion

Building software is an art. An artist prepares his canvas, paint brushes, color palettes and state of mind (at least) before touching brush on paint.

Thinking about software architecture is a step more experienced developers have learnt to embed from the beginning of a software project. It sometimes seem more tempting to just jump in, but planning a bigger picture always saves you from needless back and forth as you progress.

That said, planning architecture is not an excuse to sit forever in the analysis room. Agile methodologies require that you plan out only as much as you need to get started, and then continue the process through the software development life cycle.

Was this helpful? Hit the 💚 to help others find it too :)

Have you approached software solutions differently or in a similar fashion? Do let me know in the comments section. I’ld love to hear 🙂

Thanks to Munachimso Ugorji and Mohini Ufeli

Innocent Amadi

Written by

Software Engineer at Andela and HappyMoney, Lead at Facebook Developers Circle Lagos and Teencode Africa. @tru2cent on twitter

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade