Sunday, October 4, 2020

Applying the 4 R's of conservation to Software Development

Refuse, Reduce, Reuse and Recycle. It works to reduce landfill, It also works to ensure our code and documentation stands the test of time and do not end up in the virtual landfill.

Hopefully you'll see that applying each R will make it easier to apply the others.

Refuse
Do not write code you don't need to write. This applies at different levels, here are some examples
  • Before starting to code, analyze the problem. Not every problem gets solved with automation.
  • Before automating a process, ensure it has been properly engineered. A bad process automated is still a bad process. The resulting code will be harder to maintain as people may require drastic changes when they find problems with the process. And in a worst case scenario, people won't be able to change the bad process because they depend on the system, eventually scrapping the process and the software.
  • Always verify if you need to write new code or if something else already exists. This is: Don't write code that already exists just because you don't understand or like the existing code.
  • Avoid automating one-off tasks or tasks which take longer to automate than the time they save. However, this is a recommendation where one needs to balance being lazy (not writing unnecessary code) and being replaceable by ensuring people can do what we do once we leave. So, I make an exception for things that are part of a formal process and maybe hard for other people to understand.
Reduce
When it comes to code, less is more. Less to maintain, less opportunities for bugs to creep in, easier to extend.
  • Don't write code you "may" need. Write it as you need it. This is also called YANGI (You aren't gonna need it)
  • The less code you write, the easier it is to refactor later as new needs arise.
Reuse
Reuse existing code. The likelihood that this is the first time you have faced a particular problem or that you are the first person facing a problem is fairly low.
  • Search around for existing code, either in the form of libraries, frameworks, the internet and your own code.
  • There are many new challenges in each project, by leveraging existing code, you can focus on the new challenges, and if by looking at the existing code you find it can be improved, then Recycle it.
Recycle
The fourth R encompasses four other R:
  • Refactor existing code: As your change your code, refactor it to ensure it remains as clean and simple as you can. It is a virtuous cycle where it will be easier in the future to apply the Rs of conservation.
  • Refurbish:  As you refactor code, make an effort to leave it "as new". This includes removing old code, not just working around it.
  • Repair: Eventually operating systems, libraries, standards and needs evolve, breaking code that used to work. Frequently I see people doing back-flips trying find ways to keep the old environment when it may be easier and faster to fix the code to take advantage of the new environment.
  • Re-purpose: Whenever possible, refactor for Reuse. Identify patterns that emerge as you reuse code to create libraries, frameworks or simply to eliminate redundant code. Examples of this are creating Classes and functions from "in-line" code, introduce dependency injection, expose extensible interfaces and many others.
You will see that if you and your team follow these R's, you will end up writing less code and having a cleaner code base.

(I've updated this post which was originally published in April 2014)

Saturday, September 26, 2020

Coding is easy, creating Enterprise level code is hard

In the first chapter of The Mythical Man-Month, Frederik Brooks describes the progression from a program to a programming product to a programming system to finally be part of a programming system product; and how this increases the complexity of software development. I personally think that he low-balled the differences and, these days, the difference between one extreme to the other is not just a single digit multiplier but orders of magnitude more complicated.

This may not be obvious to the casual or beginner programmer who can do wonders by knowing a language, a platform and having an itch to scratch.

This came to mind recently when I was figuring a way to have a separate background picture in each monitor on my Linux Mint system at home. Unfortunately, this is not a default functionality in the Cinnamon Desktop environment.

Very quickly I realized that I could create a large picture composed of two pictures and set it to span across monitors. Then I figured out that I could use the same technique to span single picture across monitors. I opened my image editor and created the background. Task done! ... or was it?

If you've read my other posts, you know that I am lazy. I didn't want to manually edit each picture I wanted to put as background, so I figured out I could do it with three ImageMagick commands. One to scale and crop the image(s), and two to assemble them into the final image. 

Awesome, but... I have hundreds of pictures from my last trip to Asia and I want to rotate them as my background. Executing those three commands for each picture is still faster than editing each picture manually, but I am lazier than that. I decided to create a little bash script.

The first version of the script was about 30 lines of code and it did what I wanted it to do. After all, it is a very simple task, to execute three lines of code. I had my program. Yeah! 

Still, it was 10 times the amount of code than the original 3 lines. 

The result was really pleasing and I remembered that while searching for the original solution I had found several people wanting to do the same. So being the nice guy I am, I decided to share it with others.

Sharing it meant that now I had to:

  • account for different monitor resolutions and configurations, (+18 lines of code)
  • read parameters (+75 lines of code)
  • do parameter validation,  (+38 lines of code)
  • error checking,
  • consider edge cases,
  • ensure that dependencies were installed,  (+7 lines of code)
  • follow  standards,
  • create some help (+47 lines of "code")
  • tidy-up the code to ensure it was readable by others (code elegance should not be understated)
  • Create a git repository to keep track of future versions and be able to share it.

In total, the script right now is 300+ lines of code. If you are keeping track, this is about 10 times the original script and 100 times the original 3 command I had to execute.

And this is just for a personal script which does the basic I want it to do. I have a small list of other things I'd like the script to do so eventually the script size will grow, but for now, this is good enough.

If this were an official release (programming product), I'd probably need to test it in a variety of environments, different monitor set ups, different video cards, even different desktop managers and create an installation package. All that with the associated documentation, error checking, parameters, edge cases, etc. Probably increasing another order of magnitude. Just to show a background image!

If this was a function required for an Enterprise level system, I would also need to worry about security, additional standards, logging, decomposition and integration with other components, versioning, automated unit testing, integration into a DevOps workflow and many other ancillary tasks.

Even more important: given that more people is involved in the creation of an Enterprise System, a developer needs to understand the finesses of social interactions to be really successful.

I hope you can now see how knowing a development language is just a tiny portion of what a developer must know to create production ready enterprise level systems and I also hope this blog is helping you becoming a better developer.