In Traktor, I basically set one of the modifiers to be whether the decks are set to Upper or Lower. I use shift plus Up or Down arrow to switch between the two decks (and I also change the zoom level of the decks so that it shrinks the decks that aren’t being controlled). From there, I think duplicate every single mapping so that, if the modifier is set to Upper, then it affects the upper decks, if set to Lower then it affects the lower decks. It’s pretty straightforward from a technical perspective, just a lot of work to go through almost every single mapping to do it.
I found that VDJ had the appearance of greater flexibility, but when I started to dig into it, I found that it was too abstract – I didn’t have fine enough control over what I was mapping, which I didn’t care for.