Freestyle Development

As an older gentle-person, I’ve seen the marketing change over time for describing what computer programmers do. When I was child it was Rapid Application Development or RAD. I think this is best term. I like the “extreme” sports nature of it and it fits with the title of this post.

Agile is a modern software development methodology emphasizing adaptive planning, evolutionary development, early delivery, and continuous improvement. It promotes flexible responses to change and collaboration among self-organizing cross-functional teams.

Agile is perhaps the single biggest contributor to shit code-bases and jaded work-forces. 2-week sprints are hilariously impotent. Especially when you have 6 meetings between sprints and your management-chain infects the process daily. They just yap and you gotta drink it.

Short-term gains become long-term losses as you churn on things that matter to no one but the guy managing the jira/kanban board. But, by all means, keep doing it. It will give me time to catch up.

Because everything is planned and binned in ~2 week sprints, and everyone is RUNNING, nobody stops to smell the flowers. Stopping to think and say, “hey maybe this is architecturally wrong.” There is no time to fix systemic issues in an agile environment. You do look like you are working really hard though and getting it done!

You keep marching towards a false goal and you can’t stop!

Agile is a management technique, not an engineering technique.

Waterfall

Agile was sold as the solution to waterfall. Waterfall is the traditional approach of planning everything out and then after a Critical Design Review (CDR) you then begin to “cut metal” or type code. I believe this approach is still superior because it forces people to think about the entire journey. Not just where they will fill up for gas next.

Agile is a hedge for management that won’t/can’t specify up front what they want/need, because often they don’t know. Only develop what you need as you need it. It would probably work if everything in software wasn’t connected.

While remodeling a house, there is no way that hanging a picture or painting a wall can cause the light-switch to now not only turn on the light, but now it flushes the toilet as well

Scrum

When a word comes from a sport like Rugby. What do you expect this process to look like? It is a giant clusterfuck. All these yappers talking about coding and project management. They are distracting you!

There is no clean code, there is no silver bullet. Work hard, pay attention, ITERATE!

MVP

The Minimum Viable Product is the only thing that Agile may be good for. Thrash, Thrash, Thrash and get something going. But a stable mature “Product” should never probably never use agile. I may die on this hill. Fail as fast as you can and build MVP in a sprint. But don’t ever call it Agile, it isn’t!

Companies / Software Ruined by Agile:

  • Excel
  • … now accepting submissions in comments

please help me fix this article into a coherent rant instead of an old man yelling at the clouds 🙂

Freestyle development is when you just have a blank text file and an idea, and you go make something out of nothing. This is the way to get started to make dreams into reality.

Further Reading

(OOPs) I Made a Class

I learned to program in the 1990s when terms like Object Oriented Programming (OOP) and Rapid Application Development (RAD) were where people thought the future was headed. The exact way I “learned” C++ was through a yellow “learn c++ in 24 hours”

I guess I got the title wrong, it was yellow for sure:

I quit programming after about 3-4 months with this book. I remember they taught OOP through making terminal GUIs for DOS. I went back to Photoshop4 and decided I wasn’t smart enough.

Perhaps teaching OOP to a BASIC programmer with mid 90s C++ is what ruined me.

Main Topic

Leaving behind the baggage, let’s discuss what Object Oriented Programming is:

Objects are like people. They’re living, breathing things that have knowledge inside them about how to do things and have memory inside them so they can remember things. And rather than interacting with them at a very low level, you interact with them at a very high level of abstraction, like we’re doing right here

Steve Jobs ’94 Rolling Stone

I tell you what, that sounds great, but also terrifying. I think his quote actually shows a deep understanding of what Objects or “Classes” are in and the consequences in OOP.

Functions

Lets look at my Ray Tracer Challenge starting point for primitives:

import math

EPSILON = 1e-6 # [0-1] - grid size or fidelity (smaller is, is smaller)

tuple4 = tuple[float,float,float,float] #vector t[3]=0, point t[3]=1

# this can be replaced with math.isclose()
def float_is_equal(a:float, b:float, eps=EPSILON)->bool:
    return math.fabs(a-b) < eps
    
def tuple_is_equal(a:tuple4, b:tuple4, eps=EPSILON)->bool:
    return \
        float_is_equal(a[0], b[0], eps) and \
        float_is_equal(a[1], b[1], eps) and \
        float_is_equal(a[2], b[2], eps) and \
        float_is_equal(a[3], b[3], eps)

def tuple_neg(a:tuple4)->tuple4:
    return (-a[0], -a[1], -a[2], -a[3])

def tuple_add(a:tuple4,b:tuple4)->tuple4:
    return (a[0]+b[0], a[1]+b[1], a[2]+b[2], a[3]+b[3])

def tuple_sub(a:tuple4,b:tuple4)->tuple4:
    return (a[0]-b[0], a[1]-b[1], a[2]-b[2], a[3]-b[3])

def tuple_is_point(tuple:tuple4)->bool:
    return int(tuple[-1]) == 1 

def get_vector(x:float,y:float,z:float)->tuple4:
    return (x,y,z,0)

def get_point(x:float,y:float,z:float)->tuple4:
    return (x,y,z,1)

Ok lets try and use this:

Its not bad, but when we start adding more features to tuple it may become harder for a reasonable person to clearly see how to use this Application Programming Interface (API) for your tuple4 type.

Towards an Object

As you can see when you start down this path, the implementation can get annoying to program against. You could, with a small penalty performance wise*, wrap this functional interface in an object.

Lets motivate this a bit by looking at this code here:

import prim1 as pr
import canvas_io as cvi

ball_pos = pr.get_point(1,1,0)
#ball_vel = pr.tuple_norm(pr.tuple_mul_scale(pr.get_vector(1,1,0), 1.25))
ball_vel = pr.get_vector(15,15,0)

env_gravity = pr.get_vector(0,-1,0)
#env_wind = pr.get_vector(-0.01,0,0)
env_wind = pr.get_vector(0,0,0)

def tick(ball_pos, ball_vel, env_gravity, env_wind):
    return (pr.tuple_add(ball_pos,ball_vel), pr.tuple_add(pr.tuple_add(ball_vel,env_gravity),env_wind))


def sim(ball_pos, ball_vel, max_iters=1e3):
    pos_t = []
    for t in range(int(max_iters)):
        ball_pos, ball_vel = tick(ball_pos,ball_vel,env_gravity, env_wind)
        pos_t.append(ball_pos)
        if (ball_pos[1] <= 0): 
            print('ball hit ground')
            break

    return pos_t


pos = sim(ball_pos,ball_vel)
canvas = cvi.get_canvas(900,550)
for p in pos:
    x = int(p[0])
    y = int(550-p[1]) #swap y axis
    #y = int(p[1])
    cvi.canvas_write_pixel(canvas, x, y, (1,2,3))

#for i in range(550):
#    cvi.canvas_write_pixel(canvas, 10, i, (0,3,0))

#for i in range(900):
#    cvi.canvas_write_pixel(canvas, i, 10, (0,0,3))

#for i in range(900):
    #cvi.canvas_write_pixel(canvas, i, i, (3,3,3))

cvi.canvas_write_pixel(canvas, 10, 10, (3,0,0))
cvi.canvas_write_pixel(canvas, 899, 539, (3,0,0))

print("writing to disk")
import time
tic = time.perf_counter()
# cvi.canvas_to_ppm(canvas, "ball2.ppm")
toc = time.perf_counter()
#print("done: " + str(toc-tic) + " seconds")

import matplotlib.pyplot as plt
plt.imshow(canvas.swapaxes(0,1))
plt.show()

Python Class

I have something to admit. I looked up how to do everything you are about to see. Take it with grain of salt, and if you have feedback please check form at bottom of post (click title to break out of infinite scroll 🙂

class Tuple4:
    def __init__(self, x:float, y:float, z:float, p:float):
        self.x = x
        self.y = y
        self.z = z
        self.p = p

    def from_tuple4(t4:tuple4):
        return Tuple4(t4[0],t4[1],t4[2],t4[3])
        
    def get_point(x:float, y:float, z:float):
        return Tuple4(x,y,z,1)

    def get_vector(x:float, y:float, z:float):
        return Tuple4(x,y,z,0)
    
    def __repr__(self): #this will give us something nice in jupyter notebook when we eval in place
        return "(" + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + ", " + str(self.p) + ")"
        
    def __eq__(self:Tuple4, other):
        return tuple_is_equal((self.x, self.y, self.z, self.p), (other.x, other.y, other.z, other.p))

    def __add__(self:Tuple4, other):
        if (isinstance(other, Tuple4)):
            return tuple_add((self.x, self.y, self.z, self.p), (other.x, other.y, other.z, other.p))
            

New Usage Pattern

Honestly, we need a part ][ of this post to continue 😉

I’m object oriented out. I ❤ Functions. Teaser for next post (objects are entire programs onto themselves, this can be troublesome)

Jupyter Notebook

sorry about that… some bugs with ipython forbidden. Main github project: https://github.com/robmurrer/pyrtc