NameMapping is not impossible to circumvent... but something to keep in mind is that the properties that TestComplete uses automatically are not fixed in stone. You can edit, add, remove, adjust, etc. the properties used to identify objects to meet what you're looking for. As I've mentioned many times, I rarely stick with what TestComplete gives me automatically and usually end up doing some sort of modification.
Keep in mind that TestComplete's identification criteria is two-fold.
1) Find the parent object... at the Root, that's NameMapping.Sys. For additional layers, like your application, it starts with NameMapping.Sys and then looks at the children. So, the first criteria is "Does the parent have a child..."
2) Second criteria "...with properties that match this set." So, you may have multiple objects that have the exact same properties... but if they are children of different parent objects, TestComplete sees them as distinct objects. But the properties themselves are key to making sure that the CORRECT child object is identified.
So, for example, you have objectidentifier which COULD be something ugly like MainContent_divMain_divSubMain_btnSignOut. Which, really, is ugly because, if the page changes in hierarchy, that could change. Howerver, you can wild card it... I'd assume that, for the specific parent of the signout button, there would only be one object that would match "*btnSignOut". Likewise your href... test domains shift and change so the root URL may be different... but the rest of the path, if developer properly, should be the same... so, you're href could be edited to "*/signout.aspx" or whatever it is.
But you are not limited to using only ObjectType, href, or ObjectIdentifier... ALL the properties of the object are available to you for identification so, if there are properties that you would prefer to use, feel free to use them instead.
Now, if you're going to use XPath, you will want to us FindChildByXPath (https://support.smartbear.com/testcomplete/docs/reference/test-objects/members/web-objects/findchildbyxpath-method-web-object.html). In this case, your code would be something more on the lines of
browser = Sys.Browser(*);
page = browser.Page('myURL');
SignOut_Button = page.Buttons.FindChildByXPath('/*[@id='signout']/div[1]')
if (SignOut_Button.Exists) {
SignOut_Button.Click();
}
This pretty much completely by passes the NameMapping. Now, you can organize things into code units and so forth to build your own object identification structure, but, in your example, "Buttons" is not a child of the page... Button is a code unit that you are using to bring in the SignOut_Button object... so, you just simply need to click on the object.
One thing of note... FindChildByXPath is slower than NameMapping in object identification because it does need to look at the whole page. NameMapping, once an object is found, it remains in cache until the cache is refreshed or until it needs to be found again. I would highly suggest that you look into using NameMapping for your project... but as mentioned above, work with the properties exposed by TestComplete. If you need help in figuring out unique identification, please feel free to ask and we'll help as best we can.