[Advice] Problem Solving in Software Development & Design

07/21/2014 00:52 Spirited#1
Introduction:
A few years back, I wrote a thread advising new programmers on how to approach problems in software development. Since I only had a few months of programming experience when I wrote the thread, I decided it would be best to rewrite it. Before I begin, you should know that Computer Science is an ever-evolving field. You will never know all there is to know about programming, and you will always face new problems to solve. With that said, problem solving in software development will get easier with practice, but if you don't know how to approach problem solving to begin with, programming can be a struggle. This thread is to hopefully help ease that initial struggle when getting started.

Tips for Solving Problems:
  • Don't attempt to tackle a large problem head-on with a large solution. Analyze the problem and gain an understanding of it; then, divide the problem into manageable pieces and solve the problem for each piece, one at a time (divide and conquer). Large problems are overwhelming, so break them down; otherwise, you might get confused or burned out.

  • Recognize that you won't find a perfect solution for challenging problems on the first attempt. Solving problems is a trial and error process. To help speed up this process, check your inputs, and compare your expected output with your actual output. Step through your code on paper, or using an IDE (such as Visual Studio, QT Creator, Netbeans, or Eclipse).

  • If it works, don't try and fix it. If you have a problem somewhere in your source code, only modify what might be the problem. If you modify working code that turns out to be unrelated to the problem, don't make new problems; revert the unrelated code back to what it once was.

  • Build upon the knowledge you have already acquired. Don't go too far outside of your range of understanding. Build yourself up by finding similarities with solutions you have already created from previous problems with researched solutions. In comparison, don't try to paint in oils without painting with acrylics first.

  • Eliminate processes that don't fit the requirements of the project. As a programmer, you'll find yourself constantly thinking about solutions to problems or requirements in the project, but some of those solutions may not be the correct approach. It is your responsibility to eliminate incorrect solutions and develop replacement solutions that do fill the requirements or solve the problem. In comparison, if you have the wrong size screw driver, use another size - don't keep stripping the screw hoping for a solution.

  • Make lists. As the manager of your own project, you need to keep track of pending and on-going tasks, active problems, and solutions. Create documents that tell a story: what was the problem you solved and how did you solve it? These types of notes become very useful in the event that you encounter the same problem again.

  • Think outside the box. As simple as this may sound, our minds are trained to limit thought and to specify rather than generalize and expand. Most of the best ideas and software designs come from thinking outside the limits you usually restrict yourself to. Practice generalizing and expanding on thoughts, as this will become a very valuable skill.

Tips for Software Development:
Designing a solution for your project before writing code can significantly improve the quality of your project. Every large project should be carefully planned and mapped out. Failing to plan can result in hardships down the road when expanding the project (scaling), and may prevent you from continuing. Steps in designing and developing software using object-oriented analysis and design (OOAD):
  1. Study: Research into necessary prerequisites for developing the project. If you're creating a server, research into socket systems and networking. If you're creating a client tool, research into methods of displaying information.

  2. Requirements: With a basic tool belt to start analyzing and defining the needs of the project, create documents listing what the project needs to accomplish, what risks need to be assessed and planned around, and where quality needs to be maintained. This list will help guide you through the project. Separating your list of requirements into source development, afterthoughts, player suggestions, etc. may help organize your priorities.

  3. Design: Using your list of requirements as a guide, develop an approach to programming the project. This approach should define a model for how the project's classes will interact with each other and solve problems that may arise later in development. See the next few sections for tips on software design.

  4. Implementation: Now, using your design as a template, run through the model and start programming the project. Check back with your list of requirements you previously created to help guide you through the model. Refine your requirements and design where and when necessary. When implementing your design, ensure that you document all of your code. Documenting your work is extremely important in project scale: not only does it help others understand your code; it helps you understand your code a few months down the line.

  5. Test: After programming any feature or algorithm in the project, it is very important that you thoroughly test it before continuing, verifying that it executes as expected. This helps significantly eliminate problems that may arise later in development. If testing your algorithm concludes with problems, modify the algorithm, or re-design and re-implement if the solution doesn't meet with the project requirements.

  6. Maintenance: After releasing your application or launching your service, it is important that you plan for bug reports. Archive these bug reports and keep documents of resolved reports. This way, if the problem occurs again later in the product's lifetime, you have a reference for fixing the problem.

Tips on Software Planning:
Planning software relies on your organization skills and how your mind best drafts designs. Two very common organization techniques help diagram and model designs as connected objects and algorithms:
  • Sequence Diagrams: These diagrams are commonly used to draft algorithms, and show a process as a detailed sequence of events. Popular methods of displaying sequence diagrams include pseudocode, flow charts, hierarchical charts. Pseudocode can be interpreted as "fake code", used to outline an algorithm. [Only registered and activated users can see links. Click Here To Register...] for an example of my pseudocode. Flowcarts show the flow of an algorithm as a diagram of symbols and arrows. [Only registered and activated users can see links. Click Here To Register...] for an example from Saddleback Community College. Finally, hierarchical charts break down complex algorithms as large steps, which are then broken down further into simpler steps. For examples, google "function hierarchy diagrams".

  • Class Diagrams: These diagrams are commonly used to draft class definitions, and show objects as interactive, connected links. For an example on class hierarchy charts by Microsoft (terrible but still an example), [Only registered and activated users can see links. Click Here To Register...]. For more examples on diagramming programs, google "UML" (unified modeling language).

Tips on Software Design:
Modern programming languages, such as C#, C++, and Java, all support a highly scalable and modular system of data encapsulation called object-oriented design (OOD). In object-oriented design, data structures called classes define an object. For more information on object-oriented design and programming using classes, research into class-based programming.

When considering a design for your project, I recommend practicing at least the primary object-oriented design concepts: classes, variable and method scopes, inheritance, abstraction, polymorphism, interfaces, and modularity. Of these primary concepts, I'll explain a few of them (in specific, how they relate to software design). The rest you will have to research on your own. My apologies if these are a bit confusing at first, I don't expect you to understand them right away. Try to absorb the most you can at the time being.
  • Abstraction & Inheritance: These two concepts go hand-in-hand. As I discussed before, the ability to generalize and expand is an extremely valuable skill in computer science. Abstraction is just as it sounds, defining classes that are abstract, or general. Instead of depending on concrete details, abstract classes help establish a base infrastructure that can be reused using inheritance. Inheritance derives the general/base class and builds on top of it, which significantly helps expand the project. For example, instead of having 40 packet classes that define the same methods for creating packets, you can create one abstract class that defines general actions that all packets should do. This way if you ever need to edit the method, you edit it only once (instead of 40 times).

  • Modularity: Creating a scalable project usually means creating modules that can be split up and put back together in different ways. Abstraction and inheritance is a great technique for reusing and re-purposing code, but is only one step in creating a modular project. In software development, this may be one of the most important concepts to have a grasp on. Programmers who can reuse their old code quickly and effortlessly can develop software much faster than their competition. Creating abstract libraries is the best way to create reusable modules.

Conclusion:
Sorry to keep this short, but I am pretty exhausted. I won't be spell checking this, so pardon any mistakes I made and didn't catch right away. I hope I covered everything I wanted to cover. If you have any questions, just let me know.

Regards,
Spirited
07/21/2014 08:50 KraHen#2
Nice guide, absolutely agreed. To add one more thing : think first, write down the solution with pen and paper, see if it works, and if it can be improved. THEN start coding it.
07/21/2014 19:29 shitboi#3
Spirited mentioned the best practices of programming.
I tend to just sketch and draft my algo on paper. Draw my own version of diagrams until i got everything figured out.

I have not done up a single proper class diagram since I worked -.- I guess that reflects the fact that I am not handling complex inheritance in my models.

Mostly pseudo code internal documentation for future maintenance
07/23/2014 15:47 Super Aids#4
Quote:
Originally Posted by KraHen View Post
Nice guide, absolutely agreed. To add one more thing : think first, write down the solution with pen and paper, see if it works, and if it can be improved. THEN start coding it.
Or do it in notepad. I don't see why using pen and paper would make much difference.
07/24/2014 04:26 Spirited#5
Quote:
Originally Posted by Super Aids View Post
Or do it in notepad. I don't see why using pen and paper would make much difference.
I find Excel or Publisher to be the best tools for creating pseudocode. That way, you can split the code up into methods, use symbols (such as arrows) to show jumps to other methods, re-position things in class hierarchy, etc. It really just depends on what the author feels comfortable doing.
07/24/2014 10:10 KraHen#6
Quote:
Originally Posted by Super Aids View Post
Or do it in notepad. I don't see why using pen and paper would make much difference.
To each of his own, really, I`m most productive with my old school sketching in a notebook. :)