[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

[Extracting from Wikipedia]

Software development

Part of this section is from the Perl Design Patterns Book.

In the software development process, the top-down and bottom-up approaches play a key role.

Top-down approaches emphasize planning and a complete understanding of the system. It is inherent that no coding can begin until a sufficient level of detail has been reached in the design of at least some part of the system. The Top-Down Approach is done by attaching the stubs in place of the module. This, however, delays testing of the ultimate functional units of a system until significant design is complete. Bottom-up emphasizes coding and early testing, which can begin as soon as the first module has been specified. This approach, however, runs the risk that modules may be coded without having a clear idea of how they link to other parts of the system, and that such linking may not be as easy as first thought. Re-usability of code is one of the main benefits of the bottom-up approach.[citation needed]

Top-down design was promoted in the 1970s by IBM researcher Harlan Mills and Niklaus Wirth. Mills developed structured programming concepts for practical use and tested them in a 1969 project to automate the New York Times morgue index. The engineering and management success of this project led to the spread of the top-down approach through IBM and the rest of the computer industry. Among other achievements, Niklaus Wirth, the developer of Pascal programming language, wrote the influential paper Program Development by Stepwise Refinement. Since Niklaus Wirth went on to develop languages such as Modula and Oberon (where one could define a module before knowing about the entire program specification), one can infer that top down programming was not strictly what he promoted. Top-down methods were favored in software engineering until the late 1980s, and object-oriented programming assisted in demonstrating the idea that both aspects of top-down and bottom-up programming could be utilized.

Modern software design approaches usually combine both top-down and bottom-up approaches. Although an understanding of the complete system is usually considered necessary for good design, leading theoretically to a top-down approach, most software projects attempt to make use of existing code to some degree. Pre-existing modules give designs a bottom-up flavour. Some design approaches also use an approach where a partially-functional system is designed and coded to completion, and this system is then expanded to fulfill all the requirements for the project

Programming

Top-down is a programming style, the mainstay of traditional procedural languages, in which design begins by specifying complex pieces and then dividing them into successively smaller pieces. Eventually, the components are specific enough to be coded and the program is written. This is the exact opposite of the bottom-up programming approach which is common in object-oriented languages such as C++ or Java.

The technique for writing a program using top-down methods is to write a main procedure that names all the major functions it will need. Later, the programming team looks at the requirements of each of those functions and the process is repeated. These compartmentalized sub-routines eventually will perform actions so simple they can be easily and concisely coded. When all the various sub-routines have been coded the program is done.

By defining how the application comes together at a high level, lower level work can be self-contained. By defining how the lower level abstractions are expected to integrate into higher level ones, interfaces become clearly defined.

Top-down approach

Practicing top-down programming has several advantages:

* Separating the low level work from the higher level abstractions leads to a modular design.
* Modular design means development can be self contained.
* Having "skeleton" code illustrates clearly how low level modules integrate.
* Fewer operations errors (to reduce errors, because each module has to be processed separately, so programmers get large amount of time for processing).
* Much less time consuming (each programmer is only involved in a part of the big project).
* Very optimized way of processing (each programmer has to apply their own knowledge and experience to their parts (modules), so the project will become an optimized one).
* Easy to maintain (if an error occurs in the output, it is easy to identify the errors generated from which module of the entire program).

Bottom-up approach

Pro/ENGINEER WF4.0 proetools.com - Lego Racer Pro/ENGINEER Parts is a good example of bottom-up design because the parts are first created and then assembled without regard to how the parts will work in the assembly.

In a bottom-up approach the individual base elements of the system are first specified in great detail. These elements are then linked together to form larger subsystems, which then in turn are linked, sometimes in many levels, until a complete top-level system is formed. This strategy often resembles a "seed" model, whereby the beginnings are small, but eventually grow in complexity and completeness.

Object-oriented programming (OOP) is a programming paradigm that uses "objects" to design applications and computer programs.

In Mechanical Engineering with software programs such as Pro/ENGINEER, Solidworks, and Autodesk Inventor users can design products as pieces not part of the whole and later add those pieces together to form assemblies like building LEGO. Engineers call this piece part design.

This bottom-up approach has one weakness. We need to use a lot of intuition to decide the functionality that is to be provided by the module. If a system is to be built from existing system, this approach is more suitable as it starts from some existing modules.

Pro/ENGINEER (as well as other commercial Computer Aided Design (CAD) programs) does however hold the possibility to do Top-Down design by the use of so-called skeletons. They are generic structures that hold information on the overall layout of the product. Parts can inherit interfaces and parameters from this generic structure. Like parts, skeletons can be put into a hierarchy. Thus, it is possible to build the over all layout of a product before the parts are designed.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

C++ doesn't support the 'interface' explicitly unlike Java. So, combination of abstract class and virtual function, is used.

Let's think of following case.

ModuleA
  A : pure abstract class (interface class).
  AImpl : implementation(concrete) class inherited from A.

External module that want to use ModuleA need to know interface, but don't need to know it's implementation. So, Knowing class A should be enough to use ModuleA. And this is tightly coupled with the way of instantiation.
Let's see below

A* instance = new AImpl(argument);

This is easy way. But, in this case, definition of 'AImpl' should be included in external code. This is not good in terms of 'Information Hiding'. We want to hide implementation details (even if it's header). See following example to do this.

----- A.h
class A // interface class
{
public:
    virtual ~A(){};
    static A* Create_instance(Arguments);
    int Interface_function_A(void) = 0;
    int Interface_function_B(void) = 0;
};

---- AImpl.h
#include "A.h"
class AImpl : private A
{
    friend class A;
    ...
}
...

---- A.cpp
#include "AImpl.h"
A::Create_instance(Arguments)
{
    AImpl* instance = new AImpl(Arguments);
    return static_cast(instance);
}

Now, knowing definition of class A is enough to use this module. Therefore, implementation details are completely hidden. Besides, inheriting as 'private', can prevent module from unexpected usage (AImpl can be used only through A). Here is sample usage.

#include "A.h"
...
A* instance = A::Create_instance(Arguments);
...
delete instance;

We made function for create instance. But, we should make destroying instance be possible by 'delete' keyword. Because, in many cases, knowing instance's concrete class at the moment of deleting it, is not necessary. And unifying interfaces to destroy instance (into using 'delete') is also good to read.

+ Recent posts