Skip to Content

Computational Thinking: Using CT Practically

(This page is a work under construction…so be careful with it…)

Now that we have learned the ADPDA foundations of computational thinking, now what do we do with it? Mainly, two things:

  1. We use it as a framework to understand problems, domains, and concepts around us, and
  2. We use it to help devise a computer-based solution to something.

In other words, computational thinking helps us understand something, and helps us begin the process of programming a computer to be applied to that something.

Let’s take each of these one at a time.

Computational Thinking to Understand a Problem or Domain

Remember at the beginning of the CT Data Representation page we said that thinking about the data is more important than thinking about the code – so to begin to understand a problem, think about the things in it. Other non-CS ideas align with this – for example, conceptual modeling (and you can web search to find many other links; I also have another in-depth page on domain modeling).

A good place to start is to identify entities:

  1. Brainstorm and write down all the nouns that are used when talking about or describing the problem (or domain);
  2. Then pull out the most important ones – just a handful, probably 3-10 of them; we will call these entities;
  3. For each entity, brainstorm and list the information needed about each one of those; these are its attributes; some of the less important nouns that you originally listed may now be some of these attributes of more important entities – the word has often indicates an attribute of an entity, such as “a person has a name” (name is an attribute of the entity person). Stick to just those attributes that are relevant to your problem or understanding; be willing to throw aside unimportant attributes. Keep your ideas clean and simple.

The next step is to identify relations between entities:

  1. Brainstorm and list relationships between entities; these will often be verbs such as uses, has, and is part of, but will also be specific verbs related to the problem; for example, “an instructor teaches a course” describes the “teaches” relationship between the instructor and course entities.
  2. Think about which relationships are relevant to your problem or understanding; be conservative but be willing to throw aside unimportant relationships. Keep your ideas clean and simple.
  3. Figure out the cardinality of those relationships: how many entities of each side are involved? For example, an instructor teaches multiple courses, but each course only has one instructor (usually, but exceptions matter!)

The steps above involve abstraction (identifying relevant concepts and their attributes, ignoring irrelevant ones), pattern recognition (relationships, common attributes), and data representation.

Move on to Activity

Now that we have a good understanding of the conceptual things in our problem, now we should think about the processes, activity, or actions that happen in it.

Remember, at this point we are only trying to understand the problem, not come up with a computer solution, so we focus on workflow and processing that is inherent in the problem. In this, we think about how the entities are used in the problem domain. Some of this involves recognizing and describing common usage patterns.

For example, in a grocery store, the items a shopper is going to purchase need to be identified, the price and quantity of each need recorded, we need to add up all of the individual prices into a total, we need to know which items can be taxed and which not, and we need to calculate the tax and add it to the total; we may also need to apply coupons or other discounts. This needs to be done in a store regardless of whether it is on paper or on a computer.

At this stage we should try to list out these processes, and name them (at least with a short descriptive title). This involves decomposition and abstraction. Some of the processing pieces may be complex enough that we should describe them with flowcharts (see the algorithms page).

Computational Thinking to Help Build Software

The first step in creating software should always be understanding the problem – so hopefully by this point we have done all of the stuff in the previous section. If not, we should go back and do it…okay, now we’re back and ready to program!

Now we have to start making decisions on how to bring all of that into software, into real code. The first step is probably to decide what programming language we are going to use, and what features of it we will use. Different languages will have different features that might help support us, and different programmers know how to use those features at different levels of capability. Whereever you are in your programming ability, you need to use what you know, and perhaps try to learn some new things each time you create a program.

As before, the best place to start is with your data representation. In many modern object-oriented programming languages, the entities you identified in your understanding of the problem should probably become objects, and their type become a class. Even with OOP, you still have to decide how to represent your entities and their attributes, as arrays, tuples, lists, integers, strings, or whatever.

So first think about the data that will be in your program, and what it will look like. This also involves abstraction, decomposition, and pattern recognition.

Next, you should decide how you are going to embody the workflows and processing that is in your problem in your software. This will involve decomposing them into functions, with names and then deciding where those functions should be – in an object-oriented setting, this means in which class they are, or better yet, what objects have which processing responsibilities. Even in a non-OO programming language, you still have to decompose your processing into functions (or class methods), and figure out how to pass data in between those functions. Try to avoid global data!

But There’s More to Software…

Now you have to put it all together – this means you have to write code that just manages the application and reads in data and creates output and all that fun stuff. This is code that is not directly embodying the problem domain’s workflow and processing, but that is just managing and running the software. All of this code also needs designed, decomposed, abstracted, and may have internal data that needs represented.

So really, there are two parts to creating software: making the problem logic and problem data part – this is the part that puts your problem into a computer solution – and then there is the part that just manages the computer and the application and glues it all together.

That second part can often be the biggest part! This includes reading data in, creating a user interface and operating it, creating output data, and many other things.

Actually, a good practice is to design your user interface (UI) first, before you begin coding all the other parts (even the problem logic). Then do pretend walkthroughs of using your application through your UI design, and see if it works well. If not, fix it and repeat. Then once you have a good handle on the UI, build the program that will be behind it and make everything work.

What About AI?

AI can greatly speed up your ability to turn your problem understanding and your application behavior ideas into real code. That’s great – but you should still have some ability to review the AI-generated code and understand if it is appropriate for your software. In the AI-assisted software development world, it is more important than ever for humans to be able to read and understand code, over and above the ability to write code and know all the nuances of some library or framework.

Finally, You Should Test, Test, Test

Making sure your application works involves lots of testing. Don’t skip this and make the users hate your application because it has lots of bugs. If you want to have users actually like your application, do lots of testing and other forms of quality assurance. This is especially true if using AI.

Beginning programmers (i.e., students) often think that once they see their program work once, then it must be correct, and done. No! You need to test your program over a variety of data, conditions, environments, and platforms. For a class assignment, multiple environments and platforms isn’t that important, but still you need to create a variety of data input tests to see if your program is handling all the cases properly, including edge cases.

Below are three basic testing concepts to follow:

1. Automate your tests

Every language has at least one popular automated testing framework (see JUnit, PyUnit, and others). Whole programs can also be automatically tested, even GUI programs (see Selenium for web apps, and others). Platforms like Android offer testing instruction.

In short, learn how to automate your tests.

2. Do Black Box Testing

Create test cases that mimic real user behavior and needs and that treats your software as an unknown black box. Have at least one average case test for each piece of unique functionality that results in some unique activity or computation. For example, if your e-shopping app gives a discount for orders totaling more than $100, you need to have a test with and order less than $100 and one more than $100. Black box testing terminology calls these equivalence partitions. Then you need to test the border cases – in this example, you need a test for an order of exactly $100.00 and one of exactly $100.01, so that you know your program is correctly implementing “more than $100”. Border cases are where most software errors happen!

3. Do White Box Testing

White (really, clear) box testing ideas say: look at the code and see what you are actually running in your tests. There are many code coverage tools available to automatically calculate this!

So, automate your black box tests, and hook a coverage tool into your tests. Run all your tests, and see what code is executed, and what code has been missed. Then add tests so that you execute the code that has been missed. What those tests are depends on what code was missed – you just have to think about it!

AI in Testing?

Given a decent description of your problem, AI might be able to help you identify your black box tests, and your equivalence partitions and borders. But this needs pretty specific information which you need to create. AI should be able to help you set up automated tests in some framework, and hook your code coverage tool into it. A good AI agent might be able to run all your tests, see missing code coverage, and create white box tests to cover them. But, as with coding, a human needs to review it all, and a human needs to know what the correct “answers” are – the answers being whether or not the code is actually doing what you intend, and what your customers need.