The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,839 other subscribers

Archive for the ‘Software Development’ Category

PlasticSCM Workaround for “Can’t perform a checkout in an edited xlink.”

Posted by jpluimers on 2018/11/01

Error message during a commit (checkin) or shelve of some changes:

---------------------------
Error
---------------------------
Can't perform a checkout in an edited xlink.
---------------------------
OK
---------------------------

In this case it is during a shelve:

---------------------------
Wait a moment, please...
---------------------------
In progress...
Shelving pending changes
---------------------------
OK
---------------------------

I cannot show all changes, but the third one is an xlink:

The error did not return any meaningful results when I searched for it, but the developers on the team indicated “Errors like these happen every now and then; there is no information in Google. Sit down, cry a little, then restart with a fresh repository”.

Workaround

The workaround for this undocumented behaviour is tedious, but works:

Read the rest of this entry »

Posted in Development, PlasticSCM, Software Development, Source Code Management | Leave a Comment »

PSBL: Passive Spam Block List powered by Spamikaze

Posted by jpluimers on 2018/11/01

On my research list: [WayBackPassive Spam Block List:

PSBL is an easy-on, easy-off blacklist that does not rely on testing and should reduce false positives because any user can remove their ISP’s mail server from the list.

The idea is that 99% of the hosts that send me spam never send me legitimate email, but that people whose mail server was used by spammers should still be able to send me email.

This results in a simple listing policy: an IP address gets added to the PSBL when it sends email to a spamtrap, that email is not identified as non-spam and the IP address is not a known mail server.

Via: Hans Wolters commenting at [WayBack] For my research list: Source: Bruteforce login prevention… – Jeroen Wiert Pluimers – Google+

References:

–jeroen

Posted in *nix, *nix-tools, Development, Perl, Power User, Scripting, Software Development | Leave a Comment »

A command-line REPL for RESTful HTTP Services – Scott Hanselman

Posted by jpluimers on 2018/10/31

Somewhere in Q4 2018 (actual year, not fiscal year) when .NET Core 2.2 gets released, but you can tinker with it right now: [WayBack] A command-line REPL for RESTful HTTP Services – Scott Hanselman.

Release estimates at [WayBack] core/roadmap.md at master · dotnet/core · GitHub.

–jeroen

Posted in .NET, .NET Core, Development, Software Development | Leave a Comment »

Down on the Upside – Kevlin Henney – Medium

Posted by jpluimers on 2018/10/31

Interesting read: [WayBack] Down on the Upside – Kevlin Henney – Medium

Abstraction is a question of less over more. But is it also a question of high over low?

What developers call abstraction, is not the abstraction end-users mean. Being aware of that makes software development life a whole lot easier.

Via: [WayBack] Kevlin Henney – Google+

–jeroen

Posted in Design Patterns, Development, Software Development | Leave a Comment »

Batch files and parentheses

Posted by jpluimers on 2018/10/31

Answering [WayBack] delphi – post-build event with multiple if/copy combinations only execute if first file does not exist – Stack Overflow made me do a quick search for parentheses handling in batch files. TL;DR: it is a mess.

But it reveals some interesting links:

–jeroen

Posted in Batch-Files, Conference Topics, Conferences, Development, Event, Scripting, Software Development, Windows Development | Leave a Comment »

PowerShell: measuring size of the Windows TEMP directory

Posted by jpluimers on 2018/10/31

Due some issues in Windows, every now and then the Windows TEMP directory gets huge.

This script helps measuring the recursive size of that folder:

$WindowPath = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Windows)
$WindowTempPath = Join-Path -Path $WindowPath -ChildPath "TEMP"
$Result = Get-ChildItem $WindowTempPath -Recurse | Measure-Object -Property Length -Sum
$RecursiveSumInBytes = $Result.Sum
Write-Host "$RecursiveSumInBytes"

It uses these tricks:

  • Accessing native .NET types; in this case [WayBackEnvironment.SpecialFolder Enumeration (System) to get the “The Windows directory or SYSROOT. This corresponds to the %windir% or %SYSTEMROOT% environment variables. Added in the .NET Framework 4.”
  • Assuming the Windows TEMP directory is always named that way.
  • Using [WayBackJoin-Path to combine a base path with a child path without worrying about the path delimiter.
  • Recursively enumerating all items in that folder using [WayBackGet-ChildItem.
  • Aggregating with [WayBackMeasure-Object over the Length property of each Child-Item to determine their Sum.

After this, cleaning up uses two more tricks:

$WindowPath = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Windows)
$WindowTempPath = Join-Path -Path $WindowPath -ChildPath "TEMP"
Get-ChildItem $WindowTempPath -Recurse | foreach { Remove-Item $_.FullName -Recurse }

Inspired by:

–jeroen

Posted in CommandLine, Development, PowerShell, Software Development | Leave a Comment »

Delphi: create implementations in the same order as the interface section and sync method signatures

Posted by jpluimers on 2018/10/30

An interesting question at [WayBack] Previously i have not been big on IDE plugins.So i’m blatantly asking for pointers on the following, i.e. is there already such beasts? Or maybe i’m i… – Dany Marmur – Google+:

… asking for pointers on the following…

Crtl+C – create implementations in the same order as the interface section?
Ctrl+C – adjust the signature of the method the cursor is on interface if implementation and vice versa.

I realise they can both be very tricky to implement. Second function might not be able to handle overloads.

From that thread, a few things you might want to try:

  • [WayBack] ModelMaker Code Explorer can do both.
  • [Archive.is] DDevExtensions version 2.82 (2014-08-25): introduced “Added: Disable Alpha-Sort Class Completion (Default off)”
  • More recent versions of the IDE (I think 10.0) incorporated the “sync prototypes” action (Shift+Ctrl+Alt+P) from Castalia.

–jeroen

 

Posted in Castalia, Delphi, Development, Software Development | Leave a Comment »

Google is sunsetting Google+ by August 2019; DelphiPraxis might start English forums and have RSS

Posted by jpluimers on 2018/10/26

From [WayBack1/WayBack2] Google is sunsetting Google+ by August 2019. “sunsetting” – clarification: “no fucks were given about current users” Edit: Sticky while the shock facto… – Lars Fosdal – Google+ I learned the very successful German forum site DelphiPraxis might start English forums.

Given the excellent track record of Embarcadero maintaining infrastructure up and running for the long therm, DelphiPraxis just might be the way to go:

  • like the Delphi G+ community, DelphiPraxis are independent of Embarcadero
  • unlike Embarcadero, DelphiPraxis have managed to keep forums running since 2002 without doing pruning of old messages

Some links:

Edit:

The English board has three public RSS streams as per [WayBack] RSS feeds for new posts ? – Community Management – Delphi-PRAXiS [en]:

  1. https://en.delphipraxis.net/discover/all.xml/
  2. https://en.delphipraxis.net/rssalltopics.xml/
  3. https://en.delphipraxis.net/rss/1-new-topics.xml

The first has all posts and all comments, so is really noisy.

The second seems to be the best for just new posts.

Via: [WayBack] Have you registered at https://en.delphipraxis.net yet? If you haven’t migrated your daily Delphi browsing to Delphi-PRAXiS yet, you should. The reason… – Lars Fosdal – Google+

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

Some Delphi versions miss some of the Indy files

Posted by jpluimers on 2018/10/25

Depending on your Delphi versions, you will likely miss Indy files:

The gap between XE and XE8 is not covered, but these versions miss a lot of files too.

The cause is that Embarcadero uses their own version control system, which is merged down and up to the Indy Subversion repository at irregular and incomplete intervals likely lacking a process checking if the merge results are OK.

Related:

You can get the missing files from GitHub – graemeg/indy.

This is the delta from Delphi 2010 to XE:

...\Indy10\Core\de\IdDsnCoreResourceStrings.pas
...\Indy10\Core\de\IdResourceStringsCore.pas
...\Indy10\Core\fr\IdDsnCoreResourceStrings.pas
...\Indy10\Core\fr\IdResourceStringsCore.pas
...\Indy10\Core\ja\IdDsnCoreResourceStrings.pas
...\Indy10\Core\ja\IdResourceStringsCore.pas
...\Indy10\Core\dclindycore.res
...\Indy10\Core\IdAboutVCL.rc
...\Indy10\Core\indycore.res
...\Indy10\Protocols\de\IdDsnResourceStrings.pas
...\Indy10\Protocols\de\IdHTTPWebBrokerBridge.pas
...\Indy10\Protocols\de\IdMessageBuilder.pas
...\Indy10\Protocols\de\IdResourceStringsProtocols.pas
...\Indy10\Protocols\de\IdZLibConst.pas
...\Indy10\Protocols\fr\IdDsnResourceStrings.pas
...\Indy10\Protocols\fr\IdHTTPWebBrokerBridge.pas
...\Indy10\Protocols\fr\IdMessageBuilder.pas
...\Indy10\Protocols\fr\IdResourceStringsProtocols.pas
...\Indy10\Protocols\fr\IdZLibConst.pas
...\Indy10\Protocols\ja\IdDsnResourceStrings.pas
...\Indy10\Protocols\ja\IdHTTPWebBrokerBridge.pas
...\Indy10\Protocols\ja\IdMessageBuilder.pas
...\Indy10\Protocols\ja\IdResourceStringsProtocols.pas
...\Indy10\Protocols\ja\IdZLibConst.pas
...\Indy10\Protocols\dclindyprotocols.res
...\Indy10\Protocols\IdAllAuthentications.pas
...\Indy10\Protocols\IdAllHeaderCoders.pas
...\Indy10\Protocols\IdAuthenticationSSPI.pas
...\Indy10\Protocols\IdBlockCipherIntercept.pas
...\Indy10\Protocols\IdCompressorZLib.pas
...\Indy10\Protocols\IdFIPS.pas
...\Indy10\Protocols\IdFTPListParseIEFTPGateway.pas
...\Indy10\Protocols\IdFTPListParsePCNFSD.pas
...\Indy10\Protocols\IdFTPListParsePCTCP.pas
...\Indy10\Protocols\IdFTPListParseSuperTCP.pas
...\Indy10\Protocols\IdFTPListParseTandemGuardian.pas
...\Indy10\Protocols\IdFTPListParseUnisysClearPath.pas
...\Indy10\Protocols\IdHashSHA.pas
...\Indy10\Protocols\IdHeaderCoder2022JP.pas
...\Indy10\Protocols\IdHeaderCoderBase.pas
...\Indy10\Protocols\IdHeaderCoderPlain.pas
...\Indy10\Protocols\IdHMAC.pas
...\Indy10\Protocols\IdHMACMD5.pas
...\Indy10\Protocols\IdHMACSHA1.pas
...\Indy10\Protocols\IdHTTPWebBrokerBridge.pas
...\Indy10\Protocols\IdMessageBuilder.pas
...\Indy10\Protocols\IdSASL_CRAM_SHA1.pas
...\Indy10\Protocols\IdSASL_CRAMBase.pas
...\Indy10\Protocols\IdSASLDigest.pas
...\Indy10\Protocols\IdSSLOpenSSLUtils.pas
...\Indy10\Protocols\IdSSPI.pas
...\Indy10\Protocols\IdUriUtils.pas
...\Indy10\Protocols\IdWebDAV.pas
...\Indy10\Protocols\IdZLib.pas
...\Indy10\Protocols\IdZLibConst.pas
...\Indy10\Protocols\IdZLibHeaders.pas
...\Indy10\Protocols\indyprotocols.res
...\Indy10\System\de\IdResourceStrings.pas
...\Indy10\System\fr\IdResourceStrings.pas
...\Indy10\System\ja\IdResourceStrings.pas

This is the delta from XE to XE2 (i.e. missing as of Delphi XE2) the same sources added to XE have been gone on XE2:

...\Indy10\Core\de\IdDsnCoreResourceStrings.pas
...\Indy10\Core\de\IdResourceStringsCore.pas
...\Indy10\Core\fr\IdDsnCoreResourceStrings.pas
...\Indy10\Core\fr\IdResourceStringsCore.pas
...\Indy10\Core\ja\IdDsnCoreResourceStrings.pas
...\Indy10\Core\ja\IdResourceStringsCore.pas
...\Indy10\Core\dclIndyCore.dpk
...\Indy10\Core\dclindycore.res
...\Indy10\Core\IdAboutVCL.pas
...\Indy10\Core\IdAboutVCL.rc
...\Indy10\Core\IdAntiFreeze.pas
...\Indy10\Core\IdCoreDsnRegister.pas
...\Indy10\Core\IdCoreRegisterCool.dcr
...\Indy10\Core\IdCoreSelectionEditors.pas
...\Indy10\Core\IdDsnCoreResourceStrings.pas
...\Indy10\Core\IdDsnPropEdBindingVCL.pas
...\Indy10\Core\IdRegisterCore.pas
...\Indy10\Protocols\de\IdDsnResourceStrings.pas
...\Indy10\Protocols\de\IdHTTPWebBrokerBridge.pas
...\Indy10\Protocols\de\IdMessageBuilder.pas
...\Indy10\Protocols\de\IdResourceStringsProtocols.pas
...\Indy10\Protocols\de\IdZLibConst.pas
...\Indy10\Protocols\fr\IdDsnResourceStrings.pas
...\Indy10\Protocols\fr\IdHTTPWebBrokerBridge.pas
...\Indy10\Protocols\fr\IdMessageBuilder.pas
...\Indy10\Protocols\fr\IdResourceStringsProtocols.pas
...\Indy10\Protocols\fr\IdZLibConst.pas
...\Indy10\Protocols\ja\IdDsnResourceStrings.pas
...\Indy10\Protocols\ja\IdHTTPWebBrokerBridge.pas
...\Indy10\Protocols\ja\IdMessageBuilder.pas
...\Indy10\Protocols\ja\IdResourceStringsProtocols.pas
...\Indy10\Protocols\ja\IdZLibConst.pas
...\Indy10\Protocols\dclIndyProtocols.dpk
...\Indy10\Protocols\dclindyprotocols.res
...\Indy10\Protocols\IdDsnRegister.pas
...\Indy10\Protocols\IdDsnResourceStrings.pas
...\Indy10\Protocols\IdDsnSASLListEditorFormVCL.pas
...\Indy10\Protocols\IdRegister.pas
...\Indy10\Protocols\IdRegisterCool.dcr
...\Indy10\System\de\IdResourceStrings.pas
...\Indy10\System\fr\IdResourceStrings.pas
...\Indy10\System\ja\IdResourceStrings.pas

In fact more are missing, the Delphi 2007 to 2009 delta was this:

...\Indy10\Core
...\Indy10\Core\dclIndyCore.dpk
...\Indy10\Core\dclindycore.dpkw
...\Indy10\Core\dclIndyCore.drc
...\Indy10\Core\dclindycore.res
...\Indy10\Core\IdAbout.pas
...\Indy10\Core\IdAboutDotNET.pas
...\Indy10\Core\IdAboutVCL.pas
...\Indy10\Core\IdAntiFreeze.pas
...\Indy10\Core\IdCoreDsnRegister.pas
...\Indy10\Core\IdCoreRegister.dcr
...\Indy10\Core\IdDsnBaseCmpEdt.pas
...\Indy10\Core\IdDsnCoreResourceStrings.pas
...\Indy10\Core\IdDsnPropEdBinding.pas
...\Indy10\Core\IdDsnPropEdBindingNET.pas
...\Indy10\Core\IdDsnPropEdBindingVCL.pas
...\Indy10\Core\IdRegisterCore.pas
...\Indy10\Core\indycore.dpkw
...\Indy10\Core\IndyCore.drc
...\Indy10\Protocols
...\Indy10\Protocols\dclIndyProtocols.dpk
...\Indy10\Protocols\dclindyprotocols.dpkw
...\Indy10\Protocols\dclIndyProtocols.drc
...\Indy10\Protocols\dclindyprotocols.res
...\Indy10\Protocols\IdCompressorZLibEx.pas
...\Indy10\Protocols\IdDsnRegister.pas
...\Indy10\Protocols\IdDsnResourceStrings.pas
...\Indy10\Protocols\IdDsnSASLListEditor.pas
...\Indy10\Protocols\IdDsnSASLListEditorForm.pas
...\Indy10\Protocols\IdDsnSASLListEditorFormVCL.pas
...\Indy10\Protocols\IdHashSHA1.pas
...\Indy10\Protocols\IdHL7.pas
...\Indy10\Protocols\IdMIMETypes.pas
...\Indy10\Protocols\IdRegister.dcr
...\Indy10\Protocols\IdRegister.pas
...\Indy10\Protocols\IdRegisterCool.dcr
...\Indy10\Protocols\IdSSLOpenSSLHeadersNET.pas
...\Indy10\Protocols\IdZLibEx.pas
...\Indy10\Protocols\indyprotocols.dpkw
...\Indy10\Protocols\IndyProtocols.drc
...\Indy10\System
...\Indy10\System\IdObjs.pas
...\Indy10\System\IdObjsBase.pas
...\Indy10\System\IdObjsVCL.pas
...\Indy10\System\IdStackLinux.pas
...\Indy10\System\IdSys.pas
...\Indy10\System\IdSysBase.pas
...\Indy10\System\IdSysNativeVCL.pas
...\Indy10\System\IdSysNet.pas
...\Indy10\System\IdSysVCL.pas
...\Indy10\System\IdSysVCLNet.pas
...\Indy10\System\IdSysWin32.pas
...\Indy10\System\IndySystem.drc

RS … mentiones the files missing as of Berlin, but in fact many other delphi versions miss files too.

File only in Indy SVN: 'Core\IdAbout.pas'
File only in Indy SVN: 'Core\IdAboutDotNET.pas'
File only in Indy SVN: 'Core\IdAboutVCL.pas'
File only in Indy SVN: 'Core\IdAntiFreeze.pas'
File only in Indy SVN: 'Core\IdCoreDsnRegister.pas'
File only in Indy SVN: 'Core\IdDsnBaseCmpEdt.pas'
File only in Indy SVN: 'Core\IdDsnCoreResourceStrings.pas'
File only in Indy SVN: 'Core\IdDsnPropEdBinding.pas'
File only in Indy SVN: 'Core\IdDsnPropEdBindingNET.pas'
File only in Indy SVN: 'Core\IdDsnPropEdBindingVCL.pas'
File only in Indy SVN: 'Core\IdRegisterCore.pas'
File only in Indy SVN: 'Core\indycorefpc.pas'
File only in Indy SVN: 'Design\IdDsnCoreResourceStrings.pas'
File only in Indy SVN: 'Design\IdDsnNETCompEditor.pas'
File only in Indy SVN: 'Design\IdDsnPropEdBindingNET.pas'
File only in Indy SVN: 'Protocols\IdASN1Coder.pas'
File only in Indy SVN: 'Protocols\IdCoderTNEF.pas'
File only in Indy SVN: 'Protocols\IdDsnRegister.pas'
File only in Indy SVN: 'Protocols\IdDsnResourceStrings.pas'
File only in Indy SVN: 'Protocols\IdDsnSASLListEditor.pas'
File only in Indy SVN: 'Protocols\IdDsnSASLListEditorForm.pas'
File only in Indy SVN: 'Protocols\IdDsnSASLListEditorFormNET.pas'
File only in Indy SVN: 'Protocols\IdDsnSASLListEditorFormVCL.pas'
File only in Indy SVN: 'Protocols\IdDummyUnit.pas'
File only in Indy SVN: 'Protocols\IdHashAdler32.pas'
File only in Indy SVN: 'Protocols\IdHashIntf.pas'
File only in Indy SVN: 'Protocols\IdHashSHA1.pas'
File only in Indy SVN: 'Protocols\IdHeaderCoderBig5.pas'
File only in Indy SVN: 'Protocols\IdHL7.pas'
File only in Indy SVN: 'Protocols\IdHostnameServer.pas'
File only in Indy SVN: 'Protocols\IdLDAPV3.pas'
File only in Indy SVN: 'Protocols\IdLDAPV3Coder.pas'
File only in Indy SVN: 'Protocols\IdMIMETypes.pas'
File only in Indy SVN: 'Protocols\IdNTLMv2.pas'
File only in Indy SVN: 'Protocols\IdPOP4Server.pas'
File only in Indy SVN: 'Protocols\IdRegister.pas'
File only in Indy SVN: 'Protocols\IdResourceStringsSSLDotNet.pas'
File only in Indy SVN: 'Protocols\IdSASL_NTLM.pas'
File only in Indy SVN: 'Protocols\IdServerIOHandlerSSLOpenSSL.pas'
File only in Indy SVN: 'Protocols\IdSSH.pas'
File only in Indy SVN: 'Protocols\IdSSLDotNET.pas'
File only in Indy SVN: 'Protocols\IdTunnelCommon.pas'
File only in Indy SVN: 'Protocols\IdTunnelMaster.pas'
File only in Indy SVN: 'Protocols\IdTunnelSlave.pas'
File only in Indy SVN: 'Protocols\IdUserAccountsOTP.pas'
File only in Indy SVN: 'Protocols\indyprotocolsfpc.pas'
File only in Indy SVN: 'Protocols\ZLib\ZLib.pas'
File only in Indy SVN: 'Protocols\ZLib\ZLibConst.pas'
File only in Indy SVN: 'System\IdAssemblyInfo.pas'
File only in Indy SVN: 'System\IdIconv.pas'
File only in Indy SVN: 'System\IdResourceStringsDotNet11.pas'
File only in Indy SVN: 'System\IdResourceStringsIconv.pas'
File only in Indy SVN: 'System\IdResourceStringsKylixCompat.pas'
File only in Indy SVN: 'System\IdResourceStringsTextEncoding.pas'
File only in Indy SVN: 'System\IdStackDotNet.pas'
File only in Indy SVN: 'System\IdStackLibc.pas'
File only in Indy SVN: 'System\IdStackLinux.pas'
File only in Indy SVN: 'System\IdStackUnix.pas'
File only in Indy SVN: 'System\IdStreamNET.pas'
File only in Indy SVN: 'System\IdTransactedFileStream.pas'
File only in Indy SVN: 'System\indysystemfpc.pas'aa

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

Ralph Johnson: 22 years of design patterns – YouTube video of lecture

Posted by jpluimers on 2018/10/25

via [WayBack] Ralph Johnson: 22 years of design patterns. I thought you might find this interestinghttps://youtu.be/jhPLFLcxslM – Agustin Ortu – Google+ the below video.

Ralph Johnson is one of the Gang of Four: the authors of the famous Design Patterns: Elements of Reusable Object-Oriented Software book published October 21, 1994 and copyrighted 1995.

Google translated lecture announcement, slightly edited:

Ralph Johnson is world renowned for his high impact contributions to Software Engineering, particularly Object Orientation. His book “Design Patterns” has been best-selling in the history of computing (more than 500,000 copies sold in English and in translations into 13 languages). From his research group also emerged the first works on frameworks, patterns and refactoring. His students also created the first refactoring tool, the Smalltalk Refactoring Browser, on whose architecture all the refactoring tools of today are based.

His talk, “Twenty Years of Design Patterns,” will talk about the evolution of software patterns since its inception in 1994. Some have become common, and others have not. Some patterns have changed. Ralph Johnson will talk about several of the patterns that are more widely known, with a renewed understanding of what the book “Design Patterns” should have said.

Ralph moved from the Department of Computer Science at the University of Illinois to COO of Metaficient and many of his history is only at the WayBack machine, so here are some links to it:

  • Ralph Johnson: The Refactory is dedicated to helping organizations succeed with objects and design patterns. Principals include Ralph Johnson, an original member of the Gang of Four patterns.
  • Former Ralph E. Johnson homepage at the University of Illinois
  • Metaficient Management Team
  • 2016: 25 years of OOP Konferenz 2016 – Ralph Johnson
  • Ralph Johnson on Parallel Programming Patterns: Ralph Johnson, one of the four GoF authors, talks about the upcoming book “The Patterns for Parallel Programming”. He highlights the difficulties in dealing with discovering and writing down parallel programming patterns, how to choose and use such a pattern, and similarities with the initial Design Patterns book.
  • A Pattern Language for Parallel Programming: Ralph Johnson presents a pattern language that he and his colleagues are working on in an attempt to solve the hard issues of parallel programming through a set of design patterns: Structural Patterns, Computational Patterns, Parallel Algorithm Strategy Patterns, Implementation Strategy Patterns, and Concurrent Execution Patterns.

–jeroen

Read the rest of this entry »

Posted in Design Patterns, Development, Software Development | Leave a Comment »