510 likes | 643 Views
Coding For People. Martyn Gigg, Tessella 7 th March 2013. About Me. MPhys at Warwick: 2000 – 2004 PhD in Physics: 2004 – 2008 Tessella: 2008 - ? Mantid - Data Reduction & Analysis in collaboration with Rutherford Appleton Laboratory UK & Oak Ridge National Lab USA.
E N D
Coding For People Martyn Gigg, Tessella 7th March 2013
About Me • MPhys at Warwick: 2000 – 2004 • PhD in Physics: 2004 – 2008 • Tessella: 2008 - ? • Mantid - Data Reduction & Analysis in collaboration with Rutherford Appleton Laboratory UK & Oak Ridge National Lab USA
About Tessella – www.tessella.com • Services based software company
Tessella Employees Typically have a degree in a numerate discipline Many have PhDs in a similar field Most junior members of technical staff are recent graduates Required to keep skills up to date using 150 hours a year (~20 days) training budget
FUSION Research Project Building a fusion Tokamakin the South of France
Pharmaceutical – Drug Development • Analysis of clinical trials data and adaptive dose allocation using Bayesian statistics
Hardware vs Software • Software is just as important as hardware • Tendency to skimp on software, i.e. post doc written • Good software requires processes • Software Engineering • Requires trained people just like other disciplines
So far … • Variety of Technologies • Variety of Domains • Lots of Different and Interesting Challenges
Introducing Change • How does a business keep on making money? • Software changes to meet business needs • Further development → Reponse to change • One side = ability to track change • Version control • A solved problem
How easy is code to change? Machines don’t read (as in understand)/write code We spend more time reading than writing code Hard to understand Hard to change Hard to change Costs more
Documents • Requirements • Design/Architecture • Test Scripts • Installation Guide • Manual • Maintenance Guide
Comments // We need to check if the approver of the // document still has permission to see it Document doc = gateway.GetDocumentById(documentId); PermissionSet perm = new PermissionSet(user, doc); // Changed by John (August) return perm.CanView();
Comments /* ********************************** * r23 21-Jan-2009 John * Created class * * r23 12-Feb-2009 Bob * Added Co-Author property * * r23 01-Mar-2009 Dave * Created class * * r23 21-June-2010 John * Implemented new Workflow * * **************************************/ public class Document {
Comments publicclassWordLimitValidator{ public int wordLimit; public bool IsWithinWordLimit(Document d) { return document.WordCount <= this.wordLimit; }} publicclassClass1{// Declare the max integer Xpublicint x; // Checks the documentpublicbool Check(Document d) {// Keeps a running count, start at 0int t = 0;// Loop over the sectionsfor (int i = 0; i < d.Sections.Count; i++) {// Loop over the paragraphs in the sectionfor (int j = 0; j < d.Sections[i].Paras.Count; j++) {// Increment the total count t += d.Sections[i].Paras[j].Words.Count; } }// Check that t is less than or equal to xreturn t <= x; }}
Readability Do not use booleans as arguments! StringCreateFile(Stringfilename, BooleanoverwriteExisting, BooleankeepOpen); CreateFile("file.csv",true, false); CreateFile("file.csv",CreateMode.OverwriteExisting, LockMode.KeepOpen); StringCreateFile(Stringfilename,CreateModefileMode,LockModelockMode);
Readability Does it fit on one screen? AndAlso (document.Author.Department.Head = currentUser.Manager OrElse version.
Readability Does your code describe the domain? Public Float Class String Document Integer Public DateTime Author String Version Class Document XmlDocument XmlDocument Signature
Smells • Duplicated code: identical or very similar code exists in more than one location. • Long method: a method, function, or procedure that has grown too large. • Large class: a class that has grown too large. See God object. • Feature envy: a class that uses methods of another class excessively. • Inappropriate intimacy: a class that has dependencies on implementation details of another class. • Refused bequest: a class that overrides a method of a base class in such a way that the contract of the base class is not honoured by the derived class. See Liskov substitution principle.
Lazy class / Freeloader: a class that does too little. • Contrived complexity: forced usage of overly complicated design patterns where simpler design would suffice. • Excessively long identifiers: in particular, the use of naming conventions to provide disambiguation that should be implicit in the software architecture. • Excessive use of literals: these should be coded as named constants, to improve readability and to avoid programming errors.
A small detour: Testing • Everyone tests their code • Refactoring should leave functionality intact • Good automated tests ensure this • One of the keys to continuing success is good test coverage and also good feedback from automated tests • Modern approaches such as Test Driven Development encourage testing as part of development
Testing & Reuse • Unmanned but cost ~$370 million
Null Object void NotifyDepartmentHead(IPerson person) { if (person.Section != null && person.Section.Division != null && person.Section.Division.Department != null && person.Section.Division.Department.Manager != null) { if (! string.IsNullOrEmpty( person.Section.Division.Department.Manager.EmailAddress)) { SendEmail(person.Section.Division.Department.Manager.EmailAddress); } } }
Null Object public class NullDivision : IDivision { public IDepartment Department { get { return new NullDepartment(); } } public IPerson Manager { get { return new NullPerson() } } } public class NullSection : ISection { public IDivision Division { get { return new NullDivision(); } } public IPerson Manager { get { return new NullPerson(); } } }
Null Object void NotifyDepartmentHead(IPerson person) { String address = person.Section.Division.Department.Manager.EmailAddress; if (!String.IsNullOrEmpty(address)) SendMail(address); }
Conclusion Software needs to change, so it must be EASY to change The CODE is always right Write your code so it is easy to understand You can use patterns to solve common problems Agile methodologies embrace change
Suggested Reading • 97 Things Every Programmer Should Know [O’Reilly] • Patterns of Enterprise Application Architecture, by Martin Fowler • Clean Code: A Handbook of Agile Software Craftsmanship by Robert Martin • Head First Design Patterns, by Eric T Freeman, Elisabeth Robson, Bert Bates, Kathy Sierra • Java Puzzlers: Traps, Pitfalls, and Corner Cases, by Joshua Bloch, Neal Gafter
function GetPosString(position) { switch (position) { case 0: return "1st"; case 1: return "2nd"; case 2: return "3rd" ; default: return (position + 1) + "th"; } }
if (!$email){ global $Email; $email=$Email; if (!$email){ global $Email_Address; $email=$Email_Address; if (!$email){ global $email_address; $email=$email_address; if (!$email){ global $EmailAddress; $email = $EmailAddress; if (!$email){ global $emailaddress; $email = $emailaddress; if (!$email){ global $EMailAddress; $email = $EMailAddress; } } } } } }
public class Document { // Creates a new document object that is not yet in the database public Document(String id, int version) { // ... } // Loads a document object from the database public Document(int version, String id) { // ... }
onreadystatechange = function(){ switch(httpReq.readyState){ case 0: if(httpReq.readyState == 0){ break; } case 1: if(httpReq.readyState == 1){ break; } case 2: if(httpReq.readyState == 2){ break; } case 3: if(httpReq.readyState == 3){ break; } case 4: if(httpReq.readyState == 4){ if(httpReq.status == 200){ var val = httpReq.responseText; alert(httpReq.responseText) dataInsert(val); break; } else{ alert("Error "+httpReq.status); break; } } } };
// assign variables logFile.info("START: Assigning variables."); logFile.debug("Getting particular drug information."); // gets drugs brandNameDrugs = Utils.formatDrugList(dl.getDrugsByLabel(calculateBean.getDrugName())); logFile.debug("Getting major classifications."); // get all major classifications (usage) majorClassifications = cl.getMajorClassifications(); logFile.debug("Getting classifications."); // get all classifications classifications = cl.getClassifications(); logFile.debug("Getting all classifications."); // gets all the major classifications and classifications allClassifications = cl.getAllClassifications(); logFile.info("END: Assigning variables."); // assign variables to session for search.jsp logFile.info("START: Assigning variables to the session."); logFile.debug("Storing brandNameDrugs to the session."); request.setAttribute("brandNameDrugs", brandNameDrugs); logFile.debug("Storing majorClassifications to the session."); request.setAttribute("majorClassifications", majorClassifications); logFile.debug("Storing classifications to the session."); request.setAttribute("classifications", classifications); logFile.debug("Storing allClassifications to the session."); request.setAttribute("allClassifications", allClassifications); logFile.info("END: Assigning variables to the session.");
// "true" or "false" public static string Bool2Str(bool b) { switch(b) { case true: return System.Boolean.TrueString; case false: return System.Boolean.FalseString; default: return "error"; } }
Public Shared Sub isValidQuery(ByVal query As String) ‘… End Sub
‘'To Get date from SAP XMl as they are providing date like 20090330 Public Shared Function Getformateddate(ByVal strDate As String) As Date Dim month As String = strDate.Substring(4, 2) Dim year As String = strDate.Substring(0, 4) Dim day As String = strDate.Substring(6, 2) Dim tempdate As Date = Convert.ToDateTime(day + "/" + month + "/" + year) Return CDate(tempdate.ToShortDateString) End Function
''çatch exception in case the date is null not correct format. Try If strDate.Trim.Length = 8 AndAlso IsNumeric(strDate) Then Dim month As String = strDate.Substring(4, 2) Dim year As String = strDate.Substring(0, 4) Dim day As String = strDate.Substring(6, 2) Dim tempdate As Date = New Date(CInt(year), CInt(month), CInt(day)) Return CDate(tempdate.ToShortDateString) End If Catch ex As Exception Return Nothing End Try
DimuserAsIPerson = icp.ContentDispatcher.userDimsuperAsBoolean= user.IsDBManager user.setAsDbManager() ‘ Snip IfNotsuperThen user.removeAsDbManager()EndIf