Convert Design to Code
May 12, 2020
You can see some sample here from different oop languages:
When we write the class for a spaceship in our video game, we’re creating the blueprint to build the spaceship. Now, the blueprint itself isn’t a usable object, but from that class, we can instantiate or create one or more instances of that type of spaceship object. And to do that, many object-oriented languages use the keyword new. In Java, we’d say Spaceship then the variable name myShip
equals new Spaceship with open and close parenthesis.
Instantiation
Identifying inheritance situations
Inheritance describes an is a relationship between objects. Now that’s not some technical term. It’s just plain language, how you would talk about things in the real world. So I could say that a star fighter is a spaceship, or a cargo shuttle is a spaceship. Both of those make sense. But saying that a cargo shuttle is a star fighter does not. Those two things have a different relationship with each other, not inheritance. – I find that using the phrase is a kind of, or is a type of, is sometimes easier to use than is a. So a star fighter is a kind of spaceship, or a cargo shuttle is a type of spaceship.
Inheritance can also extend multiple levels deep. If there are going to be other types of vehicles in our game, than we might create a higher level vehicle class for spaceship to inherit from. The is a relationship still holds true here. A warp cruiser is a spaceship, and a spaceship is a vehicle. – Now, a word of warning. It’s common for new object orientated developers to overemphasize inheritance. And to come up with class diagrams with five levels of inheritance for everything. Don’t go looking for inheritance, because inheritance usually announces itself. If you find yourself creating one or two class diagrams without any inheritance, don’t worry. It’s perfectly fine.
Abstract Class
Not every method in an abstract class has to be abstract. The abstract class can have a mix of abstract methods and methods that it actually implements. In class diagram italics are used to indicate that it’s abstract and that abstract method serves as a sort of placeholder for each of the subclasses to let them know that they’ll need to individually implement it And of course, each of the subclasses are free to implement any additional methods that are unique to them. Some languages like Java or C sharp let you explicitly mark a class as abstract when declaring it which prevents the language from allowing that class to be instantiated. You must inherit from it with another subclass, implement the abstract methods in that subclass and then you can use that subclass to actually instantiate an object.
Interfaces
Interfaces are another common form of abstraction that’s supported by many object-oriented languages. An interface is a programming structure that declares a set of methods for a class to implement, but the interface itself doesn’t contain any functionality. There’s no implemented code or behavior. It’s just a collection of method signatures to specify a service.
When we defined a new class and choose to implement a specific interface, it’s like signing a contract, promising that the new class we’re defining will implement all of the methods in that interface. But, we’re free to implement the inner workings of those methods however we want as long as the method names, inputs, and outputs match the interface.
Interface vs. Abstract class
It sounds to me like interfaces are just an extreme version of abstract classes where none of the methods are implemented and everything’s abstract. – Interfaces and abstract classes can seem similar at first. But they serve different purposes. Interfaces are used to represent a capability that a class implements. Whereas and abstract class represents a type that another class can inherit from.
Consider the abstract Spaceship class that our CargoShuttle class inherits from. It represents a type of object with an is a relationship for inheritance. The CargoShuttle is a Spaceship. Now, let’s look at the Asteroid class next to it. Side-by-side it’s obvious that Spaceships and Asteroids both have a move method. But Asteroids and Spaceships are completely different things. The only thing they have in common is that they both move around in space. it would not make sense for Asteroid to inherit from Spaceship. An Asteroid isn’t a type of Spaceship. However, moving is a capability they both share. So they could both implement a common interface for Movable objects.
In UML, we represent an interface using a box that looks similar to a class. But we include a tag with double angle quotes to indicate that it’s an interface. And, for classes that implement this interface, we use the same arrow as inheritance, but with a dashed line instead of a solid line to indicate that it’s implementing an interface rather than inheriting from a class.
Now while most languages only allow a class to inherit from one other class, interfaces don’t have that restriction. A class can implement multiple interfaces. An example of when this would be useful is if we have a list or collection storing all of the objects in our game. To update the display, we can iterate through each of the potentially unknown objects in that list and simply check if it supports the Drawable interface. So we’ll call its draw method to update it on the screen.
In fact, there’s a well known saying that good developers program to an interface not to an implementation because it’s a developer’s choice how to implement those methods rather than being provided with that code.
interfaces are often a more future friendly way of programming than using inheritance.
Aggregation
Aggregation is often referred to as a has a relationship, as opposed to the is a relationship of inheritance. I wouldn’t say that the fleet is a spaceship, but I could say that the fleet has a spaceship. perhaps a better phrase for an aggregation relationship than has a is uses a, or uses many. The fleet uses many spaceships, and if the fleet ceases to fly together, the individual spaceships will continue to exist on their own.
Composition
A more specific form of aggregation is something called composition. Like aggregation, composition is based around a has-a relationship between objects but it specifically implies ownership. I might say that a spaceship has an engine, but more accurately, I should that the spaceship owns the engine. Composition implies ownership and an engine has no meaning or purpose in the system without a spaceship.
A key difference between composition and aggregation is that in a composition situation, if the owning object is destroyed by, say, an asteroid. – The contained objects are destroyed, too. The ships engine, its shield, its weapons, those are all gone. Now, although aggregation may not always be worth showing in a UML diagram, composition often can be and it’s represented with a filled-in diamond. If the lifetime of an object is dependent on another object’s existence, that’s usually worth showing, if for nothing more than to prompt the idea that, when you’re defining the owning class, you may need to write constructor and destructor methods to take care of creating and deleting those internal objects. As with aggregation we can use multiplicity symbols to indicate that a spaceship is composed of one or more engines. And we can show other objects that the spaceship has as well, giving it a shield and possibly some weapons, too.
Putting it all together gives us our final class diagram. The output of our object-oriented design process, and it’s something we can actually use to start writing code. – But that doesn’t mean this diagram is finished and set in stone. I’m sure as we start turning this into actual code, we’ll discover new problems and have to make changes. But these diagrams give us the starting point we need to begin implementation.
OOP in different languages
Development principals
SOLID
DRY
DRY principle applies to more than just software. We also want to avoid duplication in things like documentation, diagrams, and database schemas. There should only be a single source that can be referenced elsewhere.
YAGNI
A common trap that many new, overzealous programmers fall into is trying to make their code too extensible, and adding hooks for every possible variation of everything they could ever possibly see. Abstraction is good, and we want to be able to extend our programs, but abstracting too much will mean more testing, more debugging, and code bloat. We don’t want to waste time on things that will never be used.
Design patterns
Creating software that merely works is tough enough, but writing code that’s also flexible, maintainable, and extensible, that’s a real challenge. You should expect your code to undergo multiple changes throughout the development process. And even after being released, most modern applications receive updates to improve features or fix bugs. If you don’t structure your code well from the beginning, making those changes can be a major burden. This is where using a design pattern can be really useful. Design patterns are common, repeatable solutions for creating software programs. They define code architectures and best practices for solving common software design problems that occur again and again across all kinds of applications, from business apps to games. Now, design patterns aren’t strict standards with exact lines of codes to use, rather they’re templates to help structure your code in a smart way. So you’ll spend less time refactoring it and more time adding new cool features.