in reply to Splitting program into modules
Well ... some general thoughts on splitting up unknown code
Incremental strategy
- create your test suite first
- do little steps, and always test the result
- use a revision control system like git
- commit every change
- use branches for experiments
- once you found a previously untested bug expand your test suite and roll back
Prerequisites
Study and understand
==== Perl essentials
- strict and warnings
- my vs our variables,
- namespaces, scoping, blocks
- exporter
- constants
- warn and die
==== Tools and techniques
- the debugger
- trace options to log function calls
- log files
- Data::Dumper , Data::Dump
==== your application
- your data model ( database, configs)
- input and output
- avaliable doc
- stakeholders (users, contributers, maintainers) to ask
Analyze
- analyze the dependencies of your subs (x calls y calls z)
- analyze the shared variables
- try to visualize the dependencies in a graph
- the hierarchy should help identifying logical units (aka modules)
- use tools to help you analyze like B::Xref
- other tools like mentioned here: Searching for duplication in legacy code
- identify dead code (never called subs, out-commented trash)
Documentation
- once you understood a mechanism, write it down
- use Pod headers when possible
- normalize (beautify) your code with Perl::Tidy
- review your pod2html from time to time and fill gaps
Modularisation / Namespaces ?
- bundle subs into modules by functionality not technology (not all sql in one module, eg look at the TABLE names )
- require into the same namespace might be an easier intermediate step before learning to use exporter °
- modules normally require namespaces (packages)
- package variables in other modules need to be fully qualified when used outside $Pkg::var °
- same for Pkg::subs() °
- modules allow to export vars and subs when use d
- modules allow to pass and init shared variables when using import (like a database handle)
Object Oriented Programming
- logical modules are sometimes better OO classes
- check guides on "when OOP is better"
- indicator: if you have to pass around same arguments
- indicator: group of subs access always same global vars
- indicator: init() routines for globals are sometimes better ->new()
- easier to construct an object with encapsulated instance vars and class vars
- have a look at Moo before doing old style OOP
Improvement
- make your code more fault tolerant
- add argument checking to your subs
- rewrite many positional args into named args
- condense duplicated code into new functions
- limit the scope of vars and subs if possible
- give identifiers like variables meaningful names
- document your strategy for future maintainers
See Also
Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery
FootballPerl is like chess, only without the dice
update
Expanded the OOP part
°) that's an intermediate step exporting and importing is much cleaner
²) As a rule of thumb from easier to better
- require files same namespace (NB: my-lexicals can't be shared)
- try to group connected subs into namespaces with package
- use module different namespaces => full qualified identifiers for shared data
- use module different namespaces => exporting and importing shared data
- use oo-class : shared data in instance/class-vars and methods, transport via constructor and setter/getters
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^2: Splitting program into modules
by eyepopslikeamosquito (Archbishop) on Nov 12, 2018 at 06:05 UTC | |
by LanX (Saint) on Nov 12, 2018 at 10:58 UTC |
In Section
Seekers of Perl Wisdom