0%
Still working...

Pragmatic shorts #2 – A pragmatic approach (Part 2)

Hello and welcome to the second edition of Pragmatic Shorts! For more context check the introduction to short #1, A pragmatic philosophy, also you may want to check the first part of short #2 which I decided to split in 2 separate posts

I highly encourage you to read David Thomas and Andrew Hunt’s great book, The Pragmatic Programmer. This book is an awesome compilation of years of knowledge and experience from the hands of experts in software engineering.

My copy has a lot of bookmarks and highlights from the parts that has directly impacted my work!

Pragmatic Shorts, are cheat-sheet like space with a point like summary of the parts of this book that I’ve considered most relevant in my day to day job as a Software Development Engineer.

A Pragmatic Approach (Part 2)

There’s a set of approaches you can embrace while developing a software or a system that your future self, other team members and customers will thank you at some point. You may want to see this a proactive efficient approach in opposition to a well known Damage’s Analysis after neglecting some of this concepts in a hard to maintain software.

What do you do when you need to change a critical piece of your system? How do you communicate and adapt your design intention without having to spend a lot of time and effort? What can you do to know your product is in the right direction? When will your project be ready?

Let’s take a look at some points to consider when trying considering the latter questions.:

Reversibility

  • There are no final decisions – Mistakes lie in assuming that any decisions is cast into stone and critical decisions aren’t easily reversible. With every critical decision the project team commits to a smaller target and a narrower version of reality with fewer options. By the time many critical decisions have been made, the target becomes so small that if it moves, you miss by a huge amount.
  • When you rely heavily on something you can almost guarantee that it will change. There’s always more than one way to implement something.
  • Sticking to DRY principle, decoupling and using external configuration will help to have fewer critical decisions.
  • Think about maintaining flexible architecture, deployment and vendor integration.
  • You can’t plan for having architectural volatility, but you can make it easy to change, hiding third-party APIs behind your own abstraction layers, breaking code into components, splitting monolithic applications.

Prototyping/Post-it notes:

  • Offers a chance for correction at a much reduced cost since it doesn’t need to be code-based, you can prototype in a piece of paper like a post it note.
  • You prototype dynamic things like workflows and application logic, as well as things like a UI with a non-functional mock-up.
https://unsplash.com/photos/o2305170alM
UI mock up prototype
  • Is useful to prototype anything that carries a risk! As anything that hasn’t been tried before or that is totally critical to the system.
  • It is intended to be used at a higher level, higher than the rest of the project.
  • For architecture prototyping none of the individual modules need to be functional or even have code. You want a proof of concept of how the system holds as a whole.
  • What to ignore when prototyping:
    • Correctness → Dummy data will do fine.
    • Completeness → It may work in a very limited sense.
    • Robustness → Error checking or testing may be skipped here.
    • Style → Doesn’t need to be much documented.
  • Avoid prototyping when:
    • People don’t fully understand this is disposable and not final code.
    • Your prototype may be easily misinterpreted (in this case better use a Tracer Bullet).

Tracer bullets

  • How would you hit a target in a complex and shifting world? Will depend on the nature of the device you’re aiming with.
  • Use tracer bullets to hit the target – In the real world, tracer bullets are fired alongside real bullets to train soldiers to refine their aim, as a pragmatic real-time feedback. Same can happen in software development, tracer bullets give immediate feedback under actual conditions with a moving goal.
  • If your users never saw the system, you are shooting in the dark, requirements are vague, you may also have many unknowns (algorithms, technologies, etc). You won’t desire the classical specify the system to death approach. Rather look to get feedback soon and adjust your aim.
https://unsplash.com/photos/bPiuY2ZSlvU
Immediate feedback
  • The first tracer bullet in software development is a Hello world project that runs and compiles successfully. Then look for areas of uncertainty in the overall application and add an skeleton to make it work
  • Advantages of Tracer bullets:
    • Visibility: Your user will know they are seeing something immature that is in progress to their goal giving real time feedback on how close you are to their needs in each iteration.
    • Developers built a structure to work in: End-to-end interactions of you application in each iteration will make people productive and encouraged.
    • Have an integration platform: The system is connected end-to-end in an environment to which you can add new pieces of code once they have been unit-tested rather than a big-bang iteration. The impact of a new change is more limited a debugging/testing times are faster.
  • Tracer bullets don’t always hit the target and there are situations where you won’t be 100% certain of where you are going. However, a small body of code has low criteria, hence is quick and easy to change
  • TracerCode vs Prototyping: A prototype will explore specific aspects of your final system, it will help you make a decision before you start or to start again. A tracer bullet applies once you know how the application holds as a whole, so you can develop an architectural skeleton.
  • Also prototyping generates disposable code, while TracerCode is complete, forming part of the final system.

Domain languages

  • The language you use on a daily bases influence on how you think about communicating.
  • Write code using the vocabulary of you application domain, even using vocabulary, syntax and semantics of the domain’s language
  • Don’t spend more effort or time than you will save by using a domain language:
    • An internal domain language (ex. RSpec, Fenix) takes advantage of it’s host language, making it more powerful and cost free, however they are bounded by syntax and semantics.
    • An external domain language (ex. Cucumber, Ansible) won’t have such restrictions as long as you can write a good parser which is not a trivial work.
  • External domain languages are, as a general suggestion, recommended over internal when possible. A good example is to prefer external when there’s code that will be written by users of your application.
  • A cheat for creating an internal domain language is to just write functions to do the work rather than a bunch of metaprogramming.

Estimating:

  • A good trick to have a better estimation of something you are not sure is to ask to someone who has already done it.
  • Be sure to understand what you need, have a grasp of the scope of the domain and make it a habit to think about the scope before starting a guess
  • Build a model for the system, often a mental model will make you think in the steps you need to use during development alongside a rough picture of how the system will be implemented, leading to discoveries of underlying patterns and process not visible in the surface. Also will give visibility to some inaccuracies.
  • It is good to decompose a model into components and discover the mathematical rules that describe how these components interact. Each model has parameters that affect the overall model, identify each and then assign a value (or weight) to it. With this work out which parameters could have the most impact to concentrate to get them as right as you can.
  • Use passed estimation to re-calibrate your estimation system, see how close or far you were. A bad estimation is a good place to explore what happened and why you missed so far.
  • A good approach: have a optimistic, a likely and a pessimistic and arrange them into a dependency network, so you can use simple statistics to identify likely, best and worst times for the overall process.
  • Also a good tool to re-calibrate estimations is to do the project and learn about it’s times along the way, with every slice of functionality:
    • Check requirements
    • Analyze risk
    • Design, implement, integrate
    • Validate with the users
  • Iterate the schedule with code – Understand the team, it’s productivity, and the environment as key factors to determine the schedule
  • When asked for an estimate a good answer is “I’ll get back to you”. You’ll get better results by slowing down the process and work on your estimation system before giving a hard number
  • The units you use will mark a huge difference, 130 days sounds much different than 6 months, a good time scale is the next:
DurationEstimate in
1 – 15 daysDays
3 – 6 weeksWeeks
8 – 20 weeksMonths
20+ WeeksThink for a while

1 Comment

  1. […] A pragmatic approach (Part 2) […]

Comments are closed.

Recommended Posts