Sennder, Python, Me, and Uncle Bob

UI
Portal

Finance

Service

MatchingService

http
http

Things we can see happening at FS.

1. Take request from the portal.

2. Ask requested information from matching service.

3. Map received information to a data structure UI understands.

4. Respond the UI portal with structured data.

# api.py 
class MatchingServiceAPI:
	
    def get_invoice():
      pass
    
    def get_line_items():
      pass
    
    def get_orders():
      pass
# mappers/invoice.py 
class InvoiceMapper:
  def map_invoice():
      pass
      
# mappers/line_item.py    
class LineItemMapper:
  def map_line_items():
      pass
    
# mappers/orders.py
class OrderMapper:
  def map_orders():
      pass

Manipulation

Communication

Hardware is hard to change. If you've written a software thats hard to change, then Congratulations, you've written a hardware.

If I expect change to a certain module, I don't want to hear from you that our architecture doesn't support this change. 

Inexpensive Adaptability

As your CTO,

Its bad code when you change something in one module and something else way over there breaks.

A class/module should have one and only one reason to change.

Single Responsibility Principle

Tightly Coupled

UI
Portal

Finance

Service

MatchingService

status code

status code

rpc?
sockets?

http status codes?

Change in matching service API module meant change in controllers module responding to UI.

UI
Portal

Finance

Service

MatchingService

exceptions

status code

raise InvoiceAlreadyExistsException

raise InvoiceNotFoundException

raise InvoiceModificationException
try:
  pass

except InvoiceNotFoundException:
  return Response(status=404)
from matching import api as MatchingAPI

def create_invoice(invoice):

  try:
  	MatchingAPI.post_invoice(invoice)

  except InvoiceAlreadyExistsException:
  	return Response(status=409)

  except InvoiceNotFoundException:
  	return Response(status=404)

  except InvoiceModificationException:
  	return Response(status=400)

Extract, and extract, and extract untill you can't extract more functions out of a module

Refactoring

put them in class if possible.

Invoice Mapper


def map_invoice(self, invoice):
  pass

def invoice_is_reconciled(self, invoice):
  pass

def invoice_is_master_recon(self, invoice):
  pass

def map_invoice_with_line_items(self, invoice, line_items):
  pass
class Invoice:
  
  def __init__(self, payload):
    self.invoice = payload
  
  def is_reconciled(self):
    pass
  
  def is_master_reconciled(self):
    pass
  
  def format(self):
    pass
  
  def format_with_line_items(self, line_items):
    pass
class MatchingServiceAPI:
  
  def get_document()
  def get_all_documents()
  def get_line_items()
  def patch_line_items()
  def get_orders()
raise InvoiceNotFoundExeption
raise InvoiceAlreadyExistsException
raise InvoiceModificationException
raise LineItemNotFoundExeption
raise LineItemAlreadyExistsException
raise LineItemModificationException
raise OrderNotFoundExeption
raise OrderAlreadyExistsException
raise OrderModificationException

MatchingService API

Invoice API

Line Item API

Order
API

── matching_service
│   ├── api.py
│   ├── errors.py
│   ├── exceptions.py
│   ├── invoice
│   │   ├── api.py
│   │   ├── errors.py
│   │   ├── exceptions.py
│   ├── line_item
│   │   ├── api.py
│   │   ├── errors.py
│   │   ├── exception.py
│   ├── orders
│   │   ├── api.py
│   │   ├── errors.py
│   │   ├── exceptions.py
# documents/exception.py

DocumentNotFoundExeption
DocAlreadyExistsException
DocModificationException
#line_item/exception.py 

LineItemNotFoundExeption
LineItemAlreadyExistsException
LineItemModificationException
# orders/exception.py

OrderNotFoundExeption
OrderAlreadyExistsException
OrderModificationException
MatchingServiceException
from matching import api as MatchingAPI

def create_invoice(invoice):

  try:
  	MatchingAPI.post_invoice(invoice)

  except MatchingServiceException as e:
	exc = HttpExceptionFactory(e)
	raise exc

Take aways

  1. I was only able to refactor my code because there were unit tests with a 100% coverage. Tests are important!

2. Watching Coding a better world together gave me a whole new insight of writing clean code. It changed my perspective of looking at things completely. I'd recommend everyone of us to invest time in those lectures.

Take aways

3. Being a JavaScript developer, our de-facto approach to writing code in any language is the functional paradigm of things, and OO is somewhere left behind.

I rediscovered OO design and I found it making my code easier to read and easier to change.

Take aways

deck

By Minhaj Khan

deck

  • 123