There are two general mindsets about type notation in programming languages.
Declare it like you use it (or: variable-centric)
C and many C-style languages do this.
For example, reading from left to right:
int test; means that you will get an
int if on
test you access an index less than
int arr; means that you will get an
int if on
arr you access an index less than
4, and then access an index less than
As you can see, the type declaration resembles the way you would use it.
Solidity and many other modern languages use this.
With this system, the type is completely separated from the variable name. If you see
 in a type declaration, the type before the
 is always the type of the array elements.
For example, reading from right to left:
uint256 test; means that
test is an array of
3 elements, where each element is a
uint256 arr; means that
arr is an array of
10 elements, where each element is an array of
4 elements, where each element is a
When accessing it, the indices you are accessing are reversed because you are 'unpacking' the nested type. For example:
arr will be an array of
Both notations have their merits. I personally find nested notation easier to read. Nested notation is often much friendlier towards function pointers, with the disadvantage of the array indices being in opposite order with respect to the array sizes in the type declaration. Also, nested notation is much friendlier towards the
mapping data type of Solidity.
There are many forums online full of people debating this. In the end, when designing a language you just have to pick one and stay consistent. There are always going to be programmers coming from one world and getting confused by the notation in the other world.