There are plenty of things in math and physics (like special relativity or vector calculus) that seem hard but are in fact simple once you understand them. Then there are a other things, instead, that seem really simple, but they are actually hard.
I find that some software engineers and computer scientists have a superficial understanding of units and reference systems, and hold to some common but flawed ideas.
Units are symbols
In the simplest case, the unit is a symbol we stick after a number: 5 m, 3 s, 1 pound... But clearly that does not apply to everything, as in m/s for velocity or m/s2 for acceleration. Units are expressions.
So, if you store a unit in a string, that’s fine. If you compare that string to compare the unit, that’s not fine: “m^2” is the same as “m*m”, but they do not have the same string representation.
Different quantities have different physical dimensions
Two units that refer to the same physical quantity must have the same physical dimension: distance is [L], velocity is [L][T-1], and everybody learns to check their result using dimensional analysis. But the revers is not true: two units can have the same physical dimension and not refer to the same quantity. Energy density (energy per volume) and pressure (force per area) have the same physical dimension [M][L-1][T-2] but they may be not compatible. Summing the energy density of a battery with the pressure on the surface of such battery has very little physical meaning.
So, if you are writing classes for units to check that the number passed around your code have the right meaning, know that comparing the physical dimensions is necessary but not sufficient to make sure the input is valid. They actually have to refer to the same thing. For the same reason, you cannot simply convert everything that have the same physical dimension to the same unit: J/m^3 is not the same as Pa.
angles have a physical dimension of angles
Some people, carrying the previous misconception, feel that they must create another physical dimensions for angles, otherwise you would be able to sum angles to pure number. And that does not make sense! But as we have seen before, dimensional compatibility is necessary but not sufficient. So you can have quantities that have the same physical dimension but are not homogeneous.
An angle is the ratio between the circular arc within the two sides and the radius of such arch: [L] over [L] so it is a pure number. Angles are measured in units, such as radians and degrees. Pure number can have units. Among other units that dimensionless are the steradian (for solid angles) and the decibel (for ratios).
ANGLE times a LENGTH equal LENGTH
If you multiply an angle by a radius, you’ll get the length of the arc (according to the previous definition). So, you may conclude that angle times length equal length. But that’s true only if the length is the actual radius for that angle. For example: angle * radius * height gives me the area formed by the arc as the base and the height. Suppose I group angle * height: that’s not a length, because I am not getting the arc formed by the height and the angle. It’s angle times length. So, the result of angle times length depends on what you are doing.
Again, when you combine to quantities it matters what they are and how you are combining them. In general, you need to understand what’s going on. Force times length equal work only if that force and that length have a particular relationship between them. If you are trying to write a system that converts units “automatically”, you either need to make sure that it has enough information to understand the difference.
Knowing value and unit is enough to convert to a compatible unit
Again, this works in simple cases. What is 5 meters in millimeters? 5000. But if I asked you, what is 5 Kelvin in Celsius? That depends: is 5 K representing an absolute temperature or is it a difference between two temperatures? In the first case you will have -268.15 C while in the second you will have 5 C.
Temperature is the only example I know, because each unit really defines a scale with a reference point.
The component of a vectors are all of the same unit (or quantity)
If you use a Cartesian coordinate system, you are most likely to express all the components in the same unit (e.g. [1,2,3] m). You could also express them in different units (e.g. [1m, 2cm, 3Km]), but conceptually you could choose to make them uniform without loss of generality. But you may choose a spherical coordinate system, in which case you cannot express all the components with the same unit because they represent different quantities. A length in a spherical coordinate system is [length, angle, angle].
Different coordinate are in general expressed by different units and/or quantities. The type of quantity is given by the choice of actual coordinates that are used to identify the points in the space. If you define a vector class that has an array and only one unit, know that you’ll be able to only work in special cases.
A point is a vector
When someone learn the Cartesian reference system, one of the first thing that he is taught is to think as the set of coordinates used to specify the location of a point as a vector. And you can imaging this by drawing an arrow that starts from the origin and ends on the point. This actually is not strictly true, and it causes a lot of confusion. If you had the good fortune to learn generalized coordinate system, your confusion has been cleared. If you didn’t, you are confused and you may not realize it.
Imagine you have an actual vector, like a momentum, a force or an electric field. Imagine that you now apply a translation to your coordinate system: how does that affect the vectors? It doesn’t: they still point in the same direction, have the same magnitude, and have the same components on the axis. They just happen to be located at a different point. But what happens to the coordinate of a point? It changes by the amount of the translation.
For a deep understanding, you’ll need to learn generalized coordinates system (which is one of those things that is simple once you understand it). For the time being: do not use the same class for Point and Vector!
Given the components of a vector, you know the vector
A vector is identified by its magnitude and direction, so if I gave you its components in one reference system you’d expect you now know everything about that vector. This is true if you are in a Cartesian reference, but only there. If you use spherical coordinates, the first component of the vector is the component along the radial direction. That changes from point to point. You need to know at which point the coordinates are defined, because the 3 vectors that make up the basis can, in general, be different from point to point. In a Cartesian reference, they are the same.
A vector is magnitude and a direction defined at a point (it’s a “local” object). If you change coordinates, all vectors transform the same, but their transformation depends on the point where they are defined. Operations among vectors (like scalar of vector product) should also be done between vectors at the same point. If you have a Vector class, and you do no keep track the Point where the vector is defined, you’ll be able to only work in special cases.
Conclusion
As you can see, there aren’t very simple “mechanic” rules, that can be applied without understanding the semantic of what you are doing. Whatever tool you are going to use (or write) to help to keep track of units, it can’t be a substitute for your (or your users’) understanding.