4

This is a question more about how to build a c++ application than it is about c++, per se

I'm building an application that was envisioned as a Graphical application, but the specifics of the implementation require a great deal of abstract functionality to facilitate the interface, such as reading lists of objects from files, web resources, etc. I have figured out how to implement this functionality without much difficulty, but I have no good way to test it. Specifically, I've begun the implementation of the graphical environment, but it is not yet ready to work with the lower-level functionality.

I have also built a good deal of what I want the lower layer to do, but it is as-yet untested. all of this code resides in a single folder and is stored in a version control system with regular commits.

I'm relatively new to writing anything functional in C++ having only worked on class projects up to this point, but I have written a good number of programs, of various types, in PHP.

If this were a PHP project, it seems it would be simple to test any functionality:

  1. I would simply begin by implementing it interactively
  2. codify it into a small file
  3. write some code that used the functionality
  4. build it into a function
  5. import that function into my larger body of code.

This seems like a really awkward way to do the same with C++. Have I got it all backwards, how do you solve small isolated problems, in your compiled programs and import them into your projects; is there a workflow that you find helpful.

dsolimano
  • 8,870
  • 3
  • 48
  • 63
Ben West
  • 660
  • 5
  • 17

3 Answers3

2

Generally speaking, the answer to your question is using classes and unit testing. Do an internet search for Agile / Extreme Programming.

The idea is this:

  1. Do all the agile story stuff (I'll let you read about this on your own)
  2. You break out your design into classes
  3. Write unit tests that define the "spec" for your class
  4. Write empty placeholder functions.
  5. See the unit tests fail.
  6. Write code until the unit tests succeed.
  7. Go back to step 3 and repeat for the rest of your classes.

If you write code in this manner, you create reusable and robust code.

Honestly, I don't personally believe in TRUE TDD (test driven development) -- I feel it's better to write your unit tests after you've written your code (I feel the impending flame of doom coming from users screaming "AGILE OR DIE!").

EDIT: If your question is more along the lies of the actual BUILDING of multiple classes, well that's easy. Generally speaking, each of your classes should be encapsulated in 2 files (source code and header file). Just include those files (along with files from all other classes you want to use) in a new project. #include "xxx.h" in the appropriate places where you need to use the classes, write your code that uses those classes, and build. That's it.

ComtriS
  • 67
  • 2
  • 8
  • To answer your comment from below: If you've already written code (sounds like you're not using Agile/XP methods -- that's fine). Then I would create an interface to use it (which honestly you should have done already). Create a USABLE .h file (many people put stuff in .c that should be in .h, and vice-versa). Then import those files into a new project when you need them. – ComtriS Nov 18 '10 at 23:38
  • Clarification: SO -- I'm using classes, I'm working with QT, and I have a lot of the code built -- should I just take the code I've written, copy it into a new folder, write a simple interface, and then compile/test? is that the best option. – Ben West Apr 12 '12 at 20:36
1

I guess this would be the general tactic for any OO project.

First determine the main components and make sure you have a very thorough understanding of what everything is responsible for.

Write out the interface for each component, and check (logically) to see that it fits your problem.

Implement each module.

As far as testing is concerned make tester modules (stubs): for example make a class that will send input to the GUI mimicking the input that would be sent by the actual component. Since you have a clear idea of the interface, how this result was produced would be irrelevant.

Repeat this process for each component in your system and then put them together.

Hope it helps

user472875
  • 3,115
  • 4
  • 37
  • 68
0

I am currently in a similar situation, where I have implemented bits-and-pieces of functionality (file I/O through some API, main parts of the work, etc.). So maybe some of my experiences would be helpful:

  • If you have some code already, it may help to draw a diagram of what you have. Pen-and-paper, or even better UML can help here (btw, a good UML tool which can import existing classes is Umbrello). Sometimes I do this kind of "design check" after the last commit, and it helped me to spot some subtle problems, especially in the design stages, where I was refactoring classes daily;
  • If you have written code for the components, I think you can easily formulate some requirements for each one, and from these you can create some tests (e.g. with 'UnitCPPLite'). Currently, I have the test in the main file, with some boilerplate code which triggers the test execution before anything else is done in the application (although this is still not optimal);
  • Finally, I would add to the recommendation of ComtriS the idea of "include guards" (if you don't use them already), to prevent multiple inclusion of the header files. So, in practice, I typically end-up with something like this:

src/CFoo.h:

// class 'CFoo': header file
#ifndef CFOO_H
#define CFOO_H

#include <only_what_you_need_in_declaration_interface>

class CFoo {
    private:
        // class data
    public:
        // constructors, destructors, getters, setters, etc.
        void doWork();
    };
#endif /* CFOO_H */

src/CFoo.cpp:

// class 'CFoo': implementation file
#include "CFoo.h"
#include <what_you_need_in_addition_for_internal_workings_of_methods>

// code for other methods...

void CFoo::doWork() {
    // work
}

Hope it helps.

Dragos
  • 47
  • 8