Ejercicios de estilo en la programación

66
Exercises in Style Crista Lopes

description

El escritor francés Raymond Queneau escribió a mediados del siglo XX un libro llamado "Ejercicios de Estilo" donde mostraba una misma historia corta, redactada de 99 formas distintas. En esta plática realizaremos el mismo ejercicio con un programa de software. Abarcaremos distintos estilos y paradigmas: programación monolítica, orientada a objetos, relacional, orientada a aspectos, monadas, map-reduce, y muchos otros, a través de los cuales podremos apreciar la riqueza del pensamiento humano aplicado a la computación. Esto va mucho más allá de un ejercicio académico; el diseño de sistemas de gran escala se alimenta de esta variedad de estilos. También platicaremos sobre los peligros de quedar atrapado bajo un conjunto reducido de estilos a lo largo de tu carrera, y la necesidad de verdaderamente entender distintos estilos al diseñar arquitecturas de sistemas de software. Semblanza del conferencista: Crista Lopez es profesora en la Facultad de Ciencias Computacionales de la Universidad de California en Irvine. Su investigación se enfoca en prácticas de ingeniería de software para sistemas de gran escala. Previamente, fue miembro fundador del equipo en Xerox PARC creador del paradigma de programación orientado a aspectos (AOP). Crista es una de las desarrolladoras principales de OpenSimulator, una plataforma open source para crear mundos virtuales 3D. También es fundadora de Encitra, empresa especializada en la utilización de la realidad virtual para proyectos de desarrollo urbano sustentable. @cristalopes

Transcript of Ejercicios de estilo en la programación

Page 1: Ejercicios de estilo en la programación

Exercises in Style

Crista Lopes

Page 2: Ejercicios de estilo en la programación

Available on Amazon

Page 3: Ejercicios de estilo en la programación
Page 4: Ejercicios de estilo en la programación

PROGRAMMING STYLES Rules and constraints in software construction

Page 5: Ejercicios de estilo en la programación

Programming Styles

⊳ Ways of expressing tasks

⊳ Exist and recur at all scales

⊳ Frozen in Programming Languages

Page 6: Ejercicios de estilo en la programación

Why Are Styles Important?

⊳ Basic frames of reference for solutions

• Like scaffolding

⊳ Common vocabularies

• It’s a cultural thing

⊳ Some better than others

• Depending on many things!

Page 7: Ejercicios de estilo en la programación

Programming Styles

How do you teach this?

Page 8: Ejercicios de estilo en la programación

Raymond Queneau

Page 9: Ejercicios de estilo en la programación

Queneau’s Exercises in Style ⊳ Metaphor

⊳ Surprises

⊳ Dream

⊳ Prognostication

⊳ Hesitation

⊳ Precision

⊳ Negativities

⊳ Asides

⊳ Anagrams

⊳ Logical analysis

⊳ Past

⊳ Present

⊳ …

⊳ (99)

Page 10: Ejercicios de estilo en la programación

Queneau’s “Styles”

⊳ Constraints

⊳ “A Void” (La Disparition) by Georges Perec • No letter ‘e’

Page 11: Ejercicios de estilo en la programación

Exercises in Programming Style

The story: Term Frequency given a text file, output a list of the 25 most frequently-occurring words, ordered by decreasing frequency

Page 12: Ejercicios de estilo en la programación

Exercises in Programming Style

The story: Term Frequency given a text file, output a list of the 25 most frequently-occurring words, ordered by decreasing frequency

mr - 786 elizabeth - 635 very - 488 darcy - 418 such - 395 mrs - 343 much - 329 more - 327 bennet - 323 bingley - 306 jane - 295 miss - 283 one - 275 know - 239 before - 229 herself - 227 though - 226 well - 224 never - 220 …

TF Pride and Prejudice

Page 13: Ejercicios de estilo en la programación

STYLE #1 @cristalopes #style1 name

Page 14: Ejercicios de estilo en la programación
Page 15: Ejercicios de estilo en la programación

# the global list of [word, frequency] pairs word_freqs = [] # the list of stop words with open('../stop_words.txt') as f: stop_words = f.read().split(',') stop_words.extend(list(string.ascii_lowercase))

Page 16: Ejercicios de estilo en la programación

for line in open(sys.argv[1]):

for c in line:

Page 17: Ejercicios de estilo en la programación

Style #1 Main Characteristics

⊳ No abstractions

⊳ No use of library functions

@cristalopes #style1 name

Page 18: Ejercicios de estilo en la programación

Style #1 Main Characteristics

⊳ No abstractions

⊳ No use of library functions

Brain-dump Style

@cristalopes #style1 name

Page 19: Ejercicios de estilo en la programación

STYLE #2 @cristalopes #style2 name

Page 20: Ejercicios de estilo en la programación

import re, string, sys stops = set(open("../stop_words.txt").read().split(",") + list(string.ascii_lowercase)) words = [x.lower() for x in re.split("[^a-zA-Z]+", open(sys.argv[1]).read()) if len(x) > 0 and x.lower() not in stops] unique_words = list(set(words)) unique_words.sort(lambda x, y: cmp(words.count(y), words.count(x))) print "\n".join(["%s - %s" % (x, words.count(x)) for x in unique_words[:25]])

Credit: Laurie Tratt, Kings College London

Page 21: Ejercicios de estilo en la programación

import re, string, sys stops = set(open("../stop_words.txt").read().split(",") + list(string.ascii_lowercase)) words = [x.lower() for x in re.split("[^a-zA-Z]+", open(sys.argv[1]).read()) if len(x) > 0 and x.lower() not in stops] unique_words = list(set(words)) unique_words.sort(lambda x, y: cmp(words.count(y), words.count(x))) print "\n".join(["%s - %s" % (x, words.count(x)) for x in unique_words[:25]])

Page 22: Ejercicios de estilo en la programación

import re, string, sys stops = set(open("../stop_words.txt").read().split(",") + list(string.ascii_lowercase)) words = [x.lower() for x in re.split("[^a-zA-Z]+", open(sys.argv[1]).read()) if len(x) > 0 and x.lower() not in stops] unique_words = list(set(words)) unique_words.sort(lambda x,y:cmp(words.count(y), words.count(x))) print "\n".join(["%s - %s" % (x, words.count(x)) for x in unique_words[:25]])

Page 23: Ejercicios de estilo en la programación

Style #2 Main Characteristics

⊳ As few lines of code as possible

@cristalopes #style2 name

Page 24: Ejercicios de estilo en la programación

Style #2 Main Characteristics

⊳ As few lines of code as possible

Code Golf Style

@cristalopes #style2 name

Page 25: Ejercicios de estilo en la programación

Style #2 Main Characteristics

⊳ As few lines of code as possible

Try Hard Style

@cristalopes #style2 name

Page 26: Ejercicios de estilo en la programación

STYLE #3 @cristalopes #style3 name

Page 27: Ejercicios de estilo en la programación
Page 28: Ejercicios de estilo en la programación

# # Main # read_file(sys.argv[1]) filter_normalize() scan() rem_stop_words() frequencies() sort() for tf in word_freqs[0:25]: print tf[0], ' - ', tf[1]

def read_file(path):

def filter_normalize():

def scan():

def rem_stop_words():

def frequencies():

def sort():

data=[] words=[] freqs=[]

Page 29: Ejercicios de estilo en la programación

Style #3 Main Characteristics

⊳ Procedural abstractions

• maybe input, no output

⊳ Shared state

⊳ Larger problem solved by applying procedures, one after the other, changing the shared state

@cristalopes #style3 name

Page 30: Ejercicios de estilo en la programación

Style #3 Main Characteristics

⊳ Procedural abstractions

• maybe input, no output

⊳ Shared state

⊳ Commands

Cook Book Style

@cristalopes #style3 name

Page 31: Ejercicios de estilo en la programación

STYLE #4 @cristalopes #style4 name

Page 32: Ejercicios de estilo en la programación
Page 33: Ejercicios de estilo en la programación

# # Main # wfreqs=st(fq(r(sc(n(fc(rf(sys.argv[1]))))))) for tf in wfreqs[0:25]: print tf[0], ' - ', tf[1]

def read_file(path):

def filter(str_data):

def scan(str_data):

def rem_stop_words(wordl):

def frequencies(wordl):

def sort(word_freqs):

def normalize(str_data):

return ...

return ...

return ...

return ...

return ...

return ...

return ...

Page 34: Ejercicios de estilo en la programación

Style #4 Main Characteristics

⊳ Function abstractions

• f: Input Output

⊳ No shared state

⊳ Function composition f º g

@cristalopes #style4 name

Page 35: Ejercicios de estilo en la programación

Style #4 Main Characteristics

⊳ Function abstractions

• f: Input Output

⊳ No shared state

⊳ Function composition f º g

Chocolate Factory Style

Image credit: Nykamp DQ, From Math Insight. http://mathinsight.org/image/function machines composed

g

f

@cristalopes #style4 name

Page 36: Ejercicios de estilo en la programación

STYLE #5 @cristalopes #style5 name

Page 37: Ejercicios de estilo en la programación
Page 38: Ejercicios de estilo en la programación

def read_file(path, func): ... return func(…, normalize)

def filter_chars(data, func): ... return func(…, scan)

def normalize(data, func): ... return func(…,remove_stops)

# Main w_freqs=read_file(sys.argv[1], filter_chars) for tf in w_freqs[0:25]: print tf[0], ' - ', tf[1]

def scan(data, func): ... return func(…, frequencies)

def remove_stops(data, func): ... return func(…, sort)

Etc.

Page 39: Ejercicios de estilo en la programación

Style #5 Main Characteristics

⊳ Functions take one additional parameter, f

• called at the end

• given what would normally be the return value plus the next function

@cristalopes #style5 name

Page 40: Ejercicios de estilo en la programación

Style #5 Main Characteristics

⊳ Functions take one additional parameter, f

• called at the end

• given what would normally be the return value plus the next function

Crochet Style @cristalopes #style5 name

Page 41: Ejercicios de estilo en la programación

STYLE #6 @cristalopes #style6 name

Page 42: Ejercicios de estilo en la programación
Page 43: Ejercicios de estilo en la programación

class DataStorageManager(TFExercise):

class TFExercise():

class StopWordManager(TFExercise):

class WordFreqManager(TFExercise):

class WordFreqController(TFExercise):

# Main WordFreqController(sys.argv[1]).run()

def words(self):

def info(self):

def info(self): def info(self):

def info(self):

def is_stop_word(self, word):

def inc_count(self, word):

def sorted(self):

def run(self):

Page 44: Ejercicios de estilo en la programación

Style #6 Main Characteristics

⊳ Things, things and more things!

• Capsules of data and procedures

⊳ Data is never accessed directly

⊳ Capsules can reappropriate procedures from other capsules

@cristalopes #style6 name

Page 45: Ejercicios de estilo en la programación

Style #6 Main Characteristics

⊳ Things, things and more things!

• Capsules of data and procedures

⊳ Data is never accessed directly

⊳ Capsules can reappropriate procedures from other capsules

@cristalopes #style6 name Kingdom of Nouns Style

Page 46: Ejercicios de estilo en la programación

STYLE #7 @cristalopes #style7 name

Page 47: Ejercicios de estilo en la programación
Page 48: Ejercicios de estilo en la programación

class DataStorageManager():

class StopWordManager():

class WordFrequencyManager():

class WordFrequencyController():

def dispatch(self, message):

def dispatch(self, message):

def dispatch(self, message):

def dispatch(self, message):

# Main wfcntrl = WordFrequencyController() wfcntrl.dispatch([‘init’,sys.argv[1]]) wfcntrl.dispatch([‘run’])

Page 49: Ejercicios de estilo en la programación

Style #7 Main Characteristics

⊳ (Similar to #6)

⊳ Capsules receive messages via single receiving procedure

@cristalopes #style7 name

Page 50: Ejercicios de estilo en la programación

Style #7 Main Characteristics

⊳ (Similar to #6)

⊳ Capsules receive messages via single receiving procedure

@cristalopes #style7 name Letterbox Style

Page 51: Ejercicios de estilo en la programación

STYLE #8 @cristalopes #style8 name

Page 52: Ejercicios de estilo en la programación
Page 53: Ejercicios de estilo en la programación

# Main splits = map(split_words, partition(read_file(sys.argv[1]), 200)) splits.insert(0, []) word_freqs = sort(reduce(count_words, splits)) for tf in word_freqs[0:25]: print tf[0], ' - ', tf[1]

Page 54: Ejercicios de estilo en la programación

def split_words(data_str) """ Takes a string (many lines), filters, normalizes to lower case, scans for words, and filters the stop words. Returns a list of pairs (word, 1), so [(w1, 1), (w2, 1), ..., (wn, 1)] """ ... result = [] words = _rem_stop_words(_scan(_normalize(_filter(data_str)))) for w in words: result.append((w, 1)) return result

Page 55: Ejercicios de estilo en la programación

def count_words(pairs_list_1, pairs_list_2) """ Takes two lists of pairs of the form [(w1, 1), ...] and returns a list of pairs [(w1, frequency), ...], where frequency is the sum of all occurrences """ mapping = dict((k, v) for k, v in pairs_list_1) for p in pairs_list_2: if p[0] in mapping: mapping[p[0]] += p[1] else: mapping[p[0]] = 1 return mapping.items()

Page 56: Ejercicios de estilo en la programación

Style #8 Main Characteristics

⊳ Two key abstractions: map(f, chunks) and reduce(g, results)

@cristalopes #style8 name

Page 57: Ejercicios de estilo en la programación

Style #8 Main Characteristics

⊳ Two key abstractions: map(f, chunks) and reduce(g, results)

@cristalopes #style8 name Map-Reduce Style

Page 58: Ejercicios de estilo en la programación

STYLE #9 @cristalopes #style9 name

Page 59: Ejercicios de estilo en la programación
Page 60: Ejercicios de estilo en la programación

# Main connection = sqlite3.connect(':memory:') create_db_schema(connection) load_file_into_database(sys.argv[1], connection) # Now, let's query c = connection.cursor() c.execute("SELECT value, COUNT(*) as C FROM words GROUP BY value ORDER BY C DESC") for i in range(25): row = c.fetchone() if row != None: print row[0] + ' - ' + str(row[1]) connection.close()

Page 61: Ejercicios de estilo en la programación

def create_db_schema(connection): c = connection.cursor() c.execute('''CREATE TABLE documents(id PRIMARY KEY AUTOINCREMENT, name)''' c.execute('''CREATE TABLE words(id, doc_id, value)''') c.execute('''CREATE TABLE characters(id, word_id, value)''') connection.commit() c.close()

Page 62: Ejercicios de estilo en la programación

# Now let's add data to the database # Add the document itself to the database c = connection.cursor() c.execute("INSERT INTO documents (name) VALUES (?)", (path_to_f c.execute("SELECT id from documents WHERE name=?", (path_to_fil doc_id = c.fetchone()[0] # Add the words to the database c.execute("SELECT MAX(id) FROM words") row = c.fetchone() word_id = row[0] if word_id == None: word_id = 0 for w in words: c.execute("INSERT INTO words VALUES (?, ?, ?)", (word_id, d # Add the characters to the database char_id = 0 for char in w: c.execute("INSERT INTO characters VALUES (?, ?, ?)", (c char_id += 1 word_id += 1 connection.commit() c.close()

Page 63: Ejercicios de estilo en la programación

Style #9 Main Characteristics

⊳ Entities and relations between them

⊳ Query engine

• Declarative queries

@cristalopes #style9 name

Page 64: Ejercicios de estilo en la programación

Style #9 Main Characteristics

⊳ Entities and relations between them

⊳ Query engine

• Declarative queries

@cristalopes #style9 name Tabular Style

Page 65: Ejercicios de estilo en la programación

Take Home

⊳ Many ways of solving problems

• Know them, assess them

⊳ Constraints are important for communication

• Make them explicit

⊳ Don’t be hostage of one way of doing things

Page 66: Ejercicios de estilo en la programación

Available on Amazon