Abstract Data Types: Building Blocks for Streamlined Data Structures
May 24, 2023 / 6 min read /
--- views
Algorithms usually don’t specify how their data operations are performed. For instance, merge relies on unspecified external code to create lists of numbers, to check if lists are empty, and to append items into lists. The queens algorithm does the same: it doesn’t care how operations on the chessboard are made ♟️, nor how positions are stored in memory. These details are hidden behind what we call abstractions.
So, data abstractions will be a central topic. They hide details of data-handling processes. But before we can understand how data abstraction works, we need to solidify our understanding of data types.
What is Data Abstractions?
Abstractions let us omit details; they are an interface for reaping the functionality of complex things in a simple way. 🌟
Understanding Data Abstractions
For instance, cars hide complex mechanics beneath a driving panel, such that anyone can easily learn to drive without understanding any engineering.
In software, procedural abstractions hide complexities of a process beneath a procedure call. In the trade algorithm the min and max procedures hide how the minimum and maximum numbers are found, making the algorithm simpler. With abstractions on top of other abstractions, we can build modules that allow us to do complex stuff with single procedures, like this:
1arr = [5, 2, 3, 1, 4]2sort(arr)3print(arr) # [1, 2, 3, 4, 5]
In one line of code, we sort an array of numbers. The sort procedure hides the details of how the sorting is done, even though the inner workings of that task are complex.
What is Data type?
We distinguish different types of fasteners (like screws, bolts, and nails) according to the operations we can perform on them (like screwing, wrenching, and hammering). Similarly, we distinguish different types of data according to the operations that can be performed on the data.
Understanding Data Type
For instance, a data variable that can be split in positional characters, that can be converted to upper or lower case, that can receive appended characters, is of the String type. Strings represent texts. A data variable that can be inverted, that can receive XOR
, OR
, AND
operations, is of the Boolean type. Booleans can be either ✔️ True or ❌ False. Variables that can be summed, divided, subtracted, are of the Number type.
"Good programmers worry about data structures and their relationships." — LINUS TORVALDS
Abstract Data Types
An Abstract Data Type (ADT) is the specification of a group of operations that make sense for a given data type. They define an interface for working with variables holding data of a given type hiding all details of how data is stored and operated in memory. When our algorithms needs to operate on data, we don’t directly instruct the computer’s memory to read and write. We use external data-handling modules that provide procedures defined in ADTs.
For example, to operate with variables that store lists, we need: procedures for creating and deleting lists; procedures for accessing or removing the nth item of a list; and a procedure for appending a new item to a list. The definitions of these procedures (their names and what they do) are a List ADT. We can work with lists by exclusively relying on these procedures. That way, we never manipulate the computer’s memory directly.
Advantages of using ADTs
- 💧 Simplicity: ADTs make our code simpler to understand and modify. By omitting details from data handling procedures, you focus on the big picture: the problem-solving process of the algorithm.
- 💪 Flexibility: There are different ways to structure data in memory, leading to different data-handling modules for a same data type. We should choose the best for the situation at hand. Modules implementing the same ADT provide the same procedures. This means we can change the way the data is stored and manipulated just by using a different data-handling module. It’s like cars: electric cars and gas-powered cars all have the same driving interface. Anyone who can drive a car can effortlessly switch to any other.
- 🔄 Reusability: We can use the same data-handling modules in projects that require handling data of the same type.
- 🗂️ Organization: We usually need to operate several data types: numbers, text, geographical coordinates, images, and more. To better organize our code, we create distinct modules that each host code specific to a data type. That’s called separation of concerns: parts of code that deal with the same logical aspect should be grouped in their own, separate module. When they’re entangled with other functionalities, we call it spaghetti code.
- 🎁 Convenience: We can get a data-handling module coded by someone else, and learn to use the procedures defined by its ADT. Then we can use these procedures to operate with variables of a new data type right away. Understanding how the data-handling module works isn’t required.
- 🐞 Bug-Fixing: If you’re using a bug-free data-handling module, your code will be free of data-handling bugs. If you find a bug in a data handling module, fixing it once means you instantly fix all parts of your code affected by the bug.
Common Abstractions
To solve a computational problem, it is very important to understand the type of data you’re working on and the operations you’ll need to perform on it. Deciding the ADT you’ll use is equally important. Next, I present well known Abstract Data Types you should be familiar with. They appear in countless algorithms. They even come built-in with many programming languages.
Primitive Data Types
Primitive data types are those with built-in support in the programming language you’re using—they work without external modules. These always include integers, floating points, and generic operations with them (addition, subtraction, division). Most languages also come with built-in support for storing text, booleans and other simple data types in their variables.
Conclusion
In conclusion, Abstract Data Types (ADTs) serve as the fundamental building blocks for streamlined data structures. By providing a specification of operations for a given data type, ADTs allow us to work with variables holding data without concerning ourselves with the details of how the data is stored and operated in memory. The importance of ADTs lies in their ability to simplify code, offer flexibility and reusability, enhance code organization, provide convenience, and aid in bug-fixing. By utilizing ADTs, programmers can focus on problem-solving and efficiently handle various data types, leading to more efficient and maintainable software development. Understanding the significance of ADTs empowers programmers to make informed decisions when designing algorithms and data structures, ensuring the efficient handling of data in their codebase.
Reference Videos