The Seen and The Unseen Part 1

Shweta Barge
AlgoAsylum
Published in
6 min readJul 21, 2020

Written By Shweta Barge, Shrirang Karandikar.

Image Source

Programming is a skill anyone can learn with time and effort. I’ve been programming for four years and I am still learning. My general approach for learning any programming language was to understand the syntax and eventually develop expertise in this language by taking up problems and solving them in software. However, “proper” software development follows a procedure of gathering requirements and analyzing, designing, and developing implementations that meet those requirements. I started adding these steps to my practice. As I started gaining more experience, I realized that there is more than just meeting the requirements.

The Seen and The Unseen is a series of articles. Part 1 talks about different aspects of programming.

1. The Seen and The Unseen Part 1

2. The Seen and The Unseen Part 2 — Geometric Series

3. The Seen and The Unseen Part 3 — Exponential function

4. The Seen and The Unseen Part 4 — Trigonometric function

Part 2, 3, and 4 explain with an example, what effect do different implementation choices have on these aspects and how they affect the software.

With apologies to Frederic Bastiat’s “That Which is Seen, and That Which is Not Seen”, I refer to the concept of writing a program that meets the requirements as the seen aspect of it. However, software development is more than this. Good software is maintainable, ensures correctness, and is reliable. This is what I call the unseen part of it.

“That Which is Seen, and That Which is Not Seen” explains how a habit or a law in the department of economy gives birth to not only an effect but also a series of effects. He refers to the immediate effect of law as ‘That Which is Seen’ and then a series of effects unfold in succession — ‘Which is Not Seen’. To briefly explain this concept I will use ‘The Broken Window’ example from the essay. A window in a shop is broken. It costs shopkeeper six francs to fix the window. These six francs is the glazier’s pay for fixing the broken window. What is seen is that the broken window caused the money to circulate. What is not seen is if the window was not broken the shopkeeper would have used this money somewhere else, perhaps to buy new shoes. This way he could’ve enjoyed both the shoes and the window. Now he cannot do that because his six francs were spent on the window. Every action or decision thus has a seen and an unseen effect.

In the field of programming what is seen is the final implementation of the software itself. What is not seen is how a decision taken to implement affects the performance and accuracy of the software. Maybe a loop runs for a thousand iterations and that’s not necessary. A few hundred iterations could give the same output — seen, and the decision to stop earlier can have a great impact on the performance — unseen. In this article, I will show how different decisions taken during implementation affect the seen and the unseen using example of Taylor series. To improve the “seen” — meeting the specifications, we need to invest time in the “unseen” — performance, correctness, and the frameworks for efficient implementation.

Performance

As a programmer, I have written codes that correctly solve a given problem. Writing codes involves thinking of some logic and implementing it. The first implementation is called naïve implementation. This naïve implementation works fine on a single system, for a single user and a limited amount of data. But when this implementation is used in the real world it faces different challenges. The volume and value of input data may be very different, and it has to deliver the results on time. If the problem uses real-time data then the time taken to generate the output will determine whether the output is valid or up-to-date. All these characteristics determine the performance of a program or software. An optimized implementation will have reduced computation time and hence better performance. Therefore to reduce computation time a programmer needs to make the right decisions during implementation. The end-user sees the implementation giving the correct result in a satisfactory amount of time. What is not seen is the analysis and optimizations that enable the software to deliver such performance.

Visualization

Right from school visualization has helped me understand and remember things better rather than just looking at paragraphs and numbers, and this may be the case for you as well. Be it flow charts, mind maps, bar graphs, or diagrams, visualization helps in understanding and retaining the information in a faster and better way. Similarly, data visualization has its own importance in programming. Data scientists work with a huge amount of data and use data visualization to gain insight, understand relations and patterns existing in the data. I used visualization with similar goals — to gain insight into the performance of my implementations. This helps easily identify trends and anomalies, and guide the optimization process. I also used visualization strategies to monitor my changes and easily keep track of correctness. In the end, I could see a faster and more accurate function. All this visualization of data that helped in optimization and testing goes unseen. Visualization helps in understanding other unseen aspects which in turn helps in making the seen better.

Testing

After writing a program I would usually test it for a few cases to check whether it gives the right output. I soon realized that these few examples do not capture all the corner cases, and need a much larger test suite, which I do not want to run manually! As I work on improving the performance of my implementation, I need to ensure that the changes are not introducing any bugs in the implementation. Automated testing helps in ensuring correctness, and the easier the process is, the more quickly I can identify errors — as soon as I’ve introduced one.

I illustrate the above concepts by implementing a Taylor Series expansion for calculating a few mathematical functions. Let’s take a look at what a Taylor series is.

Taylor Series

A Taylor Series is an expansion of a function into an infinite sum of terms, with increasing exponents of a variable. Any continuous function can be expressed as Taylor Series.

I select the geometric, exponential, and trigonometric functions. for implementation:

The geometric series

A geometric series is a series where successive terms have a constant ratio also called the common ratio. Every term is a product of the previous term and the common ratio.
𝑎 is the first term. 𝑟 is the common ration

The exponential function

The trigonometric functions

I start with the testing framework. Rather than testing different implementations separately, I create a generic test function that takes my implementation, a reference (correct) implementation, and a set of test cases that are relevant to the function being tested. I could print out the differences between the two implementations, but visualization is much more powerful. Here is TheSeenAndTheUnseenTest()

Writing a generic function helps in ensuring maintainability. It avoids the repetition of code.

“Don’t repeat yourself. Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” — Andy Hunt and Dave Thomas.

If I had a personalized testing function for every implementation, I would be writing the same thing in different places. This would increase my work in writing, and debugging of the code. At the same time, if I want to make a change in the testing function, there is a possibility that some part of the code is not updated. Writing a generic code helps in maintaining software and maintainability is an unseen aspect of software development.

Next, Let’s look at the Taylor series expansion of the geometric series explaining the effects of different implementation choices on the unseen on the seen in Part 2.

--

--