I work on a software platform that is homegrown and, for the most part, used internally in the company but it is deployed in facilities across the globe.

This system runs on a specific set of hardware, and have many dependencies, they mostly fall into the following categories:

  1. OEM hardware drivers and libraries.
  2. Custom libraries.
  3. Local and network data stores.
  4. Custom embedded libraries running on hardware.

A team of at least 15 engineers are actively developing code that gets built as an integral part of the system.

This system has been released to users as a download from a git repo, then users would run it inside an IDE in debug mode.

There are no real software tests to run, only what the original developer deems necessary. There is no CI build system.

I recently read the Pragmatic Programmer book and it making issues in this system more pronounced to me. The worst problem I see in this system is that it is highly unorthogonal. Any slight modification would require a several other changes in different projects.

To me, this is overwhelming. So my question is: given such a complex system, how would one approach the problem of orthogonality?

  • 1
    Scrap the entire thing and start over now that you guys know what needs to be done... this seems nearly impossible to provide any sort of useful answer. TBH, I'm having a lot of trouble even imagining why having the end users run the app in a dev IDE is acceptable. However, I have no idea what the application does.
    – NotMe
    Commented Aug 31, 2017 at 19:34
  • 1
    Can you list why those slight modification make others changes in the project needed ? Copy/Paste domino's day ? Very tight dependencies in project that make any method's signature modification break others ? For each cause there is a different way to handle it. Copy/Paste must be handle by grouping common code in method. Tight dependencies by abstractions to froce decoupling.
    – Walfrat
    Commented Aug 31, 2017 at 19:34
  • 6
    Possible duplicate of I've inherited 200K lines of spaghetti code -- what now?
    – Doc Brown
    Commented Aug 31, 2017 at 19:43
  • 1
    @NotMe, scrapping the whole thing would require a huge buy-in from the rest of the team, which include the original architect. It is poised to be a political struggle which is risky. It was also a shock to my that the system is deployed in source when I started 4 years ago, and I brought it up several times, had heated discussions about it, but to no avail.
    – mbadawi23
    Commented Aug 31, 2017 at 19:44
  • @DocBrown, thank you for pointing that out, I'll take a look.
    – mbadawi23
    Commented Aug 31, 2017 at 19:49

1 Answer 1


Orthogonality refers to the different dimensions that are addressed by the components of the system. Typically, these dimensions will look something like: data storage, data processing (i.e., computing and updating), data presentation (GUI and reporting), communications (transport, synchronization), implementation (servers, workstations, end-user terminals) and so on.

Come up with a set of dimensions that represent your product. Each dimension will have a major characteristic as well as sub-dimensions, attributes that contribute to the overall dimension. For instance, communications as a dimension will have sub-dimensions of reliability, quality of service, speed, etc. Then, take the inventory of components that you hinted that you have, and produce an impact matrix -- for each component, what impact does it have on each dimension. A very good spreadsheet or set of spreadsheets can help you with this.

The impact that you provide in each cell identifies how effectively the component addresses that dimension, the costs and drawbacks.

Lack of orthogonality is indicated in such a matrix by smearing and clustering -- "smearing" occurs when some components tend to dominate multiple dimensions. "Clustering" occurs when multiple components address specific dimensions with significant overlap between components.

Data Storage Dimension Example

Let's use the "data storage" dimension, with sub-dimensions of "quantity", "speed of update", "speed of reading", "redundancy", " "ongoing deployment cost", and "flexibility" (just as a starter set). Let's use "local storage" and "network storage" as components.

For each sub-dimension we will provide a 0 to 10 figure of merit, with larger as better, a dimensionless number that we can use for comparison purposes. So, starting with "local storage":

  • "quantity" - 6 - individual computers are limited in space
  • "speed of update" - 9 (10 if using SSDs everywhere)
  • "speed of reading" - 9 (10 if using SSDs everywhere)
  • "redundancy" - 1
  • "ongoing deployment cost" - 6
  • "flexibility" - 6

Then for "network storage":

  • "quantity" - 10 - disk farms can be dynamically resized
  • "speed of update" - 4
  • "speed of reading" - 6 (depending on communications)
  • "redundancy" - 8-10 (depending on network storage implementation)
  • "ongoing deployment cost" - 9
  • "flexibility" - 5

I presume also that when you say "local storage" you mean that there are many local storage mechanisms being used. Each mechanism will count as a component and you need to evaluate them all.


Once you have this spreadsheet, you have a whole bunch of numbers on your hands and won't be sure what to do with them. There are a number of ways of looking at such a thing. You can treat it as a requirements assessment matrix, or you can create a heat map from it.

When you propose a solution, you should be able to produce a before and after impact matrix that allows you to describe the overall impact of your proposed improvements.

On the other hand, you may realize what the experts are already telling you, that the solution they have is "good enough".

  • This is so helpful, but how would I handle, for instance, a communication dimension for this system would imply different protocols, and parties involved in comm; whether to a material handler, a network location, or an automatic tester.
    – mbadawi23
    Commented Sep 1, 2017 at 0:53
  • Communication is often done through network stacks, a shorthand term meaning that a number of network protocols and capabilities are piled upon each other. The lower levels of the network stack are often taken for granted, or simply a given. However, if you have RS232 or USB comms, you will have to break them out and assess their impact separately. Also, upper levels like COM or CORBA will have to be seen as distinct components, as they have their own cost/benefits. Commented Sep 1, 2017 at 2:44
  • (cont) For an automatic tester that, let's say, only communicates using asynchronous RS422, you might break the comms into several steps: from the server to the terminal server, and from the terminal server to the tester. In one sense, the protocol for the automatic tester is fixed by choosing that model of tester, so you may be stuck. However, if you don't have a separate terminal server, you will start to see some ugly stuff that shows up on the back side of the server. Commented Sep 1, 2017 at 2:47

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.