Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: Splitting program into modules

by LanX (Saint)
on Nov 10, 2018 at 23:38 UTC ( [id://1225549]=note: print w/replies, xml ) Need Help??


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

==== 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

    Object Oriented Programming: logical modules are sometimes better OO classes ...

    As for whether and when to use OO, my simple rule of thumb is to ask "do I need more than one?": if the answer is yes, an object is indicated; if the answer is no, a module.

    A (non Perl-specific) design checklist (derived from On Coding Standards and Code Reviews):

    • Coupling and Cohesion. Systems should be designed as a set of cohesive modules as loosely coupled as is reasonably feasible.
    • Testability. Systems should be designed so that components can be easily tested in isolation.
    • Data hiding. Minimize the exposure of implementation details. Minimize global data.
    • Interfaces matter. Once an interface becomes widely used, changing it becomes practically impossible (just about anything else can be fixed in a later release).
    • Design the module's interface first.
    • Design interfaces that are: consistent; easy to use correctly; hard to use incorrectly; easy to read, maintain and extend; clearly documented; appropriate to your audience. Be sufficient, not complete; it is easier to add a new feature than to remove a mis-feature.
    • Use descriptive, explanatory, consistent and regular names.
    • Correctness, simplicity and clarity come first. Avoid unnecessary cleverness. If you must rely on cleverness, encapsulate and comment it.
    • DRY (Don't repeat yourself).
    • Establish a rational error handling policy and follow it strictly.

      I once had to maintain code which had many subs accessing a bunch of global states which where switched by calling an "init()" routine or passed flags.

      After long analysis (Freudian yes) I realized that these routines where effectively methods, the states where instance vars and the so called init() routine switched the instances.

      Well actually that was only a simplified description of what happened, I don't wanna give you nightmares. :)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      </div

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1225549]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (2)
As of 2024-04-20 03:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found