Software Engineer Flashcards
Pillars of Object-Oriented Programming.
Abstraction
Abstraction means to only show the necessary details to the user. Going back to our car example, we do not need to know the inner mechanisms of what is going on to turn on the engine. We just want to push a button or turn the keys to turn the engine on. That’s what abstraction is, we only expose the necessary details and hiding the irrelevant information. An example in code could be converting a string to lowercase letters by using .toLowerCase(). We do not need to know how the language does it, we just need the input. This can reduce the complexity of our code.
Encapsulation
Encapsulation means wrapping up data and methods together into a single unit like a class. It is also built on the idea of data hiding. The variables of a class will be hidden from other classes and can be accessed only through the methods of their current class. This is mostly for safety, so we do not have something that inadvertently changes the property of an object. We are encapsulating our properties within the object, and we can do that by setting our properties to private. We can provide public setter and getter methods to modify certain properties of a class.
Inheritance
Inheritance means passing properties from a parent class to a child class. The parent class is the base class that has all the basic properties and methods, the child class will have all the same properties and methods of the parent in addition to their own properties or methods. It helps reuse, customize and enhance the existing code. For example, we can have a Dog class with properties name, sex, and breed. We can make a child class of this parent class called Puppy. This Puppy class will inherit the same properties and methods encapsulated within the Dog class with the addition of their own relevant methods.
Polymorphism
Polymorphism means a child class can define its own unique behavior and still share the same methods or behavior of its parent class. Let’s think about our Dog parent class and our Puppy child class. This Dog class has a talk() method which will print out “Woof!”. This method will be inherited by the Puppy class. However, this is a small puppy that does not have a strong bark yet. We can modify the talk() method to print out “awoo” instead. Another thing with polymorphism is that the parent class would not change due to a change in its child class. Even though we changed the Puppy’s talk() to an “awoo” the Dog will still have a “Woof”. Polymorphism allows for class specific behavior and more reusable code.
What is Agile/Agile Methodology Process
Agile is an iterative approach to project management and software development that helps teams deliver value to their customers faster and with fewer headaches. Instead of betting everything on a “big bang” launch, an agile team delivers work in small, but consumable, increments. Requirements, plans, and results are evaluated continuously so teams have a natural mechanism for responding to change quickly.
The Agile methodology is a way to manage a project by breaking it up into several phases. It involves constant collaboration with stakeholders and continuous improvement at every stage. Once the work begins, teams cycle through a process of planning, executing, and evaluating. Continuous collaboration is vital, both with team members and project stakeholders.
Difference between Agile and Waterfall
Waterfall and Agile are two popular software development methodologies that have different approaches to project management, planning, and execution.
Waterfall methodology is a linear, sequential approach to software development. In a waterfall model, each phase of the software development lifecycle (SDLC) must be completed before moving on to the next phase. The phases are typically requirements gathering, design, implementation, testing, deployment, and maintenance. Waterfall methodology is often used in large-scale projects where the requirements are well-defined and there is little need for flexibility or changes during the development process.
Agile methodology, on the other hand, is a more iterative and flexible approach to software development. In an Agile model, the development process is broken down into smaller, more manageable phases or iterations, with each iteration focused on delivering a working product incrementally. Agile emphasizes collaboration, communication, and continuous feedback between the development team and stakeholders. Agile methodologies are often used in projects where the requirements are subject to change, or where there is a need for frequent feedback and adjustments during the development process.
Here are some key differences between Waterfall and Agile methodologies:
**Planning**: Waterfall requires a detailed plan upfront before the development process begins, while Agile emphasizes ongoing planning and reevaluation throughout the development process. **Flexibility**: Waterfall is less flexible and allows for less change during the development process, while Agile is more adaptable and allows for more changes and adjustments as the project progresses. **Delivery**: Waterfall delivers the product at the end of the project, while Agile delivers working increments of the product throughout the development process. **Communication**: Waterfall emphasizes documentation, while Agile emphasizes communication and collaboration between team members and stakeholders. **Testing**: Waterfall typically conducts testing at the end of the development process, while Agile conducts testing throughout the development process.
In summary, the Waterfall methodology is best suited for projects with well-defined requirements and a clear path to completion, while the Agile methodology is best suited for projects that require flexibility, frequent feedback, and ongoing collaboration.
5 Main Features of OOP
The main features of object oriented programming are as follows:
Classes Objects Abstraction Polymorphism Inheritance Encapsulation
What is Object Oriented Programming?
Object-oriented programming, or OOPs, is a programming model which breaks down a problem in terms of classes and objects. OOPs allows the creation of several instances of a class called objects, hence facilitating code reuse. Some object-oriented programming languages are C++, Java, Javascript, Python, etc.
The four main pillars or features of object oriented programming include Abstraction, Polymorphism, Inheritance, and Encapsulation, or you can learn it as A PIE to recall all of them easily.
What is a Static Variable
In programming, a static variable is a variable that retains its value even after the function or block in which it is declared has completed its execution. It is a type of variable that is allocated memory once, and its value persists throughout the lifetime of the program.
A static variable is declared with the ‘static’ keyword in the function or block where it is defined. The keyword static tells the compiler that the variable should not be destroyed when the function or block exits, and its value should be retained for future calls.
Static variables are commonly used in programming for various purposes. For example, they can be used to count the number of times a function has been called, or to cache data for faster access. In object-oriented programming, static variables can also be used to represent shared data across all instances of a class.
It’s important to note that static variables have different properties and behavior than non-static variables. They have a fixed memory location, and their value is shared across all instances of a class or all invocations of a function. Therefore, care should be taken when using static variables to avoid unintended consequences or unexpected behavior.
What is private/public/static
In object-oriented programming, private, public, and protected are access modifiers used to control the visibility and accessibility of class members, such as variables, methods, and inner classes. These access modifiers are used to enforce encapsulation, which is a fundamental principle of object-oriented programming that emphasizes the hiding of implementation details and providing controlled access to the internal state of objects.
Here’s a brief description of each access modifier:
private: Members that are marked as private are only accessible within the class in which they are declared. They are not visible outside the class and cannot be accessed by other classes or instances of the same class. Private members are typically used to encapsulate implementation details or to hide sensitive data. public: Members that are marked as public are accessible from any class or instance, both within and outside the same package or module. Public members are typically used to provide a well-defined interface to the class, and to allow other classes to access or modify the state of the object. protected: Members that are marked as protected are accessible within the same class, subclasses, and other classes within the same package or module. Protected members are typically used to encapsulate implementation details that are shared among subclasses or to provide a more flexible and customizable interface to the class.
It’s important to use access modifiers appropriately to enforce encapsulation and prevent unwanted access or modification of class members. By carefully controlling access to the internal state of objects, you can ensure that your code is more modular, easier to understand, and less prone to errors.
What is function overloading
Function overloading is a feature in object-oriented programming languages that allows you to define multiple functions with the same name but with different parameter lists. Each function with the same name is said to be an “overloaded” function, and the selection of which overloaded function to call is based on the number, types, and order of the parameters passed in the function call.
When you call an overloaded function, the compiler matches the arguments you passed with the parameter list of each overloaded function and selects the most appropriate one to call. The matching process takes into account the number of arguments, their types, and their order. If there is an exact match, the compiler chooses that function. If there is no exact match, the compiler tries to find a function that can be called by implicitly converting the arguments to the required types.
For example, suppose you have a function named “calculate” that takes two integer arguments and returns their sum. You can define an overloaded version of “calculate” that takes two double arguments and returns their sum as well. When you call “calculate” with two integers, the first version of the function will be called, and when you call it with two doubles, the second version will be called.
Function overloading is a powerful feature that allows you to write more expressive and flexible code, as well as making your code easier to read and maintain. It allows you to reuse function names and provide a consistent interface to your code while allowing it to handle different types of data. However, it’s important to use function overloading carefully to avoid confusion and ambiguity in your code.
What is pointer vs reference? When would you use 1 over the other?
Pointers and references are two powerful concepts in programming languages, particularly in languages like C++ where memory management is important. Both pointers and references allow you to indirectly access and manipulate data stored in memory, but they have some key differences.
A pointer is a variable that holds the memory address of another variable. You can dereference a pointer to access the value stored in the memory address it points to. Pointers can be used to dynamically allocate and deallocate memory, manipulate arrays and strings, and implement data structures such as linked lists and trees. Pointers can be reassigned to point to a different memory location at runtime.
A reference, on the other hand, is an alias for another variable. When you create a reference, you essentially create a new name for an existing variable. You can use a reference to access and manipulate the value of the original variable directly, without having to dereference a pointer. References are particularly useful in situations where you want to pass variables by reference to a function, so that the function can modify the original variables instead of creating copies.
When to use pointers vs references depends on the specific requirements of your program. Here are some general guidelines:
Use pointers when you need to allocate or deallocate memory dynamically, or when you need to manipulate arrays or strings. Use references when you want to pass variables by reference to a function, or when you want to create a new name for an existing variable. Use pointers when you need to work with the low-level details of memory management, such as when implementing data structures or interfacing with system-level APIs. Use references when you want a more intuitive and higher-level approach to working with data, particularly when passing arguments to functions.
In general, it’s best to use references whenever possible, as they are safer and more intuitive than pointers. Pointers can be more error-prone, as they can be null or uninitialized, and can cause memory leaks and other issues if not used carefully. However, pointers are still an essential tool for many programming tasks, particularly in languages like C++ where low-level memory management is important.
Difference Between Java and Python
Java and Python are both popular programming languages used in a variety of applications. Here are some key differences between the two:
Syntax: Java and Python have different syntaxes. Java has a more verbose and structured syntax, while Python has a more concise and flexible syntax. For example, in Java, you need to explicitly declare the type of a variable, while in Python, you don't. Performance: Java is typically faster than Python because Java code is compiled into machine code at runtime, while Python is interpreted. However, the performance difference between the two can vary depending on the application and implementation. Memory management: Java uses a garbage collector to manage memory automatically, while Python uses reference counting and garbage collection. This means that Java applications are less prone to memory leaks and other memory-related issues. Object-oriented programming: Both Java and Python are object-oriented languages, but Java has a more strict implementation of object-oriented programming concepts such as encapsulation, inheritance, and polymorphism. Python, on the other hand, allows for more flexibility in object-oriented programming. Platform independence: Java is platform-independent, meaning that Java code can run on any platform that has a Java Virtual Machine (JVM). Python, while often portable, is not strictly platform-independent. Community and libraries: Both Java and Python have large and active communities, with extensive libraries and frameworks available for both languages. However, Python is often preferred for its large and well-supported data science and machine learning libraries.
Overall, Java and Python are both powerful and versatile programming languages with their own strengths and weaknesses. The choice of which language to use often depends on the specific requirements of the application, the development team’s preferences, and the available resources.
Difference Between Shallow and Deep Copy
In programming, a shallow copy and a deep copy are two ways of copying objects from one variable to another.
A shallow copy creates a new object that points to the original object’s memory location. In other words, a shallow copy duplicates the reference to the original object. This means that if any changes are made to the original object, they will also be reflected in the copied object. A shallow copy is therefore a bit like creating a pointer or reference to the original object.
On the other hand, a deep copy creates a new object and copies all of the original object’s data to the new object. This means that the new object is completely independent of the original object, and changes made to the original object will not be reflected in the copied object. In other words, a deep copy creates a new object with a completely separate memory location.
To illustrate the difference between a shallow copy and a deep copy, consider a simple example of a list of integers:
In programming, a shallow copy and a deep copy are two ways of copying objects from one variable to another.
A shallow copy creates a new object that points to the original object’s memory location. In other words, a shallow copy duplicates the reference to the original object. This means that if any changes are made to the original object, they will also be reflected in the copied object. A shallow copy is therefore a bit like creating a pointer or reference to the original object.
On the other hand, a deep copy creates a new object and copies all of the original object’s data to the new object. This means that the new object is completely independent of the original object, and changes made to the original object will not be reflected in the copied object. In other words, a deep copy creates a new object with a completely separate memory location.
In summary, a shallow copy duplicates only the reference to an object, while a deep copy creates a new object with a completely separate memory location and copies all of the original object’s data. The choice of which copy method to use depends on the specific requirements of the program.
What is a primary key?
A primary key is a unique identifier for a record or row in a database table. It is a column or a set of columns that uniquely identifies each row in the table. The primary key is used to ensure the integrity and consistency of data in the table.
A primary key has the following properties:
Uniqueness: Each row in the table must have a unique value for the primary key column(s). Non-nullability: The primary key column(s) cannot have a null value. Immutability: The value of the primary key column(s) cannot be changed once it is assigned to a row. Consistency: The value of the primary key column(s) must be consistent across all tables that reference the same data.
A primary key is used to identify and link related data across different tables in a database. It is also used to enforce referential integrity, which ensures that a row in one table corresponds to a valid row in another table.
In most database management systems (DBMS), a primary key is implemented as a unique index on the primary key column(s). This index allows the DBMS to quickly retrieve rows based on the value of the primary key column(s).
What is a class?
In object-oriented programming, a class is a blueprint or template for creating objects, which are instances of the class. A class defines a set of attributes and behaviors that are shared by all objects of that class.
Attributes, also known as data members or fields, are variables that hold the state or characteristics of an object. Behaviors, also known as methods or member functions, are functions that define the actions or operations that an object can perform.
Difference between OOP and Procedural Programming
The main difference between object-oriented programming (OOP) and procedural programming is the way they model the problem and organize the code.
Procedural programming focuses on the sequence of steps that are taken to solve a problem. It is based on the idea of a step-by-step algorithm, where the program is divided into a series of functions or procedures that are executed in a specific order. Each function takes inputs, performs a set of operations, and produces an output that is passed to the next function.
Object-oriented programming, on the other hand, models the problem as a collection of objects that interact with each other to achieve a goal. An object is an instance of a class, which is a template for creating objects with specific attributes and behaviors. Objects communicate with each other by sending messages and invoking methods, which are functions that are associated with a specific object.
Some of the key differences between OOP and procedural programming are:
Data and behavior: In OOP, data and behavior are encapsulated together into objects, which can hide their implementation details and provide a clean interface for other objects to use. In procedural programming, data and behavior are separated, and functions or procedures manipulate data directly. Inheritance and polymorphism: OOP supports inheritance, where a class can inherit properties and behaviors from a parent class, and polymorphism, where objects of different classes can be treated as if they belong to a common superclass. Procedural programming does not support these features. Modularity and reusability: OOP promotes modularity and code reuse, as objects can be created from existing classes and reused in different contexts. Procedural programming can also be modular, but the level of modularity may be lower than in OOP. Code organization: OOP is typically organized around objects and their interactions, whereas procedural programming is organized around functions or procedures.
Overall, OOP provides a more flexible and modular approach to programming, and is well-suited for complex systems with many interacting components. Procedural programming, on the other hand, is simpler and more straightforward, and may be more appropriate for smaller projects or systems with fewer components.
What is memory leak and how to avoid?
Memory leak occurs when programmers create a memory in heap and forget to delete it.
The consequences of memory leak is that it reduces the performance of the computer by reducing the amount of available memory. Eventually, in the worst case, too much of the available memory may become allocated and all or part of the system or device stops working correctly, the application fails, or the system slows down vastly .
Memory leaks are particularly serious issues for programs like daemons and servers which by definition never terminate.
To avoid memory leaks, memory allocated on heap should always be freed when no longer needed.