dashingDev is a card deck designed to inspire, improve and remind developers. Each card summarizes a core concept in software development. The deck is for people from all kinds of backgrounds and all levels of skill. The cards are not specific to any technology – they describe the fundamentals of software design & development.

Beginners get inspiration on what to learn next; more advanced developers have the chance to expand their horizons with new concepts and seasoned developers get reminded of facts they once knew.

dashingDev is neither a comprehensive teaching tool nor a full checklist for validating your design. The dashingDev cards inspire and awaken curiosity.

Patterns
standards on how to solve common design problems

Singleton, Adapter, Facade, Decorator, Observer, State, Template Method, Strategy, Factory Method, Abstract Factory

Principles
guidelines on how to design & implement good software

DRY, Optimization, Single Responsibility, High Cohesion, Low Coupling, Encapsulation, Abstraction, Open & Closed, Separation of Concerns, KISS, YAGNI, Dependency Inversion, Convention over Configuration,

Practices
useful tactics for being effective as a developer

Commenting, Code Reviewing, Spiking, Pair Programming, Performance Optimizing, Solution Sketching, Retrospective, Automated Testing, Naming

patterns

Singleton

diagram for singleton

Singleton restricts the instantiation of a class to a single instance.

useful to provide data that only exists once in the application.

provide a static method which returns the sole instance of the class & make the constructor private.

examples

Registry.instance.endpoint_for("myservice")
ConfigrationStore.instance.get("password")

Adapter

diagram for adapter

Adapter provides an alternate interface for a class to align with others.

useful to convert a class's interface if it can't be changed directly.

provide a class with the required interface while retaining a reference to the adaptee or subclassing it.

examples

XMLServiceAdapter.new(xml_serv).call(json)
DatabaseORM.new(connection).all_users

Facade

diagram for facade

Facade provides a simplified interface to a complex sub-system.

useful to reduce the effort to interact with other classes and services.

provide a single orchestration class with a context-specific interface.

examples

CloudFacade.start_vm('ubuntu', ports: [80])

Decorator

diagram for decorator

Decorator enriches or changes the behavior of an existing class.

useful to dynamically add functionality to an existing interface.

provide a class that wraps an existing object while delegating all methods to it.

examples

SubscriberNotificationDecorator.new(blog_post).publish

Observer

diagram for observer

Observer signals changes to others.

useful to notify dependent objects about modifications in the subject.

provide a registration for callbacks & trigger these when the event occurs.

examples

input_element.add_change_listener(handler)

State

diagram for state

State changes the behavior of an object depending on its status.

useful to group methods which vary based on the same condition.

provide classes for each state using a common interface and maintain a reference to the current state object.

examples

self.current_state.handle_play_pause_button

Template Method

diagram for template-method

Template method specifies an algorithm without the implementation of its steps.

useful to prescribe a sequence of steps.

provide a method that calls other methods and implement them in subclasses.

examples

if (self.can_fish?) {
self.drive_to_lake; self.fish(lake)
}

Strategy

diagram for strategy

Strategy selects between different behaviors at runtime.

useful to unify classes that differ only in the characteristics of one algorithm.

provide classes for each behavior and call the appropriate class in the context.

examples

price = total + tax_strategy.calc(total)
model.serializer_strategy.convert(values)

Factory Method

diagram for factory-method

Factory method creates objects without specifying the exact class.

useful to stay flexible which concrete class with a given interface to instantiate.

provide a method that creates an object and allow to override it.

examples

def create_configuration_store {
return Hash.new
}

Abstract Factory

diagram for abstract-factory

Abstract factory groups and insulates the creation of related objects.

useful to encapsulate knowledge which classes belong together.

provide an interchangeable factory object and delegate the creation of objects to it.

examples

current_os.gui_factory.create_button()

Still not sure what all of this is?

The cards are...

Here are some examples where the cards come in handy:

principles

Don't Repeat Yourself

diagram for dry

DRY ensures that every piece of knowledge has a single source of truth.

useful because assumptions, requirements and implementations always change.

avoid duplication in classes, comments, data schema and configuration.

violation

class Line {
attr_accessor :x1, :y1, :x2, :y2, :length
}

Premature Optimization

diagram for premature-optimization

Weighing the benefits of optimization maximizes business value.

useful because we only have limited resources for a project.

avoid optimization areas of low impact or growth.

violation
introduce a cluster deployment when the server is mostly idle.

Single Responsibility

diagram for single-responsibility

Keeping classes to a single responsibility reduces effort by isolating changes.

useful because requirements evolve along different axes.

avoid mixing responsibilities that are changed by different individuals/groups.

violation

employee.calculate_pay
employee.store_in_db

High Cohesion

diagram for high-cohesion

High cohesion balances module complexity and coupling to group only related functions together.

useful because changing overloaded classes is risky.

avoid combining methods without unifying purpose or concept.

violation
a utility class

Loose Coupling

diagram for loose-coupling

Loose coupling minimizes the knowledge required to use another class.

useful because autonomous components are easier to reuse and cheaper to adapt.

avoid large class signatures, accessing internals & bi-directional dependencies.

violation

def send_letter(user) {
address = user.db_row.first_name + ...
}

Encapsulation

diagram for encapsulation

Encapsulation hides information about the internal representation of an object.

useful because implementation strategies are likely to change.

avoid direct access to classes' members.

violation

y = point.coordinates_floats[1]

Abstraction

diagram for abstraction

Abstraction generalizes a class by reducing it to its essential concept.

useful because mental capacity is limited.

avoid copying code more than twice.

violation

teacher.postgres_storage.age += 0.7

Open & Closed

diagram for open-closed The

open & closed principle allows extension without changing existing code.

useful because modifying working code introduces risk.

avoid remodeling classes in use.

violation
global variables

Separation of Concerns

diagram for separation-of-concerns

Separating concerns focusses classes on one aspect or topic.

useful because large classes overwhelm.

avoid writing giant methods or classes.

violation

ui_widget.title = account.balance + transfer.amount

Keep It Simple, Stupid

diagram for kiss

KISS implements the solution in the easiest way possible

useful because familiarity with the current context fades over time.

avoid adding complexity for making it more beautiful.

violation

additionService.instance.process(1, 2)

You Ain't Gonna Need It

diagram for yagni

YAGNI delays adding functionality until it is absolutely necessary.

useful because upfront planning often fails to project the future accurately.

avoid investing into structures that will only pay off later.

violation
presumptive features

Dependency Inversion

diagram for dependency-inversion

Dependency Inversion lets higher-level classes prescribe lower-level interfaces.

useful because lower-level classes change more often than higher-level ones.

avoid declaring direct dependencies from top to bottom.

violation

def highlevel_method() {
LowLevel.new(1,2,3)
}

Convention over Configuration

diagram for convention-over-configuration

Convention over Configuration provides structural & configurational defaults.

useful because learning a technology's specifics may be overwhelming.

avoid explicitly asking for non-essential configuration choices.

violation

class Sale < DatabaseModel {
table_name 'sales'
}

practices

Commenting

diagram for commenting

code can only describe the how but not the why

Commenting adds valuable information beyond the operations written as code.

Code Reviewing

diagram for code-reviewing

four eyes see more than two

Code reviewing enables learning, teaching and quality assurance.

Spiking

diagram for spiking

play to learn

Spiking reduces uncertainty and allows to gain confidence in a new area.

technical spikes study and evaluate a new library or technology.

functional spikes learn about the interaction with a new feature.

Pair Programming

diagram for pair-programming

two heads – one screen

Pair programming brings teams together, raises design quality and facilitates knowledge exchange.

Performance Optimizing

diagram for performance-optimizing

save time for users & servers

Performance optimizing improves speed & resource consumption to save cost and increase user retention.

Solution Sketching

diagram for solution-sketching

program with comments

Solution sketching enables clear thinking, a deeper understanding of solutions and their trade-offs.

Retrospective

diagram for retrospective

adapt to thrive

Retrospectives improve collaboration to raise effectivity, quality and happiness.

Automated Testing

diagram for automated-testing

get fast feedback

Automated testing objectively assesses the quality of features and prevents bugs.

Naming

diagram for naming

write for reading

Naming increases speed to comprehend code and reduces bugs through confusion.

Did you like it?

Thanks for browsing through the content! I had a blast preparing the cards and it would be awesome if it is helpful to you too.

There is a real world version of the cards. I still have a few decks left over from the successful Kickstarter campain:
Get the printed version

Once I receive the confirmation, I will sprint to the mailbox as soon as I can. In the very unlikely case that I run out of decks because thousands of people order the cards, shipping may take a little longer 😁

Questions, feedback, praise and love letters are welcome :) Please contact me via dashingdev@tomrothe.de or open an issue on GitHub.

© 2022 tom rothe; impressum, agb & datenschutz