Copyright © 2006 Quest Software Writing Readable, Maintainable Code Steven Feuerstein PL/SQL Evangelist

Slides:



Advertisements
Similar presentations
AN INTRODUCTION TO PL/SQL Mehdi Azarmi 1. Introduction PL/SQL is Oracle's procedural language extension to SQL, the non-procedural relational database.
Advertisements

Composition CMSC 202. Code Reuse Effective software development relies on reusing existing code. Code reuse must be more than just copying code and changing.
Coding Standard: General Rules 1.Always be consistent with existing code. 2.Adopt naming conventions consistent with selected framework. 3.Use the same.
Oracle PL/SQL Programming Steven Feuerstein PL/SQL Evangelist, Dell The Power of.
Chapter 7: User-Defined Functions II Instructor: Mohammad Mojaddam.
Abstract Data Types Data abstraction, or abstract data types, is a programming methodology where one defines not only the data structure to be used, but.
Road Map Introduction to object oriented programming. Classes
Advanced Package Concepts. 2 home back first prev next last What Will I Learn? Write packages that use the overloading feature Write packages that use.
1 Programming for Engineers in Python Autumn Lecture 5: Object Oriented Programming.
3 Copyright © 2004, Oracle. All rights reserved. Creating Packages.
Creating Packages. 2 home back first prev next last What Will I Learn? Describe the reasons for using a package Describe the two components of a package:
Terms and Rules Professor Evan Korth New York University (All rights reserved)
Chapter 1 Principles of Programming and Software Engineering.
CS241 PASCAL I - Control Structures1 PASCAL I - Control Structures Philip Fees CS241.
Chapter 1 Program Design
C++ Functions. 2 Agenda What is a function? What is a function? Types of C++ functions: Types of C++ functions: Standard functions Standard functions.
1 Using Classes Object-Oriented Programming Using C++ Second Edition 5.
Using Classes Object-Oriented Programming Using C++ Second Edition 5.
C++ Object Oriented 1. Class and Object The main purpose of C++ programming is to add object orientation to the C programming language and classes are.
METHODS Introduction to Systems Programming - COMP 1005, 1405 Instructor : Behnam Hajian
Copyright 2006 Steven Feuerstein - Page 1 Six Simple Steps to Unit Testing Happiness Steven Feuerstein
Oracle PL/SQL Programming Steven Feuerstein All About the (Amazing) Function Result Cache of Oracle Database 11g.
© The McGraw-Hill Companies, 2006 Chapter 4 Implementing methods.
Programming in Java Unit 2. Class and variable declaration A class is best thought of as a template from which objects are created. You can create many.
PL/SQLPL/SQL Oracle10g Developer: PL/SQL Programming Chapter 7 PL/SQL Packages.
CMPS 211 JavaScript Topic 1 JavaScript Syntax. 2Outline Goals and Objectives Goals and Objectives Chapter Headlines Chapter Headlines Introduction Introduction.
CSCI-383 Object-Oriented Programming & Design Lecture 13.
Oracle PL/SQL Practices. Critical elements of PL/SQL Best Practices Build your development toolbox Unit test PL/SQL programs Optimize SQL in PL/SQL programs.
Oct 15, 2007Sprenkle - CS1111 Objectives Creating your own functions.
SE: CHAPTER 7 Writing The Program
Programming for Beginners Martin Nelson Elizabeth FitzGerald Lecture 5: Software Design & Testing; Revision Session.
Using Procedures & Functions Oracle Database PL/SQL 10g Programming Chapter 9.
CPS120: Introduction to Computer Science Decision Making in Programs.
Making Good Code AKA: So, You Wrote Some Code. Now What? Ray Haggerty July 23, 2015.
CS178 Database Management PL/SQL session 8 References: ORACLE 9i PROGRAMMING A Primer Rajshekhar Sunderraman.
C++ Programming Basic Learning Prepared By The Smartpath Information systems
What is a Package? A package is an Oracle object, which holds other objects within it. Objects commonly held within a package are procedures, functions,
The Software Development Process
1 CSCD 326 Data Structures I Software Design. 2 The Software Life Cycle 1. Specification 2. Design 3. Risk Analysis 4. Verification 5. Coding 6. Testing.
Introduction to c++ programming - object oriented programming concepts - Structured Vs OOP. Classes and objects - class definition - Objects - class scope.
1 CS161 Introduction to Computer Science Topic #9.
Introduction to Classes and Objects. Real Life When a design engineer needs an electrical motor he doesn’t need to worry about –How a foundry will cast.
Object-Oriented Programming. Objectives Distinguish between object-oriented and procedure-oriented design. Define the terms class and object. Distinguish.
CREATING STORED PROCEDURES AND FUNCTIONS. Objectives After completing this lecture, you should be able to do the following: Differentiate between anonymous.
Chapter 10: Classes and Data Abstraction. Objectives In this chapter, you will: Learn about classes Learn about private, protected, and public members.
Computing Higher – SD Unit - Topic 8 – Procedure and Standard Algorithms P Lynch, St Andrew’s High School Unit 2 Software Development Process Topic.
Classes, Interfaces and Packages
Chapter 5 Methods 1. Motivations Method : groups statements that perform a function.  Level of abstraction (black box)  Code Reuse – no need to reinvent.
Chapter 10: Classes and Data Abstraction. Classes Object-oriented design (OOD): a problem solving methodology Objects: components of a solution Class:
Text TCS INTERNAL Oracle PL/SQL – Introduction. TCS INTERNAL PL SQL Introduction PLSQL means Procedural Language extension of SQL. PLSQL is a database.
Principles of Programming. Achieving an Object-Oriented Design  Abstraction and Information Hiding  Object-Oriented Design  Functional Decomposition.
Functions in C++ Top Down Design with Functions. Top-down Design Big picture first broken down into smaller pieces.
What Are Subprograms? Subprograms are named PL/SQL blocks that can take parameters and be invoked. Subprograms allow decomposition of a program into logical.
Mr H Kandjimi 2016/01/03Mr Kandjimi1 Week 3 –Modularity in C++
Oracle9i Developer: PL/SQL Programming Chapter 6 PL/SQL Packages.
Preface IIntroduction Course Objectives I-2 Oracle Complete Solution I-3 Course Agenda I-4 Tables Used in This Course I-5 The Order Entry Schema I-6 The.
Classes CS 162 (Summer 2009). Parts of a Class Instance Fields Methods.
1 Copyright © 2004, Oracle. All rights reserved. PL/SQL Programming Concepts: Review.
Creating Stored Procedures and Functions
UNIT - V STORED PROCEDURE.
Introduction to PL/SQL
About the Presentations
PL/SQL Package Week 8.
PL/SQL Scripting in Oracle:
Chapter 6 Methods: A Deeper Look
Packages and Interfaces
Object-Oriented Programming Using C++ Second Edition
Classes and Objects.
Prof. Arfaoui. COM390 Chapter 7
C++ Object Oriented 1.
Presentation transcript:

Copyright © 2006 Quest Software Writing Readable, Maintainable Code Steven Feuerstein PL/SQL Evangelist

1 How to Benefit Most From This Session Watch, listen, ask questions. Download the training materials and supporting scripts: – –"Demo zip": all the scripts I run in my class available at Use these materials as an accelerator as you venture into new territory and need to apply new techniques. Play games! Keep your brain fresh and active by mixing hard work with challenging games. – I strongly recommend Set ( filename_from_demo_zip.sql

2 Write readable, maintainable code PL/SQL allows you to write very readable, self- documenting and easily-maintained code. –This should be a primary objective for any program. Here’s what we’ll cover.... –Fundamental readability features of PL/SQL –Documentation guidelines –Techniques for avoiding hard-coding in your programs –Modular construction with packages and reusable components –Key tip: keep executable sections tiny with local modules –How to decide where to put the code –Instrumentation of your code –Build and use regression tests –The value of deterministic logic

3 Readability features you should use END labels –For program units, loops, nested blocks SUBTYPEs –Create application-specific datatypes! Named notation –Sometimes the extra typing is worth it! end_labels.sql plsql_limits.pks fullname.* namednot.sql

4 Coding Conventions It doesn’t really matter (to me, anyway!) what standards you decide to follow. The important thing is to be consistent. Everyone’s code as much as possible should look and read the same. –Don’t both defining formatting standards. –Use “pretty printers” that come with any PL/SQL IDE worth using. Here is a fairly (and free) comprehensive set of coding conventions for you to use:

5 Documentation guidelines We all hate writing comments, but there are some key places in your code where comments are very important. –Program header with modification history –Explanation of complex algorithms –Identifying workarounds and the fixes for them. Once again, standardize and automate as much as possible. –Code templates fileio92.sql /* WORKAROUND START Bug description: Bug reference: Workaround description: Post-bug fix implementation: WORKAROUND END */

6 Avoid hard-coding in your programs! Here are examples of hard-coding in PL/SQL: –Literal values IF num_requests > 100 THEN –Date format in a call to TO_DATE 'MM/DD/YY' –Language specificities '09-SEP-2001' –Constrained declarations NUMBER(10,4) –Variables declared using base datatypes, such as my_name VARCHAR2(20) –Every SQL statement you write –COMMIT and ROLLBACK statements –Comments that "explain" code –Fetching into a list of individual variables –Embedded (un-encapsulated) business rules –Reusing the same name for different purposes

7 Some tips to help you avoid hard-coding Create constants and variables to hide literal values and formulas. –Either local or defined in packages Use SUBTYPEs to avoid repetitive hard-coding declarations. –Best defined in package specifications Encapsulate SQL behind an API. –The Quest CodeGen Utility Hide COMMIT and ROLLBACK behind an API. –PL/Vision’s PLVcmt commit package offers one example. Always fetch into a record based on the cursor %ROWTYPE. –Even if the query in the cursor changes, the record structure will adapt automatically to the new fields. Declare new variables, exceptions, etc. for each new purpose. recycle_names.sql

8 Modular construction in PL/SQL Packages: some quick reminders... –Key building block for applications –Overloading –Package-level data and caching –Initialization section Local or nested modules –Avoid spaghetti code! –Keep your executable sections small/tiny.

9 Packages: key PL/SQL building block Employ object-oriented design principles –Build at higher levels of abstraction –Enforce information hiding - control what people see and do –Call packaged code from object types and triggers Encourages top-down design and bottom-up construction –TD: Design the interfaces required by the different components of your application without addressing implementation details –BU: Existing packages contain building blocks for new code Organize your stored code more effectively Implements session-persistent data

10 Overloading in packages: key usability technique Overloading (static polymorphism): two or more programs with the same name, but different signature. –You can overload in the declaration section of any PL/SQL block, including the package body (most common). Overloading is a critical feature when building comprehensive programmatic interfaces (APIs) or components using packages. –If you want others to use your code, you need to make that code as smart and as easy to use as possible. –Overloading transfers the "need to know" from the user to the overloaded program. myproc myfunc myproc Compare: DBMS_OUTPUT and p

11 How Overloading Works For two or more modules to be overloaded, the compiler must be able to distinguish between the two calls at compile-time. –Another name for overloading is "static polymorphism." There are two different "compile times": –1. When you compile the package or block containing the overloaded code. –2. When you compile programs that use the overloaded code.

12 How Overloading Works, continued Distinguishing characteristics: –The formal parameters of overloaded modules must differ in number, order or datatype family (CHAR vs. VARCHAR2 is not different enough). –The programs are of different types: procedure and function. Undistinguishing characteristics: –Functions differ only in their RETURN datatype. –Arguments differ only in their mode (IN, OUT, IN OUT). –Their formal parameters differ only in datatype and the datatypes are in the same family.

13 Quiz! Nuances of Overloading Is this a valid overloading? Will it compile? How can I use it? CREATE OR REPLACE PACKAGE sales IS PROCEDURE calc_total (zone_in IN VARCHAR2); PROCEDURE calc_total (reg_in IN VARCHAR2); END sales; BEGIN sales.calc_total ('NORTHWEST'); sales.calc_total ('ZONE2'); END; ambig_overloading.sql ?

14 Package Data: Useful and Sticky The scope of a package is your session, and any data defined at the "package level" also has session scope. –If defined in the package specification, any program can directly read/write the data. –Ideal for program-specific caching. General best practice: hide your package data in the body so that you can control access to it. Use the SERIALLY_REUSABLE pragma to move data to SGA and have memory released after each usage. thisuser.pkg thisuser.tst serial.sql

15 Package Initialization Structure The initialization section: –Is defined after and outside of any programs in the package. –Is not required. –Can have its own exception handling section. Useful for: –Perform complex setting of default or initial values. –Set up package data which does not change for the duration of a session. –Confirm that package is properly instantiated. PACKAGE BODY pkg IS PROCEDURE proc IS BEGIN END; FUNCTION func RETURN BEGIN END; BEGIN...initialize... END pkg; BEGIN after/outside of any program defined in the pkg. init.pkg init.tst datemgr.pkg

16 Packages vs. Stand-alone programs General recommendation: use packages instead of stand-alone programs. –Better way to organize code. –Can hide implementation and reduce need to recompile programs using the package. Other considerations.... –Entire package loaded when any single program is called. –Central packages can become a "bottleneck" when changes are needed. recompile.sql

17 Top Tip: Write tiny chunks of code! It is virtually impossible to understand and therefore debug or maintain code that has long, meandering executable sections. How do you follow this guideline? –Don't skimp on the packages. –Top-down design / step-wise refinement –Use lots of local or nested modules. ?!?! Your executable section should have no more than fifty lines of code in it.

18 Let’s write some code! My team is building a call support application. Customers call with problems, and we put their call in a queue if it cannot be handled immediately. –I must now write a program that distributes unhandled calls out to members of the call support team. The basic algorithm from the doc summary is: –While there are still unhandled calls in the queue, assign them to employees who are under-utilized (have fewer calls assigned to them then the average for their department). Fifty pages of doc, complicated program!

19 First: Translate the summary into code. A more or less direct translation – and no comments! PROCEDURE distribute_calls ( department_id_in IN departments.department_id%TYPE) IS BEGIN WHILE ( calls_are_unhandled ( ) ) LOOP FOR emp_rec IN emps_in_dept_cur (department_id_in) LOOP IF current_caseload (emp_rec.employee_id) < avg_caseload_for_dept (department_id_in) THEN assign_next_open_call (emp_rec.employee_id); END IF; END LOOP; END distribute_calls;

20 Explanation of Subprograms Function calls_are_unhandled: takes no arguments, returns TRUE if there is still at least one unhandled call, FALSE otherwise. Function current_caseload: returns the number of calls (case load) assigned to that employee. Function avg_caseload_for_dept: returns the average number of calls assigned to employees in that department. Procedure assign_next_open_call: assigns the employee to the call, making it handled, as opposed to unhandled.

21 Next: Implement stubs for subprograms These are all defined locally in the procedure. PROCEDURE call_manager.distribute_calls ( department_id_in IN departments.department_id%TYPE) IS FUNCTION calls_are_handled RETURN BOOLEAN IS BEGIN... END calls_are_handled; FUNCTION current_caseload ( employee_id_in IN employees.employee_id%TYPE) RETURN PLS_INTEGER IS BEGIN... END current_caseload; FUNCTION avg_caseload_for_dept ( employee_id_in IN employees.employee_id%TYPE) RETURN PLS_INTEGER IS BEGIN... END current_caseload; PROCEDURE assign_next_open_call ( employee_id_in IN employees.employee_id%TYPE) IS BEGIN... END assign_next_open_call; BEGIN

22 Next: Think about implementation of just this level. Think about what the programs need to do. Think about if you or someone has already done it. Don’t reinvent the wheel! Hey! Just last week I wrote another function that is very similar to current_caseload. It is now "buried" inside a procedure named show_caseload. I can’t call it from distribute_calls, though. It is local, private, hidden. Should I cut and paste? No! I should extract the program and expand its scope.

23 Next: Isolate and refactor common code. Now current_caseload is at the package level and can be called by any program in the package. CREATE OR REPLACE PACKAGE BODY call_manager IS FUNCTION current_caseload ( employee_id_in IN employees.employee_id%TYPE, use_in_show_in IN BOOLEAN DEFAULT TRUE) RETURN PLS_INTEGER IS BEGIN... END current_caseload; PROCEDURE show_caseload ( department_id_in IN departments.department_id%TYPE) IS BEGIN... END show_caseload; PROCEDURE distribute_calls ( department_id_in IN departments.department_id%TYPE ) IS BEGIN... END distribute_calls; END; current_ caseload distribute _calls show_ caseload Increased complexity, backward compatibility.

24 Next: Reuse existing code whenever possible. Just last week, Sally ed all of us with news of her call_util package. –Returns average workload of employee and much more. –Just what I need! I don’t have to build it myself, just call it. BEGIN WHILE ( calls_are_unhandled ( ) ) LOOP FOR emp_rec IN emps_in_dept_cur (department_id_in) LOOP IF current_caseload (emp_rec. employee_id) < call_util.dept_avg_caseload (department_id_in) THEN assign_next_open_call (emp_rec.employee_id); END IF; END LOOP; END distribute_calls; This program has the widest scope possible: it can be executed by any schema with execute authority on the call_util package, and by any program within the owning schema.

25 Next: Implement what’s left. Now I am left only with program-specific, local subprograms. So I move down to the next level of detail and apply the same process. –Write the “executive summary” first. –Keep the executable section small. –Use local modules to hide the details. Eventually, you get down to the “real code” and write relatively trivial logic.

26 Challenges of local modules Requires discipline: always be on the lookout for opportunities to refactor. Need to read from the bottom, up. –Takes some getting used to. Sometimes can feel like a "wild goose chase". –Where is the darned thing actually implemented? –Your IDE should help you understand the internal structure of the program. How do you decide when a module should be local or defined at a “higher” level?

27 To sum up the rule: Define subprograms close to usage. When should the program be local? Private to the package? Publicly accessible? The best rule to follow is: Define your subprograms as close as possible to their usage(s). The shorter the distance from usage to definition, the easier it is to find, understand and maintain that code.

28 Instrument your code. We should all assume that we are going to need visibility into the execution of our backend code. –Debuggers are helpful once you’ve found a bug. –Automatic profiling by Oracle shows code coverage and performance. –But what about application-specific issues? Tracing is different from debugging. –You should build application/context tracing, that can be enabled without changing the code base itself. –Package-based globals offer a simple way to do this. –Quest CodeGen Utility offers a free tracing mechanism (the qd_runtime package)

29 Build and use regression tests. If we don’t build solid regression tests, we cannot possibly maintain that code without... –Lots of fear, lots of bugs, intensive allocation of resources. The only way to do this from a practical standpoint is to automate the process. –Quest Code Tester for Oracle –utPLSQL –PL/Unit

30 About deterministic programs Definition: the same IN argument values always result in the same output/outcomes. –That is, the results of the program are completely determined by the program header inputs to the program. –There are not “side effects.” Most PL/SQL programs have side-effects. –Every SQL statement is a side- effect, since it is not part of the parameter list. CREATE OR REPLACE FUNCTION betwnstr ( string_in IN VARCHAR2, start_in IN INTEGER, end_in IN INTEGER, inclusive_in IN BOOLEAN DEFAULT TRUE ) RETURN VARCHAR2 DETERMINISTIC IS BEGIN RETURN ( SUBSTR ( string_in, start_in, end_in - start_in + 1 )); END betwnstr; /

31 Working with deterministic programs Most deterministic programs are small and relatively simple. –Formulas, rules, etc. Some clear benefits to deterministic code: –They are easier to test, since they have no side-effects. –Oracle will optimize/avoid execution - sometimes! My suggestions: –Segregate as much of your code into deterministic and non- deterministic program units. –Carefully declare all deterministic programs. show_deterministc.sql deterministc.sql

32 Writing readable, maintainable code PL/SQL makes it easy to write really nice, comfortable code. –Use everything the language has to offer. Be disciplined! –You can transform your code quality relatively simply and easily by following the “Write tiny chunks of code!” Take your time! –Hurrying to build code is a sure-fire way to dig a deep hole really quickly. –Standardize development, define your tests, instrument your code.

Copyright © 2006 Quest Software