Just use Python.
I develop in C++ and do my build scripts in Python, and I would find it painful to do build scripts in C++:
- Python makes it trivial to manipulate dictionaries, lists, nested dictionaries of dictionaries of lists, etc. (For example, one of my scripts uses a multi-level hierarchy of all of my tools, tools' versions, and tools' versions' paths.) C++ can do the same with templates and custom classes, but it's much more verbose (which translates to more lines of code, which generally translates to lower productivity).
- Python provides high-level libraries and routines like its XML and JSON handling, subprocess, and os.walk. Again, C++ can do this, but it's a lot more work to find the libraries, learn their APIs, correctly assemble the calls (which are often lower level), etc.
- Build scripts are a non-value-added activity (to borrow a term from lean). It's better to use as high-level a language as possible, to get them done as quickly as possible, to get back to work which benefits your users.
- In my experience, build scripts tend to grow in unforeseen ways. Even if a task seems initially simple for C++, it can get complicated in a hurry. When a new requirement comes up, it's often a lot simpler to tack on handling in a Python script than it is to do it in C++ (which may require finding or reading up on new library APIs, etc.).
Regarding the advantages which you list for C++:
- Adding a single dependency (Python) shouldn't significantly complicate your build. It's already standard on most Linux installations, for example. Thanks to Python's "batteries included" libraries, it may even be easier to manage than the C++ libraries that your build scripts would depend on.
- The type safety that C++ gives is most useful for large projects, not small scripts.
- Python complements C++ very well (high-level versus lower-level, dynamically typed versus statically typed, etc.) and can even integrate with C++ very well (thanks to SWIG and Boost.Python) if you later want to do that, so it's worth learning for a C++ programmer.
- As you said, execution speed should be a nonissue.
Try this. The initial reflection is certainly expensive, but if you're going to use it many many times, which I think you will, this is most certainly a better solution what what you're proposing. I don't like using reflection, but I find myself using it when I don't like the alternative to reflection. I do think that this will save your team a lot of headache, but you must pass the name of the method (in lowercase).
In other words, rather than pass "name", you would pass "fullname" because the name of the get method is "getFullName()".
Map<String, Method> methodMapping = null;
public Object getNode(String name) {
Map<String, Method> methods = getMethodMapping(contact.getClass());
return methods.get(name).invoke(contact);
}
public Map<String, Method> getMethodMapping(Class<?> contact) {
if(methodMapping == null) {
Map<String, Method> mapping = new HashMap<String, Method>();
Method[] methods = contact.getDeclaredMethods();
for(Method method : methods) {
if(method.getParameterTypes().length() == 0) {
if(method.getName().startsWith("get")) {
mapping.put(method.getName().substring(3).toLower(), method);
} else if (method.getName().startsWith("is"))) {
mapping.put(method.getName().substring(2).toLower(), method);
}
}
}
methodMapping = mapping;
}
return methodMapping;
}
If you need to access data contained within members of contact, you might consider building a wrapper class for contact which has all methods to access any information required. This would also be useful for guaranteeing that the names of the access fields will always remain the same (I.e. if wrapper class has getFullName() and you call with fullname, it will always work even if contact's getFullName() has been renamed -- it would cause compilation error before it would let you do that).
public class ContactWrapper {
private Contact contact;
public ContactWrapper(Contact contact) {
this.contact = contact;
}
public String getFullName() {
return contact.getFullName();
}
...
}
This solution has saved me several times, namely when I wanted to have a single data representation to use in jsf datatables and when that data needed to be exported into a report using jasper (which doesn't handle complicated object accessors well in my experience).
Best Answer
I recommend this formatting library which I wrote recently. Here is an incomplete list of its features:
(s)printf
and better than performance of IOStreams. See Speed tests.It's a new library, but it already supports almost all of the formatting options of
printf
(with different syntax), in addition to that it supports positional arguments, center alignment, custom fill character and user-defined types.Update: now it also provides a safe
printf
implementation