I am a software developer with limited exposure to designing larger systems.

I am interested in determining some common techniques, maybe even common diagrams, to help me complete the design of a middle-tier notification system that will be used in an enterprise to route notifications to subscribers.

There are a number of technological constraints that we must follow as part of our organizations blueprint:

  1. Java technologies
  2. Oracle relational databases

We've agreed on a very high level architecture that defines the various services that will be involved, as well as their responsibilities.

We've also identified which of these will be REST, which will consume from a messaging system etc.

The logical next steps for me are as follows:

  1. Defining the API between each of these services
  2. Defining a high-level logical data model that will be used for the data requirements and relationships
  3. Defining the implementation details for each of these services in isolation
  4. Validating this architecture by explaining what will happen end-to-end for both simple and complex business requirements
  5. Validating this architecture by explaining how it can scale easily
  6. Validating this architecture by explaining how it will handle error scenarios such as failover
  7. Validating this architecture by explaining how various components can easily be tested and deployed

What other common techniques that I am missing could be employed here to architect such a system?

1 Answer 1


Overall, I believe the main thing you're missing is your methodology; in fact a lot of the considerations you're looking at really aren't solved by architecture - they're solved by the way you manage your project.

If this is the first time you've ever been responsible for designing a large system, then welcome to project management - because that's what this really is; a lot of 'good' architecture happens passively as a side-effect of a well-managed project, rather than a product of a carefully-planned up-front design.

  1. Defining the API between each of these services

While doing this, I'd strongly recommend focusing on your use cases, supported behaviours and responsibilities of the services they represent.

Most importantly, think very carefully about how each service will be tested. Defining tests for an interface (based on use cases/behaviours) is essentially a design activity which forces you to think about how those interfaces work.

Ideally your message/transport layer will already be in place to allow you to build a set of scripted tests to evolve those interfaces. (It doesn't matter if there's nothing listening to the interface, that bit happens later)

It's often much easier (and faster) to create a "stable" API when you've already defined a set of test cases for each bit of functionality exposed by that service. It will also make the implementer's life very easy too

Also don't forget to consider error handling in your API/Tests.

  1. Defining the implementation details for each of these services in isolation

I would advise against doing this. Focus on making sure each service has some clearly defined requirements, responsibilities and scripted tests instead; Your tests are your design tool, and will essentially drive the implementation (Which will probably look totally different at the end compared to whatever "whiteboard" UML diagram you might think of initially).

Implementation details of services and components are a very low-level concern, and really the last thing you need to be worrying about now; once the requirements and tests are in-place; the implementation details can be fluid and easily changed at any time. Chances are you will want to do a bunch of refactoring after code review anyway.

  1. Validating this architecture by explaining what will happen end-to-end for both simple and complex business requirements

While your business requirements will inform your decisions such as the entities/relationships in your Data Layer, and the different components/services you need in your system, each business requirement is (one or more) test cases; either for your system as a whole or for individual components.

It may be better to focus on ensuring as many of these requirements as possible are covered somewhere by your automated testing. The architecture itself shouldn't really care much about business (i.e domain) requirements. Your architecture is concerned with technical issues - e.g. hardware limitations, performance constraints, etc.

  1. Validating this architecture by explaining how various components can easily be tested and deployed

Deployment is certainly an important factor to consider (along with upgrades/rollbacks/etc.). Make sure you include schema versioning with your database otherwise upgrades and rollbacks for your schema will be ugly.

Again, testing and validation has more to do with your methodology. If you use the defined tests and test cases which isolate each module to design your software, then you already know your architecture is testable.

It would be more useful to think about your acceptance criteria - i.e. how do you prove that the delivered product meets its stakeholders' expectations? What level of testing constitutes "enough" for everybody to be confident in the system (and confident it can change without falling down like a game of Jenga)? These aren't really architecture concerns, but you need to think about them before you start writing any code.

Overall any architecture necessarily changes and evolves often over time. So long as you keep it "clean", and it meets your technical requirements related to hardware/performance/etc, then your architecture is not going to be a significant factor in the success or maintainability of your system.

(However, make sure you do include enough time to research and explore options with regards to technologies, patterns, etc. e.g. Consider existing messaging products for your message layer such as RabbitMQ/ActiveMQ/MSMQ/ZeroMQ/etc.)

People sometimes think of Software architecture in the same way as architecture of a building - but this is a flawed analogy because buildings, unlike software, do not change their size and shape much over time. At best, buildings may have interior walls changed, and the decor, furniture, etc - but the fundamental architecture and foundations of a building are necessarily rigid and hard to change.

Software changes a lot over time; which means that even some of your fundamentals will eventually change. Your biggest issue is how well equipped you are to cope wih that change. Do you have enough automated testing to cover regression issues? is your code sufficiently modular and decoupled? Do developers actually understand how to work in the code? is it SOLID and DRY?

Again, many of the considerations I believe you're missing are those related to project management - e.g. code reviews, CI/Build process, design reviews, pair programming, unit testing, knowledge-sharing among developers, and most importantly communication within the team.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.