The Pragmatic Programmer: Part 2

atb00ker
4 min readNov 22, 2020

Chapter 4. Pragmatic Paranoia

23. Design by Contract

Trust between software can be maintained by contracts. In design by contract, if all the preconditions are met, a routine must guarantee that the post conditions would be met. Designing a program that does no or less than what it claims to do is the heart of design by contract.

“Do One Thing and Do It Well”
— Unix philosophy

24. Dead Programs Tell No Lies

Try…Catch is only a good habit when you have a rescue plan for inside the catch block. If you don’t, it’s better to let your program fail. A dead program does a lot less damage than a crippled one.

If you are looking to create a reliable software: crash early and crash often!

25. Assertive Programming

If it shouldn’t happen in the normal execution of a program, then add assertions to ensure that if it ever happens you are able to crash immediately.

26. How to Balance Resources

The simple rule: whoever allocates a resource must always de-allocate it ensures there are no imbalances in resource allocation, i.e a file that is opened is always closed by the routine opening it. When it doubt, reduce the scope of resource allocation.

27. Don’t Outrun Your Headlights

Instead of taking in large projects and delivering end-to-end six months down the road, it’s always better to take small steps towards the goal, verify with feedback that the step is correct and then continue for the next step.

Any steps that requires fortune telling instead of educated guess is an impractically large step.

Chapter 5. Bend, or Break

28. Decoupling

Decoupling is the technique to ensure orthogonality. It can be done by ensuring you don’t operate on the object state, instead, ask the object to make changes. Global variables, method call chaining & inheritance are just some examples that add coupling.

29. Juggling the Real World

Users don’t want to wait for the critical processing your application is doing. They want the applications to be reactive. Events can help in creating more interactive applications. FSMs, Observer Pattern, & PubSub Pattern are strategies for implementing events.

30. Transforming Programming

Pipelines enable us to transfer data from one function to another which allows us to think in terms of transforming data to achieve output. The advantage of thinking in transforming data to reach our goal is that it forces us to break big problems into small components.

Programming is about code, programs are about data.

31. Inheritance Tax

There is no option to inherit just one function from parent, you have to get them all to use just one, this exposes new irrelevant functions for the object. Moreover, it add coupling! Use alternatives like interfaces, delegation, mixins.

“You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.”
— Joe Armstrong

32. Configuration

All the configuration values should be outside the application separately in a file. This includes any business decision or system values that may change in the future. This file should be loaded by a class and all other classes should fetch values from this class allowing access control on our values.

Chapter 6. Concurrency

33. Breaking Temporal Coupling

Actions bundled together because they occur at the same time is temporal coupling. In the modern systems, it’s bad for two reason, it’s coupling & it stops unrelated routines from running concurrently. Activity Diagrams can help in identifying what processes can run concurrently.

34. Shared State Is Incorrect State

A shared state like global variables, files or databases which are accessible to multiple concurrent routines, is bound to create hard to reproduce bugs. Semaphore or mutex can ensure sequential access of the shared state.

35. Actors and Processes

The actor model allows us to create a system that does not have a shared state, Each actor has a capability of invoking other actors and process each message sequentially. This enables each process to be sequential but the system as a whole to be concurrent.

36. Blackboards

Message transfer systems like Kafka & RabbitMQ enable us to implement a laissez-faire system to avoid writing complex workflows and implement actions triggered when a message is received. This enables our systems to be concurrent by executing an action on request.

I hope you learned something new today. Good Luck with your skill development!

--

--

atb00ker

Stoic. Existentialist. Optimistically Nihilist. Snowdenist. Friendly. Confident. Perfectionist. Creative. Playful. Programmer. Philosopher.