Published August 7, 2019
There is no perfect way to code, but creating reusable behaviors and components with SOLID coding principles seems to be one secret to fast iteration and code reuse.
What is software architecture? The answer is multitiered. At the highest level, there are the architecture patterns that define the overall shape and structure of software applications. Down a level is the architecture that is specifically related to the purpose of the software application. Yet another level down resides the architecture of the modules and their interconnections. This is the domain of design patterns, packages, components, and classes. Robert C MartinSOLID is an acronym standing for :
Design Principles and Design Patterns
https://web.archive.org/web/20191116231621/https://fi.ort.edu.uy/innovaportal/file/2032/1/design_principles.pdf
- Single Responsibility Principle
- Open – Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
This one seems obvious to me. Make smaller classes. A class should do a single thing!
“A class should only have a single responsibility, that is, only changes to one part of the software’s specification should be able to affect the specification of the class.”
A class should only have a single reason to fail. Each component should have a single responsibility. Each behavior should be separated out into its own component. These components should not require any drag-and-drop, they should instead communicate via Actions.
Open Closed Principle
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. A class is closed, since it may be compiled, stored in a library, baselined, and used by client classes. But it is also open, since any new class may use it as parent, adding new features. When a descendant class is defined, there is no need to change the original or to disturb its clients. Use interfaces! Seems like an IOC principle as well. I could refactor weapons based on this, so that each weapon is an IWeapon. It would be nice to take this further so that IWeapons automatically are assigned so there is no drag and drop needed.Below are a few classes. ShapeBehavior is the base class for shapes, without the specific behaviors for shapes defined. I’ll have to do that on the child classes.
public abstract class ShapeBehavior : Monobehavior
{
public float Height {get;set;}
public float Width (get;set;}
public abstract float Area();
}
public RectangleShape : ShapeBehavior
{
public override float Area ()
{
return Height * Width;
}
}
public CircleShape : ShapeBehavior ()
{
return Radius * Radius * Mathf.PI;
}
Liskov’s Substitution Principle
Functions that use pointers to base classes must be able to use objects of derived classes without knowing it. The code should work without knowing the actual class of theBase
object.
Make sure any characteristics like fields or methods of a base class work for all kind of that base class. Otherwise, break that particular feature into a new class.
Here is a good way to look at this. There are lots of birds, but not all birds fly. A Bird, being the base class, would also have a FlightedBird base class for something like a penguin. This is described here with examples : https://www.tomdalling.com/blog/software-design/solid-class-design-the-liskov-substitution-principle
Interface Segregation Principle
Interface reuse can be costly time-wise. Don’t make them too complicated. Make them small so they only have methods of interest to them. One member or member purpose per interface. Interfaces should pretty much do only one thing, since a class can use a lot of interfaces.In Unity, interfaces are not supported.
Only internal methods use it.
public interface IStringIO{
string LoadAsString (string id);
}
public interface IJsonIO
{
JsonObject LoadAsJson(string id)
}
DO THESE instead of a larger interface that is reused amongst a lot of classes.
Dependency Inversion Principle
Use interfaces / abstractsDon’t rely on concrete references.
Interfaces are ideal
Abstract classes work too.
Unity Inspector does not support interfaces.
Unity will need abstract classes for fields, but only needs them to be designer editable.
Keep everything designer friendly.
public abstract class WeaponBase : MonoBehavior
{
public float Damage = 1f;
}
public class Sword : Weapon {}
public class Polearm : Weapon {}
I’m also quoting : https://www.youtube.com/watch?v=eIf3-aDTOOA
Comments are closed.