A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Notes on "The Principles of Clean Architecture" by Uncle Bob Martin

Notes on "The Principles of Clean Architecture" by Uncle Bob Martin


Shows Rails app structure on slide.  Why do I know this is a Rails app?  Why doesn't it tell me what the application does?  What's important about the app is hidden by the structure of the framework.  Why is the web (merely a delivery mechanism) central to the application structure.  Back in the 90's we thought the web changed everything, but it didn't.  We were duped into thinking that the web was an architecturally significant part of an application.  Shows blueprints of library and church.  The use is clear from the structure.

Suggests that Architecture is about Intent.  It's not about tools or libraries, those are details that should be hidden.

Recalls Ivar Jacobsen's classic book Object-Oriented Software Engineering: A Use Case Driven Approach.  Use Cases are like User Stories.  Best kept simple and high level.

Application specific rules (use cases) may be represented with "interactor" objects.
Cross application rules are represented in "entities".

Interface/Boundary objects/classes (act like java interfaces) provide a way for external systems to present requests.

Request model is passed thru boundary into interactor.  Interactors process request and control entities and gather results and emit response object thru interface to delivery system.

Looks like MVC but is NOT because MVC is misunderstood.

MVC is oldest pattern (predates patterns).  MVC is not an architecture.

Defines MVC as originally described in the 70s.  Model object hides a very small business rule.  There is a controller that is connected to an input device like a keyboard or mouse.  Controller sends input to model.  The view registers with the model, which sends state updates to the view, to trigger updates.  MVC was done in the *small*.  You had an MVC for *a button*.

Now we have MVC for whole pages etc, because:  What happens to any kind of good idea in software is that people know that it's a good idea and they also know that their ideas are good.  And so they figure that their ideas are that idea...and they completely lose the original idea.

Problem in app scale:  Poor boundaries.  Not clear what is view, controller or model logic.  Unless you keep extremely careful discipline the concerns will get mixed.

Talks about Plug In pattern.

Dependencies flow only one direction between a plug in and the application.

Changes in a plug in can not impact the core aplication.

Protect you business rules/core application by treating UI and data storage as plug ins.

Things that change frequently should be plugins.

Talk about model View Presenter.  Presenter gets data from app across plugin boundary.  Feeds data to view model.  View renders view model and updates presenter with UX events.

What about the Database?  We put it central to a lot of our architecture.  Because Oracle fooled us all.

The DB is a storage detail and should be abstracted away.

Use a boundary class that handles every query you might want to make.  The DB code should all live across the plug in boundary.  All SQL, etc generated in the plug in.

This architecture helps with testing, because you can easily remove the DB.

Case study:  Deferring a feature out of existence.

Worked on project called Fitnesse (a wiki, which shows test results).  They were going to build it based on MySQL, but they decided to wait and worked on Wiki text to HTML and used a mock DB.  Next they needed to do links and navigation, and so thought they were going to do DB storage.  Instead they just used a mock class that stored pages in RAM.  Then they needed to do start up and shut down, and so they were going to add DB support.  Instead they made their mock object serialize the hash to the file system.  That worked well enough, so they eventually shipped the product without database support.

Eventually they added MySQL support for a customer, but even they gave up on the DB.

Lessons:

*A good architecture allows major decisions to be deferred.*

*A good architecture maximizes the number of decisions NOT made.*

*Achieve that by using a plugin model.*

Use cases form the center of the application.

UI, Datastorage, Frameworks, etc are all external to the use cases.

Remember:  Framework authors will screw you.  You make a tremendous commitment to a framework when you adopt it.  The framework author makes NO commitment to you.

Use frameworks because they are powerful and can make you productive.

But don't follow the examples, because the framework author is going to be comfortable with too much coupling to their framework.

Frameworks are great, but keep them at length.

-- Notes by Mr Swayne.

Use cpm to manage your Perl dependencies

cpm is much faster than cpanm because it makes HTTP requests in parallel and caches modules between runs. The output is also infinitely more clear than cpanm.

# Define the local lib directory
unset PERL5LIB; unset PERL_LOCAL_LIB_ROOT; eval $(perl -Mlocal::lib=./local)

# Install cpm using cpanm
cpanm -nf -L local App::cpm # 35 modules

# Then manually install any problematic modules (as necessary) that have been moved in/out of core
cpm install Module::Build
cpm install Module::Pluggable
cpm install Archive::Extract
cpm install CGI::Cookie
cpm install CGI

# Finally fetch all the CPAN and other dependencies
export DARKPAN=https://username:passwork@mydarkpan.example.com
cpm install --resolver 02packages,$DARKPAN --resolver metadb

Note: --resolver is experimental. The standard argument is --mirror

Thanks HypnoMark

# Another form
cpm install --show-build-log-on-failure --resolver metadb --resolver 02packages,$PINTO_MIRROR --feature=client

# s/PINTO_MIRROR/DARKPAN/

Python basics

Most basic: Use the latest Python 3 (or higher)

Use multiple lines in a one-liner with \n:
echo -e "import sys\nsys.exit('Error')" | python3